PluginProbe
Media Cloud Sync / 1.0.1
Media Cloud Sync v1.0.1
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
media-cloud-sync / includes / sdk / google / google / gax / src / ApiException.php

ApiException.php in Media Cloud Sync 1.0.1, at includes/sdk/google/google/gax/src/ApiException.php

268 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * Copyright 2016 Google LLC
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following disclaimer
15 * in the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Google Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 namespace Dudlewebs\WPMCS\Google\ApiCore;
34
35 use Exception;
36 use Dudlewebs\WPMCS\Google\Protobuf\Internal\RepeatedField;
37 use Dudlewebs\WPMCS\Google\Rpc\Status;
38 use Dudlewebs\WPMCS\GuzzleHttp\Exception\RequestException;
39 use Dudlewebs\WPMCS\Google\ApiCore\Testing\MockStatus;
40 use stdClass;
41 /**
42 * Represents an exception thrown during an RPC.
43 */
44 class ApiException extends Exception
45 {
46 private $status;
47 private $metadata;
48 private $basicMessage;
49 private $decodedMetadataErrorInfo;
50 /**
51 * ApiException constructor.
52 * @param string $message
53 * @param int $code
54 * @param string|null $status
55 * @param array $optionalArgs {
56 * @type Exception|null $previous
57 * @type array|null $metadata
58 * @type string|null $basicMessage
59 * }
60 */
61 public function __construct(string $message, int $code, string $status = null, array $optionalArgs = [])
62 {
63 $optionalArgs += ['previous' => null, 'metadata' => null, 'basicMessage' => $message];
64 parent::__construct($message, $code, $optionalArgs['previous']);
65 $this->status = $status;
66 $this->metadata = $optionalArgs['metadata'];
67 $this->basicMessage = $optionalArgs['basicMessage'];
68 if ($this->metadata) {
69 $this->decodedMetadataErrorInfo = self::decodeMetadataErrorInfo($this->metadata);
70 }
71 }
72 public function getStatus()
73 {
74 return $this->status;
75 }
76 /**
77 * Returns null if metadata does not contain error info, or returns containsErrorInfo() array
78 * if the metadata does contain error info.
79 * @param array $metadata
80 * @return array $details {
81 * @type string|null $reason
82 * @type string|null $domain
83 * @type array|null $errorInfoMetadata
84 * }
85 */
86 private static function decodeMetadataErrorInfo(array $metadata)
87 {
88 $details = [];
89 // ApiExceptions created from RPC status have metadata that is an array of objects.
90 if (is_object(reset($metadata))) {
91 $metadataRpcStatus = Serializer::decodeAnyMessages($metadata);
92 $details = self::containsErrorInfo($metadataRpcStatus);
93 } elseif (self::containsErrorInfo($metadata)) {
94 $details = self::containsErrorInfo($metadata);
95 } else {
96 // For GRPC-based responses, the $metadata needs to be decoded.
97 $metadataGrpc = Serializer::decodeMetadata($metadata);
98 $details = self::containsErrorInfo($metadataGrpc);
99 }
100 return $details;
101 }
102 /**
103 * Returns the `reason` in ErrorInfo for an exception, or null if there is no ErrorInfo.
104 * @return string|null $reason
105 */
106 public function getReason()
107 {
108 return $this->decodedMetadataErrorInfo ? $this->decodedMetadataErrorInfo['reason'] : null;
109 }
110 /**
111 * Returns the `domain` in ErrorInfo for an exception, or null if there is no ErrorInfo.
112 * @return string|null $domain
113 */
114 public function getDomain()
115 {
116 return $this->decodedMetadataErrorInfo ? $this->decodedMetadataErrorInfo['domain'] : null;
117 }
118 /**
119 * Returns the `metadata` in ErrorInfo for an exception, or null if there is no ErrorInfo.
120 * @return array|null $errorInfoMetadata
121 */
122 public function getErrorInfoMetadata()
123 {
124 return $this->decodedMetadataErrorInfo ? $this->decodedMetadataErrorInfo['errorInfoMetadata'] : null;
125 }
126 /**
127 * @param stdClass $status
128 * @return ApiException
129 */
130 public static function createFromStdClass(stdClass $status)
131 {
132 $metadata = property_exists($status, 'metadata') ? $status->metadata : null;
133 return self::create($status->details, $status->code, $metadata, Serializer::decodeMetadata((array) $metadata));
134 }
135 /**
136 * @param string $basicMessage
137 * @param int $rpcCode
138 * @param array|null $metadata
139 * @param Exception $previous
140 * @return ApiException
141 */
142 public static function createFromApiResponse($basicMessage, $rpcCode, array $metadata = null, Exception $previous = null)
143 {
144 return self::create($basicMessage, $rpcCode, $metadata, Serializer::decodeMetadata((array) $metadata), $previous);
145 }
146 /**
147 * For REST-based responses, the metadata does not need to be decoded.
148 *
149 * @param string $basicMessage
150 * @param int $rpcCode
151 * @param array|null $metadata
152 * @param Exception $previous
153 * @return ApiException
154 */
155 public static function createFromRestApiResponse($basicMessage, $rpcCode, array $metadata = null, Exception $previous = null)
156 {
157 return self::create($basicMessage, $rpcCode, $metadata, is_null($metadata) ? [] : $metadata, $previous);
158 }
159 /**
160 * Checks if decoded metadata includes errorInfo message.
161 * If errorInfo is set, it will always contain `reason`, `domain`, and `metadata` keys.
162 * @param array $decodedMetadata
163 * @return array {
164 * @type string $reason
165 * @type string $domain
166 * @type array $errorInfoMetadata
167 * }
168 */
169 private static function containsErrorInfo(array $decodedMetadata)
170 {
171 if (empty($decodedMetadata)) {
172 return [];
173 }
174 foreach ($decodedMetadata as $value) {
175 $isErrorInfoArray = isset($value['reason']) && isset($value['domain']) && isset($value['metadata']);
176 if ($isErrorInfoArray) {
177 return ['reason' => $value['reason'], 'domain' => $value['domain'], 'errorInfoMetadata' => $value['metadata']];
178 }
179 }
180 return [];
181 }
182 /**
183 * Construct an ApiException with a useful message, including decoded metadata.
184 * If the decoded metadata includes an errorInfo message, then the domain, reason,
185 * and metadata fields from that message are hoisted directly into the error.
186 *
187 * @param string $basicMessage
188 * @param int $rpcCode
189 * @param iterable|null $metadata
190 * @param array $decodedMetadata
191 * @param Exception|null $previous
192 * @return ApiException
193 */
194 private static function create(string $basicMessage, int $rpcCode, $metadata, array $decodedMetadata, Exception $previous = null)
195 {
196 $containsErrorInfo = self::containsErrorInfo($decodedMetadata);
197 $rpcStatus = ApiStatus::statusFromRpcCode($rpcCode);
198 $messageData = ['message' => $basicMessage, 'code' => $rpcCode, 'status' => $rpcStatus, 'details' => $decodedMetadata];
199 if ($containsErrorInfo) {
200 $messageData = array_merge($containsErrorInfo, $messageData);
201 }
202 $message = json_encode($messageData, \JSON_PRETTY_PRINT);
203 if ($metadata instanceof RepeatedField) {
204 $metadata = iterator_to_array($metadata);
205 }
206 return new ApiException($message, $rpcCode, $rpcStatus, ['previous' => $previous, 'metadata' => $metadata, 'basicMessage' => $basicMessage]);
207 }
208 /**
209 * @param Status $status
210 * @return ApiException
211 */
212 public static function createFromRpcStatus(Status $status)
213 {
214 return self::create($status->getMessage(), $status->getCode(), $status->getDetails(), Serializer::decodeAnyMessages($status->getDetails()));
215 }
216 /**
217 * Creates an ApiException from a GuzzleHttp RequestException.
218 *
219 * @param RequestException $ex
220 * @param boolean $isStream
221 * @return ApiException
222 * @throws ValidationException
223 */
224 public static function createFromRequestException(RequestException $ex, bool $isStream = \false)
225 {
226 $res = $ex->getResponse();
227 $body = (string) $res->getBody();
228 $decoded = json_decode($body, \true);
229 // A streaming response body will return one error in an array. Parse
230 // that first (and only) error message, if provided.
231 if ($isStream && isset($decoded[0])) {
232 $decoded = $decoded[0];
233 }
234 if (isset($decoded['error']) && $decoded['error']) {
235 $error = $decoded['error'];
236 $basicMessage = $error['message'] ?? '';
237 $code = isset($error['status']) ? ApiStatus::rpcCodeFromStatus($error['status']) : $ex->getCode();
238 $metadata = $error['details'] ?? null;
239 return static::createFromRestApiResponse($basicMessage, $code, $metadata);
240 }
241 // Use the RPC code instead of the HTTP Status Code.
242 $code = ApiStatus::rpcCodeFromHttpStatusCode($res->getStatusCode());
243 return static::createFromApiResponse($body, $code);
244 }
245 /**
246 * @return null|string
247 */
248 public function getBasicMessage()
249 {
250 return $this->basicMessage;
251 }
252 /**
253 * @return mixed[]
254 */
255 public function getMetadata()
256 {
257 return $this->metadata;
258 }
259 /**
260 * String representation of ApiException
261 * @return string
262 */
263 public function __toString()
264 {
265 return __CLASS__ . ": {$this->message}\n";
266 }
267 }
268