update lock clucknut
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / build-and-push (push) Successful in 3m14s
Build, Push and Deploy / deploy-staging (push) Successful in 25s
Build, Push and Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-04-18 20:32:18 +07:00
parent 4554035227
commit dcaf267458
3359 changed files with 153185 additions and 205489 deletions

View File

@@ -46,6 +46,7 @@ class ApiException extends Exception
private $metadata;
private $basicMessage;
private $decodedMetadataErrorInfo;
private array $protobufErrors;
/**
* ApiException constructor.
@@ -62,7 +63,8 @@ public function __construct(
string $message,
int $code,
?string $status = null,
array $optionalArgs = []
array $optionalArgs = [],
array $protobufErrors = [],
) {
$optionalArgs += [
'previous' => null,
@@ -76,6 +78,7 @@ public function __construct(
if ($this->metadata) {
$this->decodedMetadataErrorInfo = self::decodeMetadataErrorInfo($this->metadata);
}
$this->protobufErrors = $protobufErrors;
}
public function getStatus()
@@ -137,6 +140,15 @@ public function getErrorInfoMetadata()
return ($this->decodedMetadataErrorInfo) ? $this->decodedMetadataErrorInfo['errorInfoMetadata'] : null;
}
/**
* Returns the unserialized errors
* @return array
*/
public function getErrorDetails(): array
{
return $this->protobufErrors;
}
/**
* @param stdClass $status
* @return ApiException
@@ -144,11 +156,14 @@ public function getErrorInfoMetadata()
public static function createFromStdClass(stdClass $status)
{
$metadata = property_exists($status, 'metadata') ? $status->metadata : null;
$errors = [];
return self::create(
$status->details,
$status->code,
$metadata,
Serializer::decodeMetadata((array) $metadata)
Serializer::decodeMetadata((array) $metadata, $errors),
$errors,
);
}
@@ -165,11 +180,13 @@ public static function createFromApiResponse(
?array $metadata = null,
?Exception $previous = null
) {
$errors = [];
return self::create(
$basicMessage,
$rpcCode,
$metadata,
Serializer::decodeMetadata((array) $metadata),
Serializer::decodeMetadata((array) $metadata, $errors),
$errors,
$previous
);
}
@@ -194,6 +211,7 @@ public static function createFromRestApiResponse(
$rpcCode,
$metadata,
is_null($metadata) ? [] : $metadata,
self::decodeMetadataToProtobufErrors($metadata ?? []),
$previous
);
}
@@ -235,6 +253,7 @@ private static function containsErrorInfo(array $decodedMetadata)
* @param int $rpcCode
* @param iterable|null $metadata
* @param array $decodedMetadata
* @param array|null $protobufErrors
* @param Exception|null $previous
* @return ApiException
*/
@@ -243,6 +262,7 @@ private static function create(
int $rpcCode,
$metadata,
array $decodedMetadata,
?array $protobufErrors = null,
?Exception $previous = null
) {
$containsErrorInfo = self::containsErrorInfo($decodedMetadata);
@@ -263,11 +283,51 @@ private static function create(
$metadata = iterator_to_array($metadata);
}
return new ApiException($message, $rpcCode, $rpcStatus, [
'previous' => $previous,
'metadata' => $metadata,
'basicMessage' => $basicMessage,
]);
return new ApiException(
$message,
$rpcCode,
$rpcStatus,
[
'previous' => $previous,
'metadata' => $metadata,
'basicMessage' => $basicMessage,
],
$protobufErrors ?? []
);
}
/**
* Encodes decoded metadata to the Protobuf error type
*
* @param array $metadata
* @return array
*/
private static function decodeMetadataToProtobufErrors(array $metadata): array
{
$result = [];
Serializer::loadKnownMetadataTypes();
foreach ($metadata as $error) {
$message = null;
if (!isset($error['@type'])) {
continue;
}
$type = $error['@type'];
if (!isset(KnownTypes::TYPE_URLS[$type])) {
continue;
}
$class = KnownTypes::TYPE_URLS[$type];
$message = new $class();
$jsonMessage = json_encode(array_diff_key($error, ['@type' => true]));
$message->mergeFromJsonString($jsonMessage);
$result[] = $message;
}
return $result;
}
/**

View File

@@ -121,7 +121,7 @@ public function addMiddleware(callable $middlewareCallable): void
$this->middlewareCallables[] = $middlewareCallable;
}
/**
/**
* Prepend a middleware to the call stack by providing a callable which will be
* invoked at the end of each call, and will return an instance of
* {@see MiddlewareInterface} when invoked.
@@ -261,7 +261,7 @@ private function setClientOptions(array $options)
if (isset($options['serviceAddress'])) {
$options['apiEndpoint'] = $this->pluck('serviceAddress', $options, false);
}
$this->validateNotNull($options, [
self::validateNotNull($options, [
'apiEndpoint',
'serviceName',
'descriptorsConfigPath',
@@ -270,7 +270,7 @@ private function setClientOptions(array $options)
'credentialsConfig',
'transportConfig',
]);
$this->traitValidate($options, [
self::traitValidate($options, [
'credentials',
'transport',
'gapicVersion',

87
vendor/google/gax/src/KnownTypes.php vendored Normal file
View File

@@ -0,0 +1,87 @@
<?php
/*
* Copyright 2025 Google LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Google\ApiCore;
/**
* @internal
*/
class KnownTypes
{
private static bool $initialized = false;
/** @deprecated use BIN_TYPES instead */
public const GRPC_TYPES = self::BIN_TYPES;
/** @deprecated use TYPE_URLS instead */
public const JSON_TYPES = self::TYPE_URLS;
public const BIN_TYPES = [
'google.rpc.retryinfo-bin' => \Google\Rpc\RetryInfo::class,
'google.rpc.debuginfo-bin' => \Google\Rpc\DebugInfo::class,
'google.rpc.quotafailure-bin' => \Google\Rpc\QuotaFailure::class,
'google.rpc.badrequest-bin' => \Google\Rpc\BadRequest::class,
'google.rpc.requestinfo-bin' => \Google\Rpc\RequestInfo::class,
'google.rpc.resourceinfo-bin' => \Google\Rpc\ResourceInfo::class,
'google.rpc.errorinfo-bin' => \Google\Rpc\ErrorInfo::class,
'google.rpc.help-bin' => \Google\Rpc\Help::class,
'google.rpc.localizedmessage-bin' => \Google\Rpc\LocalizedMessage::class,
'google.rpc.preconditionfailure-bin' => \Google\Rpc\PreconditionFailure::class,
];
public const TYPE_URLS = [
'type.googleapis.com/google.rpc.RetryInfo' => \Google\Rpc\RetryInfo::class,
'type.googleapis.com/google.rpc.DebugInfo' => \Google\Rpc\DebugInfo::class,
'type.googleapis.com/google.rpc.QuotaFailure' => \Google\Rpc\QuotaFailure::class,
'type.googleapis.com/google.rpc.BadRequest' => \Google\Rpc\BadRequest::class,
'type.googleapis.com/google.rpc.RequestInfo' => \Google\Rpc\RequestInfo::class,
'type.googleapis.com/google.rpc.ResourceInfo' => \Google\Rpc\ResourceInfo::class,
'type.googleapis.com/google.rpc.ErrorInfo' => \Google\Rpc\ErrorInfo::class,
'type.googleapis.com/google.rpc.Help' => \Google\Rpc\Help::class,
'type.googleapis.com/google.rpc.LocalizedMessage' => \Google\Rpc\LocalizedMessage::class,
'type.googleapis.com/google.rpc.PreconditionFailure' => \Google\Rpc\PreconditionFailure::class,
];
public static function allKnownTypes(): array
{
return array_values(self::TYPE_URLS);
}
public static function addKnownTypesToDescriptorPool()
{
if (self::$initialized) {
return;
}
// adds all the above protobuf classes to the descriptor pool
\GPBMetadata\Google\Rpc\ErrorDetails::initOnce();
self::$initialized = true;
}
}

