},
{
"name": "guzzlehttp/guzzle",
- "version": "7.6.1",
+ "version": "7.7.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51"
+ "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8444a2bacf1960bc6a2b62ed86b8e72e11eebe51",
- "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
+ "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
"shasum": ""
},
"require": {
"ext-json": "*",
- "guzzlehttp/promises": "^1.5",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.1",
"ext-curl": "*",
- "php-http/client-integration-tests": "^3.0",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.29 || ^9.5.23",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.6.1"
+ "source": "https://github.com/guzzle/guzzle/tree/7.7.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2023-05-15T20:43:01+00:00"
+ "time": "2023-05-21T14:04:53+00:00"
},
{
"name": "guzzlehttp/promises",
- "version": "1.5.2",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "b94b2807d85443f9719887892882d0329d1e2598"
+ "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
- "reference": "b94b2807d85443f9719887892882d0329d1e2598",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
+ "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"shasum": ""
},
"require": {
- "php": ">=5.5"
+ "php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ "bamarni/composer-bin-plugin": "^1.8.1",
+ "phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.5-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
}
},
"autoload": {
- "files": [
- "src/functions_include.php"
- ],
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/1.5.2"
+ "source": "https://github.com/guzzle/promises/tree/2.0.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2022-08-28T14:55:35+00:00"
+ "time": "2023-05-21T13:50:22+00:00"
},
{
"name": "guzzlehttp/psr7",
return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
- 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
{
public static $files = array (
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
- 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
},
{
"name": "guzzlehttp/guzzle",
- "version": "7.6.1",
- "version_normalized": "7.6.1.0",
+ "version": "7.7.0",
+ "version_normalized": "7.7.0.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51"
+ "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8444a2bacf1960bc6a2b62ed86b8e72e11eebe51",
- "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
+ "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
"shasum": ""
},
"require": {
"ext-json": "*",
- "guzzlehttp/promises": "^1.5",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.1",
"ext-curl": "*",
- "php-http/client-integration-tests": "^3.0",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.29 || ^9.5.23",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
- "time": "2023-05-15T20:43:01+00:00",
+ "time": "2023-05-21T14:04:53+00:00",
"type": "library",
"extra": {
"bamarni-bin": {
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.6.1"
+ "source": "https://github.com/guzzle/guzzle/tree/7.7.0"
},
"funding": [
{
},
{
"name": "guzzlehttp/promises",
- "version": "1.5.2",
- "version_normalized": "1.5.2.0",
+ "version": "2.0.0",
+ "version_normalized": "2.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "b94b2807d85443f9719887892882d0329d1e2598"
+ "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
- "reference": "b94b2807d85443f9719887892882d0329d1e2598",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
+ "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"shasum": ""
},
"require": {
- "php": ">=5.5"
+ "php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ "bamarni/composer-bin-plugin": "^1.8.1",
+ "phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
- "time": "2022-08-28T14:55:35+00:00",
+ "time": "2023-05-21T13:50:22+00:00",
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.5-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
}
},
"installation-source": "dist",
"autoload": {
- "files": [
- "src/functions_include.php"
- ],
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/1.5.2"
+ "source": "https://github.com/guzzle/promises/tree/2.0.0"
},
"funding": [
{
'dev_requirement' => false,
),
'guzzlehttp/guzzle' => array(
- 'pretty_version' => '7.6.1',
- 'version' => '7.6.1.0',
- 'reference' => '8444a2bacf1960bc6a2b62ed86b8e72e11eebe51',
+ 'pretty_version' => '7.7.0',
+ 'version' => '7.7.0.0',
+ 'reference' => 'fb7566caccf22d74d1ab270de3551f72a58399f5',
'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
'aliases' => array(),
'dev_requirement' => false,
),
'guzzlehttp/promises' => array(
- 'pretty_version' => '1.5.2',
- 'version' => '1.5.2.0',
- 'reference' => 'b94b2807d85443f9719887892882d0329d1e2598',
+ 'pretty_version' => '2.0.0',
+ 'version' => '2.0.0.0',
+ 'reference' => '3a494dc7dc1d7d12e511890177ae2d0e6c107da6',
'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/promises',
'aliases' => array(),
Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version.
+
+## 7.7.0 - 2023-05-21
+
+### Added
+
+- Support `guzzlehttp/promises` v2
+
+
## 7.6.1 - 2023-05-15
### Fixed
- Fix `SetCookie::fromString` MaxAge deprecation warning and skip invalid MaxAge values
+
## 7.6.0 - 2023-05-14
### Added
- Support for setting the minimum TLS version in a unified way
- Apply on request the version set in options parameters
+
## 7.5.2 - 2023-05-14
### Fixed
- Corrected docs and default connect timeout value to 300 seconds
+
## 7.5.1 - 2023-04-17
### Fixed
- Adjusted `guzzlehttp/psr7` version constraint to `^1.9.1 || ^2.4.5`
+
## 7.5.0 - 2022-08-28
### Added
- Support PHP 8.2
- Add request to delay closure params
+
## 7.4.5 - 2022-06-20
### Fixed
* Fix change in port should be considered a change in origin
* Fix `CURLOPT_HTTPAUTH` option not cleared on change of origin
+
## 7.4.4 - 2022-06-09
### Fixed
* Fix failure to strip Authorization header on HTTP downgrade
* Fix failure to strip the Cookie header on change in host or HTTP downgrade
+
## 7.4.3 - 2022-05-25
### Fixed
* Fix cross-domain cookie leakage
+
## 7.4.2 - 2022-03-20
### Fixed
- Reject non-HTTP schemes in StreamHandler
- Set a default ssl.peer_name context in StreamHandler to allow `force_ip_resolve`
+
## 7.4.1 - 2021-12-06
### Changed
- Only close curl handle if it's done [#2950](https://github.com/guzzle/guzzle/pull/2950)
+
## 7.4.0 - 2021-10-18
### Added
- Be more strict with types [#2914](https://github.com/guzzle/guzzle/pull/2914), [#2917](https://github.com/guzzle/guzzle/pull/2917), [#2919](https://github.com/guzzle/guzzle/pull/2919), [#2945](https://github.com/guzzle/guzzle/pull/2945)
+
## 7.3.0 - 2021-03-23
### Added
- Handle exceptions on invalid header consistently between PHP versions and handlers [#2872](https://github.com/guzzle/guzzle/pull/2872)
+
## 7.2.0 - 2020-10-10
### Added
- Using environment variable GUZZLE_CURL_SELECT_TIMEOUT [#2786](https://github.com/guzzle/guzzle/pull/2786)
+
## 7.1.1 - 2020-09-30
### Fixed
- We dont connect curl `sink` on HEAD requests.
- Removed some PHP 5 workarounds
+
## 7.1.0 - 2020-09-22
### Added
- `Utils::defaultCaBundle()`
- `CurlFactory::LOW_CURL_VERSION_NUMBER`
+
## 7.0.1 - 2020-06-27
* Fix multiply defined functions fatal error [#2699](https://github.com/guzzle/guzzle/pull/2699)
+
## 7.0.0 - 2020-06-27
No changes since 7.0.0-rc1.
+
## 7.0.0-rc1 - 2020-06-15
### Changed
* Use error level for logging errors in Middleware [#2629](https://github.com/guzzle/guzzle/pull/2629)
* Disabled IDN support by default and require ext-intl to use it [#2675](https://github.com/guzzle/guzzle/pull/2675)
+
## 7.0.0-beta2 - 2020-05-25
### Added
* Pool option `pool_size` [#2528](https://github.com/guzzle/guzzle/pull/2528)
+
## 7.0.0-beta1 - 2019-12-30
The diff might look very big but 95% of Guzzle users will be able to upgrade without modification.
* `uri_template()` and `UriTemplate` [#2440](https://github.com/guzzle/guzzle/pull/2440)
* Request options `save_to` and `exceptions` [#2464](https://github.com/guzzle/guzzle/pull/2464)
+
## 6.5.2 - 2019-12-23
* idn_to_ascii() fix for old PHP versions [#2489](https://github.com/guzzle/guzzle/pull/2489)
+
## 6.5.1 - 2019-12-21
* Better defaults for PHP installations with old ICU lib [#2454](https://github.com/guzzle/guzzle/pull/2454)
* IDN support for redirects [#2424](https://github.com/guzzle/guzzle/pull/2424)
+
## 6.5.0 - 2019-12-07
* Improvement: Added support for reset internal queue in MockHandler. [#2143](https://github.com/guzzle/guzzle/pull/2143)
* Fix: Prevent undefined offset when using array for ssl_key options. [#2348](https://github.com/guzzle/guzzle/pull/2348)
* Deprecated `ClientInterface::VERSION`
+
## 6.4.1 - 2019-10-23
* No `guzzle.phar` was created in 6.4.0 due expired API token. This release will fix that
* Added `parent::__construct()` to `FileCookieJar` and `SessionCookieJar`
+
## 6.4.0 - 2019-10-23
* Improvement: Improved error messages when using curl < 7.21.2 [#2108](https://github.com/guzzle/guzzle/pull/2108)
* Fix: Prevent concurrent writes to file when saving `CookieJar` [#2335](https://github.com/guzzle/guzzle/pull/2335)
* Improvement: Update `MockHandler` so we can test transfer time [#2362](https://github.com/guzzle/guzzle/pull/2362)
+
## 6.3.3 - 2018-04-22
* Fix: Default headers when decode_content is specified
* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684)
* Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827)
-
+ Minor code cleanups, documentation fixes and clarifications.
+
## 6.2.3 - 2017-02-28
* Fix deprecations with guzzle/psr7 version 1.4
+
## 6.2.2 - 2016-10-08
* Allow to pass nullable Response to delay callable
* Fix drain case where content-length is the literal string zero
* Obfuscate in-URL credentials in exceptions
+
## 6.2.1 - 2016-07-18
* Address HTTP_PROXY security vulnerability, CVE-2016-5385:
a server does not honor `Connection: close`.
* Ignore URI fragment when sending requests.
+
## 6.2.0 - 2016-03-21
* Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`.
* Bug fix: provide an empty string to `http_build_query` for HHVM workaround.
https://github.com/guzzle/guzzle/pull/1367
+
## 6.1.1 - 2015-11-22
* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler
* Bug fix: fixed regression where MockHandler was not using `sink`.
https://github.com/guzzle/guzzle/pull/1292
+
## 6.1.0 - 2015-09-08
* Feature: Added the `on_stats` request option to provide access to transfer
* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set.
https://github.com/guzzle/guzzle/pull/1189
+
## 6.0.2 - 2015-07-04
* Fixed a memory leak in the curl handlers in which references to callbacks
* Functions are now conditionally required using an additional level of
indirection to help with global Composer installations.
+
## 6.0.1 - 2015-05-27
* Fixed a bug with serializing the `query` request option where the `&`
use `form_params` or `multipart` instead.
* Various doc fixes.
+
## 6.0.0 - 2015-05-26
* See the UPGRADING.md document for more information.
* `$maxHandles` has been removed from CurlMultiHandler.
* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.
+
## 5.3.0 - 2015-05-19
* Mock now supports `save_to`
* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
* URL scheme is now always lowercased.
+
## 6.0.0-beta.1
* Requires PHP >= 5.5
* `GuzzleHttp\QueryParser` has been replaced with the
`GuzzleHttp\Psr7\parse_query`.
+
## 5.2.0 - 2015-01-27
* Added `AppliesHeadersInterface` to make applying headers to a request based
RingBridge.
* Added a guard in the Pool class to not use recursion for request retries.
+
## 5.1.0 - 2014-12-19
* Pool class no longer uses recursion when a request is intercepted.
* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
specific exceptions if necessary.
+
## 5.0.3 - 2014-11-03
This change updates query strings so that they are treated as un-encoded values
subsequently made, forcing the query-string to be converted into a Query
object).
+
## 5.0.2 - 2014-10-30
* Added a trailing `\r\n` to multipart/form-data payloads. See
string on a URL: Now allowing many more characters to be present in the
query string without being percent encoded. See https://tools.ietf.org/html/rfc3986#appendix-A
+
## 5.0.1 - 2014-10-16
Bugfix release.
* Fixed an issue where transfer statistics were not being populated in the
RingBridge. https://github.com/guzzle/guzzle/issues/866
+
## 5.0.0 - 2014-10-12
Adding support for non-blocking responses and some minor API cleanup.
argument. They now accept an associative array of options, including the
"size" key and "metadata" key which can be used to provide custom metadata.
+
## 4.2.2 - 2014-09-08
* Fixed a memory leak in the CurlAdapter when reusing cURL handles.
## Version Guidance
-| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
-|---------|----------------|---------------------|--------------|---------------------|---------------------|-------|--------------|
-| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 |
-| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 |
-| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 |
-| 6.x | Security fixes | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 |
-| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.3 |
+| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
+|---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------|
+| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 |
+| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 |
+| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 |
+| 6.x | Security fixes only | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 |
+| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.3 |
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
"require": {
"php": "^7.2.5 || ^8.0",
"ext-json": "*",
- "guzzlehttp/promises": "^1.5",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
"require-dev": {
"ext-curl": "*",
"bamarni/composer-bin-plugin": "^1.8.1",
- "php-http/client-integration-tests": "^3.0",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.29 || ^9.5.23",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
public function send(RequestInterface $request, array $options = []): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
+
return $this->sendAsync($request, $options)->wait();
}
/**
* The HttpClient PSR (PSR-18) specify this method.
*
- * @inheritDoc
+ * {@inheritDoc}
*/
public function sendRequest(RequestInterface $request): ResponseInterface
{
public function request(string $method, $uri = '', array $options = []): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
+
return $this->requestAsync($method, $uri, $options)->wait();
}
{
$defaults = [
'allow_redirects' => RedirectMiddleware::$defaultSettings,
- 'http_errors' => true,
- 'decode_content' => true,
- 'verify' => true,
- 'cookies' => false,
- 'idn_conversion' => false,
+ 'http_errors' => true,
+ 'decode_content' => true,
+ 'verify' => true,
+ 'cookies' => false,
+ 'idn_conversion' => false,
];
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
if (isset($options['form_params'])) {
if (isset($options['multipart'])) {
throw new InvalidArgumentException('You cannot use '
- . 'form_params and multipart at the same time. Use the '
- . 'form_params option if you want to send application/'
- . 'x-www-form-urlencoded requests, and the multipart '
- . 'option to send multipart/form-data requests.');
+ .'form_params and multipart at the same time. Use the '
+ .'form_params option if you want to send application/'
+ .'x-www-form-urlencoded requests, and the multipart '
+ .'option to send multipart/form-data requests.');
}
$options['body'] = \http_build_query($options['form_params'], '', '&');
unset($options['form_params']);
// Ensure that we don't have the header in different case and set the new value.
$modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
$modify['set_headers']['Authorization'] = 'Basic '
- . \base64_encode("$value[0]:$value[1]");
+ .\base64_encode("$value[0]:$value[1]");
break;
case 'digest':
// @todo: Do not rely on curl
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
- . $request->getBody()->getBoundary();
+ .$request->getBody()->getBoundary();
}
// Merge in conditional headers if they are not present.
private function invalidBody(): InvalidArgumentException
{
return new InvalidArgumentException('Passing in the "body" request '
- . 'option as an array to send a request is not supported. '
- . 'Please use the "form_params" request option to send a '
- . 'application/x-www-form-urlencoded request, or the "multipart" '
- . 'request option to send a multipart/form-data request.');
+ .'option as an array to send a request is not supported. '
+ .'Please use the "form_params" request option to send a '
+ .'application/x-www-form-urlencoded request, or the "multipart" '
+ .'request option to send a multipart/form-data request.');
}
}
$cookieJar = new self();
foreach ($cookies as $name => $value) {
$cookieJar->setCookie(new SetCookie([
- 'Domain' => $domain,
- 'Name' => $name,
- 'Value' => $value,
- 'Discard' => true
+ 'Domain' => $domain,
+ 'Name' => $name,
+ 'Value' => $value,
+ 'Discard' => true,
]));
}
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function toArray(): array
{
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void
{
if (!$domain) {
$this->cookies = [];
+
return;
} elseif (!$path) {
$this->cookies = \array_filter(
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function clearSessionCookies(): void
{
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setCookie(SetCookie $cookie): bool
{
$result = $cookie->validate();
if ($result !== true) {
if ($this->strictMode) {
- throw new \RuntimeException('Invalid cookie: ' . $result);
+ throw new \RuntimeException('Invalid cookie: '.$result);
}
$this->removeCookieIfEmpty($cookie);
+
return false;
}
/**
* Computes cookie path following RFC 6265 section 5.1.4
*
- * @link https://tools.ietf.org/html/rfc6265#section-5.1.4
+ * @see https://tools.ietf.org/html/rfc6265#section-5.1.4
*/
private function getCookiePathFromRequest(RequestInterface $request): string
{
!$cookie->isExpired() &&
(!$cookie->getSecure() || $scheme === 'https')
) {
- $values[] = $cookie->getName() . '='
- . $cookie->getValue();
+ $values[] = $cookie->getName().'='
+ .$cookie->getValue();
}
}
* necessary. Subclasses are also responsible for storing and retrieving
* cookies from a file, database, etc.
*
- * @link https://docs.python.org/2/library/cookielib.html Inspiration
+ * @see https://docs.python.org/2/library/cookielib.html Inspiration
* @extends \IteratorAggregate<SetCookie>
*/
interface CookieJarInterface extends \Countable, \IteratorAggregate
$this->setCookie(new SetCookie($cookie));
}
} elseif (\strlen($data)) {
- throw new \RuntimeException("Invalid cookie data");
+ throw new \RuntimeException('Invalid cookie data');
}
}
}
* @var array
*/
private static $defaults = [
- 'Name' => null,
- 'Value' => null,
- 'Domain' => null,
- 'Path' => '/',
- 'Max-Age' => null,
- 'Expires' => null,
- 'Secure' => false,
- 'Discard' => false,
- 'HttpOnly' => false
+ 'Name' => null,
+ 'Value' => null,
+ 'Domain' => null,
+ 'Path' => '/',
+ 'Max-Age' => null,
+ 'Expires' => null,
+ 'Secure' => false,
+ 'Discard' => false,
+ 'HttpOnly' => false,
];
/**
public function __toString()
{
- $str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; ';
+ $str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; ';
foreach ($this->data as $k => $v) {
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
if ($k === 'Expires') {
- $str .= 'Expires=' . \gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
+ $str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; ';
} else {
- $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
+ $str .= ($v === true ? $k : "{$k}={$v}").'; ';
}
}
}
return false;
}
- return (bool) \preg_match('/\.' . \preg_quote($cookieDomain, '/') . '$/', $domain);
+ return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain);
}
/**
$name
)) {
return 'Cookie name must not contain invalid characters: ASCII '
- . 'Control characters (0-31;127), space, tab and the '
- . 'following characters: ()<>@,;:\"/?={}';
+ .'Control characters (0-31;127), space, tab and the '
+ .'following characters: ()<>@,;:\"/?={}';
}
// Value must not be null. 0 and empty string are valid. Empty strings
unset($options['curl']['body_as_string']);
}
- $easy = new EasyHandle;
+ $easy = new EasyHandle();
$easy->request = $request;
$easy->options = $options;
$conf = $this->getDefaultConf($easy);
private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface
{
static $connectionErrors = [
- \CURLE_OPERATION_TIMEOUTED => true,
+ \CURLE_OPERATION_TIMEOUTED => true,
\CURLE_COULDNT_RESOLVE_HOST => true,
- \CURLE_COULDNT_CONNECT => true,
- \CURLE_SSL_CONNECT_ERROR => true,
- \CURLE_GOT_NOTHING => true,
+ \CURLE_COULDNT_CONNECT => true,
+ \CURLE_SSL_CONNECT_ERROR => true,
+ \CURLE_GOT_NOTHING => true,
];
if ($easy->createResponseException) {
private function getDefaultConf(EasyHandle $easy): array
{
$conf = [
- '_headers' => $easy->request->getHeaders(),
- \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
- \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
+ '_headers' => $easy->request->getHeaders(),
+ \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
+ \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
\CURLOPT_RETURNTRANSFER => false,
- \CURLOPT_HEADER => false,
+ \CURLOPT_HEADER => false,
\CURLOPT_CONNECTTIMEOUT => 300,
];
if ($size === null || $size > 0) {
$this->applyBody($easy->request, $easy->options, $conf);
+
return;
}
foreach (\array_keys($options['_headers']) as $key) {
if (!\strcasecmp($key, $name)) {
unset($options['_headers'][$key]);
+
return;
}
}
if (!\file_exists($cert)) {
throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
}
- # OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
- # see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
+ // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
+ // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
$ext = pathinfo($cert, \PATHINFO_EXTENSION);
if (preg_match('#^(der|p12)$#i', $ext)) {
$conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext);
}
} catch (\RuntimeException $e) {
$ctx['error'] = 'The connection unexpectedly failed without '
- . 'providing an error. The request would have been retried, '
- . 'but attempting to rewind the request body failed. '
- . 'Exception: ' . $e;
+ .'providing an error. The request would have been retried, '
+ .'but attempting to rewind the request body failed. '
+ .'Exception: '.$e;
+
return self::createRejection($easy, $ctx);
}
$easy->options['_curl_retries'] = 1;
} elseif ($easy->options['_curl_retries'] == 2) {
$ctx['error'] = 'The cURL request was retried 3 times '
- . 'and did not succeed. The most likely reason for the failure '
- . 'is that cURL was unable to rewind the body of the request '
- . 'and subsequent retries resulted in the same error. Turn on '
- . 'the debug option to see what went wrong. See '
- . 'https://bugs.php.net/bug.php?id=47204 for more information.';
+ .'and did not succeed. The most likely reason for the failure '
+ .'is that cURL was unable to rewind the body of the request '
+ .'and subsequent retries resulted in the same error. Turn on '
+ .'the debug option to see what went wrong. See '
+ .'https://bugs.php.net/bug.php?id=47204 for more information.';
+
return self::createRejection($easy, $ctx);
} else {
- $easy->options['_curl_retries']++;
+ ++$easy->options['_curl_retries'];
}
return $handler($easy->request, $easy->options);
$easy->createResponse();
} catch (\Exception $e) {
$easy->createResponseException = $e;
+
return -1;
}
if ($onHeaders !== null) {
// Associate the exception with the handle and trigger
// a curl header write error by returning 0.
$easy->onHeadersException = $e;
+
return -1;
}
}
} else {
$easy->headers[] = $value;
}
+
return \strlen($h);
};
}
\usleep(250);
}
- while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM);
+ while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
+ }
$this->processMessages();
}
*/
public function __get($name)
{
- $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name;
+ $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name;
throw new \BadMethodCallException($msg);
}
}
*
* @param string[] $headers
*
- * @throws \RuntimeException
- *
* @return array{0:string, 1:int, 2:?string, 3:array}
+ *
+ * @throws \RuntimeException
*/
public static function parseHeaders(array $headers): array
{
if ($this->onRejected) {
($this->onRejected)($reason);
}
+
return P\Create::rejectionFor($reason);
}
);
) {
$this->queue[] = $value;
} else {
- throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . Utils::describeType($value));
+ throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value));
}
}
}
if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed
|| false !== \strpos($message, 'Connection refused')
|| false !== \strpos($message, "couldn't connect to host") // error on HHVM
- || false !== \strpos($message, "connection attempt failed")
+ || false !== \strpos($message, 'connection attempt failed')
) {
$e = new ConnectException($e->getMessage(), $request, $e);
} else {
\set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool {
$errors[] = [
'message' => $msg,
- 'file' => $file,
- 'line' => $line
+ 'file' => $file,
+ 'line' => $line,
];
+
return true;
});
$message = 'Error creating resource: ';
foreach ($errors as $err) {
foreach ($err as $key => $value) {
- $message .= "[$key] $value" . \PHP_EOL;
+ $message .= "[$key] $value".\PHP_EOL;
}
}
throw new \RuntimeException(\trim($message));
if (false === $records || !isset($records[0]['ip'])) {
throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
}
+
return $uri->withHost($records[0]['ip']);
}
if ('v6' === $options['force_ip_resolve']) {
if (false === $records || !isset($records[0]['ipv6'])) {
throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
}
- return $uri->withHost('[' . $records[0]['ipv6'] . ']');
+
+ return $uri->withHost('['.$records[0]['ipv6'].']');
}
}
$context = [
'http' => [
- 'method' => $request->getMethod(),
- 'header' => $headers,
+ 'method' => $request->getMethod(),
+ 'header' => $headers,
'protocol_version' => $request->getProtocolVersion(),
- 'ignore_errors' => true,
- 'follow_location' => 0,
+ 'ignore_errors' => true,
+ 'follow_location' => 0,
],
'ssl' => [
'peer_name' => $request->getUri()->getHost(),
}
static $map = [
- \STREAM_NOTIFY_CONNECT => 'CONNECT',
+ \STREAM_NOTIFY_CONNECT => 'CONNECT',
\STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
- \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
- \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
- \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
- \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
- \STREAM_NOTIFY_PROGRESS => 'PROGRESS',
- \STREAM_NOTIFY_FAILURE => 'FAILURE',
- \STREAM_NOTIFY_COMPLETED => 'COMPLETED',
- \STREAM_NOTIFY_RESOLVE => 'RESOLVE',
+ \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
+ \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
+ \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
+ \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
+ \STREAM_NOTIFY_PROGRESS => 'PROGRESS',
+ \STREAM_NOTIFY_FAILURE => 'FAILURE',
+ \STREAM_NOTIFY_COMPLETED => 'COMPLETED',
+ \STREAM_NOTIFY_RESOLVE => 'RESOLVE',
];
static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
$value = Utils::debugResource($value);
- $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
+ $ident = $request->getMethod().' '.$request->getUri()->withFragment('');
self::addNotification(
$params,
static function (int $code, ...$passed) use ($ident, $value, $map, $args): void {
\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
foreach (\array_filter($passed) as $i => $v) {
- \fwrite($value, $args[$i] . ': "' . $v . '" ');
+ \fwrite($value, $args[$i].': "'.$v.'" ');
}
\fwrite($value, "\n");
}
} else {
$params['notification'] = self::callArray([
$params['notification'],
- $notify
+ $notify,
]);
}
}
$stack = [];
if ($this->handler !== null) {
- $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
+ $stack[] = '0) Handler: '.$this->debugCallable($this->handler);
}
$result = '';
foreach (\array_reverse($this->stack) as $tuple) {
- $depth++;
+ ++$depth;
$str = "{$depth}) Name: '{$tuple[1]}', ";
- $str .= "Function: " . $this->debugCallable($tuple[0]);
+ $str .= 'Function: '.$this->debugCallable($tuple[0]);
$result = "> {$str}\n{$result}";
$stack[] = $str;
}
*/
public function hasHandler(): bool
{
- return $this->handler !== null ;
+ return $this->handler !== null;
}
/**
if (\is_array($fn)) {
return \is_string($fn[0])
? "callable({$fn[0]}::{$fn[1]})"
- : "callable(['" . \get_class($fn[0]) . "', '{$fn[1]}'])";
+ : "callable(['".\get_class($fn[0])."', '{$fn[1]}'])";
}
/** @var object $fn */
- return 'callable(' . \spl_object_hash($fn) . ')';
+ return 'callable('.\spl_object_hash($fn).')';
}
}
/**
* Apache Common Log Format.
*
- * @link https://httpd.apache.org/docs/2.4/logs.html#common
+ * @see https://httpd.apache.org/docs/2.4/logs.html#common
*
* @var string
*/
- public const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
+ public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}';
public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
break;
case 'req_headers':
$result = \trim($request->getMethod()
- . ' ' . $request->getRequestTarget())
- . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
- . $this->headers($request);
+ .' '.$request->getRequestTarget())
+ .' HTTP/'.$request->getProtocolVersion()."\r\n"
+ .$this->headers($request);
break;
case 'res_headers':
$result = $response ?
$response->getProtocolVersion(),
$response->getStatusCode(),
$response->getReasonPhrase()
- ) . "\r\n" . $this->headers($response)
+ )."\r\n".$this->headers($response)
: 'NULL';
break;
case 'req_body':
}
$cache[$matches[1]] = $result;
+
return $result;
},
$this->template
{
$result = '';
foreach ($message->getHeaders() as $name => $values) {
- $result .= $name . ': ' . \implode(', ', $values) . "\r\n";
+ $result .= $name.': '.\implode(', ', $values)."\r\n";
}
return \trim($result);
}
$cookieJar = $options['cookies'];
$request = $cookieJar->withCookieHeader($request);
+
return $handler($request, $options)
->then(
static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface {
$cookieJar->extractCookies($request, $response);
+
return $response;
}
);
if (empty($options['http_errors'])) {
return $handler($request, $options);
}
+
return $handler($request, $options)->then(
static function (ResponseInterface $response) use ($request, $bodySummarizer) {
$code = $response->getStatusCode();
return $handler($request, $options)->then(
static function ($value) use ($request, &$container, $options) {
$container[] = [
- 'request' => $request,
+ 'request' => $request,
'response' => $value,
- 'error' => null,
- 'options' => $options
+ 'error' => null,
+ 'options' => $options,
];
+
return $value;
},
static function ($reason) use ($request, &$container, $options) {
$container[] = [
- 'request' => $request,
+ 'request' => $request,
'response' => null,
- 'error' => $reason,
- 'options' => $options
+ 'error' => $reason,
+ 'options' => $options,
];
+
return P\Create::rejectionFor($reason);
}
);
if ($after) {
$after($request, $options, $response);
}
+
return $response;
};
};
static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface {
$message = $formatter->format($request, $response);
$logger->log($logLevel, $message);
+
return $response;
},
static function ($reason) use ($logger, $request, $formatter): PromiseInterface {
$response = $reason instanceof RequestException ? $reason->getResponse() : null;
$message = $formatter->format($request, $response, P\Create::exceptionFor($reason));
$logger->error($message);
+
return P\Create::rejectionFor($reason);
}
);
// The expect header is unconditionally enabled
if ($expect === true) {
$modify['set_headers']['Expect'] = '100-Continue';
+
return;
}
* @var array
*/
public static $defaultSettings = [
- 'max' => 5,
- 'protocols' => ['http', 'https'],
- 'strict' => false,
- 'referer' => false,
+ 'max' => 5,
+ 'protocols' => ['http', 'https'],
+ 'strict' => false,
+ 'referer' => false,
'track_redirects' => false,
];
*
* More documentation for each option can be found at http://guzzlephp.org/.
*
- * @link http://docs.guzzlephp.org/en/v6/request-options.html
+ * @see http://docs.guzzlephp.org/en/v6/request-options.html
*/
final class RequestOptions
{
{
$this->decider = $decider;
$this->nextHandler = $nextHandler;
- $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
+ $this->delay = $delay ?: __CLASS__.'::exponentialDelay';
}
/**
*/
public static function exponentialDelay(int $retries): int
{
- return (int) \pow(2, $retries - 1) * 1000;
+ return (int) 2 ** ($retries - 1) * 1000;
}
public function __invoke(RequestInterface $request, array $options): PromiseInterface
}
$fn = $this->nextHandler;
+
return $fn($request, $options)
->then(
$this->onFulfilled($request, $options),
)) {
return $value;
}
+
return $this->doRetry($request, $options, $value);
};
}
)) {
return P\Create::rejectionFor($reason);
}
+
return $this->doRetry($req, $options);
};
}
{
switch (\gettype($input)) {
case 'object':
- return 'object(' . \get_class($input) . ')';
+ return 'object('.\get_class($input).')';
case 'array':
- return 'array(' . \count($input) . ')';
+ return 'array('.\count($input).')';
default:
\ob_start();
\var_dump($input);
*
* The returned handler is not wrapped by any default middlewares.
*
- * @throws \RuntimeException if no viable Handler is available.
- *
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
+ *
+ * @throws \RuntimeException if no viable Handler is available.
*/
public static function chooseHandler(): callable
{
}
// Special match if the area when prefixed with ".". Remove any
// existing leading "." and add a new leading ".".
- $area = '.' . \ltrim($area, '.');
- if (\substr($host, -(\strlen($area))) === $area) {
+ $area = '.'.\ltrim($area, '.');
+ if (\substr($host, -\strlen($area)) === $area) {
return true;
}
}
*
* @throws InvalidArgumentException if the JSON cannot be decoded.
*
- * @link https://www.php.net/manual/en/function.json-decode.php
+ * @see https://www.php.net/manual/en/function.json-decode.php
*/
public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)
{
$data = \json_decode($json, $assoc, $depth, $options);
if (\JSON_ERROR_NONE !== \json_last_error()) {
- throw new InvalidArgumentException('json_decode error: ' . \json_last_error_msg());
+ throw new InvalidArgumentException('json_decode error: '.\json_last_error_msg());
}
return $data;
*
* @throws InvalidArgumentException if the JSON cannot be encoded.
*
- * @link https://www.php.net/manual/en/function.json-encode.php
+ * @see https://www.php.net/manual/en/function.json-encode.php
*/
public static function jsonEncode($value, int $options = 0, int $depth = 512): string
{
$json = \json_encode($value, $options, $depth);
if (\JSON_ERROR_NONE !== \json_last_error()) {
- throw new InvalidArgumentException('json_encode error: ' . \json_last_error_msg());
+ throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg());
}
/** @var string */
$errorMessage = 'IDN conversion failed';
if ($errors) {
- $errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
+ $errorMessage .= ' (errors: '.implode(', ', $errors).')';
}
throw new InvalidArgumentException($errorMessage);
*
* The returned handler is not wrapped by any default middlewares.
*
- * @throws \RuntimeException if no viable Handler is available.
- *
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
*
+ * @throws \RuntimeException if no viable Handler is available.
+ *
* @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead.
*/
function choose_handler(): callable
*
* @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
*
- * @link https://www.php.net/manual/en/function.json-decode.php
+ * @see https://www.php.net/manual/en/function.json-decode.php
* @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead.
*/
function json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)
*
* @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
*
- * @link https://www.php.net/manual/en/function.json-encode.php
+ * @see https://www.php.net/manual/en/function.json-encode.php
* @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead.
*/
function json_encode($value, int $options = 0, int $depth = 512): string
// Don't redefine the functions if included multiple times.
if (!\function_exists('GuzzleHttp\describe_type')) {
- require __DIR__ . '/functions.php';
+ require __DIR__.'/functions.php';
}
# CHANGELOG
+
+## 2.0.0 - TBC
+
+### Added
+
+- Added PHP 7 type hints
+
+### Changed
+
+- All previously non-final non-exception classes have been marked as soft-final
+
+### Removed
+
+- Dropped PHP < 7.2 support
+- All functions in the `GuzzleHttp\Promise` namespace
+
+
+## 1.5.3 - 2023-05-21
+
+### Changed
+
+- Removed remaining usage of deprecated functions
+
+
## 1.5.2 - 2022-08-07
### Changed
- Officially support PHP 8.2
+
## 1.5.1 - 2021-10-22
### Fixed
- Revert "Call handler when waiting on fulfilled/rejected Promise"
- Fix pool memory leak when empty array of promises provided
+
## 1.5.0 - 2021-10-07
### Changed
- Fix manually settle promises generated with `Utils::task`
+
## 1.4.1 - 2021-02-18
### Fixed
- Fixed `each_limit` skipping promises and failing
+
## 1.4.0 - 2020-09-30
### Added
`GuzzleHttp\Promise\Coroutine::of()`.
+## Installation
+
+```shell
+composer require guzzlehttp/promises
+```
+
+
+## Version Guidance
+
+| Version | Status | PHP Version |
+|---------|------------------------|--------------|
+| 1.x | Bug and security fixes | >=5.5,<8.3 |
+| 2.x | Latest | >=7.2.5,<8.3 |
+
+
## Quick Start
A *promise* represents the eventual result of an asynchronous operation. The
$loop->addPeriodicTimer(0, [$queue, 'run']);
```
-*TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
-
## Implementation Notes
A static API was first introduced in 1.4.0, in order to mitigate problems with
functions conflicting between global and local copies of the package. The
-function API will be removed in 2.0.0. A migration table has been provided here
-for your convenience:
+function API was removed in 2.0.0. A migration table has been provided here for
+your convenience:
| Original Function | Replacement Method |
|----------------|----------------|
}
],
"require": {
- "php": ">=5.5"
+ "php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ "bamarni/composer-bin-plugin": "^1.8.1",
+ "phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
- },
- "files": ["src/functions_include.php"]
+ }
},
"autoload-dev": {
"psr-4": {
"GuzzleHttp\\Promise\\Tests\\": "tests/"
}
},
- "scripts": {
- "test": "vendor/bin/simple-phpunit",
- "test-ci": "vendor/bin/simple-phpunit --coverage-text"
- },
"extra": {
- "branch-alias": {
- "dev-master": "1.5-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
}
},
"config": {
+ "allow-plugins": {
+ "bamarni/composer-bin-plugin": true
+ },
"preferred-install": "dist",
"sort-packages": true
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
*/
class AggregateException extends RejectionException
{
- public function __construct($msg, array $reasons)
+ public function __construct(string $msg, array $reasons)
{
parent::__construct(
$reasons,
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
-use Exception;
use Generator;
use Throwable;
* $value = (yield createPromise('a'));
* try {
* $value = (yield createPromise($value . 'b'));
- * } catch (\Exception $e) {
+ * } catch (\Throwable $e) {
* // The promise was rejected.
* }
* yield $value . 'c';
*
* @return Promise
*
- * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
+ * @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
*/
final class Coroutine implements PromiseInterface
{
public function __construct(callable $generatorFn)
{
$this->generator = $generatorFn();
- $this->result = new Promise(function () {
+ $this->result = new Promise(function (): void {
while (isset($this->currentPromise)) {
$this->currentPromise->wait();
}
});
try {
$this->nextCoroutine($this->generator->current());
- } catch (\Exception $exception) {
- $this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}
/**
* Create a new coroutine.
- *
- * @return self
*/
- public static function of(callable $generatorFn)
+ public static function of(callable $generatorFn): self
{
return new self($generatorFn);
}
public function then(
callable $onFulfilled = null,
callable $onRejected = null
- ) {
+ ): PromiseInterface {
return $this->result->then($onFulfilled, $onRejected);
}
- public function otherwise(callable $onRejected)
+ public function otherwise(callable $onRejected): PromiseInterface
{
return $this->result->otherwise($onRejected);
}
- public function wait($unwrap = true)
+ public function wait(bool $unwrap = true)
{
return $this->result->wait($unwrap);
}
- public function getState()
+ public function getState(): string
{
return $this->result->getState();
}
- public function resolve($value)
+ public function resolve($value): void
{
$this->result->resolve($value);
}
- public function reject($reason)
+ public function reject($reason): void
{
$this->result->reject($reason);
}
- public function cancel()
+ public function cancel(): void
{
$this->currentPromise->cancel();
$this->result->cancel();
}
- private function nextCoroutine($yielded)
+ private function nextCoroutine($yielded): void
{
$this->currentPromise = Create::promiseFor($yielded)
->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
/**
* @internal
*/
- public function _handleSuccess($value)
+ public function _handleSuccess($value): void
{
unset($this->currentPromise);
try {
} else {
$this->result->resolve($value);
}
- } catch (Exception $exception) {
- $this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}
/**
* @internal
*/
- public function _handleFailure($reason)
+ public function _handleFailure($reason): void
{
unset($this->currentPromise);
try {
$nextYield = $this->generator->throw(Create::exceptionFor($reason));
// The throw was caught, so keep iterating on the coroutine
$this->nextCoroutine($nextYield);
- } catch (Exception $exception) {
- $this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
final class Create
* Creates a promise for a value if the value is not a promise.
*
* @param mixed $value Promise or value.
- *
- * @return PromiseInterface
*/
- public static function promiseFor($value)
+ public static function promiseFor($value): PromiseInterface
{
if ($value instanceof PromiseInterface) {
return $value;
$cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
$promise = new Promise($wfn, $cfn);
$value->then([$promise, 'resolve'], [$promise, 'reject']);
+
return $promise;
}
* If the provided reason is a promise, then it is returned as-is.
*
* @param mixed $reason Promise or reason.
- *
- * @return PromiseInterface
*/
- public static function rejectionFor($reason)
+ public static function rejectionFor($reason): PromiseInterface
{
if ($reason instanceof PromiseInterface) {
return $reason;
* Create an exception for a rejected promise value.
*
* @param mixed $reason
- *
- * @return \Exception|\Throwable
*/
- public static function exceptionFor($reason)
+ public static function exceptionFor($reason): \Throwable
{
- if ($reason instanceof \Exception || $reason instanceof \Throwable) {
+ if ($reason instanceof \Throwable) {
return $reason;
}
* Returns an iterator for the given value.
*
* @param mixed $value
- *
- * @return \Iterator
*/
- public static function iterFor($value)
+ public static function iterFor($value): \Iterator
{
if ($value instanceof \Iterator) {
return $value;
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
final class Each
* @param mixed $iterable Iterator or array to iterate over.
* @param callable $onFulfilled
* @param callable $onRejected
- *
- * @return PromiseInterface
*/
public static function of(
$iterable,
callable $onFulfilled = null,
callable $onRejected = null
- ) {
+ ): PromiseInterface {
return (new EachPromise($iterable, [
'fulfilled' => $onFulfilled,
- 'rejected' => $onRejected
+ 'rejected' => $onRejected,
]))->promise();
}
* @param int|callable $concurrency
* @param callable $onFulfilled
* @param callable $onRejected
- *
- * @return PromiseInterface
*/
public static function ofLimit(
$iterable,
$concurrency,
callable $onFulfilled = null,
callable $onRejected = null
- ) {
+ ): PromiseInterface {
return (new EachPromise($iterable, [
- 'fulfilled' => $onFulfilled,
- 'rejected' => $onRejected,
- 'concurrency' => $concurrency
+ 'fulfilled' => $onFulfilled,
+ 'rejected' => $onRejected,
+ 'concurrency' => $concurrency,
]))->promise();
}
* @param mixed $iterable
* @param int|callable $concurrency
* @param callable $onFulfilled
- *
- * @return PromiseInterface
*/
public static function ofLimitAll(
$iterable,
$concurrency,
callable $onFulfilled = null
- ) {
- return each_limit(
+ ): PromiseInterface {
+ return self::ofLimit(
$iterable,
$concurrency,
$onFulfilled,
- function ($reason, $idx, PromiseInterface $aggregate) {
+ function ($reason, $idx, PromiseInterface $aggregate): void {
$aggregate->reject($reason);
}
);
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
* Represents a promise that iterates over many promises and invokes
* side-effect functions in the process.
+ *
+ * @final
*/
class EachPromise implements PromisorInterface
{
}
/** @psalm-suppress InvalidNullableReturnType */
- public function promise()
+ public function promise(): PromiseInterface
{
if ($this->aggregate) {
return $this->aggregate;
$this->refillPending();
} catch (\Throwable $e) {
$this->aggregate->reject($e);
- } catch (\Exception $e) {
- $this->aggregate->reject($e);
}
/**
* @psalm-suppress NullableReturnStatement
- * @phpstan-ignore-next-line
*/
return $this->aggregate;
}
- private function createPromise()
+ private function createPromise(): void
{
$this->mutex = false;
- $this->aggregate = new Promise(function () {
+ $this->aggregate = new Promise(function (): void {
if ($this->checkIfFinished()) {
return;
}
});
// Clear the references when the promise is resolved.
- $clearFn = function () {
+ $clearFn = function (): void {
$this->iterable = $this->concurrency = $this->pending = null;
$this->onFulfilled = $this->onRejected = null;
$this->nextPendingIndex = 0;
$this->aggregate->then($clearFn, $clearFn);
}
- private function refillPending()
+ private function refillPending(): void
{
if (!$this->concurrency) {
// Add all pending promises.
- while ($this->addPending() && $this->advanceIterator());
+ while ($this->addPending() && $this->advanceIterator()) {
+ }
+
return;
}
// next value to yield until promise callbacks are called.
while (--$concurrency
&& $this->advanceIterator()
- && $this->addPending());
+ && $this->addPending()) {
+ }
}
- private function addPending()
+ private function addPending(): bool
{
if (!$this->iterable || !$this->iterable->valid()) {
return false;
$idx = $this->nextPendingIndex++;
$this->pending[$idx] = $promise->then(
- function ($value) use ($idx, $key) {
+ function ($value) use ($idx, $key): void {
if ($this->onFulfilled) {
call_user_func(
$this->onFulfilled,
}
$this->step($idx);
},
- function ($reason) use ($idx, $key) {
+ function ($reason) use ($idx, $key): void {
if ($this->onRejected) {
call_user_func(
$this->onRejected,
return true;
}
- private function advanceIterator()
+ private function advanceIterator(): bool
{
// Place a lock on the iterator so that we ensure to not recurse,
// preventing fatal generator errors.
try {
$this->iterable->next();
$this->mutex = false;
+
return true;
} catch (\Throwable $e) {
$this->aggregate->reject($e);
$this->mutex = false;
- return false;
- } catch (\Exception $e) {
- $this->aggregate->reject($e);
- $this->mutex = false;
+
return false;
}
}
- private function step($idx)
+ private function step(int $idx): void
{
// If the promise was already resolved, then ignore this step.
if (Is::settled($this->aggregate)) {
}
}
- private function checkIfFinished()
+ private function checkIfFinished(): bool
{
if (!$this->pending && !$this->iterable->valid()) {
// Resolve the promise if there's nothing left to do.
$this->aggregate->resolve(null);
+
return true;
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
*
* Thenning off of this promise will invoke the onFulfilled callback
* immediately and ignore other callbacks.
+ *
+ * @final
*/
class FulfilledPromise implements PromiseInterface
{
private $value;
+ /**
+ * @param mixed $value
+ */
public function __construct($value)
{
if (is_object($value) && method_exists($value, 'then')) {
public function then(
callable $onFulfilled = null,
callable $onRejected = null
- ) {
+ ): PromiseInterface {
// Return itself if there is no onFulfilled function.
if (!$onFulfilled) {
return $this;
$queue = Utils::queue();
$p = new Promise([$queue, 'run']);
$value = $this->value;
- $queue->add(static function () use ($p, $value, $onFulfilled) {
+ $queue->add(static function () use ($p, $value, $onFulfilled): void {
if (Is::pending($p)) {
try {
$p->resolve($onFulfilled($value));
} catch (\Throwable $e) {
$p->reject($e);
- } catch (\Exception $e) {
- $p->reject($e);
}
}
});
return $p;
}
- public function otherwise(callable $onRejected)
+ public function otherwise(callable $onRejected): PromiseInterface
{
return $this->then(null, $onRejected);
}
- public function wait($unwrap = true, $defaultDelivery = null)
+ public function wait(bool $unwrap = true)
{
return $unwrap ? $this->value : null;
}
- public function getState()
+ public function getState(): string
{
return self::FULFILLED;
}
- public function resolve($value)
+ public function resolve($value): void
{
if ($value !== $this->value) {
- throw new \LogicException("Cannot resolve a fulfilled promise");
+ throw new \LogicException('Cannot resolve a fulfilled promise');
}
}
- public function reject($reason)
+ public function reject($reason): void
{
- throw new \LogicException("Cannot reject a fulfilled promise");
+ throw new \LogicException('Cannot reject a fulfilled promise');
}
- public function cancel()
+ public function cancel(): void
{
// pass
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
final class Is
{
/**
* Returns true if a promise is pending.
- *
- * @return bool
*/
- public static function pending(PromiseInterface $promise)
+ public static function pending(PromiseInterface $promise): bool
{
return $promise->getState() === PromiseInterface::PENDING;
}
/**
* Returns true if a promise is fulfilled or rejected.
- *
- * @return bool
*/
- public static function settled(PromiseInterface $promise)
+ public static function settled(PromiseInterface $promise): bool
{
return $promise->getState() !== PromiseInterface::PENDING;
}
/**
* Returns true if a promise is fulfilled.
- *
- * @return bool
*/
- public static function fulfilled(PromiseInterface $promise)
+ public static function fulfilled(PromiseInterface $promise): bool
{
return $promise->getState() === PromiseInterface::FULFILLED;
}
/**
* Returns true if a promise is rejected.
- *
- * @return bool
*/
- public static function rejected(PromiseInterface $promise)
+ public static function rejected(PromiseInterface $promise): bool
{
return $promise->getState() === PromiseInterface::REJECTED;
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
* Promises/A+ implementation that avoids recursion when possible.
*
- * @link https://promisesaplus.com/
+ * @see https://promisesaplus.com/
+ *
+ * @final
*/
class Promise implements PromiseInterface
{
public function then(
callable $onFulfilled = null,
callable $onRejected = null
- ) {
+ ): PromiseInterface {
if ($this->state === self::PENDING) {
$p = new Promise(null, [$this, 'cancel']);
$this->handlers[] = [$p, $onFulfilled, $onRejected];
$p->waitList = $this->waitList;
$p->waitList[] = $this;
+
return $p;
}
// Return a fulfilled promise and immediately invoke any callbacks.
if ($this->state === self::FULFILLED) {
$promise = Create::promiseFor($this->result);
+
return $onFulfilled ? $promise->then($onFulfilled) : $promise;
}
// It's either cancelled or rejected, so return a rejected promise
// and immediately invoke any callbacks.
$rejection = Create::rejectionFor($this->result);
+
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
}
- public function otherwise(callable $onRejected)
+ public function otherwise(callable $onRejected): PromiseInterface
{
return $this->then(null, $onRejected);
}
- public function wait($unwrap = true)
+ public function wait(bool $unwrap = true)
{
$this->waitIfPending();
}
}
- public function getState()
+ public function getState(): string
{
return $this->state;
}
- public function cancel()
+ public function cancel(): void
{
if ($this->state !== self::PENDING) {
return;
$fn();
} catch (\Throwable $e) {
$this->reject($e);
- } catch (\Exception $e) {
- $this->reject($e);
}
}
}
}
- public function resolve($value)
+ public function resolve($value): void
{
$this->settle(self::FULFILLED, $value);
}
- public function reject($reason)
+ public function reject($reason): void
{
$this->settle(self::REJECTED, $reason);
}
- private function settle($state, $value)
+ private function settle(string $state, $value): void
{
if ($this->state !== self::PENDING) {
// Ignore calls with the same resolution.
if (!is_object($value) || !method_exists($value, 'then')) {
$id = $state === self::FULFILLED ? 1 : 2;
// It's a success, so resolve the handlers in the queue.
- Utils::queue()->add(static function () use ($id, $value, $handlers) {
+ Utils::queue()->add(static function () use ($id, $value, $handlers): void {
foreach ($handlers as $handler) {
self::callHandler($id, $value, $handler);
}
} else {
// Resolve the handlers when the forwarded promise is resolved.
$value->then(
- static function ($value) use ($handlers) {
+ static function ($value) use ($handlers): void {
foreach ($handlers as $handler) {
self::callHandler(1, $value, $handler);
}
},
- static function ($reason) use ($handlers) {
+ static function ($reason) use ($handlers): void {
foreach ($handlers as $handler) {
self::callHandler(2, $reason, $handler);
}
* @param mixed $value Value to pass to the callback.
* @param array $handler Array of handler data (promise and callbacks).
*/
- private static function callHandler($index, $value, array $handler)
+ private static function callHandler(int $index, $value, array $handler): void
{
/** @var PromiseInterface $promise */
$promise = $handler[0];
}
} catch (\Throwable $reason) {
$promise->reject($reason);
- } catch (\Exception $reason) {
- $promise->reject($reason);
}
}
- private function waitIfPending()
+ private function waitIfPending(): void
{
if ($this->state !== self::PENDING) {
return;
} else {
// If there's no wait function, then reject the promise.
$this->reject('Cannot wait on a promise that has '
- . 'no internal wait function. You must provide a wait '
- . 'function when constructing the promise to be able to '
- . 'wait on a promise.');
+ .'no internal wait function. You must provide a wait '
+ .'function when constructing the promise to be able to '
+ .'wait on a promise.');
}
Utils::queue()->run();
}
}
- private function invokeWaitFn()
+ private function invokeWaitFn(): void
{
try {
$wfn = $this->waitFn;
$this->waitFn = null;
$wfn(true);
- } catch (\Exception $reason) {
+ } catch (\Throwable $reason) {
if ($this->state === self::PENDING) {
// The promise has not been resolved yet, so reject the promise
// with the exception.
}
}
- private function invokeWaitList()
+ private function invokeWaitList(): void
{
$waitList = $this->waitList;
$this->waitList = null;
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
* which registers callbacks to receive either a promise’s eventual value or
* the reason why the promise cannot be fulfilled.
*
- * @link https://promisesaplus.com/
+ * @see https://promisesaplus.com/
*/
interface PromiseInterface
{
- const PENDING = 'pending';
- const FULFILLED = 'fulfilled';
- const REJECTED = 'rejected';
+ public const PENDING = 'pending';
+ public const FULFILLED = 'fulfilled';
+ public const REJECTED = 'rejected';
/**
* Appends fulfillment and rejection handlers to the promise, and returns
*
* @param callable $onFulfilled Invoked when the promise fulfills.
* @param callable $onRejected Invoked when the promise is rejected.
- *
- * @return PromiseInterface
*/
public function then(
callable $onFulfilled = null,
callable $onRejected = null
- );
+ ): PromiseInterface;
/**
* Appends a rejection handler callback to the promise, and returns a new
* fulfilled.
*
* @param callable $onRejected Invoked when the promise is rejected.
- *
- * @return PromiseInterface
*/
- public function otherwise(callable $onRejected);
+ public function otherwise(callable $onRejected): PromiseInterface;
/**
* Get the state of the promise ("pending", "rejected", or "fulfilled").
*
* The three states can be checked against the constants defined on
* PromiseInterface: PENDING, FULFILLED, and REJECTED.
- *
- * @return string
*/
- public function getState();
+ public function getState(): string;
/**
* Resolve the promise with the given value.
*
* @throws \RuntimeException if the promise is already resolved.
*/
- public function resolve($value);
+ public function resolve($value): void;
/**
* Reject the promise with the given reason.
*
* @throws \RuntimeException if the promise is already resolved.
*/
- public function reject($reason);
+ public function reject($reason): void;
/**
* Cancels the promise if possible.
*
- * @link https://github.com/promises-aplus/cancellation-spec/issues/7
+ * @see https://github.com/promises-aplus/cancellation-spec/issues/7
*/
- public function cancel();
+ public function cancel(): void;
/**
* Waits until the promise completes if possible.
*
* If the promise cannot be waited on, then the promise will be rejected.
*
- * @param bool $unwrap
- *
* @return mixed
*
* @throws \LogicException if the promise has no wait function or if the
* promise does not settle after waiting.
*/
- public function wait($unwrap = true);
+ public function wait(bool $unwrap = true);
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
{
/**
* Returns a promise.
- *
- * @return PromiseInterface
*/
- public function promise();
+ public function promise(): PromiseInterface;
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
*
* Thenning off of this promise will invoke the onRejected callback
* immediately and ignore other callbacks.
+ *
+ * @final
*/
class RejectedPromise implements PromiseInterface
{
private $reason;
+ /**
+ * @param mixed $reason
+ */
public function __construct($reason)
{
if (is_object($reason) && method_exists($reason, 'then')) {
public function then(
callable $onFulfilled = null,
callable $onRejected = null
- ) {
+ ): PromiseInterface {
// If there's no onRejected callback then just return self.
if (!$onRejected) {
return $this;
$queue = Utils::queue();
$reason = $this->reason;
$p = new Promise([$queue, 'run']);
- $queue->add(static function () use ($p, $reason, $onRejected) {
+ $queue->add(static function () use ($p, $reason, $onRejected): void {
if (Is::pending($p)) {
try {
// Return a resolved promise if onRejected does not throw.
} catch (\Throwable $e) {
// onRejected threw, so return a rejected promise.
$p->reject($e);
- } catch (\Exception $e) {
- // onRejected threw, so return a rejected promise.
- $p->reject($e);
}
}
});
return $p;
}
- public function otherwise(callable $onRejected)
+ public function otherwise(callable $onRejected): PromiseInterface
{
return $this->then(null, $onRejected);
}
- public function wait($unwrap = true, $defaultDelivery = null)
+ public function wait(bool $unwrap = true)
{
if ($unwrap) {
throw Create::exceptionFor($this->reason);
return null;
}
- public function getState()
+ public function getState(): string
{
return self::REJECTED;
}
- public function resolve($value)
+ public function resolve($value): void
{
- throw new \LogicException("Cannot resolve a rejected promise");
+ throw new \LogicException('Cannot resolve a rejected promise');
}
- public function reject($reason)
+ public function reject($reason): void
{
if ($reason !== $this->reason) {
- throw new \LogicException("Cannot reject a rejected promise");
+ throw new \LogicException('Cannot reject a rejected promise');
}
}
- public function cancel()
+ public function cancel(): void
{
// pass
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
private $reason;
/**
- * @param mixed $reason Rejection reason.
- * @param string $description Optional description
+ * @param mixed $reason Rejection reason.
+ * @param string|null $description Optional description.
*/
public function __construct($reason, $description = null)
{
$message = 'The promise was rejected';
if ($description) {
- $message .= ' with reason: ' . $description;
+ $message .= ' with reason: '.$description;
} elseif (is_string($reason)
|| (is_object($reason) && method_exists($reason, '__toString'))
) {
- $message .= ' with reason: ' . $this->reason;
+ $message .= ' with reason: '.$this->reason;
} elseif ($reason instanceof \JsonSerializable) {
- $message .= ' with reason: '
- . json_encode($this->reason, JSON_PRETTY_PRINT);
+ $message .= ' with reason: '.json_encode($this->reason, JSON_PRETTY_PRINT);
}
parent::__construct($message);
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
/**
* by calling the `run()` function of the global task queue in an event loop.
*
* GuzzleHttp\Promise\Utils::queue()->run();
+ *
+ * @final
*/
class TaskQueue implements TaskQueueInterface
{
private $enableShutdown = true;
private $queue = [];
- public function __construct($withShutdown = true)
+ public function __construct(bool $withShutdown = true)
{
if ($withShutdown) {
- register_shutdown_function(function () {
+ register_shutdown_function(function (): void {
if ($this->enableShutdown) {
// Only run the tasks if an E_ERROR didn't occur.
$err = error_get_last();
}
}
- public function isEmpty()
+ public function isEmpty(): bool
{
return !$this->queue;
}
- public function add(callable $task)
+ public function add(callable $task): void
{
$this->queue[] = $task;
}
- public function run()
+ public function run(): void
{
while ($task = array_shift($this->queue)) {
/** @var callable $task */
*
* Note: This shutdown will occur before any destructors are triggered.
*/
- public function disableShutdown()
+ public function disableShutdown(): void
{
$this->enableShutdown = false;
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
interface TaskQueueInterface
{
/**
* Returns true if the queue is empty.
- *
- * @return bool
*/
- public function isEmpty();
+ public function isEmpty(): bool;
/**
* Adds a task to the queue that will be executed the next time run is
* called.
*/
- public function add(callable $task);
+ public function add(callable $task): void;
/**
* Execute all of the pending task in the queue.
*/
- public function run();
+ public function run(): void;
}
<?php
+declare(strict_types=1);
+
namespace GuzzleHttp\Promise;
final class Utils
* }
* </code>
*
- * @param TaskQueueInterface $assign Optionally specify a new queue instance.
- *
- * @return TaskQueueInterface
+ * @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
*/
- public static function queue(TaskQueueInterface $assign = null)
+ public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface
{
static $queue;
* returns a promise that is fulfilled or rejected with the result.
*
* @param callable $task Task function to run.
- *
- * @return PromiseInterface
*/
- public static function task(callable $task)
+ public static function task(callable $task): PromiseInterface
{
$queue = self::queue();
$promise = new Promise([$queue, 'run']);
- $queue->add(function () use ($task, $promise) {
+ $queue->add(function () use ($task, $promise): void {
try {
if (Is::pending($promise)) {
$promise->resolve($task());
}
} catch (\Throwable $e) {
$promise->reject($e);
- } catch (\Exception $e) {
- $promise->reject($e);
}
});
* key mapping to the rejection reason of the promise.
*
* @param PromiseInterface $promise Promise or value.
- *
- * @return array
*/
- public static function inspect(PromiseInterface $promise)
+ public static function inspect(PromiseInterface $promise): array
{
try {
return [
'state' => PromiseInterface::FULFILLED,
- 'value' => $promise->wait()
+ 'value' => $promise->wait(),
];
} catch (RejectionException $e) {
return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
} catch (\Throwable $e) {
return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
- } catch (\Exception $e) {
- return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
}
}
* @see inspect for the inspection state array format.
*
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
- *
- * @return array
*/
- public static function inspectAll($promises)
+ public static function inspectAll($promises): array
{
$results = [];
foreach ($promises as $key => $promise) {
- $results[$key] = inspect($promise);
+ $results[$key] = self::inspect($promise);
}
return $results;
*
* @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
*
- * @return array
- *
- * @throws \Exception on error
- * @throws \Throwable on error in PHP >=7
+ * @throws \Throwable on error
*/
- public static function unwrap($promises)
+ public static function unwrap($promises): array
{
$results = [];
foreach ($promises as $key => $promise) {
*
* @param mixed $promises Promises or values.
* @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
- *
- * @return PromiseInterface
*/
- public static function all($promises, $recursive = false)
+ public static function all($promises, bool $recursive = false): PromiseInterface
{
$results = [];
$promise = Each::of(
$promises,
- function ($value, $idx) use (&$results) {
+ function ($value, $idx) use (&$results): void {
$results[$idx] = $value;
},
- function ($reason, $idx, Promise $aggregate) {
+ function ($reason, $idx, Promise $aggregate): void {
$aggregate->reject($reason);
}
)->then(function () use (&$results) {
ksort($results);
+
return $results;
});
return self::all($promises, $recursive);
}
}
+
return $results;
});
}
*
* @param int $count Total number of promises.
* @param mixed $promises Promises or values.
- *
- * @return PromiseInterface
*/
- public static function some($count, $promises)
+ public static function some(int $count, $promises): PromiseInterface
{
$results = [];
$rejections = [];
return Each::of(
$promises,
- function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
+ function ($value, $idx, PromiseInterface $p) use (&$results, $count): void {
if (Is::settled($p)) {
return;
}
$p->resolve(null);
}
},
- function ($reason) use (&$rejections) {
+ function ($reason) use (&$rejections): void {
$rejections[] = $reason;
}
)->then(
);
}
ksort($results);
+
return array_values($results);
}
);
* fulfillment value is not an array of 1 but the value directly.
*
* @param mixed $promises Promises or values.
- *
- * @return PromiseInterface
*/
- public static function any($promises)
+ public static function any($promises): PromiseInterface
{
return self::some(1, $promises)->then(function ($values) {
return $values[0];
* @see inspect for the inspection state array format.
*
* @param mixed $promises Promises or values.
- *
- * @return PromiseInterface
*/
- public static function settle($promises)
+ public static function settle($promises): PromiseInterface
{
$results = [];
return Each::of(
$promises,
- function ($value, $idx) use (&$results) {
+ function ($value, $idx) use (&$results): void {
$results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
},
- function ($reason, $idx) use (&$results) {
+ function ($reason, $idx) use (&$results): void {
$results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
}
)->then(function () use (&$results) {
ksort($results);
+
return $results;
});
}
+++ /dev/null
-<?php
-
-namespace GuzzleHttp\Promise;
-
-/**
- * Get the global task queue used for promise resolution.
- *
- * This task queue MUST be run in an event loop in order for promises to be
- * settled asynchronously. It will be automatically run when synchronously
- * waiting on a promise.
- *
- * <code>
- * while ($eventLoop->isRunning()) {
- * GuzzleHttp\Promise\queue()->run();
- * }
- * </code>
- *
- * @param TaskQueueInterface $assign Optionally specify a new queue instance.
- *
- * @return TaskQueueInterface
- *
- * @deprecated queue will be removed in guzzlehttp/promises:2.0. Use Utils::queue instead.
- */
-function queue(TaskQueueInterface $assign = null)
-{
- return Utils::queue($assign);
-}
-
-/**
- * Adds a function to run in the task queue when it is next `run()` and returns
- * a promise that is fulfilled or rejected with the result.
- *
- * @param callable $task Task function to run.
- *
- * @return PromiseInterface
- *
- * @deprecated task will be removed in guzzlehttp/promises:2.0. Use Utils::task instead.
- */
-function task(callable $task)
-{
- return Utils::task($task);
-}
-
-/**
- * Creates a promise for a value if the value is not a promise.
- *
- * @param mixed $value Promise or value.
- *
- * @return PromiseInterface
- *
- * @deprecated promise_for will be removed in guzzlehttp/promises:2.0. Use Create::promiseFor instead.
- */
-function promise_for($value)
-{
- return Create::promiseFor($value);
-}
-
-/**
- * Creates a rejected promise for a reason if the reason is not a promise. If
- * the provided reason is a promise, then it is returned as-is.
- *
- * @param mixed $reason Promise or reason.
- *
- * @return PromiseInterface
- *
- * @deprecated rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead.
- */
-function rejection_for($reason)
-{
- return Create::rejectionFor($reason);
-}
-
-/**
- * Create an exception for a rejected promise value.
- *
- * @param mixed $reason
- *
- * @return \Exception|\Throwable
- *
- * @deprecated exception_for will be removed in guzzlehttp/promises:2.0. Use Create::exceptionFor instead.
- */
-function exception_for($reason)
-{
- return Create::exceptionFor($reason);
-}
-
-/**
- * Returns an iterator for the given value.
- *
- * @param mixed $value
- *
- * @return \Iterator
- *
- * @deprecated iter_for will be removed in guzzlehttp/promises:2.0. Use Create::iterFor instead.
- */
-function iter_for($value)
-{
- return Create::iterFor($value);
-}
-
-/**
- * Synchronously waits on a promise to resolve and returns an inspection state
- * array.
- *
- * Returns a state associative array containing a "state" key mapping to a
- * valid promise state. If the state of the promise is "fulfilled", the array
- * will contain a "value" key mapping to the fulfilled value of the promise. If
- * the promise is rejected, the array will contain a "reason" key mapping to
- * the rejection reason of the promise.
- *
- * @param PromiseInterface $promise Promise or value.
- *
- * @return array
- *
- * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspect instead.
- */
-function inspect(PromiseInterface $promise)
-{
- return Utils::inspect($promise);
-}
-
-/**
- * Waits on all of the provided promises, but does not unwrap rejected promises
- * as thrown exception.
- *
- * Returns an array of inspection state arrays.
- *
- * @see inspect for the inspection state array format.
- *
- * @param PromiseInterface[] $promises Traversable of promises to wait upon.
- *
- * @return array
- *
- * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspectAll instead.
- */
-function inspect_all($promises)
-{
- return Utils::inspectAll($promises);
-}
-
-/**
- * Waits on all of the provided promises and returns the fulfilled values.
- *
- * Returns an array that contains the value of each promise (in the same order
- * the promises were provided). An exception is thrown if any of the promises
- * are rejected.
- *
- * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
- *
- * @return array
- *
- * @throws \Exception on error
- * @throws \Throwable on error in PHP >=7
- *
- * @deprecated unwrap will be removed in guzzlehttp/promises:2.0. Use Utils::unwrap instead.
- */
-function unwrap($promises)
-{
- return Utils::unwrap($promises);
-}
-
-/**
- * Given an array of promises, return a promise that is fulfilled when all the
- * items in the array are fulfilled.
- *
- * The promise's fulfillment value is an array with fulfillment values at
- * respective positions to the original array. If any promise in the array
- * rejects, the returned promise is rejected with the rejection reason.
- *
- * @param mixed $promises Promises or values.
- * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
- *
- * @return PromiseInterface
- *
- * @deprecated all will be removed in guzzlehttp/promises:2.0. Use Utils::all instead.
- */
-function all($promises, $recursive = false)
-{
- return Utils::all($promises, $recursive);
-}
-
-/**
- * Initiate a competitive race between multiple promises or values (values will
- * become immediately fulfilled promises).
- *
- * When count amount of promises have been fulfilled, the returned promise is
- * fulfilled with an array that contains the fulfillment values of the winners
- * in order of resolution.
- *
- * This promise is rejected with a {@see AggregateException} if the number of
- * fulfilled promises is less than the desired $count.
- *
- * @param int $count Total number of promises.
- * @param mixed $promises Promises or values.
- *
- * @return PromiseInterface
- *
- * @deprecated some will be removed in guzzlehttp/promises:2.0. Use Utils::some instead.
- */
-function some($count, $promises)
-{
- return Utils::some($count, $promises);
-}
-
-/**
- * Like some(), with 1 as count. However, if the promise fulfills, the
- * fulfillment value is not an array of 1 but the value directly.
- *
- * @param mixed $promises Promises or values.
- *
- * @return PromiseInterface
- *
- * @deprecated any will be removed in guzzlehttp/promises:2.0. Use Utils::any instead.
- */
-function any($promises)
-{
- return Utils::any($promises);
-}
-
-/**
- * Returns a promise that is fulfilled when all of the provided promises have
- * been fulfilled or rejected.
- *
- * The returned promise is fulfilled with an array of inspection state arrays.
- *
- * @see inspect for the inspection state array format.
- *
- * @param mixed $promises Promises or values.
- *
- * @return PromiseInterface
- *
- * @deprecated settle will be removed in guzzlehttp/promises:2.0. Use Utils::settle instead.
- */
-function settle($promises)
-{
- return Utils::settle($promises);
-}
-
-/**
- * Given an iterator that yields promises or values, returns a promise that is
- * fulfilled with a null value when the iterator has been consumed or the
- * aggregate promise has been fulfilled or rejected.
- *
- * $onFulfilled is a function that accepts the fulfilled value, iterator index,
- * and the aggregate promise. The callback can invoke any necessary side
- * effects and choose to resolve or reject the aggregate if needed.
- *
- * $onRejected is a function that accepts the rejection reason, iterator index,
- * and the aggregate promise. The callback can invoke any necessary side
- * effects and choose to resolve or reject the aggregate if needed.
- *
- * @param mixed $iterable Iterator or array to iterate over.
- * @param callable $onFulfilled
- * @param callable $onRejected
- *
- * @return PromiseInterface
- *
- * @deprecated each will be removed in guzzlehttp/promises:2.0. Use Each::of instead.
- */
-function each(
- $iterable,
- callable $onFulfilled = null,
- callable $onRejected = null
-) {
- return Each::of($iterable, $onFulfilled, $onRejected);
-}
-
-/**
- * Like each, but only allows a certain number of outstanding promises at any
- * given time.
- *
- * $concurrency may be an integer or a function that accepts the number of
- * pending promises and returns a numeric concurrency limit value to allow for
- * dynamic a concurrency size.
- *
- * @param mixed $iterable
- * @param int|callable $concurrency
- * @param callable $onFulfilled
- * @param callable $onRejected
- *
- * @return PromiseInterface
- *
- * @deprecated each_limit will be removed in guzzlehttp/promises:2.0. Use Each::ofLimit instead.
- */
-function each_limit(
- $iterable,
- $concurrency,
- callable $onFulfilled = null,
- callable $onRejected = null
-) {
- return Each::ofLimit($iterable, $concurrency, $onFulfilled, $onRejected);
-}
-
-/**
- * Like each_limit, but ensures that no promise in the given $iterable argument
- * is rejected. If any promise is rejected, then the aggregate promise is
- * rejected with the encountered rejection.
- *
- * @param mixed $iterable
- * @param int|callable $concurrency
- * @param callable $onFulfilled
- *
- * @return PromiseInterface
- *
- * @deprecated each_limit_all will be removed in guzzlehttp/promises:2.0. Use Each::ofLimitAll instead.
- */
-function each_limit_all(
- $iterable,
- $concurrency,
- callable $onFulfilled = null
-) {
- return Each::ofLimitAll($iterable, $concurrency, $onFulfilled);
-}
-
-/**
- * Returns true if a promise is fulfilled.
- *
- * @return bool
- *
- * @deprecated is_fulfilled will be removed in guzzlehttp/promises:2.0. Use Is::fulfilled instead.
- */
-function is_fulfilled(PromiseInterface $promise)
-{
- return Is::fulfilled($promise);
-}
-
-/**
- * Returns true if a promise is rejected.
- *
- * @return bool
- *
- * @deprecated is_rejected will be removed in guzzlehttp/promises:2.0. Use Is::rejected instead.
- */
-function is_rejected(PromiseInterface $promise)
-{
- return Is::rejected($promise);
-}
-
-/**
- * Returns true if a promise is fulfilled or rejected.
- *
- * @return bool
- *
- * @deprecated is_settled will be removed in guzzlehttp/promises:2.0. Use Is::settled instead.
- */
-function is_settled(PromiseInterface $promise)
-{
- return Is::settled($promise);
-}
-
-/**
- * Create a new coroutine.
- *
- * @see Coroutine
- *
- * @return PromiseInterface
- *
- * @deprecated coroutine will be removed in guzzlehttp/promises:2.0. Use Coroutine::of instead.
- */
-function coroutine(callable $generatorFn)
-{
- return Coroutine::of($generatorFn);
-}
+++ /dev/null
-<?php
-
-// Don't redefine the functions if included multiple times.
-if (!function_exists('GuzzleHttp\Promise\promise_for')) {
- require __DIR__ . '/functions.php';
-}
--- /dev/null
+{
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "friendsofphp/php-cs-fixer": "3.16.0"
+ },
+ "config": {
+ "preferred-install": "dist"
+ }
+}
--- /dev/null
+{
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "phpstan/phpstan": "1.10.11",
+ "phpstan/phpstan-deprecation-rules": "1.1.3"
+ },
+ "config": {
+ "preferred-install": "dist"
+ }
+}
--- /dev/null
+{
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "psalm/phar": "5.9.0"
+ },
+ "config": {
+ "preferred-install": "dist"
+ }
+}