PluginProbe
Media Cloud Sync / 1.4.2
Media Cloud Sync v1.4.2
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.4.2, at includes/sdk/google/google/gax/src/ApiException.php

299 lines 11.4 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\GCP\Google\ApiCore;
34
35 use Exception;
36 use Dudlewebs\WPMCS\GCP\Google\Protobuf\RepeatedField;
37 use Dudlewebs\WPMCS\GCP\Google\Rpc\Status;
38 use Dudlewebs\WPMCS\GCP\GuzzleHttp\Exception\RequestException;
39 use stdClass;
40 /**
41 * Represents an exception thrown during an RPC.
42 */
43 class ApiException extends Exception
44 {
45 private $status;
46 private $metadata;
47 private $basicMessage;
48 private $decodedMetadataErrorInfo;
49 private array $protobufErrors;
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 = [], array $protobufErrors = [])
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 $this->protobufErrors = $protobufErrors;
72 }
73 public function getStatus()
74 {
75 return $this->status;
76 }
77 /**
78 * Returns null if metadata does not contain error info, or returns containsErrorInfo() array
79 * if the metadata does contain error info.
80 * @param array $metadata
81 * @return array $details {
82 * @type string|null $reason
83 * @type string|null $domain
84 * @type array|null $errorInfoMetadata
85 * }
86 */
87 private static function decodeMetadataErrorInfo(array $metadata)
88 {
89 $details = [];
90 // ApiExceptions created from RPC status have metadata that is an array of objects.
91 if (\is_object(\reset($metadata))) {
92 $metadataRpcStatus = Serializer::decodeAnyMessages($metadata);
93 $details = self::containsErrorInfo($metadataRpcStatus);
94 } elseif (self::containsErrorInfo($metadata)) {
95 $details = self::containsErrorInfo($metadata);
96 } else {
97 // For GRPC-based responses, the $metadata needs to be decoded.
98 $metadataGrpc = Serializer::decodeMetadata($metadata);
99 $details = self::containsErrorInfo($metadataGrpc);
100 }
101 return $details;
102 }
103 /**
104 * Returns the `reason` in ErrorInfo for an exception, or null if there is no ErrorInfo.
105 * @return string|null $reason
106 */
107 public function getReason()
108 {
109 return $this->decodedMetadataErrorInfo ? $this->decodedMetadataErrorInfo['reason'] : null;
110 }
111 /**
112 * Returns the `domain` in ErrorInfo for an exception, or null if there is no ErrorInfo.
113 * @return string|null $domain
114 */
115 public function getDomain()
116 {
117 return $this->decodedMetadataErrorInfo ? $this->decodedMetadataErrorInfo['domain'] : null;
118 }
119 /**
120 * Returns the `metadata` in ErrorInfo for an exception, or null if there is no ErrorInfo.
121 * @return array|null $errorInfoMetadata
122 */
123 public function getErrorInfoMetadata()
124 {
125 return $this->decodedMetadataErrorInfo ? $this->decodedMetadataErrorInfo['errorInfoMetadata'] : null;
126 }
127 /**
128 * Returns the unserialized errors
129 * @return array
130 */
131 public function getErrorDetails() : array
132 {
133 return $this->protobufErrors;
134 }
135 /**
136 * @param stdClass $status
137 * @return ApiException
138 */
139 public static function createFromStdClass(stdClass $status)
140 {
141 $metadata = \property_exists($status, 'metadata') ? $status->metadata : null;
142 $errors = [];
143 return self::create($status->details, $status->code, $metadata, Serializer::decodeMetadata((array) $metadata, $errors), $errors);
144 }
145 /**
146 * @param string $basicMessage
147 * @param int $rpcCode
148 * @param array|null $metadata
149 * @param Exception $previous
150 * @return ApiException
151 */
152 public static function createFromApiResponse($basicMessage, $rpcCode, ?array $metadata = null, ?Exception $previous = null)
153 {
154 $errors = [];
155 return self::create($basicMessage, $rpcCode, $metadata, Serializer::decodeMetadata((array) $metadata, $errors), $errors, $previous);
156 }
157 /**
158 * For REST-based responses, the metadata does not need to be decoded.
159 *
160 * @param string $basicMessage
161 * @param int $rpcCode
162 * @param array|null $metadata
163 * @param Exception $previous
164 * @return ApiException
165 */
166 public static function createFromRestApiResponse($basicMessage, $rpcCode, ?array $metadata = null, ?Exception $previous = null)
167 {
168 return self::create($basicMessage, $rpcCode, $metadata, \is_null($metadata) ? [] : $metadata, self::decodeMetadataToProtobufErrors($metadata ?? []), $previous);
169 }
170 /**
171 * Checks if decoded metadata includes errorInfo message.
172 * If errorInfo is set, it will always contain `reason`, `domain`, and `metadata` keys.
173 * @param array $decodedMetadata
174 * @return array {
175 * @type string $reason
176 * @type string $domain
177 * @type array $errorInfoMetadata
178 * }
179 */
180 private static function containsErrorInfo(array $decodedMetadata)
181 {
182 if (empty($decodedMetadata)) {
183 return [];
184 }
185 foreach ($decodedMetadata as $value) {
186 $isErrorInfoArray = isset($value['reason']) && isset($value['domain']) && isset($value['metadata']);
187 if ($isErrorInfoArray) {
188 return ['reason' => $value['reason'], 'domain' => $value['domain'], 'errorInfoMetadata' => $value['metadata']];
189 }
190 }
191 return [];
192 }
193 /**
194 * Construct an ApiException with a useful message, including decoded metadata.
195 * If the decoded metadata includes an errorInfo message, then the domain, reason,
196 * and metadata fields from that message are hoisted directly into the error.
197 *
198 * @param string $basicMessage
199 * @param int $rpcCode
200 * @param iterable|null $metadata
201 * @param array $decodedMetadata
202 * @param array|null $protobufErrors
203 * @param Exception|null $previous
204 * @return ApiException
205 */
206 private static function create(string $basicMessage, int $rpcCode, $metadata, array $decodedMetadata, ?array $protobufErrors = null, ?Exception $previous = null)
207 {
208 $containsErrorInfo = self::containsErrorInfo($decodedMetadata);
209 $rpcStatus = ApiStatus::statusFromRpcCode($rpcCode);
210 $messageData = ['message' => $basicMessage, 'code' => $rpcCode, 'status' => $rpcStatus, 'details' => $decodedMetadata];
211 if ($containsErrorInfo) {
212 $messageData = \array_merge($containsErrorInfo, $messageData);
213 }
214 $message = \json_encode($messageData, \JSON_PRETTY_PRINT);
215 if ($metadata instanceof RepeatedField) {
216 $metadata = \iterator_to_array($metadata);
217 }
218 return new ApiException($message, $rpcCode, $rpcStatus, ['previous' => $previous, 'metadata' => $metadata, 'basicMessage' => $basicMessage], $protobufErrors ?? []);
219 }
220 /**
221 * Encodes decoded metadata to the Protobuf error type
222 *
223 * @param array $metadata
224 * @return array
225 */
226 private static function decodeMetadataToProtobufErrors(array $metadata) : array
227 {
228 $result = [];
229 Serializer::loadKnownMetadataTypes();
230 foreach ($metadata as $error) {
231 $message = null;
232 if (!isset($error['@type'])) {
233 continue;
234 }
235 $type = $error['@type'];
236 if (!isset(KnownTypes::TYPE_URLS[$type])) {
237 continue;
238 }
239 $class = KnownTypes::TYPE_URLS[$type];
240 $message = new $class();
241 $jsonMessage = \json_encode(\array_diff_key($error, ['@type' => \true]));
242 $message->mergeFromJsonString($jsonMessage);
243 $result[] = $message;
244 }
245 return $result;
246 }
247 /**
248 * @param Status $status
249 * @return ApiException
250 */
251 public static function createFromRpcStatus(Status $status)
252 {
253 return self::create($status->getMessage(), $status->getCode(), $status->getDetails(), Serializer::decodeAnyMessages($status->getDetails()));
254 }
255 /**
256 * Creates an ApiException from a GuzzleHttp RequestException.
257 *
258 * @param RequestException $ex
259 * @param boolean $isStream
260 * @return ApiException
261 * @throws ValidationException
262 */
263 public static function createFromRequestException(RequestException $ex, bool $isStream = \false)
264 {
265 $res = $ex->getResponse();
266 $body = (string) $res->getBody();
267 $decoded = \json_decode($body, \true);
268 // A streaming response body will return one error in an array. Parse
269 // that first (and only) error message, if provided.
270 if ($isStream && isset($decoded[0])) {
271 $decoded = $decoded[0];
272 }
273 if (isset($decoded['error']) && $decoded['error']) {
274 $error = $decoded['error'];
275 $basicMessage = $error['message'] ?? '';
276 $code = isset($error['status']) ? ApiStatus::rpcCodeFromStatus($error['status']) : $ex->getCode();
277 $metadata = $error['details'] ?? null;
278 return static::createFromRestApiResponse($basicMessage, $code, $metadata);
279 }
280 // Use the RPC code instead of the HTTP Status Code.
281 $code = ApiStatus::rpcCodeFromHttpStatusCode($res->getStatusCode());
282 return static::createFromApiResponse($body, $code);
283 }
284 /**
285 * @return null|string
286 */
287 public function getBasicMessage()
288 {
289 return $this->basicMessage;
290 }
291 /**
292 * @return mixed[]
293 */
294 public function getMetadata()
295 {
296 return $this->metadata;
297 }
298 }
299