View File

@@ -49,8 +49,8 @@ class TransportCallMiddleware implements MiddlewareInterface
public function __construct(
private TransportInterface $transport,
private array $transportCallMethods
)
{}
) {
}
public function __invoke(Call $call, array $options)
{

View File

@@ -269,7 +269,7 @@ class RetrySettings
*/
public function __construct(array $settings)
{
$this->validateNotNull($settings, [
self::validateNotNull($settings, [
'initialRetryDelayMillis',
'retryDelayMultiplier',
'maxRetryDelayMillis',

View File

@@ -31,6 +31,7 @@
*/
namespace Google\ApiCore;
use Exception;
use Google\Protobuf\Any;
use Google\Protobuf\Descriptor;
use Google\Protobuf\DescriptorPool;
@@ -53,18 +54,6 @@ class Serializer
private static array $snakeCaseMap = [];
private static array $camelCaseMap = [];
private static $metadataKnownTypes = [
'google.rpc.retryinfo-bin' => \Google\Rpc\RetryInfo::class,
'google.rpc.debuginfo-bin' => \Google\Rpc\DebugInfo::class,
'google.rpc.quotafailure-bin' => \Google\Rpc\QuotaFailure::class,
'google.rpc.badrequest-bin' => \Google\Rpc\BadRequest::class,
'google.rpc.requestinfo-bin' => \Google\Rpc\RequestInfo::class,
'google.rpc.resourceinfo-bin' => \Google\Rpc\ResourceInfo::class,
'google.rpc.errorinfo-bin' => \Google\Rpc\ErrorInfo::class,
'google.rpc.help-bin' => \Google\Rpc\Help::class,
'google.rpc.localizedmessage-bin' => \Google\Rpc\LocalizedMessage::class,
];
private $fieldTransformers;
private $messageTypeTransformers;
private $decodeFieldTransformers;
@@ -178,43 +167,69 @@ public static function serializeToPhpArray(Message $message)
* Decode metadata received from gRPC status object
*
* @param array $metadata
* @param null|array $errors
* @return array
*/
public static function decodeMetadata(array $metadata)
public static function decodeMetadata(array $metadata, ?array &$errors = null)
{
if (count($metadata) == 0) {
return [];
}
// ensure known types are available from the descriptor pool
KnownTypes::addKnownTypesToDescriptorPool();
$result = [];
// If metadata contains a "status" bin, use that instead
if (isset($metadata['grpc-status-details-bin'])) {
$status = new \Google\Rpc\Status();
$status->mergeFromString($metadata['grpc-status-details-bin'][0]);
foreach ($status->getDetails() as $any) {
if (isset(KnownTypes::TYPE_URLS[$any->getTypeUrl()])) {
$class = KnownTypes::TYPE_URLS[$any->getTypeUrl()];
new $class(); // add known types to descriptor pool
}
try {
$error = $any->unpack();
} catch (Exception $ex) {
// failed to unpack the $any object - keep the object as-is instead
$error = $any;
}
if (!is_null($errors)) {
$errors[] = $error;
}
$result[] = [
'@type' => $any->getTypeUrl(),
] + self::serializeToPhpArray($error);
}
return $result;
}
// look for individual error detail bins and decode those
// NOTE: This method SHOULD be superceeded by 'grpc-status-details-bin' in every case, but
// we are keeping it for now to be safe
foreach ($metadata as $key => $values) {
foreach ($values as $value) {
$decodedValue = [
'@type' => $key,
];
$decodedValue = ['@type' => $key];
if (self::hasBinaryHeaderSuffix($key)) {
if (isset(self::$metadataKnownTypes[$key])) {
$class = self::$metadataKnownTypes[$key];
if (isset(KnownTypes::BIN_TYPES[$key])) {
$class = KnownTypes::BIN_TYPES[$key];
/** @var Message $message */
$message = new $class();
try {
$message->mergeFromString($value);
$decodedValue += self::serializeToPhpArray($message);
if (!is_null($errors)) {
$errors[] = $message;
}
} catch (\Exception $e) {
// We encountered an error trying to deserialize the data
$decodedValue += [
'data' => '<Unable to deserialize data>',
];
$decodedValue['data'] = '<Unable to deserialize data>';
}
} else {
// The metadata contains an unexpected binary type
$decodedValue += [
'data' => '<Unknown Binary Data>',
];
$decodedValue['data'] = '<Unknown Binary Data>';
}
} else {
$decodedValue += [
'data' => $value,
];
$decodedValue['data'] = $value;
}
$result[] = $decodedValue;
}
@@ -238,7 +253,6 @@ public static function decodeAnyMessages($anyArray)
$unpacked = $any->unpack();
$results[] = self::serializeToPhpArray($unpacked);
} catch (\Exception $ex) {
echo "$ex\n";
// failed to unpack the $any object - show as unknown binary data
$results[] = [
'typeUrl' => $any->getTypeUrl(),
@@ -319,7 +333,7 @@ private function encodeMessageImpl(Message $message, Descriptor $messageType)
list($fields, $fieldsToOneof) = $this->getDescriptorMaps($messageType);
foreach ($fields as $field) {
$key = $field->getName();
$getter = $this->getGetter($key);
$getter = self::getGetter($key);
$v = $message->$getter();
if (is_null($v)) {
@@ -329,7 +343,7 @@ private function encodeMessageImpl(Message $message, Descriptor $messageType)
// Check and skip unset fields inside oneofs
if (isset($fieldsToOneof[$key])) {
$oneofName = $fieldsToOneof[$key];
$oneofGetter = $this->getGetter($oneofName);
$oneofGetter = self::getGetter($oneofName);
if ($message->$oneofGetter() !== $key) {
continue;
}
@@ -437,7 +451,7 @@ private function decodeMessageImpl(Message $message, Descriptor $messageType, ar
$value = $this->decodeElement($field, $v);
}
$setter = $this->getSetter($field->getName());
$setter = self::getSetter($field->getName());
$message->$setter($value);
// We must unset $value here, otherwise the protobuf c extension will mix up the references
@@ -453,9 +467,15 @@ private function decodeMessageImpl(Message $message, Descriptor $messageType, ar
*/
private function checkFieldRepeated(FieldDescriptor $field): bool
{
return method_exists($field, 'isRepeated')
? $field->isRepeated()
: $field->getLabel() === GPBLabel::REPEATED;
if (method_exists($field, 'isRepeated')) {
return $field->isRepeated();
}
if (method_exists($field, 'getLabel')) {
return $field->getLabel() === GPBLabel::REPEATED;
}
throw new \Exception('No field repeated method avaialble');
}
/**
@@ -527,7 +547,7 @@ private static function getPhpArraySerializer()
public static function loadKnownMetadataTypes()
{
foreach (self::$metadataKnownTypes as $key => $class) {
foreach (KnownTypes::allKnownTypes() as $key => $class) {
new $class();
}
}