.php_cs.dist000064400000005666146412205030006775 0ustar00setRiskyAllowed(true) ->setIndent(' ') ->setRules([ '@PSR2' => true, '@PhpCsFixer' => true, '@Symfony:risky' => true, 'concat_space' => ['spacing' => 'one'], 'array_syntax' => ['syntax' => 'short'], 'array_indentation' => true, 'combine_consecutive_unsets' => true, 'method_separation' => true, 'single_quote' => true, 'declare_equal_normalize' => true, 'function_typehint_space' => true, 'hash_to_slash_comment' => true, 'include' => true, 'lowercase_cast' => true, 'no_multiline_whitespace_before_semicolons' => true, 'no_leading_import_slash' => true, 'no_multiline_whitespace_around_double_arrow' => true, 'no_spaces_around_offset' => true, 'no_unneeded_control_parentheses' => true, 'no_unused_imports' => true, 'no_whitespace_before_comma_in_array' => true, 'no_whitespace_in_blank_line' => true, 'object_operator_without_whitespace' => true, 'single_blank_line_before_namespace' => true, 'single_class_element_per_statement' => true, 'space_after_semicolon' => true, 'standardize_not_equals' => true, 'ternary_operator_spaces' => true, 'trailing_comma_in_multiline_array' => true, 'trim_array_spaces' => true, 'unary_operator_spaces' => true, 'whitespace_after_comma_in_array' => true, 'no_extra_consecutive_blank_lines' => [ 'curly_brace_block', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'throw', 'use', ], 'binary_operator_spaces' => [ 'align_double_arrow' => true, 'align_equals' => true, ], 'braces' => [ 'allow_single_line_closure' => true, ], ]) ->setFinder( PhpCsFixer\Finder::create() ->exclude('vendor') ->exclude('tests') ->in(__DIR__) ); CHANGELOG.md000064400000005222146412205030006353 0ustar00# CHANGELOG ## 3.1.22 - 2021-05-11 - Deprecate `stream_for` method. ## 3.1.21 - 2021-03-15 - Supported set proxy&timeout on request. ## 3.1.20 - 2020-12-02 - Fix the warning when the Tea::merge method received empty arguments. ## 3.1.19 - 2020-10-09 - Fix the error when the code value is a string. ## 3.1.18 - 2020-09-28 - Require Guzzle Version 7.0 ## 3.1.17 - 2020-09-24 - TeaUnableRetryError support get error info. ## 3.1.16 - 2020-08-31 - Fix the Maximum function nesting level error when repeated network requests. ## 3.1.15 - 2020-07-28 - Improved validatePattern method. ## 3.1.14 - 2020-07-03 - Supported set properties of TeaError with `ErrorInfo`. ## 3.1.13 - 2020-06-09 - Reduce dependencies. ## 3.1.12 - 2020-05-13 - Add validate method. - Supported validate maximun&minimun of property. ## 3.1.11 - 2020-05-07 - Fixed error when class is undefined. ## 3.1.10 - 2020-05-07 - Fixed error when '$item' of array is null ## 3.1.9 - 2020-04-13 - TeaUnableRetryError add $lastException param. ## 3.1.8 - 2020-04-02 - Added some static methods of Model to validate fields of Model. ## 3.1.7 - 2020-03-27 - Improve Tea::isRetryable method. ## 3.1.6 - 2020-03-25 - Fixed bug when body is StreamInterface. ## 3.1.5 - 2020-03-25 - Improve Model.toMap method. - Improve Tea.merge method. - Fixed tests. ## 3.1.4 - 2020-03-20 - Added Tea::merge method. - Change Tea::isRetryable method. ## 3.1.3 - 2020-03-20 - Model: added toModel method. ## 3.1.2 - 2020-03-19 - Model constructor supported array type parameter. ## 3.1.1 - 2020-03-18 - Fixed bug : set method failed. - Fixed bug : get empty contents form body. ## 3.1.0 - 2020-03-13 - TeaUnableRetryError add 'lastRequest' property. - Change Tea.send() method return. - Fixed Tea. allowRetry() method. ## 3.0.0 - 2020-02-14 - Rename package name. ## 2.0.3 - 2020-02-14 - Improved Exception. ## 2.0.2 - 2019-09-11 - Supported `String`. ## 2.0.1 - 2019-08-15 - Supported `IteratorAggregate`. ## 2.0.0 - 2019-08-14 - Design `Request` as a standard `PsrRequest`. ## 1.0.10 - 2019-08-12 - Added `__toString` for `Response`. ## 1.0.9 - 2019-08-01 - Updated `Middleware`. ## 1.0.8 - 2019-07-29 - Supported `TransferStats`. ## 1.0.7 - 2019-07-27 - Improved request. ## 1.0.6 - 2019-07-23 - Trim key for parameter. ## 1.0.5 - 2019-07-23 - Supported default protocol. ## 1.0.4 - 2019-07-22 - Added `toArray()`. ## 1.0.3 - 2019-05-02 - Improved `Request`. ## 1.0.2 - 2019-05-02 - Added getHeader/getHeaders. ## 1.0.1 - 2019-04-02 - Improved design. ## 1.0.0 - 2019-05-02 - Initial release of the AlibabaCloud Tea Version 1.0.0 on Packagist See for more information. LICENSE.md000064400000001115146412205030006143 0ustar00Copyright (c) 2009-present, Alibaba Cloud All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. README.md000064400000000611146412205030006016 0ustar00 ## Installation ``` composer require alibabacloud/tea --optimize-autoloader ``` > Some users may not be able to install due to network problems, you can try to switch the Composer mirror. ## Changelog Detailed changes for each release are documented in the [release notes](CHANGELOG.md). ## License [Apache-2.0](LICENSE.md) Copyright (c) 2009-present, Alibaba Cloud All rights reserved. composer.json000064400000004070146412205030007264 0ustar00{ "name": "alibabacloud/tea", "homepage": "https://www.alibabacloud.com/", "description": "Client of Tea for PHP", "keywords": [ "tea", "client", "alibabacloud", "cloud" ], "type": "library", "license": "Apache-2.0", "support": { "source": "https://github.com/aliyun/tea-php", "issues": "https://github.com/aliyun/tea-php/issues" }, "authors": [ { "name": "Alibaba Cloud SDK", "email": "sdk-team@alibabacloud.com", "homepage": "http://www.alibabacloud.com" } ], "require": { "php": ">=5.5", "ext-curl": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-openssl": "*", "ext-simplexml": "*", "ext-xmlwriter": "*", "guzzlehttp/guzzle": "^6.3|^7.0", "adbario/php-dot-notation": "^2.4" }, "require-dev": { "symfony/dotenv": "^3.4", "phpunit/phpunit": "*", "symfony/var-dumper": "^3.4" }, "suggest": { "ext-sockets": "To use client-side monitoring" }, "autoload": { "psr-4": { "AlibabaCloud\\Tea\\": "src" } }, "autoload-dev": { "psr-4": { "AlibabaCloud\\Tea\\Tests\\": "tests" } }, "config": { "sort-packages": true, "preferred-install": "dist", "optimize-autoloader": true }, "prefer-stable": true, "minimum-stability": "dev", "scripts": { "cs": "phpcs --standard=PSR2 -n ./", "cbf": "phpcbf --standard=PSR2 -n ./", "fixer": "php-cs-fixer fix ./", "test": [ "@clearCache", "phpunit --colors=always" ], "unit": [ "@clearCache", "phpunit --testsuite=Unit --colors=always" ], "feature": [ "@clearCache", "phpunit --testsuite=Feature --colors=always" ], "clearCache": "rm -rf cache/*", "coverage": "open cache/coverage/index.html" } } src/Exception/TeaError.php000064400000002122146412205030011517 0ustar00errorInfo = $errorInfo; if (!empty($errorInfo)) { $properties = ['name', 'message', 'code', 'data']; foreach ($properties as $property) { if (isset($errorInfo[$property])) { $this->{$property} = $errorInfo[$property]; } } } } /** * @return array */ public function getErrorInfo() { return $this->errorInfo; } } src/Exception/TeaRetryError.php000064400000000670146412205030012553 0ustar00getErrorInfo(); } parent::__construct($error_info, $lastException->getMessage(), $lastException->getCode(), $lastException); $this->lastRequest = $lastRequest; $this->lastException = $lastException; } public function getLastRequest() { return $this->lastRequest; } public function getLastException() { return $this->lastException; } } src/Helper.php000064400000004501146412205030007260 0ustar00 $ord) { if ($k !== $i) { return false; } if (!\is_int($ord)) { return false; } if ($ord < 0 || $ord > 255) { return false; } ++$i; } return true; } /** * Convert a bytes to string(utf8). * * @param array $bytes * * @return string the return string */ public static function toString($bytes) { $str = ''; foreach ($bytes as $ch) { $str .= \chr($ch); } return $str; } /** * @return array */ public static function merge(array $arrays) { $result = []; foreach ($arrays as $array) { foreach ($array as $key => $value) { if (\is_int($key)) { $result[] = $value; continue; } if (isset($result[$key]) && \is_array($result[$key])) { $result[$key] = self::merge( [$result[$key], $value] ); continue; } $result[$key] = $value; } } return $result; } } src/Model.php000064400000006076146412205030007112 0ustar00 $v) { $this->{$k} = $v; } } } public function getName($name = null) { if (null === $name) { return $this->_name; } return isset($this->_name[$name]) ? $this->_name[$name] : $name; } public function toMap() { $map = get_object_vars($this); foreach ($map as $k => $m) { if (0 === strpos($k, '_')) { unset($map[$k]); } } $res = []; foreach ($map as $k => $v) { $name = isset($this->_name[$k]) ? $this->_name[$k] : $k; $res[$name] = $v; } return $res; } public function validate() { $vars = get_object_vars($this); foreach ($vars as $k => $v) { if (isset($this->_required[$k]) && $this->_required[$k] && empty($v)) { throw new \InvalidArgumentException("{$k} is required."); } } } public static function validateRequired($fieldName, $field, $val = null) { if (true === $val && null === $field) { throw new \InvalidArgumentException($fieldName . ' is required'); } } public static function validateMaxLength($fieldName, $field, $val = null) { if (null !== $field && \strlen($field) > (int) $val) { throw new \InvalidArgumentException($fieldName . ' is exceed max-length: ' . $val); } } public static function validateMinLength($fieldName, $field, $val = null) { if (null !== $field && \strlen($field) < (int) $val) { throw new \InvalidArgumentException($fieldName . ' is less than min-length: ' . $val); } } public static function validatePattern($fieldName, $field, $regex = '') { if (null !== $field && '' !== $field && !preg_match("/^{$regex}$/", $field)) { throw new \InvalidArgumentException($fieldName . ' is not match ' . $regex); } } public static function validateMaximum($fieldName, $field, $val) { if (null !== $field && $field > $val) { throw new \InvalidArgumentException($fieldName . ' cannot be greater than ' . $val); } } public static function validateMinimum($fieldName, $field, $val) { if (null !== $field && $field < $val) { throw new \InvalidArgumentException($fieldName . ' cannot be less than ' . $val); } } /** * @param array $map * @param Model $model * * @return mixed */ public static function toModel($map, $model) { $names = $model->getName(); $names = array_flip($names); foreach ($map as $key => $value) { $name = isset($names[$key]) ? $names[$key] : $key; $model->{$name} = $value; } return $model; } } src/Parameter.php000064400000002011146412205030007753 0ustar00toArray()); } /** * @return array */ public function getRealParameters() { $array = []; $obj = new ReflectionObject($this); $properties = $obj->getProperties(); foreach ($properties as $property) { $docComment = $property->getDocComment(); $key = trim(Helper::findFromString($docComment, '@real', "\n")); $value = $property->getValue($this); $array[$key] = $value; } return $array; } /** * @return array */ public function toArray() { return $this->getRealParameters(); } } src/Request.php000064400000005654146412205030007503 0ustar00method = $method; } /** * These fields are compatible if you define other fields. * Mainly for compatibility situations where the code generator cannot generate set properties. * * @return PsrRequest */ public function getPsrRequest() { $this->assertQuery($this->query); $request = clone $this; $uri = $request->getUri(); if ($this->query) { $uri = $uri->withQuery(http_build_query($this->query)); } if ($this->port) { $uri = $uri->withPort($this->port); } if ($this->protocol) { $uri = $uri->withScheme($this->protocol); } if ($this->pathname) { $uri = $uri->withPath($this->pathname); } if (isset($this->headers['host'])) { $uri = $uri->withHost($this->headers['host']); } $request = $request->withUri($uri); $request = $request->withMethod($this->method); if ('' !== $this->body && null !== $this->body) { if ($this->body instanceof StreamInterface) { $request = $request->withBody($this->body); } else { $body = $this->body; if (Helper::isBytes($this->body)) { $body = Helper::toString($this->body); } if (\function_exists('\GuzzleHttp\Psr7\stream_for')) { // @deprecated stream_for will be removed in guzzlehttp/psr7:2.0 $request = $request->withBody(\GuzzleHttp\Psr7\stream_for($body)); } else { $request = $request->withBody(\GuzzleHttp\Psr7\Utils::streamFor($body)); } } } if ($this->headers) { foreach ($this->headers as $key => $value) { $request = $request->withHeader($key, $value); } } return $request; } /** * @param array $query */ private function assertQuery($query) { if (!\is_array($query) && $query !== null) { throw new InvalidArgumentException('Query must be array.'); } } } src/Response.php000064400000016610146412205030007643 0ustar00getStatusCode(), $response->getHeaders(), $response->getBody(), $response->getProtocolVersion(), $response->getReasonPhrase() ); $this->headers = $response->getHeaders(); $this->body = $response->getBody(); $this->statusCode = $response->getStatusCode(); if ($this->body->isSeekable()) { $this->body->seek(0); } if (Helper::isJson((string) $this->getBody())) { $this->dot = new Dot($this->toArray()); } else { $this->dot = new Dot(); } } /** * @return string */ public function __toString() { return (string) $this->getBody(); } /** * @param string $name * * @return null|mixed */ public function __get($name) { $data = $this->dot->all(); if (!isset($data[$name])) { return null; } return json_decode(json_encode($data))->{$name}; } /** * @param string $name * @param mixed $value */ public function __set($name, $value) { $this->dot->set($name, $value); } /** * @param string $name * * @return bool */ public function __isset($name) { return $this->dot->has($name); } /** * @param $offset */ public function __unset($offset) { $this->dot->delete($offset); } /** * @return array */ public function toArray() { return \GuzzleHttp\json_decode((string) $this->getBody(), true); } /** * @param array|int|string $keys * @param mixed $value */ public function add($keys, $value = null) { return $this->dot->add($keys, $value); } /** * @return array */ public function all() { return $this->dot->all(); } /** * @param null|array|int|string $keys */ public function clear($keys = null) { return $this->dot->clear($keys); } /** * @param array|int|string $keys */ public function delete($keys) { return $this->dot->delete($keys); } /** * @param string $delimiter * @param null|array $items * @param string $prepend * * @return array */ public function flatten($delimiter = '.', $items = null, $prepend = '') { return $this->dot->flatten($delimiter, $items, $prepend); } /** * @param null|int|string $key * @param mixed $default * * @return mixed */ public function get($key = null, $default = null) { return $this->dot->get($key, $default); } /** * @param array|int|string $keys * * @return bool */ public function has($keys) { return $this->dot->has($keys); } /** * @param null|array|int|string $keys * * @return bool */ public function isEmpty($keys = null) { return $this->dot->isEmpty($keys); } /** * @param array|self|string $key * @param array|self $value */ public function merge($key, $value = []) { return $this->dot->merge($key, $value); } /** * @param array|self|string $key * @param array|self $value */ public function mergeRecursive($key, $value = []) { return $this->dot->mergeRecursive($key, $value); } /** * @param array|self|string $key * @param array|self $value */ public function mergeRecursiveDistinct($key, $value = []) { return $this->dot->mergeRecursiveDistinct($key, $value); } /** * @param null|int|string $key * @param mixed $default * * @return mixed */ public function pull($key = null, $default = null) { return $this->dot->pull($key, $default); } /** * @param null|int|string $key * @param mixed $value * * @return mixed */ public function push($key = null, $value = null) { return $this->dot->push($key, $value); } /** * Replace all values or values within the given key * with an array or Dot object. * * @param array|self|string $key * @param array|self $value */ public function replace($key, $value = []) { return $this->dot->replace($key, $value); } /** * Set a given key / value pair or pairs. * * @param array|int|string $keys * @param mixed $value */ public function set($keys, $value = null) { return $this->dot->set($keys, $value); } /** * Replace all items with a given array. * * @param mixed $items */ public function setArray($items) { return $this->dot->setArray($items); } /** * Replace all items with a given array as a reference. */ public function setReference(array &$items) { return $this->dot->setReference($items); } /** * Return the value of a given key or all the values as JSON. * * @param mixed $key * @param int $options * * @return string */ public function toJson($key = null, $options = 0) { return $this->dot->toJson($key, $options); } /** * Retrieve an external iterator. */ #[\ReturnTypeWillChange] public function getIterator() { return $this->dot->getIterator(); } /** * Whether a offset exists. * * @param $offset * * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->dot->offsetExists($offset); } /** * Offset to retrieve. * * @param $offset * * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->dot->offsetGet($offset); } /** * Offset to set. * * @param $offset * @param $value */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->dot->offsetSet($offset, $value); } /** * Offset to unset. * * @param $offset */ #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->dot->offsetUnset($offset); } /** * Count elements of an object. * * @param null $key * * @return int */ #[\ReturnTypeWillChange] public function count($key = null) { return $this->dot->count($key); } } src/Tea.php000064400000016462146412205030006563 0ustar00getPsrRequest(); } $config = self::resolveConfig($config); $res = self::client()->send( $request, $config ); return new Response($res); } /** * @return PromiseInterface */ public static function sendAsync(RequestInterface $request, array $config = []) { if (method_exists($request, 'getPsrRequest')) { $request = $request->getPsrRequest(); } $config = self::resolveConfig($config); return self::client()->sendAsync( $request, $config ); } /** * @return Client */ public static function client(array $config = []) { if (isset(self::$config['handler'])) { $stack = self::$config['handler']; } else { $stack = HandlerStack::create(); $stack->push(Middleware::mapResponse(static function (ResponseInterface $response) { return new Response($response); })); } self::$config['handler'] = $stack; if (!isset(self::$config['on_stats'])) { self::$config['on_stats'] = function (TransferStats $stats) { Response::$info = $stats->getHandlerStats(); }; } $new_config = Helper::merge([self::$config, $config]); return new Client($new_config); } /** * @param string $method * @param string|UriInterface $uri * @param array $options * * @throws GuzzleException * * @return ResponseInterface */ public static function request($method, $uri, $options = []) { return self::client()->request($method, $uri, $options); } /** * @param string $method * @param string $uri * @param array $options * * @throws GuzzleException * * @return string */ public static function string($method, $uri, $options = []) { return (string) self::client()->request($method, $uri, $options) ->getBody(); } /** * @param string $method * @param string|UriInterface $uri * @param array $options * * @return PromiseInterface */ public static function requestAsync($method, $uri, $options = []) { return self::client()->requestAsync($method, $uri, $options); } /** * @param string|UriInterface $uri * @param array $options * * @throws GuzzleException * * @return null|mixed */ public static function getHeaders($uri, $options = []) { return self::request('HEAD', $uri, $options)->getHeaders(); } /** * @param string|UriInterface $uri * @param string $key * @param null|mixed $default * * @throws GuzzleException * * @return null|mixed */ public static function getHeader($uri, $key, $default = null) { $headers = self::getHeaders($uri); return isset($headers[$key][0]) ? $headers[$key][0] : $default; } /** * @param int $retryTimes * @param float $now * * @return bool */ public static function allowRetry(array $runtime, $retryTimes, $now) { unset($now); if (!isset($retryTimes) || null === $retryTimes || !\is_numeric($retryTimes)) { return false; } if ($retryTimes > 0 && (empty($runtime) || !isset($runtime['retryable']) || !$runtime['retryable'] || !isset($runtime['maxAttempts']))) { return false; } $maxAttempts = $runtime['maxAttempts']; $retry = empty($maxAttempts) ? 0 : (int) $maxAttempts; return $retry >= $retryTimes; } /** * @param int $retryTimes * * @return int */ public static function getBackoffTime(array $runtime, $retryTimes) { $backOffTime = 0; $policy = isset($runtime['policy']) ? $runtime['policy'] : ''; if (empty($policy) || 'no' == $policy) { return $backOffTime; } $period = isset($runtime['period']) ? $runtime['period'] : ''; if (null !== $period && '' !== $period) { $backOffTime = (int) $period; if ($backOffTime <= 0) { return $retryTimes; } } return $backOffTime; } public static function sleep($time) { sleep($time); } public static function isRetryable($retry, $retryTimes = 0) { if ($retry instanceof TeaError) { return true; } if (\is_array($retry)) { $max = isset($retry['maxAttempts']) ? (int) ($retry['maxAttempts']) : 3; return $retryTimes <= $max; } return false; } /** * @param mixed|Model[] ...$item * * @return mixed */ public static function merge(...$item) { $tmp = []; $n = 0; foreach ($item as $i) { if (\is_object($i)) { if ($i instanceof Model) { $i = $i->toMap(); } else { $i = json_decode(json_encode($i), true); } } if (null === $i) { continue; } if (\is_array($i)) { $tmp[$n++] = $i; } } if (\count($tmp)) { return \call_user_func_array('array_merge', $tmp); } return []; } private static function resolveConfig(array $config = []) { $options = new Dot(['http_errors' => false]); if (isset($config['httpProxy']) && !empty($config['httpProxy'])) { $options->set('proxy.http', $config['httpProxy']); } if (isset($config['httpsProxy']) && !empty($config['httpsProxy'])) { $options->set('proxy.https', $config['httpsProxy']); } if (isset($config['noProxy']) && !empty($config['noProxy'])) { $options->set('proxy.no', $config['noProxy']); } // readTimeout&connectTimeout unit is millisecond $read_timeout = isset($config['readTimeout']) && !empty($config['readTimeout']) ? (int) $config['readTimeout'] : 0; $con_timeout = isset($config['connectTimeout']) && !empty($config['connectTimeout']) ? (int) $config['connectTimeout'] : 0; // timeout unit is second $options->set('timeout', ($read_timeout + $con_timeout) / 1000); return $options->all(); } }