📈 Remove Sentry/GlitchTip
Signed-off-by: Luke Tainton <luke@tainton.uk>
This commit is contained in:
@@ -7,13 +7,6 @@ require_once __DIR__ . "/../vendor/autoload.php";
|
|||||||
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . "/..");
|
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . "/..");
|
||||||
$dotenv->load();
|
$dotenv->load();
|
||||||
|
|
||||||
// GlitchTip
|
|
||||||
Sentry\init([
|
|
||||||
'dsn' => 'https://06f1b7e10e04409686f8ddad61f218ec@logs.tainton.uk/2',
|
|
||||||
'release' => $_ENV['APP_VERSION']
|
|
||||||
]);
|
|
||||||
throw new Exception("Test exception");
|
|
||||||
|
|
||||||
// Session
|
// Session
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"ramsey/uuid": "^4.1",
|
"ramsey/uuid": "^4.1"
|
||||||
"sentry/sdk": "^2.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1865
composer.lock
generated
1865
composer.lock
generated
File diff suppressed because it is too large
Load Diff
2
vendor/clue/stream-filter/.gitignore
vendored
2
vendor/clue/stream-filter/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
/vendor
|
|
||||||
/composer.lock
|
|
||||||
27
vendor/clue/stream-filter/.travis.yml
vendored
27
vendor/clue/stream-filter/.travis.yml
vendored
@@ -1,27 +0,0 @@
|
|||||||
language: php
|
|
||||||
|
|
||||||
php:
|
|
||||||
# - 5.3 # requires old distro, see below
|
|
||||||
- 5.4
|
|
||||||
- 5.5
|
|
||||||
- 5.6
|
|
||||||
- 7.0
|
|
||||||
- 7.1
|
|
||||||
- 7.2
|
|
||||||
- hhvm # ignore errors, see below
|
|
||||||
|
|
||||||
# lock distro so new future defaults will not break the build
|
|
||||||
dist: trusty
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- php: 5.3
|
|
||||||
dist: precise
|
|
||||||
allow_failures:
|
|
||||||
- php: hhvm
|
|
||||||
|
|
||||||
install:
|
|
||||||
- composer install --no-interaction
|
|
||||||
|
|
||||||
script:
|
|
||||||
- vendor/bin/phpunit --coverage-text
|
|
||||||
63
vendor/clue/stream-filter/CHANGELOG.md
vendored
63
vendor/clue/stream-filter/CHANGELOG.md
vendored
@@ -1,63 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## 1.4.1 (2019-04-09)
|
|
||||||
|
|
||||||
* Fix: Check if the function is declared before declaring it.
|
|
||||||
(#23 by @Niko9911)
|
|
||||||
|
|
||||||
* Improve test suite to also test against PHP 7.2 and
|
|
||||||
add test for base64 encoding and decoding filters.
|
|
||||||
(#22 by @arubacao and #25 by @Nyholm and @clue)
|
|
||||||
|
|
||||||
## 1.4.0 (2017-08-18)
|
|
||||||
|
|
||||||
* Feature / Fix: The `fun()` function does not pass filter parameter `null`
|
|
||||||
to underlying `stream_filter_append()` by default
|
|
||||||
(#15 by @Nyholm)
|
|
||||||
|
|
||||||
Certain filters (such as `convert.quoted-printable-encode`) do not accept
|
|
||||||
a filter parameter at all. If no explicit filter parameter is given, we no
|
|
||||||
longer pass a default `null` value.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$encode = Filter\fun('convert.quoted-printable-encode');
|
|
||||||
assert('t=C3=A4st' === $encode('täst'));
|
|
||||||
```
|
|
||||||
|
|
||||||
* Add examples and improve documentation
|
|
||||||
(#13 and #20 by @clue and #18 by @Nyholm)
|
|
||||||
|
|
||||||
* Improve test suite by adding PHPUnit to require-dev,
|
|
||||||
fix HHVM build for now again and ignore future HHVM build errors,
|
|
||||||
lock Travis distro so new future defaults will not break the build
|
|
||||||
and test on PHP 7.1
|
|
||||||
(#12, #14 and #19 by @clue and #16 by @Nyholm)
|
|
||||||
|
|
||||||
## 1.3.0 (2015-11-08)
|
|
||||||
|
|
||||||
* Feature: Support accessing built-in filters as callbacks
|
|
||||||
(#5 by @clue)
|
|
||||||
|
|
||||||
```php
|
|
||||||
$fun = Filter\fun('zlib.deflate');
|
|
||||||
|
|
||||||
$ret = $fun('hello') . $fun('world') . $fun();
|
|
||||||
assert('helloworld' === gzinflate($ret));
|
|
||||||
```
|
|
||||||
|
|
||||||
## 1.2.0 (2015-10-23)
|
|
||||||
|
|
||||||
* Feature: Invoke close event when closing filter (flush buffer)
|
|
||||||
(#9 by @clue)
|
|
||||||
|
|
||||||
## 1.1.0 (2015-10-22)
|
|
||||||
|
|
||||||
* Feature: Abort filter operation when catching an Exception
|
|
||||||
(#10 by @clue)
|
|
||||||
|
|
||||||
* Feature: Additional safeguards to prevent filter state corruption
|
|
||||||
(#7 by @clue)
|
|
||||||
|
|
||||||
## 1.0.0 (2015-10-18)
|
|
||||||
|
|
||||||
* First tagged release
|
|
||||||
21
vendor/clue/stream-filter/LICENSE
vendored
21
vendor/clue/stream-filter/LICENSE
vendored
@@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 Christian Lück
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is furnished
|
|
||||||
to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
301
vendor/clue/stream-filter/README.md
vendored
301
vendor/clue/stream-filter/README.md
vendored
@@ -1,301 +0,0 @@
|
|||||||
# clue/stream-filter [](https://travis-ci.org/clue/php-stream-filter)
|
|
||||||
|
|
||||||
A simple and modern approach to stream filtering in PHP
|
|
||||||
|
|
||||||
**Table of contents**
|
|
||||||
|
|
||||||
* [Why?](#why)
|
|
||||||
* [Usage](#usage)
|
|
||||||
* [append()](#append)
|
|
||||||
* [prepend()](#prepend)
|
|
||||||
* [fun()](#fun)
|
|
||||||
* [remove()](#remove)
|
|
||||||
* [Install](#install)
|
|
||||||
* [Tests](#tests)
|
|
||||||
* [License](#license)
|
|
||||||
|
|
||||||
## Why?
|
|
||||||
|
|
||||||
PHP's stream filtering system is great!
|
|
||||||
|
|
||||||
It offers very powerful stream filtering options and comes with a useful set of built-in filters.
|
|
||||||
These filters can be used to easily and efficiently perform various transformations on-the-fly, such as:
|
|
||||||
|
|
||||||
* read from a gzip'ed input file,
|
|
||||||
* transcode from ISO-8859-1 (Latin1) to UTF-8,
|
|
||||||
* write to a bzip output file
|
|
||||||
* and much more.
|
|
||||||
|
|
||||||
But let's face it:
|
|
||||||
Its API is [*difficult to work with*](https://www.php.net/manual/en/php-user-filter.filter.php)
|
|
||||||
and its documentation is [*subpar*](https://stackoverflow.com/questions/27103269/what-is-a-bucket-brigade).
|
|
||||||
This combined means its powerful features are often neglected.
|
|
||||||
|
|
||||||
This project aims to make these features more accessible to a broader audience.
|
|
||||||
* **Lightweight, SOLID design** -
|
|
||||||
Provides a thin abstraction that is [*just good enough*](https://en.wikipedia.org/wiki/Principle_of_good_enough)
|
|
||||||
and does not get in your way.
|
|
||||||
Custom filters require trivial effort.
|
|
||||||
* **Good test coverage** -
|
|
||||||
Comes with an automated tests suite and is regularly tested in the *real world*
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
This lightweight library consists only of a few simple functions.
|
|
||||||
All functions reside under the `Clue\StreamFilter` namespace.
|
|
||||||
|
|
||||||
The below examples assume you use an import statement similar to this:
|
|
||||||
|
|
||||||
```php
|
|
||||||
use Clue\StreamFilter as Filter;
|
|
||||||
|
|
||||||
Filter\append(…);
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can also refer to them with their fully-qualified name:
|
|
||||||
|
|
||||||
```php
|
|
||||||
\Clue\StreamFilter\append(…);
|
|
||||||
```
|
|
||||||
|
|
||||||
### append()
|
|
||||||
|
|
||||||
The `append($stream, $callback, $read_write = STREAM_FILTER_ALL)` function can be used to
|
|
||||||
append a filter callback to the given stream.
|
|
||||||
|
|
||||||
Each stream can have a list of filters attached.
|
|
||||||
This function appends a filter to the end of this list.
|
|
||||||
|
|
||||||
This function returns a filter resource which can be passed to [`remove()`](#remove).
|
|
||||||
If the given filter can not be added, it throws an `Exception`.
|
|
||||||
|
|
||||||
The `$stream` can be any valid stream resource, such as:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$stream = fopen('demo.txt', 'w+');
|
|
||||||
```
|
|
||||||
|
|
||||||
The `$callback` should be a valid callable function which accepts an individual chunk of data
|
|
||||||
and should return the updated chunk:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$filter = Filter\append($stream, function ($chunk) {
|
|
||||||
// will be called each time you read or write a $chunk to/from the stream
|
|
||||||
return $chunk;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
As such, you can also use native PHP functions or any other `callable`:
|
|
||||||
|
|
||||||
```php
|
|
||||||
Filter\append($stream, 'strtoupper');
|
|
||||||
|
|
||||||
// will write "HELLO" to the underlying stream
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
```
|
|
||||||
|
|
||||||
If the `$callback` accepts invocation without parameters, then this signature
|
|
||||||
will be invoked once ending (flushing) the filter:
|
|
||||||
|
|
||||||
```php
|
|
||||||
Filter\append($stream, function ($chunk = null) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
// will be called once ending the filter
|
|
||||||
return 'end';
|
|
||||||
}
|
|
||||||
// will be called each time you read or write a $chunk to/from the stream
|
|
||||||
return $chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note: Legacy PHP versions (PHP < 5.4) do not support passing additional data
|
|
||||||
from the end signal handler if the stream is being closed.
|
|
||||||
|
|
||||||
If your callback throws an `Exception`, then the filter process will be aborted.
|
|
||||||
In order to play nice with PHP's stream handling, the `Exception` will be
|
|
||||||
transformed to a PHP warning instead:
|
|
||||||
|
|
||||||
```php
|
|
||||||
Filter\append($stream, function ($chunk) {
|
|
||||||
throw new \RuntimeException('Unexpected chunk');
|
|
||||||
});
|
|
||||||
|
|
||||||
// raises an E_USER_WARNING with "Error invoking filter: Unexpected chunk"
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
```
|
|
||||||
|
|
||||||
The optional `$read_write` parameter can be used to only invoke the `$callback` when either writing to the stream or only when reading from the stream:
|
|
||||||
|
|
||||||
```php
|
|
||||||
Filter\append($stream, function ($chunk) {
|
|
||||||
// will be called each time you write to the stream
|
|
||||||
return $chunk;
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
Filter\append($stream, function ($chunk) {
|
|
||||||
// will be called each time you read from the stream
|
|
||||||
return $chunk;
|
|
||||||
}, STREAM_FILTER_READ);
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note that once a filter has been added to stream, the stream can no longer be passed to
|
|
||||||
> [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php)
|
|
||||||
> (and family).
|
|
||||||
>
|
|
||||||
> > Warning: stream_select(): cannot cast a filtered stream on this system in {file} on line {line}
|
|
||||||
>
|
|
||||||
> This is due to limitations of PHP's stream filter support, as it can no longer reliably
|
|
||||||
> tell when the underlying stream resource is actually ready.
|
|
||||||
> As an alternative, consider calling `stream_select()` on the unfiltered stream and
|
|
||||||
> then pass the unfiltered data through the [`fun()`](#fun) function.
|
|
||||||
|
|
||||||
### prepend()
|
|
||||||
|
|
||||||
The `prepend($stream, $callback, $read_write = STREAM_FILTER_ALL)` function can be used to
|
|
||||||
prepend a filter callback to the given stream.
|
|
||||||
|
|
||||||
Each stream can have a list of filters attached.
|
|
||||||
This function prepends a filter to the start of this list.
|
|
||||||
|
|
||||||
This function returns a filter resource which can be passed to [`remove()`](#remove).
|
|
||||||
If the given filter can not be added, it throws an `Exception`.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$filter = Filter\prepend($stream, function ($chunk) {
|
|
||||||
// will be called each time you read or write a $chunk to/from the stream
|
|
||||||
return $chunk;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Except for the position in the list of filters, this function behaves exactly
|
|
||||||
like the [`append()`](#append) function.
|
|
||||||
For more details about its behavior, see also the [`append()`](#append) function.
|
|
||||||
|
|
||||||
### fun()
|
|
||||||
|
|
||||||
The `fun($filter, $parameters = null)` function can be used to
|
|
||||||
create a filter function which uses the given built-in `$filter`.
|
|
||||||
|
|
||||||
PHP comes with a useful set of [built-in filters](https://www.php.net/manual/en/filters.php).
|
|
||||||
Using `fun()` makes accessing these as easy as passing an input string to filter
|
|
||||||
and getting the filtered output string.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$fun = Filter\fun('string.rot13');
|
|
||||||
|
|
||||||
assert('grfg' === $fun('test'));
|
|
||||||
assert('test' === $fun($fun('test'));
|
|
||||||
```
|
|
||||||
|
|
||||||
Please note that not all filter functions may be available depending on installed
|
|
||||||
PHP extensions and the PHP version in use.
|
|
||||||
In particular, [HHVM](https://hhvm.com/) may not offer the same filter functions
|
|
||||||
or parameters as Zend PHP.
|
|
||||||
Accessing an unknown filter function will result in a `RuntimeException`:
|
|
||||||
|
|
||||||
```php
|
|
||||||
Filter\fun('unknown'); // throws RuntimeException
|
|
||||||
```
|
|
||||||
|
|
||||||
Some filters may accept or require additional filter parameters – most
|
|
||||||
filters do not require filter parameters.
|
|
||||||
If given, the optional `$parameters` argument will be passed to the
|
|
||||||
underlying filter handler as-is.
|
|
||||||
In particular, note how *not passing* this parameter at all differs from
|
|
||||||
explicitly passing a `null` value (which many filters do not accept).
|
|
||||||
Please refer to the individual filter definition for more details.
|
|
||||||
For example, the `string.strip_tags` filter can be invoked like this:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$fun = Filter\fun('string.strip_tags', '<a><b>');
|
|
||||||
|
|
||||||
$ret = $fun('<b>h<br>i</b>');
|
|
||||||
assert('<b>hi</b>' === $ret);
|
|
||||||
```
|
|
||||||
|
|
||||||
Under the hood, this function allocates a temporary memory stream, so it's
|
|
||||||
recommended to clean up the filter function after use.
|
|
||||||
Also, some filter functions (in particular the
|
|
||||||
[zlib compression filters](https://www.php.net/manual/en/filters.compression.php))
|
|
||||||
may use internal buffers and may emit a final data chunk on close.
|
|
||||||
The filter function can be closed by invoking without any arguments:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$fun = Filter\fun('zlib.deflate');
|
|
||||||
|
|
||||||
$ret = $fun('hello') . $fun('world') . $fun();
|
|
||||||
assert('helloworld' === gzinflate($ret));
|
|
||||||
```
|
|
||||||
|
|
||||||
The filter function must not be used anymore after it has been closed.
|
|
||||||
Doing so will result in a `RuntimeException`:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$fun = Filter\fun('string.rot13');
|
|
||||||
$fun();
|
|
||||||
|
|
||||||
$fun('test'); // throws RuntimeException
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note: If you're using the zlib compression filters, then you should be wary
|
|
||||||
about engine inconsistencies between different PHP versions and HHVM.
|
|
||||||
These inconsistencies exist in the underlying PHP engines and there's little we
|
|
||||||
can do about this in this library.
|
|
||||||
[Our test suite](tests/) contains several test cases that exhibit these issues.
|
|
||||||
If you feel some test case is missing or outdated, we're happy to accept PRs! :)
|
|
||||||
|
|
||||||
### remove()
|
|
||||||
|
|
||||||
The `remove($filter)` function can be used to
|
|
||||||
remove a filter previously added via [`append()`](#append) or [`prepend()`](#prepend).
|
|
||||||
|
|
||||||
```php
|
|
||||||
$filter = Filter\append($stream, function () {
|
|
||||||
// …
|
|
||||||
});
|
|
||||||
Filter\remove($filter);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
The recommended way to install this library is [through Composer](https://getcomposer.org).
|
|
||||||
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
|
|
||||||
|
|
||||||
This project follows [SemVer](https://semver.org/).
|
|
||||||
This will install the latest supported version:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ composer require clue/stream-filter:^1.4.1
|
|
||||||
```
|
|
||||||
|
|
||||||
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
|
|
||||||
|
|
||||||
This project aims to run on any platform and thus does not require any PHP
|
|
||||||
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
|
|
||||||
HHVM.
|
|
||||||
It's *highly recommended to use PHP 7+* for this project.
|
|
||||||
Older PHP versions may suffer from a number of inconsistencies documented above.
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
To run the test suite, you first need to clone this repo and then install all
|
|
||||||
dependencies [through Composer](https://getcomposer.org):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ composer install
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the test suite, go to the project root and run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ php vendor/bin/phpunit
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is released under the permissive [MIT license](LICENSE).
|
|
||||||
|
|
||||||
> Did you know that I offer custom development services and issuing invoices for
|
|
||||||
sponsorships of releases and for contributions? Contact me (@clue) for details.
|
|
||||||
23
vendor/clue/stream-filter/composer.json
vendored
23
vendor/clue/stream-filter/composer.json
vendored
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "clue/stream-filter",
|
|
||||||
"description": "A simple and modern approach to stream filtering in PHP",
|
|
||||||
"keywords": ["stream", "callback", "filter", "php_user_filter", "stream_filter_append", "stream_filter_register", "bucket brigade"],
|
|
||||||
"homepage": "https://github.com/clue/php-stream-filter",
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Christian Lück",
|
|
||||||
"email": "christian@lueck.tv"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^5.0 || ^4.8"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": { "Clue\\StreamFilter\\": "src/" },
|
|
||||||
"files": [ "src/functions_include.php" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// $ echo test | php examples/base64_encode.php | php examples/base64_decode.php
|
|
||||||
|
|
||||||
require __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
// decoding requires buffering in chunks of 4 bytes each
|
|
||||||
$buffer = '';
|
|
||||||
Clue\StreamFilter\append(STDIN, function ($chunk = null) use (&$buffer) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
if (strlen($buffer) % 4 !== 0) {
|
|
||||||
throw new \UnexpectedValueException('Invalid length');
|
|
||||||
}
|
|
||||||
$chunk = $buffer;
|
|
||||||
} else {
|
|
||||||
$buffer .= $chunk;
|
|
||||||
$len = strlen($buffer) - (strlen($buffer) % 4);
|
|
||||||
$chunk = (string)substr($buffer, 0, $len);
|
|
||||||
$buffer = (string)substr($buffer, $len);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret = base64_decode($chunk, true);
|
|
||||||
if ($ret === false) {
|
|
||||||
throw new \UnexpectedValueException('Not a valid base64 encoded chunk');
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}, STREAM_FILTER_READ);
|
|
||||||
|
|
||||||
fpassthru(STDIN);
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// $ echo test | php examples/base64_encode.php | base64 --decode
|
|
||||||
|
|
||||||
require __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
// encoding requires buffering in chunks of 3 bytes each
|
|
||||||
$buffer = '';
|
|
||||||
Clue\StreamFilter\append(STDIN, function ($chunk = null) use (&$buffer) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
return base64_encode($buffer);
|
|
||||||
}
|
|
||||||
$buffer .= $chunk;
|
|
||||||
$len = strlen($buffer) - (strlen($buffer) % 3);
|
|
||||||
$chunk = substr($buffer, 0, $len);
|
|
||||||
$buffer = substr($buffer, $len);
|
|
||||||
|
|
||||||
return base64_encode($chunk);
|
|
||||||
}, STREAM_FILTER_READ);
|
|
||||||
|
|
||||||
fpassthru(STDIN);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// $ echo test | php examples/uppercase.php
|
|
||||||
|
|
||||||
require __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
Clue\StreamFilter\append(STDIN, 'strtoupper');
|
|
||||||
|
|
||||||
fpassthru(STDIN);
|
|
||||||
19
vendor/clue/stream-filter/phpunit.xml.dist
vendored
19
vendor/clue/stream-filter/phpunit.xml.dist
vendored
@@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<phpunit bootstrap="vendor/autoload.php"
|
|
||||||
colors="true"
|
|
||||||
convertErrorsToExceptions="true"
|
|
||||||
convertNoticesToExceptions="true"
|
|
||||||
convertWarningsToExceptions="true"
|
|
||||||
>
|
|
||||||
<testsuites>
|
|
||||||
<testsuite>
|
|
||||||
<directory>./tests/</directory>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
<filter>
|
|
||||||
<whitelist>
|
|
||||||
<directory>./src/</directory>
|
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
</phpunit>
|
|
||||||
120
vendor/clue/stream-filter/src/CallbackFilter.php
vendored
120
vendor/clue/stream-filter/src/CallbackFilter.php
vendored
@@ -1,120 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Clue\StreamFilter;
|
|
||||||
|
|
||||||
use php_user_filter;
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use ReflectionFunction;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
* @see append()
|
|
||||||
* @see prepend()
|
|
||||||
*/
|
|
||||||
class CallbackFilter extends php_user_filter
|
|
||||||
{
|
|
||||||
private $callback;
|
|
||||||
private $closed = true;
|
|
||||||
private $supportsClose = false;
|
|
||||||
|
|
||||||
public function onCreate()
|
|
||||||
{
|
|
||||||
$this->closed = false;
|
|
||||||
|
|
||||||
if (!is_callable($this->params)) {
|
|
||||||
throw new InvalidArgumentException('No valid callback parameter given to stream_filter_(append|prepend)');
|
|
||||||
}
|
|
||||||
$this->callback = $this->params;
|
|
||||||
|
|
||||||
// callback supports end event if it accepts invocation without arguments
|
|
||||||
$ref = new ReflectionFunction($this->callback);
|
|
||||||
$this->supportsClose = ($ref->getNumberOfRequiredParameters() === 0);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onClose()
|
|
||||||
{
|
|
||||||
$this->closed = true;
|
|
||||||
|
|
||||||
// callback supports closing and is not already closed
|
|
||||||
if ($this->supportsClose) {
|
|
||||||
$this->supportsClose = false;
|
|
||||||
// invoke without argument to signal end and discard resulting buffer
|
|
||||||
try {
|
|
||||||
call_user_func($this->callback);
|
|
||||||
} catch (Exception $ignored) {
|
|
||||||
// this might be called during engine shutdown, so it's not safe
|
|
||||||
// to raise any errors or exceptions here
|
|
||||||
// trigger_error('Error closing filter: ' . $ignored->getMessage(), E_USER_WARNING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->callback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filter($in, $out, &$consumed, $closing)
|
|
||||||
{
|
|
||||||
// concatenate whole buffer from input brigade
|
|
||||||
$data = '';
|
|
||||||
while ($bucket = stream_bucket_make_writeable($in)) {
|
|
||||||
$consumed += $bucket->datalen;
|
|
||||||
$data .= $bucket->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip processing callback that already ended
|
|
||||||
if ($this->closed) {
|
|
||||||
return PSFS_FEED_ME;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only invoke filter function if buffer is not empty
|
|
||||||
// this may skip flushing a closing filter
|
|
||||||
if ($data !== '') {
|
|
||||||
try {
|
|
||||||
$data = call_user_func($this->callback, $data);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// exception should mark filter as closed
|
|
||||||
$this->onClose();
|
|
||||||
trigger_error('Error invoking filter: ' . $e->getMessage(), E_USER_WARNING);
|
|
||||||
|
|
||||||
return PSFS_ERR_FATAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark filter as closed after processing closing chunk
|
|
||||||
if ($closing) {
|
|
||||||
$this->closed = true;
|
|
||||||
|
|
||||||
// callback supports closing and is not already closed
|
|
||||||
if ($this->supportsClose) {
|
|
||||||
$this->supportsClose = false;
|
|
||||||
|
|
||||||
// invoke without argument to signal end and append resulting buffer
|
|
||||||
try {
|
|
||||||
$data .= call_user_func($this->callback);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
trigger_error('Error ending filter: ' . $e->getMessage(), E_USER_WARNING);
|
|
||||||
|
|
||||||
return PSFS_ERR_FATAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($data !== '') {
|
|
||||||
// create a new bucket for writing the resulting buffer to the output brigade
|
|
||||||
// reusing an existing bucket turned out to be bugged in some environments (ancient PHP versions and HHVM)
|
|
||||||
$bucket = @stream_bucket_new($this->stream, $data);
|
|
||||||
|
|
||||||
// legacy PHP versions (PHP < 5.4) do not support passing data from the event signal handler
|
|
||||||
// because closing the stream invalidates the stream and its stream bucket brigade before
|
|
||||||
// invoking the filter close handler.
|
|
||||||
if ($bucket !== false) {
|
|
||||||
stream_bucket_append($out, $bucket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PSFS_PASS_ON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
146
vendor/clue/stream-filter/src/functions.php
vendored
146
vendor/clue/stream-filter/src/functions.php
vendored
@@ -1,146 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Clue\StreamFilter;
|
|
||||||
|
|
||||||
use RuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* append a callback filter to the given stream
|
|
||||||
*
|
|
||||||
* @param resource $stream
|
|
||||||
* @param callable $callback
|
|
||||||
* @param int $read_write
|
|
||||||
* @return resource filter resource which can be used for `remove()`
|
|
||||||
* @throws Exception on error
|
|
||||||
* @uses stream_filter_append()
|
|
||||||
*/
|
|
||||||
function append($stream, $callback, $read_write = STREAM_FILTER_ALL)
|
|
||||||
{
|
|
||||||
$ret = @stream_filter_append($stream, register(), $read_write, $callback);
|
|
||||||
|
|
||||||
if ($ret === false) {
|
|
||||||
$error = error_get_last() + array('message' => '');
|
|
||||||
throw new RuntimeException('Unable to append filter: ' . $error['message']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* prepend a callback filter to the given stream
|
|
||||||
*
|
|
||||||
* @param resource $stream
|
|
||||||
* @param callable $callback
|
|
||||||
* @param int $read_write
|
|
||||||
* @return resource filter resource which can be used for `remove()`
|
|
||||||
* @throws Exception on error
|
|
||||||
* @uses stream_filter_prepend()
|
|
||||||
*/
|
|
||||||
function prepend($stream, $callback, $read_write = STREAM_FILTER_ALL)
|
|
||||||
{
|
|
||||||
$ret = @stream_filter_prepend($stream, register(), $read_write, $callback);
|
|
||||||
|
|
||||||
if ($ret === false) {
|
|
||||||
$error = error_get_last() + array('message' => '');
|
|
||||||
throw new RuntimeException('Unable to prepend filter: ' . $error['message']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates filter fun (function) which uses the given built-in $filter
|
|
||||||
*
|
|
||||||
* Some filters may accept or require additional filter parameters – most
|
|
||||||
* filters do not require filter parameters.
|
|
||||||
* If given, the optional `$parameters` argument will be passed to the
|
|
||||||
* underlying filter handler as-is.
|
|
||||||
* In particular, note how *not passing* this parameter at all differs from
|
|
||||||
* explicitly passing a `null` value (which many filters do not accept).
|
|
||||||
* Please refer to the individual filter definition for more details.
|
|
||||||
*
|
|
||||||
* @param string $filter built-in filter name. See stream_get_filters() or http://php.net/manual/en/filters.php
|
|
||||||
* @param mixed $parameters (optional) parameters to pass to the built-in filter as-is
|
|
||||||
* @return callable a filter callback which can be append()'ed or prepend()'ed
|
|
||||||
* @throws RuntimeException on error
|
|
||||||
* @link http://php.net/manual/en/filters.php
|
|
||||||
* @see stream_get_filters()
|
|
||||||
* @see append()
|
|
||||||
*/
|
|
||||||
function fun($filter, $parameters = null)
|
|
||||||
{
|
|
||||||
$fp = fopen('php://memory', 'w');
|
|
||||||
if (func_num_args() === 1) {
|
|
||||||
$filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE);
|
|
||||||
} else {
|
|
||||||
$filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE, $parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($filter === false) {
|
|
||||||
fclose($fp);
|
|
||||||
$error = error_get_last() + array('message' => '');
|
|
||||||
throw new RuntimeException('Unable to access built-in filter: ' . $error['message']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// append filter function which buffers internally
|
|
||||||
$buffer = '';
|
|
||||||
append($fp, function ($chunk) use (&$buffer) {
|
|
||||||
$buffer .= $chunk;
|
|
||||||
|
|
||||||
// always return empty string in order to skip actually writing to stream resource
|
|
||||||
return '';
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
$closed = false;
|
|
||||||
|
|
||||||
return function ($chunk = null) use ($fp, $filter, &$buffer, &$closed) {
|
|
||||||
if ($closed) {
|
|
||||||
throw new \RuntimeException('Unable to perform operation on closed stream');
|
|
||||||
}
|
|
||||||
if ($chunk === null) {
|
|
||||||
$closed = true;
|
|
||||||
$buffer = '';
|
|
||||||
fclose($fp);
|
|
||||||
return $buffer;
|
|
||||||
}
|
|
||||||
// initialize buffer and invoke filters by attempting to write to stream
|
|
||||||
$buffer = '';
|
|
||||||
fwrite($fp, $chunk);
|
|
||||||
|
|
||||||
// buffer now contains everything the filter function returned
|
|
||||||
return $buffer;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove a callback filter from the given stream
|
|
||||||
*
|
|
||||||
* @param resource $filter
|
|
||||||
* @return boolean true on success or false on error
|
|
||||||
* @throws Exception on error
|
|
||||||
* @uses stream_filter_remove()
|
|
||||||
*/
|
|
||||||
function remove($filter)
|
|
||||||
{
|
|
||||||
if (@stream_filter_remove($filter) === false) {
|
|
||||||
throw new RuntimeException('Unable to remove given filter');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* registers the callback filter and returns the resulting filter name
|
|
||||||
*
|
|
||||||
* There should be little reason to call this function manually.
|
|
||||||
*
|
|
||||||
* @return string filter name
|
|
||||||
* @uses CallbackFilter
|
|
||||||
*/
|
|
||||||
function register()
|
|
||||||
{
|
|
||||||
static $registered = null;
|
|
||||||
if ($registered === null) {
|
|
||||||
$registered = 'stream-callback';
|
|
||||||
stream_filter_register($registered, __NAMESPACE__ . '\CallbackFilter');
|
|
||||||
}
|
|
||||||
return $registered;
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
if (!function_exists('Clue\\StreamFilter\\append')) {
|
|
||||||
require __DIR__ . '/functions.php';
|
|
||||||
}
|
|
||||||
386
vendor/clue/stream-filter/tests/FilterTest.php
vendored
386
vendor/clue/stream-filter/tests/FilterTest.php
vendored
@@ -1,386 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Clue\StreamFilter;
|
|
||||||
|
|
||||||
class FilterTest extends PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testAppendSimpleCallback()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) {
|
|
||||||
return strtoupper($chunk);
|
|
||||||
});
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
fwrite($stream, 'world');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('HELLOWORLD', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendNativePhpFunction()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, 'strtoupper');
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
fwrite($stream, 'world');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('HELLOWORLD', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendChangingChunkSize()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) {
|
|
||||||
return str_replace(array('a','e','i','o','u'), '', $chunk);
|
|
||||||
});
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
fwrite($stream, 'world');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('hllwrld', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendReturningEmptyStringWillNotPassThrough()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) {
|
|
||||||
return '';
|
|
||||||
});
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
fwrite($stream, 'world');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendEndEventCanBeBufferedOnClose()
|
|
||||||
{
|
|
||||||
if (PHP_VERSION < 5.4) $this->markTestSkipped('Not supported on legacy PHP');
|
|
||||||
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk = null) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
// this signals the end event
|
|
||||||
return '!';
|
|
||||||
}
|
|
||||||
return $chunk . ' ';
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
$buffered = '';
|
|
||||||
StreamFilter\append($stream, function ($chunk) use (&$buffered) {
|
|
||||||
$buffered .= $chunk;
|
|
||||||
return '';
|
|
||||||
});
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
fwrite($stream, 'world');
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('hello world !', $buffered);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendEndEventWillBeCalledOnRemove()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
$ended = false;
|
|
||||||
$filter = StreamFilter\append($stream, function ($chunk = null) use (&$ended) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
$ended = true;
|
|
||||||
}
|
|
||||||
return $chunk;
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
$this->assertEquals(0, $ended);
|
|
||||||
StreamFilter\remove($filter);
|
|
||||||
$this->assertEquals(1, $ended);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendEndEventWillBeCalledOnClose()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
$ended = false;
|
|
||||||
StreamFilter\append($stream, function ($chunk = null) use (&$ended) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
$ended = true;
|
|
||||||
}
|
|
||||||
return $chunk;
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
$this->assertEquals(0, $ended);
|
|
||||||
fclose($stream);
|
|
||||||
$this->assertEquals(1, $ended);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendWriteOnly()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
$invoked = 0;
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) use (&$invoked) {
|
|
||||||
++$invoked;
|
|
||||||
|
|
||||||
return $chunk;
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
fwrite($stream, 'a');
|
|
||||||
fwrite($stream, 'b');
|
|
||||||
fwrite($stream, 'c');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals(3, $invoked);
|
|
||||||
$this->assertEquals('abc', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendReadOnly()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
$invoked = 0;
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) use (&$invoked) {
|
|
||||||
++$invoked;
|
|
||||||
|
|
||||||
return $chunk;
|
|
||||||
}, STREAM_FILTER_READ);
|
|
||||||
|
|
||||||
fwrite($stream, 'a');
|
|
||||||
fwrite($stream, 'b');
|
|
||||||
fwrite($stream, 'c');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals(0, $invoked);
|
|
||||||
$this->assertEquals('abc', stream_get_contents($stream));
|
|
||||||
$this->assertEquals(1, $invoked);
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testOrderCallingAppendAfterPrepend()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) {
|
|
||||||
return '[' . $chunk . ']';
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
StreamFilter\prepend($stream, function ($chunk) {
|
|
||||||
return '(' . $chunk . ')';
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('[(hello)]', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRemoveFilter()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
$first = StreamFilter\append($stream, function ($chunk) {
|
|
||||||
return $chunk . '?';
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) {
|
|
||||||
return $chunk . '!';
|
|
||||||
}, STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
StreamFilter\remove($first);
|
|
||||||
|
|
||||||
fwrite($stream, 'hello');
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('hello!', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendFunDechunk()
|
|
||||||
{
|
|
||||||
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (dechunk filter does not exist)');
|
|
||||||
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, StreamFilter\fun('dechunk'), STREAM_FILTER_WRITE);
|
|
||||||
|
|
||||||
fwrite($stream, "2\r\nhe\r\n");
|
|
||||||
fwrite($stream, "3\r\nllo\r\n");
|
|
||||||
fwrite($stream, "0\r\n\r\n");
|
|
||||||
rewind($stream);
|
|
||||||
|
|
||||||
$this->assertEquals('hello', stream_get_contents($stream));
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendThrows()
|
|
||||||
{
|
|
||||||
$this->createErrorHandler($errors);
|
|
||||||
|
|
||||||
$stream = $this->createStream();
|
|
||||||
$this->createErrorHandler($errors);
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk) {
|
|
||||||
throw new \DomainException($chunk);
|
|
||||||
});
|
|
||||||
|
|
||||||
fwrite($stream, 'test');
|
|
||||||
|
|
||||||
$this->removeErrorHandler();
|
|
||||||
$this->assertCount(1, $errors);
|
|
||||||
$this->assertContains('test', $errors[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendThrowsDuringEnd()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
$this->createErrorHandler($errors);
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk = null) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
throw new \DomainException('end');
|
|
||||||
}
|
|
||||||
return $chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
fclose($stream);
|
|
||||||
|
|
||||||
$this->removeErrorHandler();
|
|
||||||
|
|
||||||
// We can only assert we're not seeing an exception here…
|
|
||||||
// * php 5.3-5.6 sees one error here
|
|
||||||
// * php 7 does not see any error here
|
|
||||||
// * hhvm sees the same error twice
|
|
||||||
//
|
|
||||||
// If you're curious:
|
|
||||||
//
|
|
||||||
// var_dump($errors);
|
|
||||||
// $this->assertCount(1, $errors);
|
|
||||||
// $this->assertContains('end', $errors[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendThrowsShouldTriggerEnd()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
$this->createErrorHandler($errors);
|
|
||||||
|
|
||||||
$ended = false;
|
|
||||||
StreamFilter\append($stream, function ($chunk = null) use (&$ended) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
$ended = true;
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
throw new \DomainException($chunk);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->assertEquals(false, $ended);
|
|
||||||
fwrite($stream, 'test');
|
|
||||||
$this->assertEquals(true, $ended);
|
|
||||||
|
|
||||||
$this->removeErrorHandler();
|
|
||||||
$this->assertCount(1, $errors);
|
|
||||||
$this->assertContains('test', $errors[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAppendThrowsShouldTriggerEndButIgnoreExceptionDuringEnd()
|
|
||||||
{
|
|
||||||
//$this->markTestIncomplete();
|
|
||||||
$stream = $this->createStream();
|
|
||||||
$this->createErrorHandler($errors);
|
|
||||||
|
|
||||||
StreamFilter\append($stream, function ($chunk = null) {
|
|
||||||
if ($chunk === null) {
|
|
||||||
$chunk = 'end';
|
|
||||||
//return '';
|
|
||||||
}
|
|
||||||
throw new \DomainException($chunk);
|
|
||||||
});
|
|
||||||
|
|
||||||
fwrite($stream, 'test');
|
|
||||||
|
|
||||||
$this->removeErrorHandler();
|
|
||||||
$this->assertCount(1, $errors);
|
|
||||||
$this->assertContains('test', $errors[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException RuntimeException
|
|
||||||
*/
|
|
||||||
public function testAppendInvalidStreamIsRuntimeError()
|
|
||||||
{
|
|
||||||
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (does not reject invalid stream)');
|
|
||||||
StreamFilter\append(false, function () { });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException RuntimeException
|
|
||||||
*/
|
|
||||||
public function testPrependInvalidStreamIsRuntimeError()
|
|
||||||
{
|
|
||||||
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (does not reject invalid stream)');
|
|
||||||
StreamFilter\prepend(false, function () { });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException RuntimeException
|
|
||||||
*/
|
|
||||||
public function testRemoveInvalidFilterIsRuntimeError()
|
|
||||||
{
|
|
||||||
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (does not reject invalid filters)');
|
|
||||||
StreamFilter\remove(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function testInvalidCallbackIsInvalidArgument()
|
|
||||||
{
|
|
||||||
$stream = $this->createStream();
|
|
||||||
|
|
||||||
StreamFilter\append($stream, 'a-b-c');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createStream()
|
|
||||||
{
|
|
||||||
return fopen('php://memory', 'r+');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createErrorHandler(&$errors)
|
|
||||||
{
|
|
||||||
$errors = array();
|
|
||||||
set_error_handler(function ($_, $message) use (&$errors) {
|
|
||||||
$errors []= $message;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private function removeErrorHandler()
|
|
||||||
{
|
|
||||||
restore_error_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
61
vendor/clue/stream-filter/tests/FunTest.php
vendored
61
vendor/clue/stream-filter/tests/FunTest.php
vendored
@@ -1,61 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Clue\StreamFilter as Filter;
|
|
||||||
|
|
||||||
class FunTest extends PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testFunInRot13()
|
|
||||||
{
|
|
||||||
$rot = Filter\fun('string.rot13');
|
|
||||||
|
|
||||||
$this->assertEquals('grfg', $rot('test'));
|
|
||||||
$this->assertEquals('test', $rot($rot('test')));
|
|
||||||
$this->assertEquals(null, $rot());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunInQuotedPrintable()
|
|
||||||
{
|
|
||||||
$encode = Filter\fun('convert.quoted-printable-encode');
|
|
||||||
$decode = Filter\fun('convert.quoted-printable-decode');
|
|
||||||
|
|
||||||
$this->assertEquals('t=C3=A4st', $encode('täst'));
|
|
||||||
$this->assertEquals('täst', $decode($encode('täst')));
|
|
||||||
$this->assertEquals(null, $encode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException RuntimeException
|
|
||||||
*/
|
|
||||||
public function testFunWriteAfterCloseRot13()
|
|
||||||
{
|
|
||||||
$rot = Filter\fun('string.rot13');
|
|
||||||
|
|
||||||
$this->assertEquals(null, $rot());
|
|
||||||
$rot('test');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException RuntimeException
|
|
||||||
*/
|
|
||||||
public function testFunInvalid()
|
|
||||||
{
|
|
||||||
Filter\fun('unknown');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunInBase64()
|
|
||||||
{
|
|
||||||
$encode = Filter\fun('convert.base64-encode');
|
|
||||||
$decode = Filter\fun('convert.base64-decode');
|
|
||||||
|
|
||||||
$string = 'test';
|
|
||||||
$this->assertEquals(base64_encode($string), $encode($string) . $encode());
|
|
||||||
$this->assertEquals($string, $decode(base64_encode($string)));
|
|
||||||
|
|
||||||
$encode = Filter\fun('convert.base64-encode');
|
|
||||||
$decode = Filter\fun('convert.base64-decode');
|
|
||||||
$this->assertEquals($string, $decode($encode($string) . $encode()));
|
|
||||||
|
|
||||||
$encode = Filter\fun('convert.base64-encode');
|
|
||||||
$this->assertEquals(null, $encode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
79
vendor/clue/stream-filter/tests/FunZlibTest.php
vendored
79
vendor/clue/stream-filter/tests/FunZlibTest.php
vendored
@@ -1,79 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Clue\StreamFilter;
|
|
||||||
|
|
||||||
class BuiltInZlibTest extends PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testFunZlibDeflateHelloWorld()
|
|
||||||
{
|
|
||||||
$deflate = StreamFilter\fun('zlib.deflate');
|
|
||||||
|
|
||||||
$data = $deflate('hello') . $deflate(' ') . $deflate('world') . $deflate();
|
|
||||||
|
|
||||||
$this->assertEquals(gzdeflate('hello world'), $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunZlibDeflateEmpty()
|
|
||||||
{
|
|
||||||
if (PHP_VERSION >= 7) $this->markTestSkipped('Not supported on PHP7 (empty string does not invoke filter)');
|
|
||||||
|
|
||||||
$deflate = StreamFilter\fun('zlib.deflate');
|
|
||||||
|
|
||||||
//$data = gzdeflate('');
|
|
||||||
$data = $deflate();
|
|
||||||
|
|
||||||
$this->assertEquals("\x03\x00", $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunZlibDeflateBig()
|
|
||||||
{
|
|
||||||
$deflate = StreamFilter\fun('zlib.deflate');
|
|
||||||
|
|
||||||
$n = 1000;
|
|
||||||
$expected = str_repeat('hello', $n);
|
|
||||||
|
|
||||||
$bytes = '';
|
|
||||||
for ($i = 0; $i < $n; ++$i) {
|
|
||||||
$bytes .= $deflate('hello');
|
|
||||||
}
|
|
||||||
$bytes .= $deflate();
|
|
||||||
|
|
||||||
$this->assertEquals($expected, gzinflate($bytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunZlibInflateHelloWorld()
|
|
||||||
{
|
|
||||||
$inflate = StreamFilter\fun('zlib.inflate');
|
|
||||||
|
|
||||||
$data = $inflate(gzdeflate('hello world')) . $inflate();
|
|
||||||
|
|
||||||
$this->assertEquals('hello world', $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunZlibInflateEmpty()
|
|
||||||
{
|
|
||||||
$inflate = StreamFilter\fun('zlib.inflate');
|
|
||||||
|
|
||||||
$data = $inflate("\x03\x00") . $inflate();
|
|
||||||
|
|
||||||
$this->assertEquals('', $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFunZlibInflateBig()
|
|
||||||
{
|
|
||||||
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (final chunk will not be emitted)');
|
|
||||||
|
|
||||||
$inflate = StreamFilter\fun('zlib.inflate');
|
|
||||||
|
|
||||||
$expected = str_repeat('hello', 10);
|
|
||||||
$bytes = gzdeflate($expected);
|
|
||||||
|
|
||||||
$ret = '';
|
|
||||||
foreach (str_split($bytes, 2) as $chunk) {
|
|
||||||
$ret .= $inflate($chunk);
|
|
||||||
}
|
|
||||||
$ret .= $inflate();
|
|
||||||
|
|
||||||
$this->assertEquals($expected, $ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
vendor/composer/autoload_classmap.php
vendored
11
vendor/composer/autoload_classmap.php
vendored
@@ -6,15 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||||||
$baseDir = dirname($vendorDir);
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'ArithmeticError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php',
|
|
||||||
'AssertionError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php',
|
|
||||||
'DivisionByZeroError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php',
|
|
||||||
'Error' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/Error.php',
|
|
||||||
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
|
||||||
'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
|
|
||||||
'SessionUpdateTimestampHandlerInterface' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php',
|
|
||||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
|
||||||
'TypeError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/TypeError.php',
|
|
||||||
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
|
||||||
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
|
||||||
);
|
);
|
||||||
|
|||||||
14
vendor/composer/autoload_files.php
vendored
14
vendor/composer/autoload_files.php
vendored
@@ -6,20 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||||||
$baseDir = dirname($vendorDir);
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
|
||||||
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
|
||||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
|
||||||
'9c67151ae59aff4788964ce8eb2a0f43' => $vendorDir . '/clue/stream-filter/src/functions_include.php',
|
|
||||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
|
||||||
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
|
||||||
'8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
|
|
||||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
|
||||||
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
|
|
||||||
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
|
||||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
|
||||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
|
||||||
'09f6b20656683369174dd6fa83b7e5fb' => $vendorDir . '/symfony/polyfill-uuid/bootstrap.php',
|
|
||||||
'fb4ca2d97fe7ba6af750497425204e70' => $vendorDir . '/sentry/sentry/src/functions.php',
|
|
||||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||||
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
||||||
);
|
);
|
||||||
|
|||||||
24
vendor/composer/autoload_psr4.php
vendored
24
vendor/composer/autoload_psr4.php
vendored
@@ -6,32 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||||||
$baseDir = dirname($vendorDir);
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'),
|
|
||||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
|
||||||
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
|
||||||
'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'),
|
|
||||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
|
|
||||||
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
|
|
||||||
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
||||||
'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'),
|
|
||||||
'Sentry\\' => array($vendorDir . '/sentry/sentry/src'),
|
|
||||||
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
||||||
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
|
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
|
||||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
|
||||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
|
||||||
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
|
||||||
'PackageVersions\\' => array($vendorDir . '/composer/package-versions-deprecated/src/PackageVersions'),
|
|
||||||
'Jean85\\' => array($vendorDir . '/jean85/pretty-package-versions/src'),
|
|
||||||
'Http\\Promise\\' => array($vendorDir . '/php-http/promise/src'),
|
|
||||||
'Http\\Message\\' => array($vendorDir . '/php-http/message/src', $vendorDir . '/php-http/message-factory/src'),
|
|
||||||
'Http\\Factory\\Guzzle\\' => array($vendorDir . '/http-interop/http-factory-guzzle/src'),
|
|
||||||
'Http\\Discovery\\' => array($vendorDir . '/php-http/discovery/src'),
|
|
||||||
'Http\\Client\\Common\\' => array($vendorDir . '/php-http/client-common/src'),
|
|
||||||
'Http\\Client\\' => array($vendorDir . '/php-http/httplug/src'),
|
|
||||||
'Http\\Adapter\\Guzzle6\\' => array($vendorDir . '/php-http/guzzle6-adapter/src'),
|
|
||||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
|
||||||
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
|
||||||
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
|
||||||
'Clue\\StreamFilter\\' => array($vendorDir . '/clue/stream-filter/src'),
|
|
||||||
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
||||||
);
|
);
|
||||||
|
|||||||
166
vendor/composer/autoload_static.php
vendored
166
vendor/composer/autoload_static.php
vendored
@@ -7,20 +7,6 @@ namespace Composer\Autoload;
|
|||||||
class ComposerStaticInita47a22c36b23233ed3ce46b8027644b1
|
class ComposerStaticInita47a22c36b23233ed3ce46b8027644b1
|
||||||
{
|
{
|
||||||
public static $files = array (
|
public static $files = array (
|
||||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
|
||||||
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
|
||||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
|
||||||
'9c67151ae59aff4788964ce8eb2a0f43' => __DIR__ . '/..' . '/clue/stream-filter/src/functions_include.php',
|
|
||||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
|
||||||
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
|
||||||
'8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php',
|
|
||||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
|
||||||
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php',
|
|
||||||
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
|
|
||||||
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
|
|
||||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
|
||||||
'09f6b20656683369174dd6fa83b7e5fb' => __DIR__ . '/..' . '/symfony/polyfill-uuid/bootstrap.php',
|
|
||||||
'fb4ca2d97fe7ba6af750497425204e70' => __DIR__ . '/..' . '/sentry/sentry/src/functions.php',
|
|
||||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||||
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
||||||
);
|
);
|
||||||
@@ -28,52 +14,13 @@ class ComposerStaticInita47a22c36b23233ed3ce46b8027644b1
|
|||||||
public static $prefixLengthsPsr4 = array (
|
public static $prefixLengthsPsr4 = array (
|
||||||
'S' =>
|
'S' =>
|
||||||
array (
|
array (
|
||||||
'Symfony\\Polyfill\\Uuid\\' => 22,
|
|
||||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
|
||||||
'Symfony\\Polyfill\\Php72\\' => 23,
|
|
||||||
'Symfony\\Polyfill\\Php70\\' => 23,
|
|
||||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
|
|
||||||
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
|
|
||||||
'Symfony\\Polyfill\\Ctype\\' => 23,
|
'Symfony\\Polyfill\\Ctype\\' => 23,
|
||||||
'Symfony\\Component\\OptionsResolver\\' => 34,
|
|
||||||
'Sentry\\' => 7,
|
|
||||||
),
|
),
|
||||||
'R' =>
|
'R' =>
|
||||||
array (
|
array (
|
||||||
'Ramsey\\Uuid\\' => 12,
|
'Ramsey\\Uuid\\' => 12,
|
||||||
'Ramsey\\Collection\\' => 18,
|
'Ramsey\\Collection\\' => 18,
|
||||||
),
|
),
|
||||||
'P' =>
|
|
||||||
array (
|
|
||||||
'Psr\\Log\\' => 8,
|
|
||||||
'Psr\\Http\\Message\\' => 17,
|
|
||||||
'Psr\\Http\\Client\\' => 16,
|
|
||||||
'PackageVersions\\' => 16,
|
|
||||||
),
|
|
||||||
'J' =>
|
|
||||||
array (
|
|
||||||
'Jean85\\' => 7,
|
|
||||||
),
|
|
||||||
'H' =>
|
|
||||||
array (
|
|
||||||
'Http\\Promise\\' => 13,
|
|
||||||
'Http\\Message\\' => 13,
|
|
||||||
'Http\\Factory\\Guzzle\\' => 20,
|
|
||||||
'Http\\Discovery\\' => 15,
|
|
||||||
'Http\\Client\\Common\\' => 19,
|
|
||||||
'Http\\Client\\' => 12,
|
|
||||||
'Http\\Adapter\\Guzzle6\\' => 21,
|
|
||||||
),
|
|
||||||
'G' =>
|
|
||||||
array (
|
|
||||||
'GuzzleHttp\\Psr7\\' => 16,
|
|
||||||
'GuzzleHttp\\Promise\\' => 19,
|
|
||||||
'GuzzleHttp\\' => 11,
|
|
||||||
),
|
|
||||||
'C' =>
|
|
||||||
array (
|
|
||||||
'Clue\\StreamFilter\\' => 18,
|
|
||||||
),
|
|
||||||
'B' =>
|
'B' =>
|
||||||
array (
|
array (
|
||||||
'Brick\\Math\\' => 11,
|
'Brick\\Math\\' => 11,
|
||||||
@@ -81,42 +28,10 @@ class ComposerStaticInita47a22c36b23233ed3ce46b8027644b1
|
|||||||
);
|
);
|
||||||
|
|
||||||
public static $prefixDirsPsr4 = array (
|
public static $prefixDirsPsr4 = array (
|
||||||
'Symfony\\Polyfill\\Uuid\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-uuid',
|
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Php80\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Php72\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
|
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Php70\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php70',
|
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
|
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Intl\\Idn\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
|
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Ctype\\' =>
|
'Symfony\\Polyfill\\Ctype\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||||
),
|
),
|
||||||
'Symfony\\Component\\OptionsResolver\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/options-resolver',
|
|
||||||
),
|
|
||||||
'Sentry\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/sentry/sentry/src',
|
|
||||||
),
|
|
||||||
'Ramsey\\Uuid\\' =>
|
'Ramsey\\Uuid\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/ramsey/uuid/src',
|
0 => __DIR__ . '/..' . '/ramsey/uuid/src',
|
||||||
@@ -125,98 +40,17 @@ class ComposerStaticInita47a22c36b23233ed3ce46b8027644b1
|
|||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/ramsey/collection/src',
|
0 => __DIR__ . '/..' . '/ramsey/collection/src',
|
||||||
),
|
),
|
||||||
'Psr\\Log\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
|
||||||
),
|
|
||||||
'Psr\\Http\\Message\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
|
||||||
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
|
||||||
),
|
|
||||||
'Psr\\Http\\Client\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
|
||||||
),
|
|
||||||
'PackageVersions\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/composer/package-versions-deprecated/src/PackageVersions',
|
|
||||||
),
|
|
||||||
'Jean85\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/jean85/pretty-package-versions/src',
|
|
||||||
),
|
|
||||||
'Http\\Promise\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-http/promise/src',
|
|
||||||
),
|
|
||||||
'Http\\Message\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-http/message/src',
|
|
||||||
1 => __DIR__ . '/..' . '/php-http/message-factory/src',
|
|
||||||
),
|
|
||||||
'Http\\Factory\\Guzzle\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/http-interop/http-factory-guzzle/src',
|
|
||||||
),
|
|
||||||
'Http\\Discovery\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-http/discovery/src',
|
|
||||||
),
|
|
||||||
'Http\\Client\\Common\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-http/client-common/src',
|
|
||||||
),
|
|
||||||
'Http\\Client\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-http/httplug/src',
|
|
||||||
),
|
|
||||||
'Http\\Adapter\\Guzzle6\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-http/guzzle6-adapter/src',
|
|
||||||
),
|
|
||||||
'GuzzleHttp\\Psr7\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
|
||||||
),
|
|
||||||
'GuzzleHttp\\Promise\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
|
|
||||||
),
|
|
||||||
'GuzzleHttp\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
|
||||||
),
|
|
||||||
'Clue\\StreamFilter\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/clue/stream-filter/src',
|
|
||||||
),
|
|
||||||
'Brick\\Math\\' =>
|
'Brick\\Math\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/brick/math/src',
|
0 => __DIR__ . '/..' . '/brick/math/src',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $classMap = array (
|
|
||||||
'ArithmeticError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php',
|
|
||||||
'AssertionError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php',
|
|
||||||
'DivisionByZeroError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php',
|
|
||||||
'Error' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/Error.php',
|
|
||||||
'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
|
||||||
'ParseError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
|
|
||||||
'SessionUpdateTimestampHandlerInterface' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php',
|
|
||||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
|
||||||
'TypeError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/TypeError.php',
|
|
||||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
|
||||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
|
||||||
);
|
|
||||||
|
|
||||||
public static function getInitializer(ClassLoader $loader)
|
public static function getInitializer(ClassLoader $loader)
|
||||||
{
|
{
|
||||||
return \Closure::bind(function () use ($loader) {
|
return \Closure::bind(function () use ($loader) {
|
||||||
$loader->prefixLengthsPsr4 = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$prefixLengthsPsr4;
|
$loader->prefixLengthsPsr4 = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$prefixLengthsPsr4;
|
||||||
$loader->prefixDirsPsr4 = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$prefixDirsPsr4;
|
$loader->prefixDirsPsr4 = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$prefixDirsPsr4;
|
||||||
$loader->classMap = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$classMap;
|
|
||||||
|
|
||||||
}, null, ClassLoader::class);
|
}, null, ClassLoader::class);
|
||||||
}
|
}
|
||||||
|
|||||||
1922
vendor/composer/installed.json
vendored
1922
vendor/composer/installed.json
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,120 +0,0 @@
|
|||||||
# CHANGELOG
|
|
||||||
|
|
||||||
## 1.1.3 - 2017-09-06
|
|
||||||
|
|
||||||
This release fixes a bug that caused PackageVersions to prevent
|
|
||||||
the `composer remove` and `composer update` commands to fail when
|
|
||||||
this package is removed.
|
|
||||||
|
|
||||||
In addition to that, mutation testing has been added to the suite,
|
|
||||||
ensuring that the package is accurately and extensively tested.
|
|
||||||
|
|
||||||
Total issues resolved: **3**
|
|
||||||
|
|
||||||
- [40: Mutation testing, PHP 7.1 testing](https://github.com/Ocramius/PackageVersions/pull/40) thanks to @Ocramius
|
|
||||||
- [41: Removing this package on install results in file access error](https://github.com/Ocramius/PackageVersions/issues/41) thanks to @Xerkus
|
|
||||||
- [46: #41 Avoid issues when the package is scheduled for removal](https://github.com/Ocramius/PackageVersions/pull/46) thanks to @Jean85
|
|
||||||
|
|
||||||
## 1.1.2 - 2016-12-30
|
|
||||||
|
|
||||||
This release fixes a bug that caused PackageVersions to be enabled
|
|
||||||
even when it was part of a globally installed package.
|
|
||||||
|
|
||||||
Total issues resolved: **3**
|
|
||||||
|
|
||||||
- [35: remove all temp directories](https://github.com/Ocramius/PackageVersions/pull/35)
|
|
||||||
- [38: Interferes with other projects when installed globally](https://github.com/Ocramius/PackageVersions/issues/38)
|
|
||||||
- [39: Ignore the global plugin when updating local projects](https://github.com/Ocramius/PackageVersions/pull/39)
|
|
||||||
|
|
||||||
## 1.1.1 - 2016-07-25
|
|
||||||
|
|
||||||
This release removes the [`"files"`](https://getcomposer.org/doc/04-schema.md#files) directive from
|
|
||||||
[`composer.json`](https://github.com/Ocramius/PackageVersions/commit/86f2636f7c5e7b56fa035fa3826d5fcf80b6dc72),
|
|
||||||
as it is no longer needed for `composer install --classmap-authoritative`.
|
|
||||||
Also, that directive was causing issues with HHVM installations, since
|
|
||||||
PackageVersions is not compatible with it.
|
|
||||||
|
|
||||||
Total issues resolved: **1**
|
|
||||||
|
|
||||||
- [34: Fatal error during travis build after update to 1.1.0](https://github.com/Ocramius/PackageVersions/issues/34)
|
|
||||||
|
|
||||||
## 1.1.0 - 2016-07-22
|
|
||||||
|
|
||||||
This release introduces support for running `composer install --classmap-authoritative`
|
|
||||||
and `composer install --no-scripts`. Please note that performance
|
|
||||||
while using these modes may be degraded, but the package will
|
|
||||||
still work.
|
|
||||||
|
|
||||||
Additionally, the package was tuned to prevent the plugin from
|
|
||||||
running twice at installation.
|
|
||||||
|
|
||||||
Total issues resolved: **10**
|
|
||||||
|
|
||||||
- [18: Fails when using composer install --no-scripts](https://github.com/Ocramius/PackageVersions/issues/18)
|
|
||||||
- [20: CS (spacing)](https://github.com/Ocramius/PackageVersions/pull/20)
|
|
||||||
- [22: Document the way the require-dev section is treated](https://github.com/Ocramius/PackageVersions/issues/22)
|
|
||||||
- [23: Underline that composer.lock is used as source of information](https://github.com/Ocramius/PackageVersions/pull/23)
|
|
||||||
- [27: Fix incompatibility with --classmap-authoritative](https://github.com/Ocramius/PackageVersions/pull/27)
|
|
||||||
- [29: mention optimize-autoloader composer.json config option in README](https://github.com/Ocramius/PackageVersions/pull/29)
|
|
||||||
- [30: The version class is generated twice during composer update](https://github.com/Ocramius/PackageVersions/issues/30)
|
|
||||||
- [31: Remove double registration of the event listeners](https://github.com/Ocramius/PackageVersions/pull/31)
|
|
||||||
- [32: Update the usage of mock APIs to use the new API](https://github.com/Ocramius/PackageVersions/pull/32)
|
|
||||||
- [33: Fix for #18 - support running with --no-scripts flag](https://github.com/Ocramius/PackageVersions/pull/33)
|
|
||||||
|
|
||||||
## 1.0.4 - 2016-04-23
|
|
||||||
|
|
||||||
This release includes a fix/workaround for composer/composer#5237,
|
|
||||||
which causes `ocramius/package-versions` to sometimes generate a
|
|
||||||
`Versions` class with malformed name (something like
|
|
||||||
`Versions_composer_tmp0`) when running `composer require <package-name>`.
|
|
||||||
|
|
||||||
Total issues resolved: **2**
|
|
||||||
|
|
||||||
- [16: Workaround for composer/composer#5237 - class parsing](https://github.com/Ocramius/PackageVersions/pull/16)
|
|
||||||
- [17: Weird Class name being generated](https://github.com/Ocramius/PackageVersions/issues/17)
|
|
||||||
|
|
||||||
## 1.0.3 - 2016-02-26
|
|
||||||
|
|
||||||
This release fixes an issue related to concurrent autoloader
|
|
||||||
re-generation caused by multiple composer plugins being installed.
|
|
||||||
The issue was solved by removing autoloader re-generation from this
|
|
||||||
package, but it may still affect other packages.
|
|
||||||
|
|
||||||
It is now recommended that you run `composer dump-autoload --optimize`
|
|
||||||
after installation when using this particular package.
|
|
||||||
Please note that `composer (install|update) -o` is not sufficient
|
|
||||||
to avoid autoload overhead when using this particular package.
|
|
||||||
|
|
||||||
Total issues resolved: **1**
|
|
||||||
|
|
||||||
- [15: Remove autoload re-dump optimization](https://github.com/Ocramius/PackageVersions/pull/15)
|
|
||||||
|
|
||||||
## 1.0.2 - 2016-02-24
|
|
||||||
|
|
||||||
This release fixes issues related to installing the component without
|
|
||||||
any dev dependencies or with packages that don't have a source or dist
|
|
||||||
reference, which is usual with packages defined directly in the
|
|
||||||
`composer.json`.
|
|
||||||
|
|
||||||
Total issues resolved: **3**
|
|
||||||
|
|
||||||
- [11: fix composer install --no-dev PHP7](https://github.com/Ocramius/PackageVersions/pull/11)
|
|
||||||
- [12: Packages don't always have a source/reference](https://github.com/Ocramius/PackageVersions/issues/12)
|
|
||||||
- [13: Fix #12 - support dist and missing package version references](https://github.com/Ocramius/PackageVersions/pull/13)
|
|
||||||
|
|
||||||
## 1.0.1 - 2016-02-01
|
|
||||||
|
|
||||||
This release fixes an issue related with composer updates to
|
|
||||||
already installed versions.
|
|
||||||
Using `composer require` within a package that already used
|
|
||||||
`ocramius/package-versions` caused the installation to be unable
|
|
||||||
to write the `PackageVersions\Versions` class to a file.
|
|
||||||
|
|
||||||
Total issues resolved: **6**
|
|
||||||
|
|
||||||
- [2: remove unused use statement](https://github.com/Ocramius/PackageVersions/pull/2)
|
|
||||||
- [3: Remove useless files from dist package](https://github.com/Ocramius/PackageVersions/pull/3)
|
|
||||||
- [5: failed to open stream: phar error: write operations disabled by the php.ini setting phar.readonly](https://github.com/Ocramius/PackageVersions/issues/5)
|
|
||||||
- [6: Fix/#5 use composer vendor dir](https://github.com/Ocramius/PackageVersions/pull/6)
|
|
||||||
- [7: Hotfix - #5 generate package versions also when in phar context](https://github.com/Ocramius/PackageVersions/pull/7)
|
|
||||||
- [8: Versions class should be ignored by VCS, as it is an install-time artifact](https://github.com/Ocramius/PackageVersions/pull/8)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
title: Contributing
|
|
||||||
---
|
|
||||||
|
|
||||||
# Contributing
|
|
||||||
|
|
||||||
* Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
|
|
||||||
* The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
|
|
||||||
* Any contribution must provide tests for additional introduced conditions
|
|
||||||
* Any un-confirmed issue needs a failing test case before being accepted
|
|
||||||
* Pull requests must be sent from a new hotfix/feature branch, not from `master`.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
To install the project and run the tests, you need to clone it first:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ git clone git://github.com/Ocramius/PackageVersions.git
|
|
||||||
```
|
|
||||||
|
|
||||||
You will then need to run a composer installation:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd PackageVersions
|
|
||||||
$ curl -s https://getcomposer.org/installer | php
|
|
||||||
$ php composer.phar update
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
The PHPUnit version to be used is the one installed as a dev- dependency via composer:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ ./vendor/bin/phpunit
|
|
||||||
```
|
|
||||||
|
|
||||||
Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement
|
|
||||||
won't be merged.
|
|
||||||
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2016 Marco Pivetta
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Package Versions
|
|
||||||
|
|
||||||
**`composer/package-versions-deprecated` is a fully-compatible fork of [`ocramius/package-versions`](https://github.com/Ocramius/PackageVersions)** which provides compatibility with Composer 1 and 2 on PHP 7+. It replaces ocramius/package-versions so if you have a dependency requiring it and you want to use Composer v2 but can not upgrade to PHP 7.4 just yet, you can require this package instead.
|
|
||||||
|
|
||||||
If you have a direct dependency on ocramius/package-versions, we recommend instead that once you migrated to Composer 2 you also migrate to use the `Composer\Versions` class which offers the functionality present here out of the box.
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
## Security contact information
|
|
||||||
|
|
||||||
To report a security vulnerability, please use the
|
|
||||||
[Tidelift security contact](https://tidelift.com/security).
|
|
||||||
Tidelift will coordinate the fix and disclosure.
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "composer/package-versions-deprecated",
|
|
||||||
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
|
|
||||||
"type": "composer-plugin",
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Marco Pivetta",
|
|
||||||
"email": "ocramius@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jordi Boggiano",
|
|
||||||
"email": "j.boggiano@seld.be"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": "^7",
|
|
||||||
"composer-plugin-api": "^1.1.0 || ^2.0"
|
|
||||||
},
|
|
||||||
"replace": {
|
|
||||||
"ocramius/package-versions": "1.10.99"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^6.5 || ^7",
|
|
||||||
"composer/composer": "^1.9.3 || ^2.0@dev",
|
|
||||||
"ext-zip": "^1.13"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"PackageVersions\\": "src/PackageVersions"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"PackageVersionsTest\\": "test/PackageVersionsTest"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"class": "PackageVersions\\Installer",
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"post-update-cmd": "PackageVersions\\Installer::dumpVersionsClass",
|
|
||||||
"post-install-cmd": "PackageVersions\\Installer::dumpVersionsClass"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2603
vendor/composer/package-versions-deprecated/composer.lock
generated
vendored
2603
vendor/composer/package-versions-deprecated/composer.lock
generated
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<ruleset>
|
|
||||||
<arg name="basepath" value="."/>
|
|
||||||
<arg name="extensions" value="php"/>
|
|
||||||
<arg name="parallel" value="80"/>
|
|
||||||
<arg name="cache" value=".phpcs-cache"/>
|
|
||||||
<arg name="colors"/>
|
|
||||||
|
|
||||||
<arg value="nps"/>
|
|
||||||
|
|
||||||
<file>src</file>
|
|
||||||
<file>test</file>
|
|
||||||
|
|
||||||
<rule ref="Doctrine">
|
|
||||||
<exclude-pattern>src/PackageVersions/Versions.php</exclude-pattern>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule ref="Generic.Strings.UnnecessaryStringConcat.Found">
|
|
||||||
<exclude-pattern>src/PackageVersions/Installer.php</exclude-pattern>
|
|
||||||
</rule>
|
|
||||||
</ruleset>
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PackageVersions;
|
|
||||||
|
|
||||||
use Generator;
|
|
||||||
use OutOfBoundsException;
|
|
||||||
use UnexpectedValueException;
|
|
||||||
use function array_key_exists;
|
|
||||||
use function array_merge;
|
|
||||||
use function basename;
|
|
||||||
use function file_exists;
|
|
||||||
use function file_get_contents;
|
|
||||||
use function getcwd;
|
|
||||||
use function iterator_to_array;
|
|
||||||
use function json_decode;
|
|
||||||
use function json_encode;
|
|
||||||
use function sprintf;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* This is a fallback for {@see \PackageVersions\Versions::getVersion()}
|
|
||||||
* Do not use this class directly: it is intended to be only used when
|
|
||||||
* {@see \PackageVersions\Versions} fails to be generated, which typically
|
|
||||||
* happens when running composer with `--no-scripts` flag)
|
|
||||||
*/
|
|
||||||
final class FallbackVersions
|
|
||||||
{
|
|
||||||
const ROOT_PACKAGE_NAME = 'unknown/root-package@UNKNOWN';
|
|
||||||
|
|
||||||
private function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws OutOfBoundsException If a version cannot be located.
|
|
||||||
* @throws UnexpectedValueException If the composer.lock file could not be located.
|
|
||||||
*/
|
|
||||||
public static function getVersion(string $packageName): string
|
|
||||||
{
|
|
||||||
$versions = iterator_to_array(self::getVersions(self::getPackageData()));
|
|
||||||
|
|
||||||
if (! array_key_exists($packageName, $versions)) {
|
|
||||||
throw new OutOfBoundsException(
|
|
||||||
'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $versions[$packageName];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed[]
|
|
||||||
*
|
|
||||||
* @throws UnexpectedValueException
|
|
||||||
*/
|
|
||||||
private static function getPackageData(): array
|
|
||||||
{
|
|
||||||
$checkedPaths = [
|
|
||||||
// The top-level project's ./vendor/composer/installed.json
|
|
||||||
getcwd() . '/vendor/composer/installed.json',
|
|
||||||
__DIR__ . '/../../../../composer/installed.json',
|
|
||||||
// The top-level project's ./composer.lock
|
|
||||||
getcwd() . '/composer.lock',
|
|
||||||
__DIR__ . '/../../../../../composer.lock',
|
|
||||||
// This package's composer.lock
|
|
||||||
__DIR__ . '/../../composer.lock',
|
|
||||||
];
|
|
||||||
|
|
||||||
$packageData = [];
|
|
||||||
foreach ($checkedPaths as $path) {
|
|
||||||
if (! file_exists($path)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = json_decode(file_get_contents($path), true);
|
|
||||||
switch (basename($path)) {
|
|
||||||
case 'installed.json':
|
|
||||||
// composer 2.x installed.json format
|
|
||||||
if (isset($data['packages'])) {
|
|
||||||
$packageData[] = $data['packages'];
|
|
||||||
} else {
|
|
||||||
// composer 1.x installed.json format
|
|
||||||
$packageData[] = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'composer.lock':
|
|
||||||
$packageData[] = $data['packages'] + ($data['packages-dev'] ?? []);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// intentionally left blank
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($packageData !== []) {
|
|
||||||
return array_merge(...$packageData);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnexpectedValueException(sprintf(
|
|
||||||
'PackageVersions could not locate the `vendor/composer/installed.json` or your `composer.lock` '
|
|
||||||
. 'location. This is assumed to be in %s. If you customized your composer vendor directory and ran composer '
|
|
||||||
. 'installation with --no-scripts, or if you deployed without the required composer files, PackageVersions '
|
|
||||||
. 'can\'t detect installed versions.',
|
|
||||||
json_encode($checkedPaths)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed[] $packageData
|
|
||||||
*
|
|
||||||
* @return Generator&string[]
|
|
||||||
*
|
|
||||||
* @psalm-return Generator<string, string>
|
|
||||||
*/
|
|
||||||
private static function getVersions(array $packageData): Generator
|
|
||||||
{
|
|
||||||
foreach ($packageData as $package) {
|
|
||||||
yield $package['name'] => $package['version'] . '@' . (
|
|
||||||
$package['source']['reference'] ?? $package['dist']['reference'] ?? ''
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
yield self::ROOT_PACKAGE_NAME => self::ROOT_PACKAGE_NAME;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PackageVersions;
|
|
||||||
|
|
||||||
use Composer\Composer;
|
|
||||||
use Composer\Config;
|
|
||||||
use Composer\EventDispatcher\EventSubscriberInterface;
|
|
||||||
use Composer\IO\IOInterface;
|
|
||||||
use Composer\Package\AliasPackage;
|
|
||||||
use Composer\Package\Locker;
|
|
||||||
use Composer\Package\PackageInterface;
|
|
||||||
use Composer\Package\RootPackageInterface;
|
|
||||||
use Composer\Plugin\PluginInterface;
|
|
||||||
use Composer\Script\Event;
|
|
||||||
use Composer\Script\ScriptEvents;
|
|
||||||
use Generator;
|
|
||||||
use RuntimeException;
|
|
||||||
|
|
||||||
use function array_key_exists;
|
|
||||||
use function array_merge;
|
|
||||||
use function chmod;
|
|
||||||
use function dirname;
|
|
||||||
use function file_exists;
|
|
||||||
use function file_put_contents;
|
|
||||||
use function is_writable;
|
|
||||||
use function iterator_to_array;
|
|
||||||
use function rename;
|
|
||||||
use function sprintf;
|
|
||||||
use function uniqid;
|
|
||||||
use function var_export;
|
|
||||||
|
|
||||||
final class Installer implements PluginInterface, EventSubscriberInterface
|
|
||||||
{
|
|
||||||
private static $generatedClassTemplate = <<<'PHP'
|
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PackageVersions;
|
|
||||||
|
|
||||||
use Composer\InstalledVersions;
|
|
||||||
use OutOfBoundsException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is generated by composer/package-versions-deprecated, specifically by
|
|
||||||
* @see \PackageVersions\Installer
|
|
||||||
*
|
|
||||||
* This file is overwritten at every run of `composer install` or `composer update`.
|
|
||||||
*
|
|
||||||
* @deprecated in favor of the Composer\InstalledVersions class provided by Composer 2. Require composer-runtime-api:^2 to ensure it is present.
|
|
||||||
*/
|
|
||||||
%s
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @deprecated please use {@see \Composer\InstalledVersions::getRootPackage()} instead. The
|
|
||||||
* equivalent expression for this constant's contents is
|
|
||||||
* `\Composer\InstalledVersions::getRootPackage()['name']`.
|
|
||||||
* This constant will be removed in version 2.0.0.
|
|
||||||
*/
|
|
||||||
const ROOT_PACKAGE_NAME = '%s';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of all available composer packages.
|
|
||||||
* Dont read this array from your calling code, but use the \PackageVersions\Versions::getVersion() method instead.
|
|
||||||
*
|
|
||||||
* @var array<string, string>
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
const VERSIONS = %s;
|
|
||||||
|
|
||||||
private function __construct()
|
|
||||||
{
|
|
||||||
class_exists(InstalledVersions::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws OutOfBoundsException If a version cannot be located.
|
|
||||||
*
|
|
||||||
* @psalm-param key-of<self::VERSIONS> $packageName
|
|
||||||
* @psalm-pure
|
|
||||||
*
|
|
||||||
* @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not
|
|
||||||
* cause any side effects here.
|
|
||||||
*/
|
|
||||||
public static function getVersion(string $packageName): string
|
|
||||||
{
|
|
||||||
if (class_exists(InstalledVersions::class, false)) {
|
|
||||||
return InstalledVersions::getPrettyVersion($packageName)
|
|
||||||
. '@' . InstalledVersions::getReference($packageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset(self::VERSIONS[$packageName])) {
|
|
||||||
return self::VERSIONS[$packageName];
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new OutOfBoundsException(
|
|
||||||
'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PHP;
|
|
||||||
|
|
||||||
public function activate(Composer $composer, IOInterface $io)
|
|
||||||
{
|
|
||||||
// Nothing to do here, as all features are provided through event listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deactivate(Composer $composer, IOInterface $io)
|
|
||||||
{
|
|
||||||
// Nothing to do here, as all features are provided through event listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
public function uninstall(Composer $composer, IOInterface $io)
|
|
||||||
{
|
|
||||||
// Nothing to do here, as all features are provided through event listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public static function getSubscribedEvents(): array
|
|
||||||
{
|
|
||||||
return [ScriptEvents::POST_AUTOLOAD_DUMP => 'dumpVersionsClass'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws RuntimeException
|
|
||||||
*/
|
|
||||||
public static function dumpVersionsClass(Event $composerEvent)
|
|
||||||
{
|
|
||||||
$composer = $composerEvent->getComposer();
|
|
||||||
$rootPackage = $composer->getPackage();
|
|
||||||
$versions = iterator_to_array(self::getVersions($composer->getLocker(), $rootPackage));
|
|
||||||
|
|
||||||
if (! array_key_exists('composer/package-versions-deprecated', $versions)) {
|
|
||||||
//plugin must be globally installed - we only want to generate versions for projects which specifically
|
|
||||||
//require composer/package-versions-deprecated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$versionClass = self::generateVersionsClass($rootPackage->getName(), $versions);
|
|
||||||
|
|
||||||
self::writeVersionClassToFile($versionClass, $composer, $composerEvent->getIO());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[] $versions
|
|
||||||
*/
|
|
||||||
private static function generateVersionsClass(string $rootPackageName, array $versions): string
|
|
||||||
{
|
|
||||||
return sprintf(
|
|
||||||
self::$generatedClassTemplate,
|
|
||||||
'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-(
|
|
||||||
$rootPackageName,
|
|
||||||
var_export($versions, true)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws RuntimeException
|
|
||||||
*/
|
|
||||||
private static function writeVersionClassToFile(string $versionClassSource, Composer $composer, IOInterface $io)
|
|
||||||
{
|
|
||||||
$installPath = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage())
|
|
||||||
. '/src/PackageVersions/Versions.php';
|
|
||||||
|
|
||||||
$installDir = dirname($installPath);
|
|
||||||
if (! file_exists($installDir)) {
|
|
||||||
$io->write('<info>composer/package-versions-deprecated:</info> Package not found (probably scheduled for removal); generation of version class skipped.');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! is_writable($installDir)) {
|
|
||||||
$io->write(
|
|
||||||
sprintf(
|
|
||||||
'<info>composer/package-versions-deprecated:</info> %s is not writable; generation of version class skipped.',
|
|
||||||
$installDir
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$io->write('<info>composer/package-versions-deprecated:</info> Generating version class...');
|
|
||||||
|
|
||||||
$installPathTmp = $installPath . '_' . uniqid('tmp', true);
|
|
||||||
file_put_contents($installPathTmp, $versionClassSource);
|
|
||||||
chmod($installPathTmp, 0664);
|
|
||||||
rename($installPathTmp, $installPath);
|
|
||||||
|
|
||||||
$io->write('<info>composer/package-versions-deprecated:</info> ...done generating version class');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws RuntimeException
|
|
||||||
*/
|
|
||||||
private static function locateRootPackageInstallPath(
|
|
||||||
Config $composerConfig,
|
|
||||||
RootPackageInterface $rootPackage
|
|
||||||
): string {
|
|
||||||
if (self::getRootPackageAlias($rootPackage)->getName() === 'composer/package-versions-deprecated') {
|
|
||||||
return dirname($composerConfig->get('vendor-dir'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $composerConfig->get('vendor-dir') . '/composer/package-versions-deprecated';
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function getRootPackageAlias(RootPackageInterface $rootPackage): PackageInterface
|
|
||||||
{
|
|
||||||
$package = $rootPackage;
|
|
||||||
|
|
||||||
while ($package instanceof AliasPackage) {
|
|
||||||
$package = $package->getAliasOf();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $package;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Generator&string[]
|
|
||||||
*
|
|
||||||
* @psalm-return Generator<string, string>
|
|
||||||
*/
|
|
||||||
private static function getVersions(Locker $locker, RootPackageInterface $rootPackage): Generator
|
|
||||||
{
|
|
||||||
$lockData = $locker->getLockData();
|
|
||||||
|
|
||||||
$lockData['packages-dev'] = $lockData['packages-dev'] ?? [];
|
|
||||||
|
|
||||||
foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) {
|
|
||||||
yield $package['name'] => $package['version'] . '@' . (
|
|
||||||
$package['source']['reference'] ?? $package['dist']['reference'] ?? ''
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($rootPackage->getReplaces() as $replace) {
|
|
||||||
$version = $replace->getPrettyConstraint();
|
|
||||||
if ($version === 'self.version') {
|
|
||||||
$version = $rootPackage->getPrettyVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
yield $replace->getTarget() => $version . '@' . $rootPackage->getSourceReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
yield $rootPackage->getName() => $rootPackage->getPrettyVersion() . '@' . $rootPackage->getSourceReference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PackageVersions;
|
|
||||||
|
|
||||||
use Composer\InstalledVersions;
|
|
||||||
use OutOfBoundsException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is generated by composer/package-versions-deprecated, specifically by
|
|
||||||
* @see \PackageVersions\Installer
|
|
||||||
*
|
|
||||||
* This file is overwritten at every run of `composer install` or `composer update`.
|
|
||||||
*
|
|
||||||
* @deprecated in favor of the Composer\InstalledVersions class provided by Composer 2. Require composer-runtime-api:^2 to ensure it is present.
|
|
||||||
*/
|
|
||||||
final class Versions
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @deprecated please use {@see \Composer\InstalledVersions::getRootPackage()} instead. The
|
|
||||||
* equivalent expression for this constant's contents is
|
|
||||||
* `\Composer\InstalledVersions::getRootPackage()['name']`.
|
|
||||||
* This constant will be removed in version 2.0.0.
|
|
||||||
*/
|
|
||||||
const ROOT_PACKAGE_NAME = '__root__';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of all available composer packages.
|
|
||||||
* Dont read this array from your calling code, but use the \PackageVersions\Versions::getVersion() method instead.
|
|
||||||
*
|
|
||||||
* @var array<string, string>
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
const VERSIONS = array (
|
|
||||||
'brick/math' => '0.8.15@9b08d412b9da9455b210459ff71414de7e6241cd',
|
|
||||||
'clue/stream-filter' => 'v1.4.1@5a58cc30a8bd6a4eb8f856adf61dd3e013f53f71',
|
|
||||||
'composer/package-versions-deprecated' => '1.10.99@dd51b4443d58b34b6d9344cf4c288e621c9a826f',
|
|
||||||
'guzzlehttp/guzzle' => '6.5.5@9d4290de1cfd701f38099ef7e183b64b4b7b0c5e',
|
|
||||||
'guzzlehttp/promises' => 'v1.3.1@a59da6cf61d80060647ff4d3eb2c03a2bc694646',
|
|
||||||
'guzzlehttp/psr7' => '1.6.1@239400de7a173fe9901b9ac7c06497751f00727a',
|
|
||||||
'http-interop/http-factory-guzzle' => '1.0.0@34861658efb9899a6618cef03de46e2a52c80fc0',
|
|
||||||
'jean85/pretty-package-versions' => '1.5.0@e9f4324e88b8664be386d90cf60fbc202e1f7fc9',
|
|
||||||
'paragonie/random_compat' => 'v9.99.99@84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95',
|
|
||||||
'php-http/client-common' => '2.3.0@e37e46c610c87519753135fb893111798c69076a',
|
|
||||||
'php-http/discovery' => '1.9.1@64a18cc891957e05d91910b3c717d6bd11fbede9',
|
|
||||||
'php-http/guzzle6-adapter' => 'v2.0.1@6074a4b1f4d5c21061b70bab3b8ad484282fe31f',
|
|
||||||
'php-http/httplug' => '2.2.0@191a0a1b41ed026b717421931f8d3bd2514ffbf9',
|
|
||||||
'php-http/message' => '1.8.0@ce8f43ac1e294b54aabf5808515c3554a19c1e1c',
|
|
||||||
'php-http/message-factory' => 'v1.0.2@a478cb11f66a6ac48d8954216cfed9aa06a501a1',
|
|
||||||
'php-http/promise' => '1.1.0@4c4c1f9b7289a2ec57cde7f1e9762a5789506f88',
|
|
||||||
'psr/http-client' => '1.0.1@2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
|
||||||
'psr/http-factory' => '1.0.1@12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
|
||||||
'psr/http-message' => '1.0.1@f6561bf28d520154e4b0ec72be95418abe6d9363',
|
|
||||||
'psr/log' => '1.1.3@0f73288fd15629204f9d42b7055f72dacbe811fc',
|
|
||||||
'ralouphie/getallheaders' => '3.0.3@120b605dfeb996808c31b6477290a714d356e822',
|
|
||||||
'ramsey/collection' => '1.0.1@925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca',
|
|
||||||
'ramsey/uuid' => '4.1.0@988dbefc7878d0a35f12afb4df1f7dd0bd153c43',
|
|
||||||
'sentry/sdk' => '2.1.0@18921af9c2777517ef9fb480845c22a98554d6af',
|
|
||||||
'sentry/sentry' => '2.4.2@b3b4f4a08b184c3f22b208f357e8720ef42938b0',
|
|
||||||
'symfony/deprecation-contracts' => 'v2.1.3@5e20b83385a77593259c9f8beb2c43cd03b2ac14',
|
|
||||||
'symfony/options-resolver' => 'v5.1.3@9ff59517938f88d90b6e65311fef08faa640f681',
|
|
||||||
'symfony/polyfill-ctype' => 'v1.18.1@1c302646f6efc070cd46856e600e5e0684d6b454',
|
|
||||||
'symfony/polyfill-intl-idn' => 'v1.18.1@5dcab1bc7146cf8c1beaa4502a3d9be344334251',
|
|
||||||
'symfony/polyfill-intl-normalizer' => 'v1.18.1@37078a8dd4a2a1e9ab0231af7c6cb671b2ed5a7e',
|
|
||||||
'symfony/polyfill-php70' => 'v1.18.1@0dd93f2c578bdc9c72697eaa5f1dd25644e618d3',
|
|
||||||
'symfony/polyfill-php72' => 'v1.18.1@639447d008615574653fb3bc60d1986d7172eaae',
|
|
||||||
'symfony/polyfill-php80' => 'v1.18.1@d87d5766cbf48d72388a9f6b85f280c8ad51f981',
|
|
||||||
'symfony/polyfill-uuid' => 'v1.18.1@da48e2cccd323e48c16c26481bf5800f6ab1c49d',
|
|
||||||
'__root__' => 'dev-feature/issue-6@bbba704df39737db9ed6c9969b4a2e476832606c',
|
|
||||||
);
|
|
||||||
|
|
||||||
private function __construct()
|
|
||||||
{
|
|
||||||
class_exists(InstalledVersions::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws OutOfBoundsException If a version cannot be located.
|
|
||||||
*
|
|
||||||
* @psalm-param key-of<self::VERSIONS> $packageName
|
|
||||||
* @psalm-pure
|
|
||||||
*
|
|
||||||
* @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not
|
|
||||||
* cause any side effects here.
|
|
||||||
*/
|
|
||||||
public static function getVersion(string $packageName): string
|
|
||||||
{
|
|
||||||
if (class_exists(InstalledVersions::class, false)) {
|
|
||||||
return InstalledVersions::getPrettyVersion($packageName)
|
|
||||||
. '@' . InstalledVersions::getReference($packageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset(self::VERSIONS[$packageName])) {
|
|
||||||
return self::VERSIONS[$packageName];
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new OutOfBoundsException(
|
|
||||||
'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
vendor/guzzlehttp/guzzle/.php_cs
vendored
23
vendor/guzzlehttp/guzzle/.php_cs
vendored
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
$config = PhpCsFixer\Config::create()
|
|
||||||
->setRiskyAllowed(true)
|
|
||||||
->setRules([
|
|
||||||
'@PSR2' => true,
|
|
||||||
'array_syntax' => ['syntax' => 'short'],
|
|
||||||
'declare_strict_types' => false,
|
|
||||||
'concat_space' => ['spacing'=>'one'],
|
|
||||||
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
|
|
||||||
'ordered_imports' => true,
|
|
||||||
// 'phpdoc_align' => ['align'=>'vertical'],
|
|
||||||
// 'native_function_invocation' => true,
|
|
||||||
])
|
|
||||||
->setFinder(
|
|
||||||
PhpCsFixer\Finder::create()
|
|
||||||
->in(__DIR__.'/src')
|
|
||||||
->in(__DIR__.'/tests')
|
|
||||||
->name('*.php')
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
return $config;
|
|
||||||
1338
vendor/guzzlehttp/guzzle/CHANGELOG.md
vendored
1338
vendor/guzzlehttp/guzzle/CHANGELOG.md
vendored
File diff suppressed because it is too large
Load Diff
18
vendor/guzzlehttp/guzzle/Dockerfile
vendored
18
vendor/guzzlehttp/guzzle/Dockerfile
vendored
@@ -1,18 +0,0 @@
|
|||||||
FROM composer:latest as setup
|
|
||||||
|
|
||||||
RUN mkdir /guzzle
|
|
||||||
|
|
||||||
WORKDIR /guzzle
|
|
||||||
|
|
||||||
RUN set -xe \
|
|
||||||
&& composer init --name=guzzlehttp/test --description="Simple project for testing Guzzle scripts" --author="Márk Sági-Kazár <mark.sagikazar@gmail.com>" --no-interaction \
|
|
||||||
&& composer require guzzlehttp/guzzle
|
|
||||||
|
|
||||||
|
|
||||||
FROM php:7.3
|
|
||||||
|
|
||||||
RUN mkdir /guzzle
|
|
||||||
|
|
||||||
WORKDIR /guzzle
|
|
||||||
|
|
||||||
COPY --from=setup /guzzle /guzzle
|
|
||||||
19
vendor/guzzlehttp/guzzle/LICENSE
vendored
19
vendor/guzzlehttp/guzzle/LICENSE
vendored
@@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
90
vendor/guzzlehttp/guzzle/README.md
vendored
90
vendor/guzzlehttp/guzzle/README.md
vendored
@@ -1,90 +0,0 @@
|
|||||||
Guzzle, PHP HTTP client
|
|
||||||
=======================
|
|
||||||
|
|
||||||
[](https://github.com/guzzle/guzzle/releases)
|
|
||||||
[](https://travis-ci.org/guzzle/guzzle)
|
|
||||||
[](https://packagist.org/packages/guzzlehttp/guzzle)
|
|
||||||
|
|
||||||
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
|
|
||||||
trivial to integrate with web services.
|
|
||||||
|
|
||||||
- Simple interface for building query strings, POST requests, streaming large
|
|
||||||
uploads, streaming large downloads, using HTTP cookies, uploading JSON data,
|
|
||||||
etc...
|
|
||||||
- Can send both synchronous and asynchronous requests using the same interface.
|
|
||||||
- Uses PSR-7 interfaces for requests, responses, and streams. This allows you
|
|
||||||
to utilize other PSR-7 compatible libraries with Guzzle.
|
|
||||||
- Abstracts away the underlying HTTP transport, allowing you to write
|
|
||||||
environment and transport agnostic code; i.e., no hard dependency on cURL,
|
|
||||||
PHP streams, sockets, or non-blocking event loops.
|
|
||||||
- Middleware system allows you to augment and compose client behavior.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$client = new \GuzzleHttp\Client();
|
|
||||||
$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
|
|
||||||
|
|
||||||
echo $response->getStatusCode(); # 200
|
|
||||||
echo $response->getHeaderLine('content-type'); # 'application/json; charset=utf8'
|
|
||||||
echo $response->getBody(); # '{"id": 1420053, "name": "guzzle", ...}'
|
|
||||||
|
|
||||||
# Send an asynchronous request.
|
|
||||||
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
|
|
||||||
$promise = $client->sendAsync($request)->then(function ($response) {
|
|
||||||
echo 'I completed! ' . $response->getBody();
|
|
||||||
});
|
|
||||||
|
|
||||||
$promise->wait();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Help and docs
|
|
||||||
|
|
||||||
- [Documentation](http://guzzlephp.org/)
|
|
||||||
- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle)
|
|
||||||
- [Gitter](https://gitter.im/guzzle/guzzle)
|
|
||||||
|
|
||||||
|
|
||||||
## Installing Guzzle
|
|
||||||
|
|
||||||
The recommended way to install Guzzle is through
|
|
||||||
[Composer](http://getcomposer.org).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install Composer
|
|
||||||
curl -sS https://getcomposer.org/installer | php
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, run the Composer command to install the latest stable version of Guzzle:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require guzzlehttp/guzzle
|
|
||||||
```
|
|
||||||
|
|
||||||
After installing, you need to require Composer's autoloader:
|
|
||||||
|
|
||||||
```php
|
|
||||||
require 'vendor/autoload.php';
|
|
||||||
```
|
|
||||||
|
|
||||||
You can then later update Guzzle using composer:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer update
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## 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 |
|
|
||||||
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 |
|
|
||||||
| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 |
|
|
||||||
| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 |
|
|
||||||
|
|
||||||
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
|
|
||||||
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
|
|
||||||
[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
|
|
||||||
[guzzle-6-repo]: https://github.com/guzzle/guzzle
|
|
||||||
[guzzle-3-docs]: http://guzzle3.readthedocs.org
|
|
||||||
[guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/
|
|
||||||
[guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/
|
|
||||||
1203
vendor/guzzlehttp/guzzle/UPGRADING.md
vendored
1203
vendor/guzzlehttp/guzzle/UPGRADING.md
vendored
File diff suppressed because it is too large
Load Diff
59
vendor/guzzlehttp/guzzle/composer.json
vendored
59
vendor/guzzlehttp/guzzle/composer.json
vendored
@@ -1,59 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "guzzlehttp/guzzle",
|
|
||||||
"type": "library",
|
|
||||||
"description": "Guzzle is a PHP HTTP client library",
|
|
||||||
"keywords": [
|
|
||||||
"framework",
|
|
||||||
"http",
|
|
||||||
"rest",
|
|
||||||
"web service",
|
|
||||||
"curl",
|
|
||||||
"client",
|
|
||||||
"HTTP client"
|
|
||||||
],
|
|
||||||
"homepage": "http://guzzlephp.org/",
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Michael Dowling",
|
|
||||||
"email": "mtdowling@gmail.com",
|
|
||||||
"homepage": "https://github.com/mtdowling"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.5",
|
|
||||||
"ext-json": "*",
|
|
||||||
"symfony/polyfill-intl-idn": "^1.17.0",
|
|
||||||
"guzzlehttp/promises": "^1.0",
|
|
||||||
"guzzlehttp/psr7": "^1.6.1"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"ext-curl": "*",
|
|
||||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
|
||||||
"psr/log": "^1.1"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"psr/log": "Required for using the Log middleware"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"sort-packages": true
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "6.5-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\": "src/"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"src/functions_include.php"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\Tests\\": "tests/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
501
vendor/guzzlehttp/guzzle/src/Client.php
vendored
501
vendor/guzzlehttp/guzzle/src/Client.php
vendored
@@ -1,501 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Cookie\CookieJar;
|
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
|
||||||
use GuzzleHttp\Promise;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\UriInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @method ResponseInterface get(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method ResponseInterface head(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method ResponseInterface put(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method ResponseInterface post(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
|
|
||||||
* @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
|
|
||||||
*/
|
|
||||||
class Client implements ClientInterface
|
|
||||||
{
|
|
||||||
/** @var array Default request options */
|
|
||||||
private $config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clients accept an array of constructor parameters.
|
|
||||||
*
|
|
||||||
* Here's an example of creating a client using a base_uri and an array of
|
|
||||||
* default request options to apply to each request:
|
|
||||||
*
|
|
||||||
* $client = new Client([
|
|
||||||
* 'base_uri' => 'http://www.foo.com/1.0/',
|
|
||||||
* 'timeout' => 0,
|
|
||||||
* 'allow_redirects' => false,
|
|
||||||
* 'proxy' => '192.168.16.1:10'
|
|
||||||
* ]);
|
|
||||||
*
|
|
||||||
* Client configuration settings include the following options:
|
|
||||||
*
|
|
||||||
* - handler: (callable) Function that transfers HTTP requests over the
|
|
||||||
* wire. The function is called with a Psr7\Http\Message\RequestInterface
|
|
||||||
* and array of transfer options, and must return a
|
|
||||||
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
|
|
||||||
* Psr7\Http\Message\ResponseInterface on success.
|
|
||||||
* If no handler is provided, a default handler will be created
|
|
||||||
* that enables all of the request options below by attaching all of the
|
|
||||||
* default middleware to the handler.
|
|
||||||
* - base_uri: (string|UriInterface) Base URI of the client that is merged
|
|
||||||
* into relative URIs. Can be a string or instance of UriInterface.
|
|
||||||
* - **: any request option
|
|
||||||
*
|
|
||||||
* @param array $config Client configuration settings.
|
|
||||||
*
|
|
||||||
* @see \GuzzleHttp\RequestOptions for a list of available request options.
|
|
||||||
*/
|
|
||||||
public function __construct(array $config = [])
|
|
||||||
{
|
|
||||||
if (!isset($config['handler'])) {
|
|
||||||
$config['handler'] = HandlerStack::create();
|
|
||||||
} elseif (!is_callable($config['handler'])) {
|
|
||||||
throw new \InvalidArgumentException('handler must be a callable');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the base_uri to a UriInterface
|
|
||||||
if (isset($config['base_uri'])) {
|
|
||||||
$config['base_uri'] = Psr7\uri_for($config['base_uri']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->configureDefaults($config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $method
|
|
||||||
* @param array $args
|
|
||||||
*
|
|
||||||
* @return Promise\PromiseInterface
|
|
||||||
*/
|
|
||||||
public function __call($method, $args)
|
|
||||||
{
|
|
||||||
if (count($args) < 1) {
|
|
||||||
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = $args[0];
|
|
||||||
$opts = isset($args[1]) ? $args[1] : [];
|
|
||||||
|
|
||||||
return substr($method, -5) === 'Async'
|
|
||||||
? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
|
|
||||||
: $this->request($method, $uri, $opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronously send an HTTP request.
|
|
||||||
*
|
|
||||||
* @param array $options Request options to apply to the given
|
|
||||||
* request and to the transfer. See \GuzzleHttp\RequestOptions.
|
|
||||||
*
|
|
||||||
* @return Promise\PromiseInterface
|
|
||||||
*/
|
|
||||||
public function sendAsync(RequestInterface $request, array $options = [])
|
|
||||||
{
|
|
||||||
// Merge the base URI into the request URI if needed.
|
|
||||||
$options = $this->prepareDefaults($options);
|
|
||||||
|
|
||||||
return $this->transfer(
|
|
||||||
$request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
|
|
||||||
$options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an HTTP request.
|
|
||||||
*
|
|
||||||
* @param array $options Request options to apply to the given
|
|
||||||
* request and to the transfer. See \GuzzleHttp\RequestOptions.
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws GuzzleException
|
|
||||||
*/
|
|
||||||
public function send(RequestInterface $request, array $options = [])
|
|
||||||
{
|
|
||||||
$options[RequestOptions::SYNCHRONOUS] = true;
|
|
||||||
return $this->sendAsync($request, $options)->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and send an asynchronous HTTP request.
|
|
||||||
*
|
|
||||||
* Use an absolute path to override the base path of the client, or a
|
|
||||||
* relative path to append to the base path of the client. The URL can
|
|
||||||
* contain the query string as well. Use an array to provide a URL
|
|
||||||
* template and additional variables to use in the URL template expansion.
|
|
||||||
*
|
|
||||||
* @param string $method HTTP method
|
|
||||||
* @param string|UriInterface $uri URI object or string.
|
|
||||||
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
|
|
||||||
*
|
|
||||||
* @return Promise\PromiseInterface
|
|
||||||
*/
|
|
||||||
public function requestAsync($method, $uri = '', array $options = [])
|
|
||||||
{
|
|
||||||
$options = $this->prepareDefaults($options);
|
|
||||||
// Remove request modifying parameter because it can be done up-front.
|
|
||||||
$headers = isset($options['headers']) ? $options['headers'] : [];
|
|
||||||
$body = isset($options['body']) ? $options['body'] : null;
|
|
||||||
$version = isset($options['version']) ? $options['version'] : '1.1';
|
|
||||||
// Merge the URI into the base URI.
|
|
||||||
$uri = $this->buildUri($uri, $options);
|
|
||||||
if (is_array($body)) {
|
|
||||||
$this->invalidBody();
|
|
||||||
}
|
|
||||||
$request = new Psr7\Request($method, $uri, $headers, $body, $version);
|
|
||||||
// Remove the option so that they are not doubly-applied.
|
|
||||||
unset($options['headers'], $options['body'], $options['version']);
|
|
||||||
|
|
||||||
return $this->transfer($request, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and send an HTTP request.
|
|
||||||
*
|
|
||||||
* Use an absolute path to override the base path of the client, or a
|
|
||||||
* relative path to append to the base path of the client. The URL can
|
|
||||||
* contain the query string as well.
|
|
||||||
*
|
|
||||||
* @param string $method HTTP method.
|
|
||||||
* @param string|UriInterface $uri URI object or string.
|
|
||||||
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws GuzzleException
|
|
||||||
*/
|
|
||||||
public function request($method, $uri = '', array $options = [])
|
|
||||||
{
|
|
||||||
$options[RequestOptions::SYNCHRONOUS] = true;
|
|
||||||
return $this->requestAsync($method, $uri, $options)->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a client configuration option.
|
|
||||||
*
|
|
||||||
* These options include default request options of the client, a "handler"
|
|
||||||
* (if utilized by the concrete client), and a "base_uri" if utilized by
|
|
||||||
* the concrete client.
|
|
||||||
*
|
|
||||||
* @param string|null $option The config option to retrieve.
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getConfig($option = null)
|
|
||||||
{
|
|
||||||
return $option === null
|
|
||||||
? $this->config
|
|
||||||
: (isset($this->config[$option]) ? $this->config[$option] : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $uri
|
|
||||||
*
|
|
||||||
* @return UriInterface
|
|
||||||
*/
|
|
||||||
private function buildUri($uri, array $config)
|
|
||||||
{
|
|
||||||
// for BC we accept null which would otherwise fail in uri_for
|
|
||||||
$uri = Psr7\uri_for($uri === null ? '' : $uri);
|
|
||||||
|
|
||||||
if (isset($config['base_uri'])) {
|
|
||||||
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
|
|
||||||
$idnOptions = ($config['idn_conversion'] === true) ? IDNA_DEFAULT : $config['idn_conversion'];
|
|
||||||
$uri = Utils::idnUriConvert($uri, $idnOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the default options for a client.
|
|
||||||
*
|
|
||||||
* @param array $config
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function configureDefaults(array $config)
|
|
||||||
{
|
|
||||||
$defaults = [
|
|
||||||
'allow_redirects' => RedirectMiddleware::$defaultSettings,
|
|
||||||
'http_errors' => true,
|
|
||||||
'decode_content' => true,
|
|
||||||
'verify' => true,
|
|
||||||
'cookies' => false,
|
|
||||||
'idn_conversion' => true,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
|
|
||||||
|
|
||||||
// We can only trust the HTTP_PROXY environment variable in a CLI
|
|
||||||
// process due to the fact that PHP has no reliable mechanism to
|
|
||||||
// get environment variables that start with "HTTP_".
|
|
||||||
if (php_sapi_name() === 'cli' && getenv('HTTP_PROXY')) {
|
|
||||||
$defaults['proxy']['http'] = getenv('HTTP_PROXY');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($proxy = getenv('HTTPS_PROXY')) {
|
|
||||||
$defaults['proxy']['https'] = $proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($noProxy = getenv('NO_PROXY')) {
|
|
||||||
$cleanedNoProxy = str_replace(' ', '', $noProxy);
|
|
||||||
$defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->config = $config + $defaults;
|
|
||||||
|
|
||||||
if (!empty($config['cookies']) && $config['cookies'] === true) {
|
|
||||||
$this->config['cookies'] = new CookieJar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the default user-agent header.
|
|
||||||
if (!isset($this->config['headers'])) {
|
|
||||||
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
|
||||||
} else {
|
|
||||||
// Add the User-Agent header if one was not already set.
|
|
||||||
foreach (array_keys($this->config['headers']) as $name) {
|
|
||||||
if (strtolower($name) === 'user-agent') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->config['headers']['User-Agent'] = default_user_agent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merges default options into the array.
|
|
||||||
*
|
|
||||||
* @param array $options Options to modify by reference
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function prepareDefaults(array $options)
|
|
||||||
{
|
|
||||||
$defaults = $this->config;
|
|
||||||
|
|
||||||
if (!empty($defaults['headers'])) {
|
|
||||||
// Default headers are only added if they are not present.
|
|
||||||
$defaults['_conditional'] = $defaults['headers'];
|
|
||||||
unset($defaults['headers']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special handling for headers is required as they are added as
|
|
||||||
// conditional headers and as headers passed to a request ctor.
|
|
||||||
if (array_key_exists('headers', $options)) {
|
|
||||||
// Allows default headers to be unset.
|
|
||||||
if ($options['headers'] === null) {
|
|
||||||
$defaults['_conditional'] = [];
|
|
||||||
unset($options['headers']);
|
|
||||||
} elseif (!is_array($options['headers'])) {
|
|
||||||
throw new \InvalidArgumentException('headers must be an array');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shallow merge defaults underneath options.
|
|
||||||
$result = $options + $defaults;
|
|
||||||
|
|
||||||
// Remove null values.
|
|
||||||
foreach ($result as $k => $v) {
|
|
||||||
if ($v === null) {
|
|
||||||
unset($result[$k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transfers the given request and applies request options.
|
|
||||||
*
|
|
||||||
* The URI of the request is not modified and the request options are used
|
|
||||||
* as-is without merging in default options.
|
|
||||||
*
|
|
||||||
* @param array $options See \GuzzleHttp\RequestOptions.
|
|
||||||
*
|
|
||||||
* @return Promise\PromiseInterface
|
|
||||||
*/
|
|
||||||
private function transfer(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
// save_to -> sink
|
|
||||||
if (isset($options['save_to'])) {
|
|
||||||
$options['sink'] = $options['save_to'];
|
|
||||||
unset($options['save_to']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// exceptions -> http_errors
|
|
||||||
if (isset($options['exceptions'])) {
|
|
||||||
$options['http_errors'] = $options['exceptions'];
|
|
||||||
unset($options['exceptions']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$request = $this->applyOptions($request, $options);
|
|
||||||
/** @var HandlerStack $handler */
|
|
||||||
$handler = $options['handler'];
|
|
||||||
|
|
||||||
try {
|
|
||||||
return Promise\promise_for($handler($request, $options));
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return Promise\rejection_for($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the array of request options to a request.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return RequestInterface
|
|
||||||
*/
|
|
||||||
private function applyOptions(RequestInterface $request, array &$options)
|
|
||||||
{
|
|
||||||
$modify = [
|
|
||||||
'set_headers' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
if (isset($options['headers'])) {
|
|
||||||
$modify['set_headers'] = $options['headers'];
|
|
||||||
unset($options['headers']);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.');
|
|
||||||
}
|
|
||||||
$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.
|
|
||||||
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
|
||||||
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['multipart'])) {
|
|
||||||
$options['body'] = new Psr7\MultipartStream($options['multipart']);
|
|
||||||
unset($options['multipart']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['json'])) {
|
|
||||||
$options['body'] = \GuzzleHttp\json_encode($options['json']);
|
|
||||||
unset($options['json']);
|
|
||||||
// Ensure that we don't have the header in different case and set the new value.
|
|
||||||
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
|
||||||
$options['_conditional']['Content-Type'] = 'application/json';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($options['decode_content'])
|
|
||||||
&& $options['decode_content'] !== true
|
|
||||||
) {
|
|
||||||
// Ensure that we don't have the header in different case and set the new value.
|
|
||||||
$options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
|
|
||||||
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['body'])) {
|
|
||||||
if (is_array($options['body'])) {
|
|
||||||
$this->invalidBody();
|
|
||||||
}
|
|
||||||
$modify['body'] = Psr7\stream_for($options['body']);
|
|
||||||
unset($options['body']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($options['auth']) && is_array($options['auth'])) {
|
|
||||||
$value = $options['auth'];
|
|
||||||
$type = isset($value[2]) ? strtolower($value[2]) : 'basic';
|
|
||||||
switch ($type) {
|
|
||||||
case 'basic':
|
|
||||||
// Ensure that we don't have the header in different case and set the new value.
|
|
||||||
$modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
|
|
||||||
$modify['set_headers']['Authorization'] = 'Basic '
|
|
||||||
. base64_encode("$value[0]:$value[1]");
|
|
||||||
break;
|
|
||||||
case 'digest':
|
|
||||||
// @todo: Do not rely on curl
|
|
||||||
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
|
|
||||||
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
|
||||||
break;
|
|
||||||
case 'ntlm':
|
|
||||||
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
|
|
||||||
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['query'])) {
|
|
||||||
$value = $options['query'];
|
|
||||||
if (is_array($value)) {
|
|
||||||
$value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
|
|
||||||
}
|
|
||||||
if (!is_string($value)) {
|
|
||||||
throw new \InvalidArgumentException('query must be a string or array');
|
|
||||||
}
|
|
||||||
$modify['query'] = $value;
|
|
||||||
unset($options['query']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that sink is not an invalid value.
|
|
||||||
if (isset($options['sink'])) {
|
|
||||||
// TODO: Add more sink validation?
|
|
||||||
if (is_bool($options['sink'])) {
|
|
||||||
throw new \InvalidArgumentException('sink must not be a boolean');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$request = Psr7\modify_request($request, $modify);
|
|
||||||
if ($request->getBody() instanceof Psr7\MultipartStream) {
|
|
||||||
// Use a multipart/form-data POST if a Content-Type is not set.
|
|
||||||
// Ensure that we don't have the header in different case and set the new value.
|
|
||||||
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
|
||||||
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
|
||||||
. $request->getBody()->getBoundary();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge in conditional headers if they are not present.
|
|
||||||
if (isset($options['_conditional'])) {
|
|
||||||
// Build up the changes so it's in a single clone of the message.
|
|
||||||
$modify = [];
|
|
||||||
foreach ($options['_conditional'] as $k => $v) {
|
|
||||||
if (!$request->hasHeader($k)) {
|
|
||||||
$modify['set_headers'][$k] = $v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$request = Psr7\modify_request($request, $modify);
|
|
||||||
// Don't pass this internal value along to middleware/handlers.
|
|
||||||
unset($options['_conditional']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw Exception with pre-set message.
|
|
||||||
* @return void
|
|
||||||
* @throws \InvalidArgumentException Invalid body.
|
|
||||||
*/
|
|
||||||
private function invalidBody()
|
|
||||||
{
|
|
||||||
throw new \InvalidArgumentException('Passing in the "body" request '
|
|
||||||
. 'option as an array to send a POST request has been deprecated. '
|
|
||||||
. '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.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
87
vendor/guzzlehttp/guzzle/src/ClientInterface.php
vendored
87
vendor/guzzlehttp/guzzle/src/ClientInterface.php
vendored
@@ -1,87 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\UriInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client interface for sending HTTP requests.
|
|
||||||
*/
|
|
||||||
interface ClientInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @deprecated Will be removed in Guzzle 7.0.0
|
|
||||||
*/
|
|
||||||
const VERSION = '6.5.5';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an HTTP request.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request to send
|
|
||||||
* @param array $options Request options to apply to the given
|
|
||||||
* request and to the transfer.
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws GuzzleException
|
|
||||||
*/
|
|
||||||
public function send(RequestInterface $request, array $options = []);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronously send an HTTP request.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request to send
|
|
||||||
* @param array $options Request options to apply to the given
|
|
||||||
* request and to the transfer.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function sendAsync(RequestInterface $request, array $options = []);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and send an HTTP request.
|
|
||||||
*
|
|
||||||
* Use an absolute path to override the base path of the client, or a
|
|
||||||
* relative path to append to the base path of the client. The URL can
|
|
||||||
* contain the query string as well.
|
|
||||||
*
|
|
||||||
* @param string $method HTTP method.
|
|
||||||
* @param string|UriInterface $uri URI object or string.
|
|
||||||
* @param array $options Request options to apply.
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws GuzzleException
|
|
||||||
*/
|
|
||||||
public function request($method, $uri, array $options = []);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and send an asynchronous HTTP request.
|
|
||||||
*
|
|
||||||
* Use an absolute path to override the base path of the client, or a
|
|
||||||
* relative path to append to the base path of the client. The URL can
|
|
||||||
* contain the query string as well. Use an array to provide a URL
|
|
||||||
* template and additional variables to use in the URL template expansion.
|
|
||||||
*
|
|
||||||
* @param string $method HTTP method
|
|
||||||
* @param string|UriInterface $uri URI object or string.
|
|
||||||
* @param array $options Request options to apply.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function requestAsync($method, $uri, array $options = []);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a client configuration option.
|
|
||||||
*
|
|
||||||
* These options include default request options of the client, a "handler"
|
|
||||||
* (if utilized by the concrete client), and a "base_uri" if utilized by
|
|
||||||
* the concrete client.
|
|
||||||
*
|
|
||||||
* @param string|null $option The config option to retrieve.
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getConfig($option = null);
|
|
||||||
}
|
|
||||||
316
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
vendored
316
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
vendored
@@ -1,316 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Cookie;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cookie jar that stores cookies as an array
|
|
||||||
*/
|
|
||||||
class CookieJar implements CookieJarInterface
|
|
||||||
{
|
|
||||||
/** @var SetCookie[] Loaded cookie data */
|
|
||||||
private $cookies = [];
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $strictMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bool $strictMode Set to true to throw exceptions when invalid
|
|
||||||
* cookies are added to the cookie jar.
|
|
||||||
* @param array $cookieArray Array of SetCookie objects or a hash of
|
|
||||||
* arrays that can be used with the SetCookie
|
|
||||||
* constructor
|
|
||||||
*/
|
|
||||||
public function __construct($strictMode = false, $cookieArray = [])
|
|
||||||
{
|
|
||||||
$this->strictMode = $strictMode;
|
|
||||||
|
|
||||||
foreach ($cookieArray as $cookie) {
|
|
||||||
if (!($cookie instanceof SetCookie)) {
|
|
||||||
$cookie = new SetCookie($cookie);
|
|
||||||
}
|
|
||||||
$this->setCookie($cookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Cookie jar from an associative array and domain.
|
|
||||||
*
|
|
||||||
* @param array $cookies Cookies to create the jar from
|
|
||||||
* @param string $domain Domain to set the cookies to
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function fromArray(array $cookies, $domain)
|
|
||||||
{
|
|
||||||
$cookieJar = new self();
|
|
||||||
foreach ($cookies as $name => $value) {
|
|
||||||
$cookieJar->setCookie(new SetCookie([
|
|
||||||
'Domain' => $domain,
|
|
||||||
'Name' => $name,
|
|
||||||
'Value' => $value,
|
|
||||||
'Discard' => true
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $cookieJar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public static function getCookieValue($value)
|
|
||||||
{
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate if this cookie should be persisted to storage
|
|
||||||
* that survives between requests.
|
|
||||||
*
|
|
||||||
* @param SetCookie $cookie Being evaluated.
|
|
||||||
* @param bool $allowSessionCookies If we should persist session cookies
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function shouldPersist(
|
|
||||||
SetCookie $cookie,
|
|
||||||
$allowSessionCookies = false
|
|
||||||
) {
|
|
||||||
if ($cookie->getExpires() || $allowSessionCookies) {
|
|
||||||
if (!$cookie->getDiscard()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds and returns the cookie based on the name
|
|
||||||
*
|
|
||||||
* @param string $name cookie name to search for
|
|
||||||
* @return SetCookie|null cookie that was found or null if not found
|
|
||||||
*/
|
|
||||||
public function getCookieByName($name)
|
|
||||||
{
|
|
||||||
// don't allow a non string name
|
|
||||||
if ($name === null || !is_scalar($name)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
foreach ($this->cookies as $cookie) {
|
|
||||||
if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
|
|
||||||
return $cookie;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toArray()
|
|
||||||
{
|
|
||||||
return array_map(function (SetCookie $cookie) {
|
|
||||||
return $cookie->toArray();
|
|
||||||
}, $this->getIterator()->getArrayCopy());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clear($domain = null, $path = null, $name = null)
|
|
||||||
{
|
|
||||||
if (!$domain) {
|
|
||||||
$this->cookies = [];
|
|
||||||
return;
|
|
||||||
} elseif (!$path) {
|
|
||||||
$this->cookies = array_filter(
|
|
||||||
$this->cookies,
|
|
||||||
function (SetCookie $cookie) use ($domain) {
|
|
||||||
return !$cookie->matchesDomain($domain);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} elseif (!$name) {
|
|
||||||
$this->cookies = array_filter(
|
|
||||||
$this->cookies,
|
|
||||||
function (SetCookie $cookie) use ($path, $domain) {
|
|
||||||
return !($cookie->matchesPath($path) &&
|
|
||||||
$cookie->matchesDomain($domain));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->cookies = array_filter(
|
|
||||||
$this->cookies,
|
|
||||||
function (SetCookie $cookie) use ($path, $domain, $name) {
|
|
||||||
return !($cookie->getName() == $name &&
|
|
||||||
$cookie->matchesPath($path) &&
|
|
||||||
$cookie->matchesDomain($domain));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clearSessionCookies()
|
|
||||||
{
|
|
||||||
$this->cookies = array_filter(
|
|
||||||
$this->cookies,
|
|
||||||
function (SetCookie $cookie) {
|
|
||||||
return !$cookie->getDiscard() && $cookie->getExpires();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCookie(SetCookie $cookie)
|
|
||||||
{
|
|
||||||
// If the name string is empty (but not 0), ignore the set-cookie
|
|
||||||
// string entirely.
|
|
||||||
$name = $cookie->getName();
|
|
||||||
if (!$name && $name !== '0') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only allow cookies with set and valid domain, name, value
|
|
||||||
$result = $cookie->validate();
|
|
||||||
if ($result !== true) {
|
|
||||||
if ($this->strictMode) {
|
|
||||||
throw new \RuntimeException('Invalid cookie: ' . $result);
|
|
||||||
} else {
|
|
||||||
$this->removeCookieIfEmpty($cookie);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve conflicts with previously set cookies
|
|
||||||
foreach ($this->cookies as $i => $c) {
|
|
||||||
|
|
||||||
// Two cookies are identical, when their path, and domain are
|
|
||||||
// identical.
|
|
||||||
if ($c->getPath() != $cookie->getPath() ||
|
|
||||||
$c->getDomain() != $cookie->getDomain() ||
|
|
||||||
$c->getName() != $cookie->getName()
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The previously set cookie is a discard cookie and this one is
|
|
||||||
// not so allow the new cookie to be set
|
|
||||||
if (!$cookie->getDiscard() && $c->getDiscard()) {
|
|
||||||
unset($this->cookies[$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the new cookie's expiration is further into the future, then
|
|
||||||
// replace the old cookie
|
|
||||||
if ($cookie->getExpires() > $c->getExpires()) {
|
|
||||||
unset($this->cookies[$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the value has changed, we better change it
|
|
||||||
if ($cookie->getValue() !== $c->getValue()) {
|
|
||||||
unset($this->cookies[$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The cookie exists, so no need to continue
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->cookies[] = $cookie;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function count()
|
|
||||||
{
|
|
||||||
return count($this->cookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIterator()
|
|
||||||
{
|
|
||||||
return new \ArrayIterator(array_values($this->cookies));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function extractCookies(
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response
|
|
||||||
) {
|
|
||||||
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
|
||||||
foreach ($cookieHeader as $cookie) {
|
|
||||||
$sc = SetCookie::fromString($cookie);
|
|
||||||
if (!$sc->getDomain()) {
|
|
||||||
$sc->setDomain($request->getUri()->getHost());
|
|
||||||
}
|
|
||||||
if (0 !== strpos($sc->getPath(), '/')) {
|
|
||||||
$sc->setPath($this->getCookiePathFromRequest($request));
|
|
||||||
}
|
|
||||||
$this->setCookie($sc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes cookie path following RFC 6265 section 5.1.4
|
|
||||||
*
|
|
||||||
* @link https://tools.ietf.org/html/rfc6265#section-5.1.4
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function getCookiePathFromRequest(RequestInterface $request)
|
|
||||||
{
|
|
||||||
$uriPath = $request->getUri()->getPath();
|
|
||||||
if ('' === $uriPath) {
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
if (0 !== strpos($uriPath, '/')) {
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
if ('/' === $uriPath) {
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
return substr($uriPath, 0, $lastSlashPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function withCookieHeader(RequestInterface $request)
|
|
||||||
{
|
|
||||||
$values = [];
|
|
||||||
$uri = $request->getUri();
|
|
||||||
$scheme = $uri->getScheme();
|
|
||||||
$host = $uri->getHost();
|
|
||||||
$path = $uri->getPath() ?: '/';
|
|
||||||
|
|
||||||
foreach ($this->cookies as $cookie) {
|
|
||||||
if ($cookie->matchesPath($path) &&
|
|
||||||
$cookie->matchesDomain($host) &&
|
|
||||||
!$cookie->isExpired() &&
|
|
||||||
(!$cookie->getSecure() || $scheme === 'https')
|
|
||||||
) {
|
|
||||||
$values[] = $cookie->getName() . '='
|
|
||||||
. $cookie->getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $values
|
|
||||||
? $request->withHeader('Cookie', implode('; ', $values))
|
|
||||||
: $request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a cookie already exists and the server asks to set it again with a
|
|
||||||
* null value, the cookie must be deleted.
|
|
||||||
*
|
|
||||||
* @param SetCookie $cookie
|
|
||||||
*/
|
|
||||||
private function removeCookieIfEmpty(SetCookie $cookie)
|
|
||||||
{
|
|
||||||
$cookieValue = $cookie->getValue();
|
|
||||||
if ($cookieValue === null || $cookieValue === '') {
|
|
||||||
$this->clear(
|
|
||||||
$cookie->getDomain(),
|
|
||||||
$cookie->getPath(),
|
|
||||||
$cookie->getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Cookie;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores HTTP cookies.
|
|
||||||
*
|
|
||||||
* It extracts cookies from HTTP requests, and returns them in HTTP responses.
|
|
||||||
* CookieJarInterface instances automatically expire contained cookies when
|
|
||||||
* necessary. Subclasses are also responsible for storing and retrieving
|
|
||||||
* cookies from a file, database, etc.
|
|
||||||
*
|
|
||||||
* @link http://docs.python.org/2/library/cookielib.html Inspiration
|
|
||||||
*/
|
|
||||||
interface CookieJarInterface extends \Countable, \IteratorAggregate
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create a request with added cookie headers.
|
|
||||||
*
|
|
||||||
* If no matching cookies are found in the cookie jar, then no Cookie
|
|
||||||
* header is added to the request and the same request is returned.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request object to modify.
|
|
||||||
*
|
|
||||||
* @return RequestInterface returns the modified request.
|
|
||||||
*/
|
|
||||||
public function withCookieHeader(RequestInterface $request);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract cookies from an HTTP response and store them in the CookieJar.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request that was sent
|
|
||||||
* @param ResponseInterface $response Response that was received
|
|
||||||
*/
|
|
||||||
public function extractCookies(
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a cookie in the cookie jar.
|
|
||||||
*
|
|
||||||
* @param SetCookie $cookie Cookie to set.
|
|
||||||
*
|
|
||||||
* @return bool Returns true on success or false on failure
|
|
||||||
*/
|
|
||||||
public function setCookie(SetCookie $cookie);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove cookies currently held in the cookie jar.
|
|
||||||
*
|
|
||||||
* Invoking this method without arguments will empty the whole cookie jar.
|
|
||||||
* If given a $domain argument only cookies belonging to that domain will
|
|
||||||
* be removed. If given a $domain and $path argument, cookies belonging to
|
|
||||||
* the specified path within that domain are removed. If given all three
|
|
||||||
* arguments, then the cookie with the specified name, path and domain is
|
|
||||||
* removed.
|
|
||||||
*
|
|
||||||
* @param string|null $domain Clears cookies matching a domain
|
|
||||||
* @param string|null $path Clears cookies matching a domain and path
|
|
||||||
* @param string|null $name Clears cookies matching a domain, path, and name
|
|
||||||
*
|
|
||||||
* @return CookieJarInterface
|
|
||||||
*/
|
|
||||||
public function clear($domain = null, $path = null, $name = null);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discard all sessions cookies.
|
|
||||||
*
|
|
||||||
* Removes cookies that don't have an expire field or a have a discard
|
|
||||||
* field set to true. To be called when the user agent shuts down according
|
|
||||||
* to RFC 2965.
|
|
||||||
*/
|
|
||||||
public function clearSessionCookies();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the cookie jar to an array.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function toArray();
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Cookie;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persists non-session cookies using a JSON formatted file
|
|
||||||
*/
|
|
||||||
class FileCookieJar extends CookieJar
|
|
||||||
{
|
|
||||||
/** @var string filename */
|
|
||||||
private $filename;
|
|
||||||
|
|
||||||
/** @var bool Control whether to persist session cookies or not. */
|
|
||||||
private $storeSessionCookies;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new FileCookieJar object
|
|
||||||
*
|
|
||||||
* @param string $cookieFile File to store the cookie data
|
|
||||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
|
||||||
* in the cookie jar.
|
|
||||||
*
|
|
||||||
* @throws \RuntimeException if the file cannot be found or created
|
|
||||||
*/
|
|
||||||
public function __construct($cookieFile, $storeSessionCookies = false)
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->filename = $cookieFile;
|
|
||||||
$this->storeSessionCookies = $storeSessionCookies;
|
|
||||||
|
|
||||||
if (file_exists($cookieFile)) {
|
|
||||||
$this->load($cookieFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the file when shutting down
|
|
||||||
*/
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->save($this->filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the cookies to a file.
|
|
||||||
*
|
|
||||||
* @param string $filename File to save
|
|
||||||
* @throws \RuntimeException if the file cannot be found or created
|
|
||||||
*/
|
|
||||||
public function save($filename)
|
|
||||||
{
|
|
||||||
$json = [];
|
|
||||||
foreach ($this as $cookie) {
|
|
||||||
/** @var SetCookie $cookie */
|
|
||||||
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
|
||||||
$json[] = $cookie->toArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$jsonStr = \GuzzleHttp\json_encode($json);
|
|
||||||
if (false === file_put_contents($filename, $jsonStr, LOCK_EX)) {
|
|
||||||
throw new \RuntimeException("Unable to save file {$filename}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load cookies from a JSON formatted file.
|
|
||||||
*
|
|
||||||
* Old cookies are kept unless overwritten by newly loaded ones.
|
|
||||||
*
|
|
||||||
* @param string $filename Cookie file to load.
|
|
||||||
* @throws \RuntimeException if the file cannot be loaded.
|
|
||||||
*/
|
|
||||||
public function load($filename)
|
|
||||||
{
|
|
||||||
$json = file_get_contents($filename);
|
|
||||||
if (false === $json) {
|
|
||||||
throw new \RuntimeException("Unable to load file {$filename}");
|
|
||||||
} elseif ($json === '') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = \GuzzleHttp\json_decode($json, true);
|
|
||||||
if (is_array($data)) {
|
|
||||||
foreach (json_decode($json, true) as $cookie) {
|
|
||||||
$this->setCookie(new SetCookie($cookie));
|
|
||||||
}
|
|
||||||
} elseif (strlen($data)) {
|
|
||||||
throw new \RuntimeException("Invalid cookie file: {$filename}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Cookie;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persists cookies in the client session
|
|
||||||
*/
|
|
||||||
class SessionCookieJar extends CookieJar
|
|
||||||
{
|
|
||||||
/** @var string session key */
|
|
||||||
private $sessionKey;
|
|
||||||
|
|
||||||
/** @var bool Control whether to persist session cookies or not. */
|
|
||||||
private $storeSessionCookies;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new SessionCookieJar object
|
|
||||||
*
|
|
||||||
* @param string $sessionKey Session key name to store the cookie
|
|
||||||
* data in session
|
|
||||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
|
||||||
* in the cookie jar.
|
|
||||||
*/
|
|
||||||
public function __construct($sessionKey, $storeSessionCookies = false)
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->sessionKey = $sessionKey;
|
|
||||||
$this->storeSessionCookies = $storeSessionCookies;
|
|
||||||
$this->load();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves cookies to session when shutting down
|
|
||||||
*/
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save cookies to the client session
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$json = [];
|
|
||||||
foreach ($this as $cookie) {
|
|
||||||
/** @var SetCookie $cookie */
|
|
||||||
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
|
||||||
$json[] = $cookie->toArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION[$this->sessionKey] = json_encode($json);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the contents of the client session into the data array
|
|
||||||
*/
|
|
||||||
protected function load()
|
|
||||||
{
|
|
||||||
if (!isset($_SESSION[$this->sessionKey])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$data = json_decode($_SESSION[$this->sessionKey], true);
|
|
||||||
if (is_array($data)) {
|
|
||||||
foreach ($data as $cookie) {
|
|
||||||
$this->setCookie(new SetCookie($cookie));
|
|
||||||
}
|
|
||||||
} elseif (strlen($data)) {
|
|
||||||
throw new \RuntimeException("Invalid cookie data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
403
vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
vendored
403
vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
vendored
@@ -1,403 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Cookie;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set-Cookie object
|
|
||||||
*/
|
|
||||||
class SetCookie
|
|
||||||
{
|
|
||||||
/** @var array */
|
|
||||||
private static $defaults = [
|
|
||||||
'Name' => null,
|
|
||||||
'Value' => null,
|
|
||||||
'Domain' => null,
|
|
||||||
'Path' => '/',
|
|
||||||
'Max-Age' => null,
|
|
||||||
'Expires' => null,
|
|
||||||
'Secure' => false,
|
|
||||||
'Discard' => false,
|
|
||||||
'HttpOnly' => false
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @var array Cookie data */
|
|
||||||
private $data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new SetCookie object from a string
|
|
||||||
*
|
|
||||||
* @param string $cookie Set-Cookie header string
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function fromString($cookie)
|
|
||||||
{
|
|
||||||
// Create the default return array
|
|
||||||
$data = self::$defaults;
|
|
||||||
// Explode the cookie string using a series of semicolons
|
|
||||||
$pieces = array_filter(array_map('trim', explode(';', $cookie)));
|
|
||||||
// The name of the cookie (first kvp) must exist and include an equal sign.
|
|
||||||
if (empty($pieces[0]) || !strpos($pieces[0], '=')) {
|
|
||||||
return new self($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the cookie pieces into the parsed data array
|
|
||||||
foreach ($pieces as $part) {
|
|
||||||
$cookieParts = explode('=', $part, 2);
|
|
||||||
$key = trim($cookieParts[0]);
|
|
||||||
$value = isset($cookieParts[1])
|
|
||||||
? trim($cookieParts[1], " \n\r\t\0\x0B")
|
|
||||||
: true;
|
|
||||||
|
|
||||||
// Only check for non-cookies when cookies have been found
|
|
||||||
if (empty($data['Name'])) {
|
|
||||||
$data['Name'] = $key;
|
|
||||||
$data['Value'] = $value;
|
|
||||||
} else {
|
|
||||||
foreach (array_keys(self::$defaults) as $search) {
|
|
||||||
if (!strcasecmp($search, $key)) {
|
|
||||||
$data[$search] = $value;
|
|
||||||
continue 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$data[$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new self($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data Array of cookie data provided by a Cookie parser
|
|
||||||
*/
|
|
||||||
public function __construct(array $data = [])
|
|
||||||
{
|
|
||||||
$this->data = array_replace(self::$defaults, $data);
|
|
||||||
// Extract the Expires value and turn it into a UNIX timestamp if needed
|
|
||||||
if (!$this->getExpires() && $this->getMaxAge()) {
|
|
||||||
// Calculate the Expires date
|
|
||||||
$this->setExpires(time() + $this->getMaxAge());
|
|
||||||
} elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
|
|
||||||
$this->setExpires($this->getExpires());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString()
|
|
||||||
{
|
|
||||||
$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) . '; ';
|
|
||||||
} else {
|
|
||||||
$str .= ($v === true ? $k : "{$k}={$v}") . '; ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rtrim($str, '; ');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toArray()
|
|
||||||
{
|
|
||||||
return $this->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cookie name
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return $this->data['Name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the cookie name
|
|
||||||
*
|
|
||||||
* @param string $name Cookie name
|
|
||||||
*/
|
|
||||||
public function setName($name)
|
|
||||||
{
|
|
||||||
$this->data['Name'] = $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cookie value
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getValue()
|
|
||||||
{
|
|
||||||
return $this->data['Value'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the cookie value
|
|
||||||
*
|
|
||||||
* @param string $value Cookie value
|
|
||||||
*/
|
|
||||||
public function setValue($value)
|
|
||||||
{
|
|
||||||
$this->data['Value'] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the domain
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getDomain()
|
|
||||||
{
|
|
||||||
return $this->data['Domain'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the domain of the cookie
|
|
||||||
*
|
|
||||||
* @param string $domain
|
|
||||||
*/
|
|
||||||
public function setDomain($domain)
|
|
||||||
{
|
|
||||||
$this->data['Domain'] = $domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the path
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getPath()
|
|
||||||
{
|
|
||||||
return $this->data['Path'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the path of the cookie
|
|
||||||
*
|
|
||||||
* @param string $path Path of the cookie
|
|
||||||
*/
|
|
||||||
public function setPath($path)
|
|
||||||
{
|
|
||||||
$this->data['Path'] = $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum lifetime of the cookie in seconds
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public function getMaxAge()
|
|
||||||
{
|
|
||||||
return $this->data['Max-Age'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the max-age of the cookie
|
|
||||||
*
|
|
||||||
* @param int $maxAge Max age of the cookie in seconds
|
|
||||||
*/
|
|
||||||
public function setMaxAge($maxAge)
|
|
||||||
{
|
|
||||||
$this->data['Max-Age'] = $maxAge;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNIX timestamp when the cookie Expires
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getExpires()
|
|
||||||
{
|
|
||||||
return $this->data['Expires'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the unix timestamp for which the cookie will expire
|
|
||||||
*
|
|
||||||
* @param int $timestamp Unix timestamp
|
|
||||||
*/
|
|
||||||
public function setExpires($timestamp)
|
|
||||||
{
|
|
||||||
$this->data['Expires'] = is_numeric($timestamp)
|
|
||||||
? (int) $timestamp
|
|
||||||
: strtotime($timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether or not this is a secure cookie
|
|
||||||
*
|
|
||||||
* @return bool|null
|
|
||||||
*/
|
|
||||||
public function getSecure()
|
|
||||||
{
|
|
||||||
return $this->data['Secure'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether or not the cookie is secure
|
|
||||||
*
|
|
||||||
* @param bool $secure Set to true or false if secure
|
|
||||||
*/
|
|
||||||
public function setSecure($secure)
|
|
||||||
{
|
|
||||||
$this->data['Secure'] = $secure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether or not this is a session cookie
|
|
||||||
*
|
|
||||||
* @return bool|null
|
|
||||||
*/
|
|
||||||
public function getDiscard()
|
|
||||||
{
|
|
||||||
return $this->data['Discard'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether or not this is a session cookie
|
|
||||||
*
|
|
||||||
* @param bool $discard Set to true or false if this is a session cookie
|
|
||||||
*/
|
|
||||||
public function setDiscard($discard)
|
|
||||||
{
|
|
||||||
$this->data['Discard'] = $discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether or not this is an HTTP only cookie
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getHttpOnly()
|
|
||||||
{
|
|
||||||
return $this->data['HttpOnly'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether or not this is an HTTP only cookie
|
|
||||||
*
|
|
||||||
* @param bool $httpOnly Set to true or false if this is HTTP only
|
|
||||||
*/
|
|
||||||
public function setHttpOnly($httpOnly)
|
|
||||||
{
|
|
||||||
$this->data['HttpOnly'] = $httpOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the cookie matches a path value.
|
|
||||||
*
|
|
||||||
* A request-path path-matches a given cookie-path if at least one of
|
|
||||||
* the following conditions holds:
|
|
||||||
*
|
|
||||||
* - The cookie-path and the request-path are identical.
|
|
||||||
* - The cookie-path is a prefix of the request-path, and the last
|
|
||||||
* character of the cookie-path is %x2F ("/").
|
|
||||||
* - The cookie-path is a prefix of the request-path, and the first
|
|
||||||
* character of the request-path that is not included in the cookie-
|
|
||||||
* path is a %x2F ("/") character.
|
|
||||||
*
|
|
||||||
* @param string $requestPath Path to check against
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function matchesPath($requestPath)
|
|
||||||
{
|
|
||||||
$cookiePath = $this->getPath();
|
|
||||||
|
|
||||||
// Match on exact matches or when path is the default empty "/"
|
|
||||||
if ($cookiePath === '/' || $cookiePath == $requestPath) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that the cookie-path is a prefix of the request path.
|
|
||||||
if (0 !== strpos($requestPath, $cookiePath)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match if the last character of the cookie-path is "/"
|
|
||||||
if (substr($cookiePath, -1, 1) === '/') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match if the first character not included in cookie path is "/"
|
|
||||||
return substr($requestPath, strlen($cookiePath), 1) === '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the cookie matches a domain value
|
|
||||||
*
|
|
||||||
* @param string $domain Domain to check against
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function matchesDomain($domain)
|
|
||||||
{
|
|
||||||
// Remove the leading '.' as per spec in RFC 6265.
|
|
||||||
// http://tools.ietf.org/html/rfc6265#section-5.2.3
|
|
||||||
$cookieDomain = ltrim($this->getDomain(), '.');
|
|
||||||
|
|
||||||
// Domain not set or exact match.
|
|
||||||
if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matching the subdomain according to RFC 6265.
|
|
||||||
// http://tools.ietf.org/html/rfc6265#section-5.1.3
|
|
||||||
if (filter_var($domain, FILTER_VALIDATE_IP)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the cookie is expired
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isExpired()
|
|
||||||
{
|
|
||||||
return $this->getExpires() !== null && time() > $this->getExpires();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the cookie is valid according to RFC 6265
|
|
||||||
*
|
|
||||||
* @return bool|string Returns true if valid or an error message if invalid
|
|
||||||
*/
|
|
||||||
public function validate()
|
|
||||||
{
|
|
||||||
// Names must not be empty, but can be 0
|
|
||||||
$name = $this->getName();
|
|
||||||
if (empty($name) && !is_numeric($name)) {
|
|
||||||
return 'The cookie name must not be empty';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any of the invalid characters are present in the cookie name
|
|
||||||
if (preg_match(
|
|
||||||
'/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
|
|
||||||
$name
|
|
||||||
)) {
|
|
||||||
return 'Cookie name must not contain invalid characters: ASCII '
|
|
||||||
. 'Control characters (0-31;127), space, tab and the '
|
|
||||||
. 'following characters: ()<>@,;:\"/?={}';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value must not be empty, but can be 0
|
|
||||||
$value = $this->getValue();
|
|
||||||
if (empty($value) && !is_numeric($value)) {
|
|
||||||
return 'The cookie value must not be empty';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domains must not be empty, but can be 0
|
|
||||||
// A "0" is not a valid internet domain, but may be used as server name
|
|
||||||
// in a private network.
|
|
||||||
$domain = $this->getDomain();
|
|
||||||
if (empty($domain) && !is_numeric($domain)) {
|
|
||||||
return 'The cookie domain must not be empty';
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception when an HTTP error occurs (4xx or 5xx error)
|
|
||||||
*/
|
|
||||||
class BadResponseException extends RequestException
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
$message,
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
\Exception $previous = null,
|
|
||||||
array $handlerContext = []
|
|
||||||
) {
|
|
||||||
if (null === $response) {
|
|
||||||
@trigger_error(
|
|
||||||
'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
|
|
||||||
E_USER_DEPRECATED
|
|
||||||
);
|
|
||||||
}
|
|
||||||
parent::__construct($message, $request, $response, $previous, $handlerContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception when a client error is encountered (4xx codes)
|
|
||||||
*/
|
|
||||||
class ClientException extends BadResponseException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when a connection cannot be established.
|
|
||||||
*
|
|
||||||
* Note that no response is present for a ConnectException
|
|
||||||
*/
|
|
||||||
class ConnectException extends RequestException
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
$message,
|
|
||||||
RequestInterface $request,
|
|
||||||
\Exception $previous = null,
|
|
||||||
array $handlerContext = []
|
|
||||||
) {
|
|
||||||
parent::__construct($message, $request, null, $previous, $handlerContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return null
|
|
||||||
*/
|
|
||||||
public function getResponse()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasResponse()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
if (interface_exists(Throwable::class)) {
|
|
||||||
interface GuzzleException extends Throwable
|
|
||||||
{
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* @method string getMessage()
|
|
||||||
* @method \Throwable|null getPrevious()
|
|
||||||
* @method mixed getCode()
|
|
||||||
* @method string getFile()
|
|
||||||
* @method int getLine()
|
|
||||||
* @method array getTrace()
|
|
||||||
* @method string getTraceAsString()
|
|
||||||
*/
|
|
||||||
interface GuzzleException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
final class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\UriInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP Request exception
|
|
||||||
*/
|
|
||||||
class RequestException extends TransferException
|
|
||||||
{
|
|
||||||
/** @var RequestInterface */
|
|
||||||
private $request;
|
|
||||||
|
|
||||||
/** @var ResponseInterface|null */
|
|
||||||
private $response;
|
|
||||||
|
|
||||||
/** @var array */
|
|
||||||
private $handlerContext;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
$message,
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
\Exception $previous = null,
|
|
||||||
array $handlerContext = []
|
|
||||||
) {
|
|
||||||
// Set the code of the exception if the response is set and not future.
|
|
||||||
$code = $response && !($response instanceof PromiseInterface)
|
|
||||||
? $response->getStatusCode()
|
|
||||||
: 0;
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
$this->request = $request;
|
|
||||||
$this->response = $response;
|
|
||||||
$this->handlerContext = $handlerContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap non-RequestExceptions with a RequestException
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param \Exception $e
|
|
||||||
*
|
|
||||||
* @return RequestException
|
|
||||||
*/
|
|
||||||
public static function wrapException(RequestInterface $request, \Exception $e)
|
|
||||||
{
|
|
||||||
return $e instanceof RequestException
|
|
||||||
? $e
|
|
||||||
: new RequestException($e->getMessage(), $request, null, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a new exception with a normalized error message
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request
|
|
||||||
* @param ResponseInterface $response Response received
|
|
||||||
* @param \Exception $previous Previous exception
|
|
||||||
* @param array $ctx Optional handler context.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function create(
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
\Exception $previous = null,
|
|
||||||
array $ctx = []
|
|
||||||
) {
|
|
||||||
if (!$response) {
|
|
||||||
return new self(
|
|
||||||
'Error completing request',
|
|
||||||
$request,
|
|
||||||
null,
|
|
||||||
$previous,
|
|
||||||
$ctx
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$level = (int) floor($response->getStatusCode() / 100);
|
|
||||||
if ($level === 4) {
|
|
||||||
$label = 'Client error';
|
|
||||||
$className = ClientException::class;
|
|
||||||
} elseif ($level === 5) {
|
|
||||||
$label = 'Server error';
|
|
||||||
$className = ServerException::class;
|
|
||||||
} else {
|
|
||||||
$label = 'Unsuccessful request';
|
|
||||||
$className = __CLASS__;
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = $request->getUri();
|
|
||||||
$uri = static::obfuscateUri($uri);
|
|
||||||
|
|
||||||
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
|
||||||
// <html> ... (truncated)
|
|
||||||
$message = sprintf(
|
|
||||||
'%s: `%s %s` resulted in a `%s %s` response',
|
|
||||||
$label,
|
|
||||||
$request->getMethod(),
|
|
||||||
$uri,
|
|
||||||
$response->getStatusCode(),
|
|
||||||
$response->getReasonPhrase()
|
|
||||||
);
|
|
||||||
|
|
||||||
$summary = static::getResponseBodySummary($response);
|
|
||||||
|
|
||||||
if ($summary !== null) {
|
|
||||||
$message .= ":\n{$summary}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return new $className($message, $request, $response, $previous, $ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a short summary of the response
|
|
||||||
*
|
|
||||||
* Will return `null` if the response is not printable.
|
|
||||||
*
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public static function getResponseBodySummary(ResponseInterface $response)
|
|
||||||
{
|
|
||||||
return \GuzzleHttp\Psr7\get_message_body_summary($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obfuscates URI if there is a username and a password present
|
|
||||||
*
|
|
||||||
* @param UriInterface $uri
|
|
||||||
*
|
|
||||||
* @return UriInterface
|
|
||||||
*/
|
|
||||||
private static function obfuscateUri(UriInterface $uri)
|
|
||||||
{
|
|
||||||
$userInfo = $uri->getUserInfo();
|
|
||||||
|
|
||||||
if (false !== ($pos = strpos($userInfo, ':'))) {
|
|
||||||
return $uri->withUserInfo(substr($userInfo, 0, $pos), '***');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the request that caused the exception
|
|
||||||
*
|
|
||||||
* @return RequestInterface
|
|
||||||
*/
|
|
||||||
public function getRequest()
|
|
||||||
{
|
|
||||||
return $this->request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the associated response
|
|
||||||
*
|
|
||||||
* @return ResponseInterface|null
|
|
||||||
*/
|
|
||||||
public function getResponse()
|
|
||||||
{
|
|
||||||
return $this->response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a response was received
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasResponse()
|
|
||||||
{
|
|
||||||
return $this->response !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get contextual information about the error from the underlying handler.
|
|
||||||
*
|
|
||||||
* The contents of this array will vary depending on which handler you are
|
|
||||||
* using. It may also be just an empty array. Relying on this data will
|
|
||||||
* couple you to a specific handler, but can give more debug information
|
|
||||||
* when needed.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getHandlerContext()
|
|
||||||
{
|
|
||||||
return $this->handlerContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
use Psr\Http\Message\StreamInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when a seek fails on a stream.
|
|
||||||
*/
|
|
||||||
class SeekException extends \RuntimeException implements GuzzleException
|
|
||||||
{
|
|
||||||
private $stream;
|
|
||||||
|
|
||||||
public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
|
|
||||||
{
|
|
||||||
$this->stream = $stream;
|
|
||||||
$msg = $msg ?: 'Could not seek the stream to position ' . $pos;
|
|
||||||
parent::__construct($msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return StreamInterface
|
|
||||||
*/
|
|
||||||
public function getStream()
|
|
||||||
{
|
|
||||||
return $this->stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception when a server error is encountered (5xx codes)
|
|
||||||
*/
|
|
||||||
class ServerException extends BadResponseException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
class TooManyRedirectsException extends RequestException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Exception;
|
|
||||||
|
|
||||||
class TransferException extends \RuntimeException implements GuzzleException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
585
vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
vendored
585
vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
vendored
@@ -1,585 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\ConnectException;
|
|
||||||
use GuzzleHttp\Exception\RequestException;
|
|
||||||
use GuzzleHttp\Promise\FulfilledPromise;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use GuzzleHttp\Psr7\LazyOpenStream;
|
|
||||||
use GuzzleHttp\TransferStats;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates curl resources from a request
|
|
||||||
*/
|
|
||||||
class CurlFactory implements CurlFactoryInterface
|
|
||||||
{
|
|
||||||
const CURL_VERSION_STR = 'curl_version';
|
|
||||||
const LOW_CURL_VERSION_NUMBER = '7.21.2';
|
|
||||||
|
|
||||||
/** @var array */
|
|
||||||
private $handles = [];
|
|
||||||
|
|
||||||
/** @var int Total number of idle handles to keep in cache */
|
|
||||||
private $maxHandles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $maxHandles Maximum number of idle handles.
|
|
||||||
*/
|
|
||||||
public function __construct($maxHandles)
|
|
||||||
{
|
|
||||||
$this->maxHandles = $maxHandles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
if (isset($options['curl']['body_as_string'])) {
|
|
||||||
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
|
||||||
unset($options['curl']['body_as_string']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$easy = new EasyHandle;
|
|
||||||
$easy->request = $request;
|
|
||||||
$easy->options = $options;
|
|
||||||
$conf = $this->getDefaultConf($easy);
|
|
||||||
$this->applyMethod($easy, $conf);
|
|
||||||
$this->applyHandlerOptions($easy, $conf);
|
|
||||||
$this->applyHeaders($easy, $conf);
|
|
||||||
unset($conf['_headers']);
|
|
||||||
|
|
||||||
// Add handler options from the request configuration options
|
|
||||||
if (isset($options['curl'])) {
|
|
||||||
$conf = array_replace($conf, $options['curl']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
|
|
||||||
$easy->handle = $this->handles
|
|
||||||
? array_pop($this->handles)
|
|
||||||
: curl_init();
|
|
||||||
curl_setopt_array($easy->handle, $conf);
|
|
||||||
|
|
||||||
return $easy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function release(EasyHandle $easy)
|
|
||||||
{
|
|
||||||
$resource = $easy->handle;
|
|
||||||
unset($easy->handle);
|
|
||||||
|
|
||||||
if (count($this->handles) >= $this->maxHandles) {
|
|
||||||
curl_close($resource);
|
|
||||||
} else {
|
|
||||||
// Remove all callback functions as they can hold onto references
|
|
||||||
// and are not cleaned up by curl_reset. Using curl_setopt_array
|
|
||||||
// does not work for some reason, so removing each one
|
|
||||||
// individually.
|
|
||||||
curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
|
|
||||||
curl_setopt($resource, CURLOPT_READFUNCTION, null);
|
|
||||||
curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
|
|
||||||
curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
|
|
||||||
curl_reset($resource);
|
|
||||||
$this->handles[] = $resource;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Completes a cURL transaction, either returning a response promise or a
|
|
||||||
* rejected promise.
|
|
||||||
*
|
|
||||||
* @param callable $handler
|
|
||||||
* @param EasyHandle $easy
|
|
||||||
* @param CurlFactoryInterface $factory Dictates how the handle is released
|
|
||||||
*
|
|
||||||
* @return \GuzzleHttp\Promise\PromiseInterface
|
|
||||||
*/
|
|
||||||
public static function finish(
|
|
||||||
callable $handler,
|
|
||||||
EasyHandle $easy,
|
|
||||||
CurlFactoryInterface $factory
|
|
||||||
) {
|
|
||||||
if (isset($easy->options['on_stats'])) {
|
|
||||||
self::invokeStats($easy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$easy->response || $easy->errno) {
|
|
||||||
return self::finishError($handler, $easy, $factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the response if it is present and there is no error.
|
|
||||||
$factory->release($easy);
|
|
||||||
|
|
||||||
// Rewind the body of the response if possible.
|
|
||||||
$body = $easy->response->getBody();
|
|
||||||
if ($body->isSeekable()) {
|
|
||||||
$body->rewind();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FulfilledPromise($easy->response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function invokeStats(EasyHandle $easy)
|
|
||||||
{
|
|
||||||
$curlStats = curl_getinfo($easy->handle);
|
|
||||||
$curlStats['appconnect_time'] = curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME);
|
|
||||||
$stats = new TransferStats(
|
|
||||||
$easy->request,
|
|
||||||
$easy->response,
|
|
||||||
$curlStats['total_time'],
|
|
||||||
$easy->errno,
|
|
||||||
$curlStats
|
|
||||||
);
|
|
||||||
call_user_func($easy->options['on_stats'], $stats);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function finishError(
|
|
||||||
callable $handler,
|
|
||||||
EasyHandle $easy,
|
|
||||||
CurlFactoryInterface $factory
|
|
||||||
) {
|
|
||||||
// Get error information and release the handle to the factory.
|
|
||||||
$ctx = [
|
|
||||||
'errno' => $easy->errno,
|
|
||||||
'error' => curl_error($easy->handle),
|
|
||||||
'appconnect_time' => curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME),
|
|
||||||
] + curl_getinfo($easy->handle);
|
|
||||||
$ctx[self::CURL_VERSION_STR] = curl_version()['version'];
|
|
||||||
$factory->release($easy);
|
|
||||||
|
|
||||||
// Retry when nothing is present or when curl failed to rewind.
|
|
||||||
if (empty($easy->options['_err_message'])
|
|
||||||
&& (!$easy->errno || $easy->errno == 65)
|
|
||||||
) {
|
|
||||||
return self::retryFailedRewind($handler, $easy, $ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::createRejection($easy, $ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function createRejection(EasyHandle $easy, array $ctx)
|
|
||||||
{
|
|
||||||
static $connectionErrors = [
|
|
||||||
CURLE_OPERATION_TIMEOUTED => true,
|
|
||||||
CURLE_COULDNT_RESOLVE_HOST => true,
|
|
||||||
CURLE_COULDNT_CONNECT => true,
|
|
||||||
CURLE_SSL_CONNECT_ERROR => true,
|
|
||||||
CURLE_GOT_NOTHING => true,
|
|
||||||
];
|
|
||||||
|
|
||||||
// If an exception was encountered during the onHeaders event, then
|
|
||||||
// return a rejected promise that wraps that exception.
|
|
||||||
if ($easy->onHeadersException) {
|
|
||||||
return \GuzzleHttp\Promise\rejection_for(
|
|
||||||
new RequestException(
|
|
||||||
'An error was encountered during the on_headers event',
|
|
||||||
$easy->request,
|
|
||||||
$easy->response,
|
|
||||||
$easy->onHeadersException,
|
|
||||||
$ctx
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
|
|
||||||
$message = sprintf(
|
|
||||||
'cURL error %s: %s (%s)',
|
|
||||||
$ctx['errno'],
|
|
||||||
$ctx['error'],
|
|
||||||
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$message = sprintf(
|
|
||||||
'cURL error %s: %s (%s) for %s',
|
|
||||||
$ctx['errno'],
|
|
||||||
$ctx['error'],
|
|
||||||
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html',
|
|
||||||
$easy->request->getUri()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a connection exception if it was a specific error code.
|
|
||||||
$error = isset($connectionErrors[$easy->errno])
|
|
||||||
? new ConnectException($message, $easy->request, null, $ctx)
|
|
||||||
: new RequestException($message, $easy->request, $easy->response, null, $ctx);
|
|
||||||
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($error);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDefaultConf(EasyHandle $easy)
|
|
||||||
{
|
|
||||||
$conf = [
|
|
||||||
'_headers' => $easy->request->getHeaders(),
|
|
||||||
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
|
|
||||||
CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
|
|
||||||
CURLOPT_RETURNTRANSFER => false,
|
|
||||||
CURLOPT_HEADER => false,
|
|
||||||
CURLOPT_CONNECTTIMEOUT => 150,
|
|
||||||
];
|
|
||||||
|
|
||||||
if (defined('CURLOPT_PROTOCOLS')) {
|
|
||||||
$conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
$version = $easy->request->getProtocolVersion();
|
|
||||||
if ($version == 1.1) {
|
|
||||||
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
|
||||||
} elseif ($version == 2.0) {
|
|
||||||
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
|
||||||
} else {
|
|
||||||
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function applyMethod(EasyHandle $easy, array &$conf)
|
|
||||||
{
|
|
||||||
$body = $easy->request->getBody();
|
|
||||||
$size = $body->getSize();
|
|
||||||
|
|
||||||
if ($size === null || $size > 0) {
|
|
||||||
$this->applyBody($easy->request, $easy->options, $conf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$method = $easy->request->getMethod();
|
|
||||||
if ($method === 'PUT' || $method === 'POST') {
|
|
||||||
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
|
||||||
if (!$easy->request->hasHeader('Content-Length')) {
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
|
||||||
}
|
|
||||||
} elseif ($method === 'HEAD') {
|
|
||||||
$conf[CURLOPT_NOBODY] = true;
|
|
||||||
unset(
|
|
||||||
$conf[CURLOPT_WRITEFUNCTION],
|
|
||||||
$conf[CURLOPT_READFUNCTION],
|
|
||||||
$conf[CURLOPT_FILE],
|
|
||||||
$conf[CURLOPT_INFILE]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function applyBody(RequestInterface $request, array $options, array &$conf)
|
|
||||||
{
|
|
||||||
$size = $request->hasHeader('Content-Length')
|
|
||||||
? (int) $request->getHeaderLine('Content-Length')
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Send the body as a string if the size is less than 1MB OR if the
|
|
||||||
// [curl][body_as_string] request value is set.
|
|
||||||
if (($size !== null && $size < 1000000) ||
|
|
||||||
!empty($options['_body_as_string'])
|
|
||||||
) {
|
|
||||||
$conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
|
|
||||||
// Don't duplicate the Content-Length header
|
|
||||||
$this->removeHeader('Content-Length', $conf);
|
|
||||||
$this->removeHeader('Transfer-Encoding', $conf);
|
|
||||||
} else {
|
|
||||||
$conf[CURLOPT_UPLOAD] = true;
|
|
||||||
if ($size !== null) {
|
|
||||||
$conf[CURLOPT_INFILESIZE] = $size;
|
|
||||||
$this->removeHeader('Content-Length', $conf);
|
|
||||||
}
|
|
||||||
$body = $request->getBody();
|
|
||||||
if ($body->isSeekable()) {
|
|
||||||
$body->rewind();
|
|
||||||
}
|
|
||||||
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
|
|
||||||
return $body->read($length);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the Expect header is not present, prevent curl from adding it
|
|
||||||
if (!$request->hasHeader('Expect')) {
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = 'Expect:';
|
|
||||||
}
|
|
||||||
|
|
||||||
// cURL sometimes adds a content-type by default. Prevent this.
|
|
||||||
if (!$request->hasHeader('Content-Type')) {
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function applyHeaders(EasyHandle $easy, array &$conf)
|
|
||||||
{
|
|
||||||
foreach ($conf['_headers'] as $name => $values) {
|
|
||||||
foreach ($values as $value) {
|
|
||||||
$value = (string) $value;
|
|
||||||
if ($value === '') {
|
|
||||||
// cURL requires a special format for empty headers.
|
|
||||||
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = "$name;";
|
|
||||||
} else {
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the Accept header if one was not set
|
|
||||||
if (!$easy->request->hasHeader('Accept')) {
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = 'Accept:';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a header from the options array.
|
|
||||||
*
|
|
||||||
* @param string $name Case-insensitive header to remove
|
|
||||||
* @param array $options Array of options to modify
|
|
||||||
*/
|
|
||||||
private function removeHeader($name, array &$options)
|
|
||||||
{
|
|
||||||
foreach (array_keys($options['_headers']) as $key) {
|
|
||||||
if (!strcasecmp($key, $name)) {
|
|
||||||
unset($options['_headers'][$key]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function applyHandlerOptions(EasyHandle $easy, array &$conf)
|
|
||||||
{
|
|
||||||
$options = $easy->options;
|
|
||||||
if (isset($options['verify'])) {
|
|
||||||
if ($options['verify'] === false) {
|
|
||||||
unset($conf[CURLOPT_CAINFO]);
|
|
||||||
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
|
|
||||||
$conf[CURLOPT_SSL_VERIFYPEER] = false;
|
|
||||||
} else {
|
|
||||||
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
|
|
||||||
$conf[CURLOPT_SSL_VERIFYPEER] = true;
|
|
||||||
if (is_string($options['verify'])) {
|
|
||||||
// Throw an error if the file/folder/link path is not valid or doesn't exist.
|
|
||||||
if (!file_exists($options['verify'])) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"SSL CA bundle not found: {$options['verify']}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
|
||||||
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
|
||||||
if (is_dir($options['verify']) ||
|
|
||||||
(is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
|
|
||||||
$conf[CURLOPT_CAPATH] = $options['verify'];
|
|
||||||
} else {
|
|
||||||
$conf[CURLOPT_CAINFO] = $options['verify'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($options['decode_content'])) {
|
|
||||||
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
|
||||||
if ($accept) {
|
|
||||||
$conf[CURLOPT_ENCODING] = $accept;
|
|
||||||
} else {
|
|
||||||
$conf[CURLOPT_ENCODING] = '';
|
|
||||||
// Don't let curl send the header over the wire
|
|
||||||
$conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['sink'])) {
|
|
||||||
$sink = $options['sink'];
|
|
||||||
if (!is_string($sink)) {
|
|
||||||
$sink = \GuzzleHttp\Psr7\stream_for($sink);
|
|
||||||
} elseif (!is_dir(dirname($sink))) {
|
|
||||||
// Ensure that the directory exists before failing in curl.
|
|
||||||
throw new \RuntimeException(sprintf(
|
|
||||||
'Directory %s does not exist for sink value of %s',
|
|
||||||
dirname($sink),
|
|
||||||
$sink
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
$sink = new LazyOpenStream($sink, 'w+');
|
|
||||||
}
|
|
||||||
$easy->sink = $sink;
|
|
||||||
$conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
|
|
||||||
return $sink->write($write);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Use a default temp stream if no sink was set.
|
|
||||||
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
|
|
||||||
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
|
|
||||||
}
|
|
||||||
$timeoutRequiresNoSignal = false;
|
|
||||||
if (isset($options['timeout'])) {
|
|
||||||
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
|
||||||
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CURL default value is CURL_IPRESOLVE_WHATEVER
|
|
||||||
if (isset($options['force_ip_resolve'])) {
|
|
||||||
if ('v4' === $options['force_ip_resolve']) {
|
|
||||||
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
|
||||||
} elseif ('v6' === $options['force_ip_resolve']) {
|
|
||||||
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['connect_timeout'])) {
|
|
||||||
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
|
|
||||||
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
|
||||||
$conf[CURLOPT_NOSIGNAL] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['proxy'])) {
|
|
||||||
if (!is_array($options['proxy'])) {
|
|
||||||
$conf[CURLOPT_PROXY] = $options['proxy'];
|
|
||||||
} else {
|
|
||||||
$scheme = $easy->request->getUri()->getScheme();
|
|
||||||
if (isset($options['proxy'][$scheme])) {
|
|
||||||
$host = $easy->request->getUri()->getHost();
|
|
||||||
if (!isset($options['proxy']['no']) ||
|
|
||||||
!\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
|
|
||||||
) {
|
|
||||||
$conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['cert'])) {
|
|
||||||
$cert = $options['cert'];
|
|
||||||
if (is_array($cert)) {
|
|
||||||
$conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
|
|
||||||
$cert = $cert[0];
|
|
||||||
}
|
|
||||||
if (!file_exists($cert)) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"SSL certificate not found: {$cert}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$conf[CURLOPT_SSLCERT] = $cert;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['ssl_key'])) {
|
|
||||||
if (is_array($options['ssl_key'])) {
|
|
||||||
if (count($options['ssl_key']) === 2) {
|
|
||||||
list($sslKey, $conf[CURLOPT_SSLKEYPASSWD]) = $options['ssl_key'];
|
|
||||||
} else {
|
|
||||||
list($sslKey) = $options['ssl_key'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sslKey = isset($sslKey) ? $sslKey: $options['ssl_key'];
|
|
||||||
|
|
||||||
if (!file_exists($sslKey)) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"SSL private key not found: {$sslKey}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$conf[CURLOPT_SSLKEY] = $sslKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['progress'])) {
|
|
||||||
$progress = $options['progress'];
|
|
||||||
if (!is_callable($progress)) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
'progress client option must be callable'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$conf[CURLOPT_NOPROGRESS] = false;
|
|
||||||
$conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
|
|
||||||
$args = func_get_args();
|
|
||||||
// PHP 5.5 pushed the handle onto the start of the args
|
|
||||||
if (is_resource($args[0])) {
|
|
||||||
array_shift($args);
|
|
||||||
}
|
|
||||||
call_user_func_array($progress, $args);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($options['debug'])) {
|
|
||||||
$conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
|
|
||||||
$conf[CURLOPT_VERBOSE] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function ensures that a response was set on a transaction. If one
|
|
||||||
* was not set, then the request is retried if possible. This error
|
|
||||||
* typically means you are sending a payload, curl encountered a
|
|
||||||
* "Connection died, retrying a fresh connect" error, tried to rewind the
|
|
||||||
* stream, and then encountered a "necessary data rewind wasn't possible"
|
|
||||||
* error, causing the request to be sent through curl_multi_info_read()
|
|
||||||
* without an error status.
|
|
||||||
*/
|
|
||||||
private static function retryFailedRewind(
|
|
||||||
callable $handler,
|
|
||||||
EasyHandle $easy,
|
|
||||||
array $ctx
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
// Only rewind if the body has been read from.
|
|
||||||
$body = $easy->request->getBody();
|
|
||||||
if ($body->tell() > 0) {
|
|
||||||
$body->rewind();
|
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
return self::createRejection($easy, $ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retry no more than 3 times before giving up.
|
|
||||||
if (!isset($easy->options['_curl_retries'])) {
|
|
||||||
$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.';
|
|
||||||
return self::createRejection($easy, $ctx);
|
|
||||||
} else {
|
|
||||||
$easy->options['_curl_retries']++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $handler($easy->request, $easy->options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createHeaderFn(EasyHandle $easy)
|
|
||||||
{
|
|
||||||
if (isset($easy->options['on_headers'])) {
|
|
||||||
$onHeaders = $easy->options['on_headers'];
|
|
||||||
|
|
||||||
if (!is_callable($onHeaders)) {
|
|
||||||
throw new \InvalidArgumentException('on_headers must be callable');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$onHeaders = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return function ($ch, $h) use (
|
|
||||||
$onHeaders,
|
|
||||||
$easy,
|
|
||||||
&$startingResponse
|
|
||||||
) {
|
|
||||||
$value = trim($h);
|
|
||||||
if ($value === '') {
|
|
||||||
$startingResponse = true;
|
|
||||||
$easy->createResponse();
|
|
||||||
if ($onHeaders !== null) {
|
|
||||||
try {
|
|
||||||
$onHeaders($easy->response);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// Associate the exception with the handle and trigger
|
|
||||||
// a curl header write error by returning 0.
|
|
||||||
$easy->onHeadersException = $e;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif ($startingResponse) {
|
|
||||||
$startingResponse = false;
|
|
||||||
$easy->headers = [$value];
|
|
||||||
} else {
|
|
||||||
$easy->headers[] = $value;
|
|
||||||
}
|
|
||||||
return strlen($h);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
interface CurlFactoryInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a cURL handle resource.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request
|
|
||||||
* @param array $options Transfer options
|
|
||||||
*
|
|
||||||
* @return EasyHandle
|
|
||||||
* @throws \RuntimeException when an option cannot be applied
|
|
||||||
*/
|
|
||||||
public function create(RequestInterface $request, array $options);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release an easy handle, allowing it to be reused or closed.
|
|
||||||
*
|
|
||||||
* This function must call unset on the easy handle's "handle" property.
|
|
||||||
*
|
|
||||||
* @param EasyHandle $easy
|
|
||||||
*/
|
|
||||||
public function release(EasyHandle $easy);
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP handler that uses cURL easy handles as a transport layer.
|
|
||||||
*
|
|
||||||
* When using the CurlHandler, custom curl options can be specified as an
|
|
||||||
* associative array of curl option constants mapping to values in the
|
|
||||||
* **curl** key of the "client" key of the request.
|
|
||||||
*/
|
|
||||||
class CurlHandler
|
|
||||||
{
|
|
||||||
/** @var CurlFactoryInterface */
|
|
||||||
private $factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accepts an associative array of options:
|
|
||||||
*
|
|
||||||
* - factory: Optional curl factory used to create cURL handles.
|
|
||||||
*
|
|
||||||
* @param array $options Array of options to use with the handler
|
|
||||||
*/
|
|
||||||
public function __construct(array $options = [])
|
|
||||||
{
|
|
||||||
$this->factory = isset($options['handle_factory'])
|
|
||||||
? $options['handle_factory']
|
|
||||||
: new CurlFactory(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
if (isset($options['delay'])) {
|
|
||||||
usleep($options['delay'] * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
$easy = $this->factory->create($request, $options);
|
|
||||||
curl_exec($easy->handle);
|
|
||||||
$easy->errno = curl_errno($easy->handle);
|
|
||||||
|
|
||||||
return CurlFactory::finish($this, $easy, $this->factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,219 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise as P;
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
use GuzzleHttp\Utils;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an asynchronous response using curl_multi_* functions.
|
|
||||||
*
|
|
||||||
* When using the CurlMultiHandler, custom curl options can be specified as an
|
|
||||||
* associative array of curl option constants mapping to values in the
|
|
||||||
* **curl** key of the provided request options.
|
|
||||||
*
|
|
||||||
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
|
||||||
*/
|
|
||||||
class CurlMultiHandler
|
|
||||||
{
|
|
||||||
/** @var CurlFactoryInterface */
|
|
||||||
private $factory;
|
|
||||||
private $selectTimeout;
|
|
||||||
private $active;
|
|
||||||
private $handles = [];
|
|
||||||
private $delays = [];
|
|
||||||
private $options = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This handler accepts the following options:
|
|
||||||
*
|
|
||||||
* - handle_factory: An optional factory used to create curl handles
|
|
||||||
* - select_timeout: Optional timeout (in seconds) to block before timing
|
|
||||||
* out while selecting curl handles. Defaults to 1 second.
|
|
||||||
* - options: An associative array of CURLMOPT_* options and
|
|
||||||
* corresponding values for curl_multi_setopt()
|
|
||||||
*
|
|
||||||
* @param array $options
|
|
||||||
*/
|
|
||||||
public function __construct(array $options = [])
|
|
||||||
{
|
|
||||||
$this->factory = isset($options['handle_factory'])
|
|
||||||
? $options['handle_factory'] : new CurlFactory(50);
|
|
||||||
|
|
||||||
if (isset($options['select_timeout'])) {
|
|
||||||
$this->selectTimeout = $options['select_timeout'];
|
|
||||||
} elseif ($selectTimeout = getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
|
|
||||||
$this->selectTimeout = $selectTimeout;
|
|
||||||
} else {
|
|
||||||
$this->selectTimeout = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->options = isset($options['options']) ? $options['options'] : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __get($name)
|
|
||||||
{
|
|
||||||
if ($name === '_mh') {
|
|
||||||
$this->_mh = curl_multi_init();
|
|
||||||
|
|
||||||
foreach ($this->options as $option => $value) {
|
|
||||||
// A warning is raised in case of a wrong option.
|
|
||||||
curl_multi_setopt($this->_mh, $option, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Further calls to _mh will return the value directly, without entering the
|
|
||||||
// __get() method at all.
|
|
||||||
return $this->_mh;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \BadMethodCallException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
if (isset($this->_mh)) {
|
|
||||||
curl_multi_close($this->_mh);
|
|
||||||
unset($this->_mh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
$easy = $this->factory->create($request, $options);
|
|
||||||
$id = (int) $easy->handle;
|
|
||||||
|
|
||||||
$promise = new Promise(
|
|
||||||
[$this, 'execute'],
|
|
||||||
function () use ($id) {
|
|
||||||
return $this->cancel($id);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
|
|
||||||
|
|
||||||
return $promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ticks the curl event loop.
|
|
||||||
*/
|
|
||||||
public function tick()
|
|
||||||
{
|
|
||||||
// Add any delayed handles if needed.
|
|
||||||
if ($this->delays) {
|
|
||||||
$currentTime = Utils::currentTime();
|
|
||||||
foreach ($this->delays as $id => $delay) {
|
|
||||||
if ($currentTime >= $delay) {
|
|
||||||
unset($this->delays[$id]);
|
|
||||||
curl_multi_add_handle(
|
|
||||||
$this->_mh,
|
|
||||||
$this->handles[$id]['easy']->handle
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step through the task queue which may add additional requests.
|
|
||||||
P\queue()->run();
|
|
||||||
|
|
||||||
if ($this->active &&
|
|
||||||
curl_multi_select($this->_mh, $this->selectTimeout) === -1
|
|
||||||
) {
|
|
||||||
// Perform a usleep if a select returns -1.
|
|
||||||
// See: https://bugs.php.net/bug.php?id=61141
|
|
||||||
usleep(250);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
|
|
||||||
|
|
||||||
$this->processMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs until all outstanding connections have completed.
|
|
||||||
*/
|
|
||||||
public function execute()
|
|
||||||
{
|
|
||||||
$queue = P\queue();
|
|
||||||
|
|
||||||
while ($this->handles || !$queue->isEmpty()) {
|
|
||||||
// If there are no transfers, then sleep for the next delay
|
|
||||||
if (!$this->active && $this->delays) {
|
|
||||||
usleep($this->timeToNext());
|
|
||||||
}
|
|
||||||
$this->tick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function addRequest(array $entry)
|
|
||||||
{
|
|
||||||
$easy = $entry['easy'];
|
|
||||||
$id = (int) $easy->handle;
|
|
||||||
$this->handles[$id] = $entry;
|
|
||||||
if (empty($easy->options['delay'])) {
|
|
||||||
curl_multi_add_handle($this->_mh, $easy->handle);
|
|
||||||
} else {
|
|
||||||
$this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels a handle from sending and removes references to it.
|
|
||||||
*
|
|
||||||
* @param int $id Handle ID to cancel and remove.
|
|
||||||
*
|
|
||||||
* @return bool True on success, false on failure.
|
|
||||||
*/
|
|
||||||
private function cancel($id)
|
|
||||||
{
|
|
||||||
// Cannot cancel if it has been processed.
|
|
||||||
if (!isset($this->handles[$id])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$handle = $this->handles[$id]['easy']->handle;
|
|
||||||
unset($this->delays[$id], $this->handles[$id]);
|
|
||||||
curl_multi_remove_handle($this->_mh, $handle);
|
|
||||||
curl_close($handle);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function processMessages()
|
|
||||||
{
|
|
||||||
while ($done = curl_multi_info_read($this->_mh)) {
|
|
||||||
$id = (int) $done['handle'];
|
|
||||||
curl_multi_remove_handle($this->_mh, $done['handle']);
|
|
||||||
|
|
||||||
if (!isset($this->handles[$id])) {
|
|
||||||
// Probably was cancelled.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entry = $this->handles[$id];
|
|
||||||
unset($this->handles[$id], $this->delays[$id]);
|
|
||||||
$entry['easy']->errno = $done['result'];
|
|
||||||
$entry['deferred']->resolve(
|
|
||||||
CurlFactory::finish(
|
|
||||||
$this,
|
|
||||||
$entry['easy'],
|
|
||||||
$this->factory
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function timeToNext()
|
|
||||||
{
|
|
||||||
$currentTime = Utils::currentTime();
|
|
||||||
$nextTime = PHP_INT_MAX;
|
|
||||||
foreach ($this->delays as $time) {
|
|
||||||
if ($time < $nextTime) {
|
|
||||||
$nextTime = $time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max(0, $nextTime - $currentTime) * 1000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\Psr7\Response;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\StreamInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a cURL easy handle and the data it populates.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
final class EasyHandle
|
|
||||||
{
|
|
||||||
/** @var resource cURL resource */
|
|
||||||
public $handle;
|
|
||||||
|
|
||||||
/** @var StreamInterface Where data is being written */
|
|
||||||
public $sink;
|
|
||||||
|
|
||||||
/** @var array Received HTTP headers so far */
|
|
||||||
public $headers = [];
|
|
||||||
|
|
||||||
/** @var ResponseInterface Received response (if any) */
|
|
||||||
public $response;
|
|
||||||
|
|
||||||
/** @var RequestInterface Request being sent */
|
|
||||||
public $request;
|
|
||||||
|
|
||||||
/** @var array Request options */
|
|
||||||
public $options = [];
|
|
||||||
|
|
||||||
/** @var int cURL error number (if any) */
|
|
||||||
public $errno = 0;
|
|
||||||
|
|
||||||
/** @var \Exception Exception during on_headers (if any) */
|
|
||||||
public $onHeadersException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach a response to the easy handle based on the received headers.
|
|
||||||
*
|
|
||||||
* @throws \RuntimeException if no headers have been received.
|
|
||||||
*/
|
|
||||||
public function createResponse()
|
|
||||||
{
|
|
||||||
if (empty($this->headers)) {
|
|
||||||
throw new \RuntimeException('No headers have been received');
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP-version SP status-code SP reason-phrase
|
|
||||||
$startLine = explode(' ', array_shift($this->headers), 3);
|
|
||||||
$headers = \GuzzleHttp\headers_from_lines($this->headers);
|
|
||||||
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
|
||||||
|
|
||||||
if (!empty($this->options['decode_content'])
|
|
||||||
&& isset($normalizedKeys['content-encoding'])
|
|
||||||
) {
|
|
||||||
$headers['x-encoded-content-encoding']
|
|
||||||
= $headers[$normalizedKeys['content-encoding']];
|
|
||||||
unset($headers[$normalizedKeys['content-encoding']]);
|
|
||||||
if (isset($normalizedKeys['content-length'])) {
|
|
||||||
$headers['x-encoded-content-length']
|
|
||||||
= $headers[$normalizedKeys['content-length']];
|
|
||||||
|
|
||||||
$bodyLength = (int) $this->sink->getSize();
|
|
||||||
if ($bodyLength) {
|
|
||||||
$headers[$normalizedKeys['content-length']] = $bodyLength;
|
|
||||||
} else {
|
|
||||||
unset($headers[$normalizedKeys['content-length']]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach a response to the easy handle with the parsed headers.
|
|
||||||
$this->response = new Response(
|
|
||||||
$startLine[1],
|
|
||||||
$headers,
|
|
||||||
$this->sink,
|
|
||||||
substr($startLine[0], 5),
|
|
||||||
isset($startLine[2]) ? (string) $startLine[2] : null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __get($name)
|
|
||||||
{
|
|
||||||
$msg = $name === 'handle'
|
|
||||||
? 'The EasyHandle has been released'
|
|
||||||
: 'Invalid property: ' . $name;
|
|
||||||
throw new \BadMethodCallException($msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
195
vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
vendored
195
vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
vendored
@@ -1,195 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\RequestException;
|
|
||||||
use GuzzleHttp\HandlerStack;
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use GuzzleHttp\Promise\RejectedPromise;
|
|
||||||
use GuzzleHttp\TransferStats;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler that returns responses or throw exceptions from a queue.
|
|
||||||
*/
|
|
||||||
class MockHandler implements \Countable
|
|
||||||
{
|
|
||||||
private $queue = [];
|
|
||||||
private $lastRequest;
|
|
||||||
private $lastOptions;
|
|
||||||
private $onFulfilled;
|
|
||||||
private $onRejected;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new MockHandler that uses the default handler stack list of
|
|
||||||
* middlewares.
|
|
||||||
*
|
|
||||||
* @param array $queue Array of responses, callables, or exceptions.
|
|
||||||
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
|
||||||
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
|
||||||
*
|
|
||||||
* @return HandlerStack
|
|
||||||
*/
|
|
||||||
public static function createWithMiddleware(
|
|
||||||
array $queue = null,
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The passed in value must be an array of
|
|
||||||
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
|
||||||
* callables, or Promises.
|
|
||||||
*
|
|
||||||
* @param array $queue
|
|
||||||
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
|
||||||
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
array $queue = null,
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
$this->onFulfilled = $onFulfilled;
|
|
||||||
$this->onRejected = $onRejected;
|
|
||||||
|
|
||||||
if ($queue) {
|
|
||||||
call_user_func_array([$this, 'append'], $queue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
if (!$this->queue) {
|
|
||||||
throw new \OutOfBoundsException('Mock queue is empty');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['delay']) && is_numeric($options['delay'])) {
|
|
||||||
usleep($options['delay'] * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->lastRequest = $request;
|
|
||||||
$this->lastOptions = $options;
|
|
||||||
$response = array_shift($this->queue);
|
|
||||||
|
|
||||||
if (isset($options['on_headers'])) {
|
|
||||||
if (!is_callable($options['on_headers'])) {
|
|
||||||
throw new \InvalidArgumentException('on_headers must be callable');
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$options['on_headers']($response);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$msg = 'An error was encountered during the on_headers event';
|
|
||||||
$response = new RequestException($msg, $request, $response, $e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_callable($response)) {
|
|
||||||
$response = call_user_func($response, $request, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $response instanceof \Exception
|
|
||||||
? \GuzzleHttp\Promise\rejection_for($response)
|
|
||||||
: \GuzzleHttp\Promise\promise_for($response);
|
|
||||||
|
|
||||||
return $response->then(
|
|
||||||
function ($value) use ($request, $options) {
|
|
||||||
$this->invokeStats($request, $options, $value);
|
|
||||||
if ($this->onFulfilled) {
|
|
||||||
call_user_func($this->onFulfilled, $value);
|
|
||||||
}
|
|
||||||
if (isset($options['sink'])) {
|
|
||||||
$contents = (string) $value->getBody();
|
|
||||||
$sink = $options['sink'];
|
|
||||||
|
|
||||||
if (is_resource($sink)) {
|
|
||||||
fwrite($sink, $contents);
|
|
||||||
} elseif (is_string($sink)) {
|
|
||||||
file_put_contents($sink, $contents);
|
|
||||||
} elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
|
|
||||||
$sink->write($contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $value;
|
|
||||||
},
|
|
||||||
function ($reason) use ($request, $options) {
|
|
||||||
$this->invokeStats($request, $options, null, $reason);
|
|
||||||
if ($this->onRejected) {
|
|
||||||
call_user_func($this->onRejected, $reason);
|
|
||||||
}
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds one or more variadic requests, exceptions, callables, or promises
|
|
||||||
* to the queue.
|
|
||||||
*/
|
|
||||||
public function append()
|
|
||||||
{
|
|
||||||
foreach (func_get_args() as $value) {
|
|
||||||
if ($value instanceof ResponseInterface
|
|
||||||
|| $value instanceof \Exception
|
|
||||||
|| $value instanceof PromiseInterface
|
|
||||||
|| is_callable($value)
|
|
||||||
) {
|
|
||||||
$this->queue[] = $value;
|
|
||||||
} else {
|
|
||||||
throw new \InvalidArgumentException('Expected a response or '
|
|
||||||
. 'exception. Found ' . \GuzzleHttp\describe_type($value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the last received request.
|
|
||||||
*
|
|
||||||
* @return RequestInterface
|
|
||||||
*/
|
|
||||||
public function getLastRequest()
|
|
||||||
{
|
|
||||||
return $this->lastRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the last received request options.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getLastOptions()
|
|
||||||
{
|
|
||||||
return $this->lastOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of remaining items in the queue.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function count()
|
|
||||||
{
|
|
||||||
return count($this->queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reset()
|
|
||||||
{
|
|
||||||
$this->queue = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function invokeStats(
|
|
||||||
RequestInterface $request,
|
|
||||||
array $options,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
$reason = null
|
|
||||||
) {
|
|
||||||
if (isset($options['on_stats'])) {
|
|
||||||
$transferTime = isset($options['transfer_time']) ? $options['transfer_time'] : 0;
|
|
||||||
$stats = new TransferStats($request, $response, $transferTime, $reason);
|
|
||||||
call_user_func($options['on_stats'], $stats);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
55
vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
vendored
55
vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
vendored
@@ -1,55 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\RequestOptions;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides basic proxies for handlers.
|
|
||||||
*/
|
|
||||||
class Proxy
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Sends synchronous requests to a specific handler while sending all other
|
|
||||||
* requests to another handler.
|
|
||||||
*
|
|
||||||
* @param callable $default Handler used for normal responses
|
|
||||||
* @param callable $sync Handler used for synchronous responses.
|
|
||||||
*
|
|
||||||
* @return callable Returns the composed handler.
|
|
||||||
*/
|
|
||||||
public static function wrapSync(
|
|
||||||
callable $default,
|
|
||||||
callable $sync
|
|
||||||
) {
|
|
||||||
return function (RequestInterface $request, array $options) use ($default, $sync) {
|
|
||||||
return empty($options[RequestOptions::SYNCHRONOUS])
|
|
||||||
? $default($request, $options)
|
|
||||||
: $sync($request, $options);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends streaming requests to a streaming compatible handler while sending
|
|
||||||
* all other requests to a default handler.
|
|
||||||
*
|
|
||||||
* This, for example, could be useful for taking advantage of the
|
|
||||||
* performance benefits of curl while still supporting true streaming
|
|
||||||
* through the StreamHandler.
|
|
||||||
*
|
|
||||||
* @param callable $default Handler used for non-streaming responses
|
|
||||||
* @param callable $streaming Handler used for streaming responses
|
|
||||||
*
|
|
||||||
* @return callable Returns the composed handler.
|
|
||||||
*/
|
|
||||||
public static function wrapStreaming(
|
|
||||||
callable $default,
|
|
||||||
callable $streaming
|
|
||||||
) {
|
|
||||||
return function (RequestInterface $request, array $options) use ($default, $streaming) {
|
|
||||||
return empty($options['stream'])
|
|
||||||
? $default($request, $options)
|
|
||||||
: $streaming($request, $options);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,545 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Handler;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\ConnectException;
|
|
||||||
use GuzzleHttp\Exception\RequestException;
|
|
||||||
use GuzzleHttp\Promise\FulfilledPromise;
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use GuzzleHttp\TransferStats;
|
|
||||||
use GuzzleHttp\Utils;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\StreamInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP handler that uses PHP's HTTP stream wrapper.
|
|
||||||
*/
|
|
||||||
class StreamHandler
|
|
||||||
{
|
|
||||||
private $lastHeaders = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends an HTTP request.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request to send.
|
|
||||||
* @param array $options Request transfer options.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
// Sleep if there is a delay specified.
|
|
||||||
if (isset($options['delay'])) {
|
|
||||||
usleep($options['delay'] * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
$startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Does not support the expect header.
|
|
||||||
$request = $request->withoutHeader('Expect');
|
|
||||||
|
|
||||||
// Append a content-length header if body size is zero to match
|
|
||||||
// cURL's behavior.
|
|
||||||
if (0 === $request->getBody()->getSize()) {
|
|
||||||
$request = $request->withHeader('Content-Length', '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->createResponse(
|
|
||||||
$request,
|
|
||||||
$options,
|
|
||||||
$this->createStream($request, $options),
|
|
||||||
$startTime
|
|
||||||
);
|
|
||||||
} catch (\InvalidArgumentException $e) {
|
|
||||||
throw $e;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// Determine if the error was a networking error.
|
|
||||||
$message = $e->getMessage();
|
|
||||||
// This list can probably get more comprehensive.
|
|
||||||
if (strpos($message, 'getaddrinfo') // DNS lookup failed
|
|
||||||
|| strpos($message, 'Connection refused')
|
|
||||||
|| strpos($message, "couldn't connect to host") // error on HHVM
|
|
||||||
|| strpos($message, "connection attempt failed")
|
|
||||||
) {
|
|
||||||
$e = new ConnectException($e->getMessage(), $request, $e);
|
|
||||||
}
|
|
||||||
$e = RequestException::wrapException($request, $e);
|
|
||||||
$this->invokeStats($options, $request, $startTime, null, $e);
|
|
||||||
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function invokeStats(
|
|
||||||
array $options,
|
|
||||||
RequestInterface $request,
|
|
||||||
$startTime,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
$error = null
|
|
||||||
) {
|
|
||||||
if (isset($options['on_stats'])) {
|
|
||||||
$stats = new TransferStats(
|
|
||||||
$request,
|
|
||||||
$response,
|
|
||||||
Utils::currentTime() - $startTime,
|
|
||||||
$error,
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
call_user_func($options['on_stats'], $stats);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createResponse(
|
|
||||||
RequestInterface $request,
|
|
||||||
array $options,
|
|
||||||
$stream,
|
|
||||||
$startTime
|
|
||||||
) {
|
|
||||||
$hdrs = $this->lastHeaders;
|
|
||||||
$this->lastHeaders = [];
|
|
||||||
$parts = explode(' ', array_shift($hdrs), 3);
|
|
||||||
$ver = explode('/', $parts[0])[1];
|
|
||||||
$status = $parts[1];
|
|
||||||
$reason = isset($parts[2]) ? $parts[2] : null;
|
|
||||||
$headers = \GuzzleHttp\headers_from_lines($hdrs);
|
|
||||||
list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
|
||||||
$stream = Psr7\stream_for($stream);
|
|
||||||
$sink = $stream;
|
|
||||||
|
|
||||||
if (strcasecmp('HEAD', $request->getMethod())) {
|
|
||||||
$sink = $this->createSink($stream, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
|
|
||||||
|
|
||||||
if (isset($options['on_headers'])) {
|
|
||||||
try {
|
|
||||||
$options['on_headers']($response);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$msg = 'An error was encountered during the on_headers event';
|
|
||||||
$ex = new RequestException($msg, $request, $response, $e);
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not drain when the request is a HEAD request because they have
|
|
||||||
// no body.
|
|
||||||
if ($sink !== $stream) {
|
|
||||||
$this->drain(
|
|
||||||
$stream,
|
|
||||||
$sink,
|
|
||||||
$response->getHeaderLine('Content-Length')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->invokeStats($options, $request, $startTime, $response, null);
|
|
||||||
|
|
||||||
return new FulfilledPromise($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createSink(StreamInterface $stream, array $options)
|
|
||||||
{
|
|
||||||
if (!empty($options['stream'])) {
|
|
||||||
return $stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sink = isset($options['sink'])
|
|
||||||
? $options['sink']
|
|
||||||
: fopen('php://temp', 'r+');
|
|
||||||
|
|
||||||
return is_string($sink)
|
|
||||||
? new Psr7\LazyOpenStream($sink, 'w+')
|
|
||||||
: Psr7\stream_for($sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkDecode(array $options, array $headers, $stream)
|
|
||||||
{
|
|
||||||
// Automatically decode responses when instructed.
|
|
||||||
if (!empty($options['decode_content'])) {
|
|
||||||
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
|
||||||
if (isset($normalizedKeys['content-encoding'])) {
|
|
||||||
$encoding = $headers[$normalizedKeys['content-encoding']];
|
|
||||||
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
|
|
||||||
$stream = new Psr7\InflateStream(
|
|
||||||
Psr7\stream_for($stream)
|
|
||||||
);
|
|
||||||
$headers['x-encoded-content-encoding']
|
|
||||||
= $headers[$normalizedKeys['content-encoding']];
|
|
||||||
// Remove content-encoding header
|
|
||||||
unset($headers[$normalizedKeys['content-encoding']]);
|
|
||||||
// Fix content-length header
|
|
||||||
if (isset($normalizedKeys['content-length'])) {
|
|
||||||
$headers['x-encoded-content-length']
|
|
||||||
= $headers[$normalizedKeys['content-length']];
|
|
||||||
|
|
||||||
$length = (int) $stream->getSize();
|
|
||||||
if ($length === 0) {
|
|
||||||
unset($headers[$normalizedKeys['content-length']]);
|
|
||||||
} else {
|
|
||||||
$headers[$normalizedKeys['content-length']] = [$length];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$stream, $headers];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Drains the source stream into the "sink" client option.
|
|
||||||
*
|
|
||||||
* @param StreamInterface $source
|
|
||||||
* @param StreamInterface $sink
|
|
||||||
* @param string $contentLength Header specifying the amount of
|
|
||||||
* data to read.
|
|
||||||
*
|
|
||||||
* @return StreamInterface
|
|
||||||
* @throws \RuntimeException when the sink option is invalid.
|
|
||||||
*/
|
|
||||||
private function drain(
|
|
||||||
StreamInterface $source,
|
|
||||||
StreamInterface $sink,
|
|
||||||
$contentLength
|
|
||||||
) {
|
|
||||||
// If a content-length header is provided, then stop reading once
|
|
||||||
// that number of bytes has been read. This can prevent infinitely
|
|
||||||
// reading from a stream when dealing with servers that do not honor
|
|
||||||
// Connection: Close headers.
|
|
||||||
Psr7\copy_to_stream(
|
|
||||||
$source,
|
|
||||||
$sink,
|
|
||||||
(strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
|
|
||||||
);
|
|
||||||
|
|
||||||
$sink->seek(0);
|
|
||||||
$source->close();
|
|
||||||
|
|
||||||
return $sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a resource and check to ensure it was created successfully
|
|
||||||
*
|
|
||||||
* @param callable $callback Callable that returns stream resource
|
|
||||||
*
|
|
||||||
* @return resource
|
|
||||||
* @throws \RuntimeException on error
|
|
||||||
*/
|
|
||||||
private function createResource(callable $callback)
|
|
||||||
{
|
|
||||||
$errors = null;
|
|
||||||
set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
|
|
||||||
$errors[] = [
|
|
||||||
'message' => $msg,
|
|
||||||
'file' => $file,
|
|
||||||
'line' => $line
|
|
||||||
];
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$resource = $callback();
|
|
||||||
restore_error_handler();
|
|
||||||
|
|
||||||
if (!$resource) {
|
|
||||||
$message = 'Error creating resource: ';
|
|
||||||
foreach ($errors as $err) {
|
|
||||||
foreach ($err as $key => $value) {
|
|
||||||
$message .= "[$key] $value" . PHP_EOL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new \RuntimeException(trim($message));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createStream(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
static $methods;
|
|
||||||
if (!$methods) {
|
|
||||||
$methods = array_flip(get_class_methods(__CLASS__));
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP/1.1 streams using the PHP stream wrapper require a
|
|
||||||
// Connection: close header
|
|
||||||
if ($request->getProtocolVersion() == '1.1'
|
|
||||||
&& !$request->hasHeader('Connection')
|
|
||||||
) {
|
|
||||||
$request = $request->withHeader('Connection', 'close');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure SSL is verified by default
|
|
||||||
if (!isset($options['verify'])) {
|
|
||||||
$options['verify'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$params = [];
|
|
||||||
$context = $this->getDefaultContext($request);
|
|
||||||
|
|
||||||
if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
|
|
||||||
throw new \InvalidArgumentException('on_headers must be callable');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($options)) {
|
|
||||||
foreach ($options as $key => $value) {
|
|
||||||
$method = "add_{$key}";
|
|
||||||
if (isset($methods[$method])) {
|
|
||||||
$this->{$method}($request, $context, $value, $params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['stream_context'])) {
|
|
||||||
if (!is_array($options['stream_context'])) {
|
|
||||||
throw new \InvalidArgumentException('stream_context must be an array');
|
|
||||||
}
|
|
||||||
$context = array_replace_recursive(
|
|
||||||
$context,
|
|
||||||
$options['stream_context']
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Microsoft NTLM authentication only supported with curl handler
|
|
||||||
if (isset($options['auth'])
|
|
||||||
&& is_array($options['auth'])
|
|
||||||
&& isset($options['auth'][2])
|
|
||||||
&& 'ntlm' == $options['auth'][2]
|
|
||||||
) {
|
|
||||||
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = $this->resolveHost($request, $options);
|
|
||||||
|
|
||||||
$context = $this->createResource(
|
|
||||||
function () use ($context, $params) {
|
|
||||||
return stream_context_create($context, $params);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->createResource(
|
|
||||||
function () use ($uri, &$http_response_header, $context, $options) {
|
|
||||||
$resource = fopen((string) $uri, 'r', null, $context);
|
|
||||||
$this->lastHeaders = $http_response_header;
|
|
||||||
|
|
||||||
if (isset($options['read_timeout'])) {
|
|
||||||
$readTimeout = $options['read_timeout'];
|
|
||||||
$sec = (int) $readTimeout;
|
|
||||||
$usec = ($readTimeout - $sec) * 100000;
|
|
||||||
stream_set_timeout($resource, $sec, $usec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $resource;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function resolveHost(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
$uri = $request->getUri();
|
|
||||||
|
|
||||||
if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
|
|
||||||
if ('v4' === $options['force_ip_resolve']) {
|
|
||||||
$records = dns_get_record($uri->getHost(), DNS_A);
|
|
||||||
if (!isset($records[0]['ip'])) {
|
|
||||||
throw new ConnectException(
|
|
||||||
sprintf(
|
|
||||||
"Could not resolve IPv4 address for host '%s'",
|
|
||||||
$uri->getHost()
|
|
||||||
),
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$uri = $uri->withHost($records[0]['ip']);
|
|
||||||
} elseif ('v6' === $options['force_ip_resolve']) {
|
|
||||||
$records = dns_get_record($uri->getHost(), DNS_AAAA);
|
|
||||||
if (!isset($records[0]['ipv6'])) {
|
|
||||||
throw new ConnectException(
|
|
||||||
sprintf(
|
|
||||||
"Could not resolve IPv6 address for host '%s'",
|
|
||||||
$uri->getHost()
|
|
||||||
),
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDefaultContext(RequestInterface $request)
|
|
||||||
{
|
|
||||||
$headers = '';
|
|
||||||
foreach ($request->getHeaders() as $name => $value) {
|
|
||||||
foreach ($value as $val) {
|
|
||||||
$headers .= "$name: $val\r\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$context = [
|
|
||||||
'http' => [
|
|
||||||
'method' => $request->getMethod(),
|
|
||||||
'header' => $headers,
|
|
||||||
'protocol_version' => $request->getProtocolVersion(),
|
|
||||||
'ignore_errors' => true,
|
|
||||||
'follow_location' => 0,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$body = (string) $request->getBody();
|
|
||||||
|
|
||||||
if (!empty($body)) {
|
|
||||||
$context['http']['content'] = $body;
|
|
||||||
// Prevent the HTTP handler from adding a Content-Type header.
|
|
||||||
if (!$request->hasHeader('Content-Type')) {
|
|
||||||
$context['http']['header'] .= "Content-Type:\r\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$context['http']['header'] = rtrim($context['http']['header']);
|
|
||||||
|
|
||||||
return $context;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add_proxy(RequestInterface $request, &$options, $value, &$params)
|
|
||||||
{
|
|
||||||
if (!is_array($value)) {
|
|
||||||
$options['http']['proxy'] = $value;
|
|
||||||
} else {
|
|
||||||
$scheme = $request->getUri()->getScheme();
|
|
||||||
if (isset($value[$scheme])) {
|
|
||||||
if (!isset($value['no'])
|
|
||||||
|| !\GuzzleHttp\is_host_in_noproxy(
|
|
||||||
$request->getUri()->getHost(),
|
|
||||||
$value['no']
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
$options['http']['proxy'] = $value[$scheme];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add_timeout(RequestInterface $request, &$options, $value, &$params)
|
|
||||||
{
|
|
||||||
if ($value > 0) {
|
|
||||||
$options['http']['timeout'] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add_verify(RequestInterface $request, &$options, $value, &$params)
|
|
||||||
{
|
|
||||||
if ($value === true) {
|
|
||||||
// PHP 5.6 or greater will find the system cert by default. When
|
|
||||||
// < 5.6, use the Guzzle bundled cacert.
|
|
||||||
if (PHP_VERSION_ID < 50600) {
|
|
||||||
$options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
|
|
||||||
}
|
|
||||||
} elseif (is_string($value)) {
|
|
||||||
$options['ssl']['cafile'] = $value;
|
|
||||||
if (!file_exists($value)) {
|
|
||||||
throw new \RuntimeException("SSL CA bundle not found: $value");
|
|
||||||
}
|
|
||||||
} elseif ($value === false) {
|
|
||||||
$options['ssl']['verify_peer'] = false;
|
|
||||||
$options['ssl']['verify_peer_name'] = false;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw new \InvalidArgumentException('Invalid verify request option');
|
|
||||||
}
|
|
||||||
|
|
||||||
$options['ssl']['verify_peer'] = true;
|
|
||||||
$options['ssl']['verify_peer_name'] = true;
|
|
||||||
$options['ssl']['allow_self_signed'] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add_cert(RequestInterface $request, &$options, $value, &$params)
|
|
||||||
{
|
|
||||||
if (is_array($value)) {
|
|
||||||
$options['ssl']['passphrase'] = $value[1];
|
|
||||||
$value = $value[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($value)) {
|
|
||||||
throw new \RuntimeException("SSL certificate not found: {$value}");
|
|
||||||
}
|
|
||||||
|
|
||||||
$options['ssl']['local_cert'] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add_progress(RequestInterface $request, &$options, $value, &$params)
|
|
||||||
{
|
|
||||||
$this->addNotification(
|
|
||||||
$params,
|
|
||||||
function ($code, $a, $b, $c, $transferred, $total) use ($value) {
|
|
||||||
if ($code == STREAM_NOTIFY_PROGRESS) {
|
|
||||||
$value($total, $transferred, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add_debug(RequestInterface $request, &$options, $value, &$params)
|
|
||||||
{
|
|
||||||
if ($value === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static $map = [
|
|
||||||
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',
|
|
||||||
];
|
|
||||||
static $args = ['severity', 'message', 'message_code',
|
|
||||||
'bytes_transferred', 'bytes_max'];
|
|
||||||
|
|
||||||
$value = \GuzzleHttp\debug_resource($value);
|
|
||||||
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
|
|
||||||
$this->addNotification(
|
|
||||||
$params,
|
|
||||||
function () use ($ident, $value, $map, $args) {
|
|
||||||
$passed = func_get_args();
|
|
||||||
$code = array_shift($passed);
|
|
||||||
fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
|
||||||
foreach (array_filter($passed) as $i => $v) {
|
|
||||||
fwrite($value, $args[$i] . ': "' . $v . '" ');
|
|
||||||
}
|
|
||||||
fwrite($value, "\n");
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function addNotification(array &$params, callable $notify)
|
|
||||||
{
|
|
||||||
// Wrap the existing function if needed.
|
|
||||||
if (!isset($params['notification'])) {
|
|
||||||
$params['notification'] = $notify;
|
|
||||||
} else {
|
|
||||||
$params['notification'] = $this->callArray([
|
|
||||||
$params['notification'],
|
|
||||||
$notify
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function callArray(array $functions)
|
|
||||||
{
|
|
||||||
return function () use ($functions) {
|
|
||||||
$args = func_get_args();
|
|
||||||
foreach ($functions as $fn) {
|
|
||||||
call_user_func_array($fn, $args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
277
vendor/guzzlehttp/guzzle/src/HandlerStack.php
vendored
277
vendor/guzzlehttp/guzzle/src/HandlerStack.php
vendored
@@ -1,277 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
|
||||||
* an HTTP handler function.
|
|
||||||
*/
|
|
||||||
class HandlerStack
|
|
||||||
{
|
|
||||||
/** @var callable|null */
|
|
||||||
private $handler;
|
|
||||||
|
|
||||||
/** @var array */
|
|
||||||
private $stack = [];
|
|
||||||
|
|
||||||
/** @var callable|null */
|
|
||||||
private $cached;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a default handler stack that can be used by clients.
|
|
||||||
*
|
|
||||||
* The returned handler will wrap the provided handler or use the most
|
|
||||||
* appropriate default handler for your system. The returned HandlerStack has
|
|
||||||
* support for cookies, redirects, HTTP error exceptions, and preparing a body
|
|
||||||
* before sending.
|
|
||||||
*
|
|
||||||
* The returned handler stack can be passed to a client in the "handler"
|
|
||||||
* option.
|
|
||||||
*
|
|
||||||
* @param callable $handler HTTP handler function to use with the stack. If no
|
|
||||||
* handler is provided, the best handler for your
|
|
||||||
* system will be utilized.
|
|
||||||
*
|
|
||||||
* @return HandlerStack
|
|
||||||
*/
|
|
||||||
public static function create(callable $handler = null)
|
|
||||||
{
|
|
||||||
$stack = new self($handler ?: choose_handler());
|
|
||||||
$stack->push(Middleware::httpErrors(), 'http_errors');
|
|
||||||
$stack->push(Middleware::redirect(), 'allow_redirects');
|
|
||||||
$stack->push(Middleware::cookies(), 'cookies');
|
|
||||||
$stack->push(Middleware::prepareBody(), 'prepare_body');
|
|
||||||
|
|
||||||
return $stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $handler Underlying HTTP handler.
|
|
||||||
*/
|
|
||||||
public function __construct(callable $handler = null)
|
|
||||||
{
|
|
||||||
$this->handler = $handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes the handler stack as a composed handler
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return ResponseInterface|PromiseInterface
|
|
||||||
*/
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
$handler = $this->resolve();
|
|
||||||
|
|
||||||
return $handler($request, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dumps a string representation of the stack.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function __toString()
|
|
||||||
{
|
|
||||||
$depth = 0;
|
|
||||||
$stack = [];
|
|
||||||
if ($this->handler) {
|
|
||||||
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = '';
|
|
||||||
foreach (array_reverse($this->stack) as $tuple) {
|
|
||||||
$depth++;
|
|
||||||
$str = "{$depth}) Name: '{$tuple[1]}', ";
|
|
||||||
$str .= "Function: " . $this->debugCallable($tuple[0]);
|
|
||||||
$result = "> {$str}\n{$result}";
|
|
||||||
$stack[] = $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array_keys($stack) as $k) {
|
|
||||||
$result .= "< {$stack[$k]}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the HTTP handler that actually returns a promise.
|
|
||||||
*
|
|
||||||
* @param callable $handler Accepts a request and array of options and
|
|
||||||
* returns a Promise.
|
|
||||||
*/
|
|
||||||
public function setHandler(callable $handler)
|
|
||||||
{
|
|
||||||
$this->handler = $handler;
|
|
||||||
$this->cached = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the builder has a handler.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasHandler()
|
|
||||||
{
|
|
||||||
return (bool) $this->handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unshift a middleware to the bottom of the stack.
|
|
||||||
*
|
|
||||||
* @param callable $middleware Middleware function
|
|
||||||
* @param string $name Name to register for this middleware.
|
|
||||||
*/
|
|
||||||
public function unshift(callable $middleware, $name = null)
|
|
||||||
{
|
|
||||||
array_unshift($this->stack, [$middleware, $name]);
|
|
||||||
$this->cached = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Push a middleware to the top of the stack.
|
|
||||||
*
|
|
||||||
* @param callable $middleware Middleware function
|
|
||||||
* @param string $name Name to register for this middleware.
|
|
||||||
*/
|
|
||||||
public function push(callable $middleware, $name = '')
|
|
||||||
{
|
|
||||||
$this->stack[] = [$middleware, $name];
|
|
||||||
$this->cached = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a middleware before another middleware by name.
|
|
||||||
*
|
|
||||||
* @param string $findName Middleware to find
|
|
||||||
* @param callable $middleware Middleware function
|
|
||||||
* @param string $withName Name to register for this middleware.
|
|
||||||
*/
|
|
||||||
public function before($findName, callable $middleware, $withName = '')
|
|
||||||
{
|
|
||||||
$this->splice($findName, $withName, $middleware, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a middleware after another middleware by name.
|
|
||||||
*
|
|
||||||
* @param string $findName Middleware to find
|
|
||||||
* @param callable $middleware Middleware function
|
|
||||||
* @param string $withName Name to register for this middleware.
|
|
||||||
*/
|
|
||||||
public function after($findName, callable $middleware, $withName = '')
|
|
||||||
{
|
|
||||||
$this->splice($findName, $withName, $middleware, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a middleware by instance or name from the stack.
|
|
||||||
*
|
|
||||||
* @param callable|string $remove Middleware to remove by instance or name.
|
|
||||||
*/
|
|
||||||
public function remove($remove)
|
|
||||||
{
|
|
||||||
$this->cached = null;
|
|
||||||
$idx = is_callable($remove) ? 0 : 1;
|
|
||||||
$this->stack = array_values(array_filter(
|
|
||||||
$this->stack,
|
|
||||||
function ($tuple) use ($idx, $remove) {
|
|
||||||
return $tuple[$idx] !== $remove;
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose the middleware and handler into a single callable function.
|
|
||||||
*
|
|
||||||
* @return callable
|
|
||||||
*/
|
|
||||||
public function resolve()
|
|
||||||
{
|
|
||||||
if (!$this->cached) {
|
|
||||||
if (!($prev = $this->handler)) {
|
|
||||||
throw new \LogicException('No handler has been specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array_reverse($this->stack) as $fn) {
|
|
||||||
$prev = $fn[0]($prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->cached = $prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
private function findByName($name)
|
|
||||||
{
|
|
||||||
foreach ($this->stack as $k => $v) {
|
|
||||||
if ($v[1] === $name) {
|
|
||||||
return $k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \InvalidArgumentException("Middleware not found: $name");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splices a function into the middleware list at a specific position.
|
|
||||||
*
|
|
||||||
* @param string $findName
|
|
||||||
* @param string $withName
|
|
||||||
* @param callable $middleware
|
|
||||||
* @param bool $before
|
|
||||||
*/
|
|
||||||
private function splice($findName, $withName, callable $middleware, $before)
|
|
||||||
{
|
|
||||||
$this->cached = null;
|
|
||||||
$idx = $this->findByName($findName);
|
|
||||||
$tuple = [$middleware, $withName];
|
|
||||||
|
|
||||||
if ($before) {
|
|
||||||
if ($idx === 0) {
|
|
||||||
array_unshift($this->stack, $tuple);
|
|
||||||
} else {
|
|
||||||
$replacement = [$tuple, $this->stack[$idx]];
|
|
||||||
array_splice($this->stack, $idx, 1, $replacement);
|
|
||||||
}
|
|
||||||
} elseif ($idx === count($this->stack) - 1) {
|
|
||||||
$this->stack[] = $tuple;
|
|
||||||
} else {
|
|
||||||
$replacement = [$this->stack[$idx], $tuple];
|
|
||||||
array_splice($this->stack, $idx, 1, $replacement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a debug string for a given callable.
|
|
||||||
*
|
|
||||||
* @param array|callable $fn Function to write as a string.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function debugCallable($fn)
|
|
||||||
{
|
|
||||||
if (is_string($fn)) {
|
|
||||||
return "callable({$fn})";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($fn)) {
|
|
||||||
return is_string($fn[0])
|
|
||||||
? "callable({$fn[0]}::{$fn[1]})"
|
|
||||||
: "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'callable(' . spl_object_hash($fn) . ')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
185
vendor/guzzlehttp/guzzle/src/MessageFormatter.php
vendored
185
vendor/guzzlehttp/guzzle/src/MessageFormatter.php
vendored
@@ -1,185 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use Psr\Http\Message\MessageInterface;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats log messages using variable substitutions for requests, responses,
|
|
||||||
* and other transactional data.
|
|
||||||
*
|
|
||||||
* The following variable substitutions are supported:
|
|
||||||
*
|
|
||||||
* - {request}: Full HTTP request message
|
|
||||||
* - {response}: Full HTTP response message
|
|
||||||
* - {ts}: ISO 8601 date in GMT
|
|
||||||
* - {date_iso_8601} ISO 8601 date in GMT
|
|
||||||
* - {date_common_log} Apache common log date using the configured timezone.
|
|
||||||
* - {host}: Host of the request
|
|
||||||
* - {method}: Method of the request
|
|
||||||
* - {uri}: URI of the request
|
|
||||||
* - {version}: Protocol version
|
|
||||||
* - {target}: Request target of the request (path + query + fragment)
|
|
||||||
* - {hostname}: Hostname of the machine that sent the request
|
|
||||||
* - {code}: Status code of the response (if available)
|
|
||||||
* - {phrase}: Reason phrase of the response (if available)
|
|
||||||
* - {error}: Any error messages (if available)
|
|
||||||
* - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
|
|
||||||
* - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
|
|
||||||
* - {req_headers}: Request headers
|
|
||||||
* - {res_headers}: Response headers
|
|
||||||
* - {req_body}: Request body
|
|
||||||
* - {res_body}: Response body
|
|
||||||
*/
|
|
||||||
class MessageFormatter
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Apache Common Log Format.
|
|
||||||
* @link http://httpd.apache.org/docs/2.4/logs.html#common
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
|
||||||
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
|
||||||
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
|
||||||
|
|
||||||
/** @var string Template used to format log messages */
|
|
||||||
private $template;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $template Log message template
|
|
||||||
*/
|
|
||||||
public function __construct($template = self::CLF)
|
|
||||||
{
|
|
||||||
$this->template = $template ?: self::CLF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a formatted message string.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request Request that was sent
|
|
||||||
* @param ResponseInterface $response Response that was received
|
|
||||||
* @param \Exception $error Exception that was received
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function format(
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
\Exception $error = null
|
|
||||||
) {
|
|
||||||
$cache = [];
|
|
||||||
|
|
||||||
return preg_replace_callback(
|
|
||||||
'/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
|
|
||||||
function (array $matches) use ($request, $response, $error, &$cache) {
|
|
||||||
if (isset($cache[$matches[1]])) {
|
|
||||||
return $cache[$matches[1]];
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = '';
|
|
||||||
switch ($matches[1]) {
|
|
||||||
case 'request':
|
|
||||||
$result = Psr7\str($request);
|
|
||||||
break;
|
|
||||||
case 'response':
|
|
||||||
$result = $response ? Psr7\str($response) : '';
|
|
||||||
break;
|
|
||||||
case 'req_headers':
|
|
||||||
$result = trim($request->getMethod()
|
|
||||||
. ' ' . $request->getRequestTarget())
|
|
||||||
. ' HTTP/' . $request->getProtocolVersion() . "\r\n"
|
|
||||||
. $this->headers($request);
|
|
||||||
break;
|
|
||||||
case 'res_headers':
|
|
||||||
$result = $response ?
|
|
||||||
sprintf(
|
|
||||||
'HTTP/%s %d %s',
|
|
||||||
$response->getProtocolVersion(),
|
|
||||||
$response->getStatusCode(),
|
|
||||||
$response->getReasonPhrase()
|
|
||||||
) . "\r\n" . $this->headers($response)
|
|
||||||
: 'NULL';
|
|
||||||
break;
|
|
||||||
case 'req_body':
|
|
||||||
$result = $request->getBody();
|
|
||||||
break;
|
|
||||||
case 'res_body':
|
|
||||||
$result = $response ? $response->getBody() : 'NULL';
|
|
||||||
break;
|
|
||||||
case 'ts':
|
|
||||||
case 'date_iso_8601':
|
|
||||||
$result = gmdate('c');
|
|
||||||
break;
|
|
||||||
case 'date_common_log':
|
|
||||||
$result = date('d/M/Y:H:i:s O');
|
|
||||||
break;
|
|
||||||
case 'method':
|
|
||||||
$result = $request->getMethod();
|
|
||||||
break;
|
|
||||||
case 'version':
|
|
||||||
$result = $request->getProtocolVersion();
|
|
||||||
break;
|
|
||||||
case 'uri':
|
|
||||||
case 'url':
|
|
||||||
$result = $request->getUri();
|
|
||||||
break;
|
|
||||||
case 'target':
|
|
||||||
$result = $request->getRequestTarget();
|
|
||||||
break;
|
|
||||||
case 'req_version':
|
|
||||||
$result = $request->getProtocolVersion();
|
|
||||||
break;
|
|
||||||
case 'res_version':
|
|
||||||
$result = $response
|
|
||||||
? $response->getProtocolVersion()
|
|
||||||
: 'NULL';
|
|
||||||
break;
|
|
||||||
case 'host':
|
|
||||||
$result = $request->getHeaderLine('Host');
|
|
||||||
break;
|
|
||||||
case 'hostname':
|
|
||||||
$result = gethostname();
|
|
||||||
break;
|
|
||||||
case 'code':
|
|
||||||
$result = $response ? $response->getStatusCode() : 'NULL';
|
|
||||||
break;
|
|
||||||
case 'phrase':
|
|
||||||
$result = $response ? $response->getReasonPhrase() : 'NULL';
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
$result = $error ? $error->getMessage() : 'NULL';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// handle prefixed dynamic headers
|
|
||||||
if (strpos($matches[1], 'req_header_') === 0) {
|
|
||||||
$result = $request->getHeaderLine(substr($matches[1], 11));
|
|
||||||
} elseif (strpos($matches[1], 'res_header_') === 0) {
|
|
||||||
$result = $response
|
|
||||||
? $response->getHeaderLine(substr($matches[1], 11))
|
|
||||||
: 'NULL';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$cache[$matches[1]] = $result;
|
|
||||||
return $result;
|
|
||||||
},
|
|
||||||
$this->template
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get headers from message as string
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function headers(MessageInterface $message)
|
|
||||||
{
|
|
||||||
$result = '';
|
|
||||||
foreach ($message->getHeaders() as $name => $values) {
|
|
||||||
$result .= $name . ': ' . implode(', ', $values) . "\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return trim($result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
254
vendor/guzzlehttp/guzzle/src/Middleware.php
vendored
254
vendor/guzzlehttp/guzzle/src/Middleware.php
vendored
@@ -1,254 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Cookie\CookieJarInterface;
|
|
||||||
use GuzzleHttp\Exception\RequestException;
|
|
||||||
use GuzzleHttp\Promise\RejectedPromise;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functions used to create and wrap handlers with handler middleware.
|
|
||||||
*/
|
|
||||||
final class Middleware
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Middleware that adds cookies to requests.
|
|
||||||
*
|
|
||||||
* The options array must be set to a CookieJarInterface in order to use
|
|
||||||
* cookies. This is typically handled for you by a client.
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
*/
|
|
||||||
public static function cookies()
|
|
||||||
{
|
|
||||||
return function (callable $handler) {
|
|
||||||
return function ($request, array $options) use ($handler) {
|
|
||||||
if (empty($options['cookies'])) {
|
|
||||||
return $handler($request, $options);
|
|
||||||
} elseif (!($options['cookies'] instanceof CookieJarInterface)) {
|
|
||||||
throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
|
|
||||||
}
|
|
||||||
$cookieJar = $options['cookies'];
|
|
||||||
$request = $cookieJar->withCookieHeader($request);
|
|
||||||
return $handler($request, $options)
|
|
||||||
->then(
|
|
||||||
function ($response) use ($cookieJar, $request) {
|
|
||||||
$cookieJar->extractCookies($request, $response);
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that throws exceptions for 4xx or 5xx responses when the
|
|
||||||
* "http_error" request option is set to true.
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
*/
|
|
||||||
public static function httpErrors()
|
|
||||||
{
|
|
||||||
return function (callable $handler) {
|
|
||||||
return function ($request, array $options) use ($handler) {
|
|
||||||
if (empty($options['http_errors'])) {
|
|
||||||
return $handler($request, $options);
|
|
||||||
}
|
|
||||||
return $handler($request, $options)->then(
|
|
||||||
function (ResponseInterface $response) use ($request) {
|
|
||||||
$code = $response->getStatusCode();
|
|
||||||
if ($code < 400) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
throw RequestException::create($request, $response);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that pushes history data to an ArrayAccess container.
|
|
||||||
*
|
|
||||||
* @param array|\ArrayAccess $container Container to hold the history (by reference).
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
* @throws \InvalidArgumentException if container is not an array or ArrayAccess.
|
|
||||||
*/
|
|
||||||
public static function history(&$container)
|
|
||||||
{
|
|
||||||
if (!is_array($container) && !$container instanceof \ArrayAccess) {
|
|
||||||
throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (callable $handler) use (&$container) {
|
|
||||||
return function ($request, array $options) use ($handler, &$container) {
|
|
||||||
return $handler($request, $options)->then(
|
|
||||||
function ($value) use ($request, &$container, $options) {
|
|
||||||
$container[] = [
|
|
||||||
'request' => $request,
|
|
||||||
'response' => $value,
|
|
||||||
'error' => null,
|
|
||||||
'options' => $options
|
|
||||||
];
|
|
||||||
return $value;
|
|
||||||
},
|
|
||||||
function ($reason) use ($request, &$container, $options) {
|
|
||||||
$container[] = [
|
|
||||||
'request' => $request,
|
|
||||||
'response' => null,
|
|
||||||
'error' => $reason,
|
|
||||||
'options' => $options
|
|
||||||
];
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that invokes a callback before and after sending a request.
|
|
||||||
*
|
|
||||||
* The provided listener cannot modify or alter the response. It simply
|
|
||||||
* "taps" into the chain to be notified before returning the promise. The
|
|
||||||
* before listener accepts a request and options array, and the after
|
|
||||||
* listener accepts a request, options array, and response promise.
|
|
||||||
*
|
|
||||||
* @param callable $before Function to invoke before forwarding the request.
|
|
||||||
* @param callable $after Function invoked after forwarding.
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
*/
|
|
||||||
public static function tap(callable $before = null, callable $after = null)
|
|
||||||
{
|
|
||||||
return function (callable $handler) use ($before, $after) {
|
|
||||||
return function ($request, array $options) use ($handler, $before, $after) {
|
|
||||||
if ($before) {
|
|
||||||
$before($request, $options);
|
|
||||||
}
|
|
||||||
$response = $handler($request, $options);
|
|
||||||
if ($after) {
|
|
||||||
$after($request, $options, $response);
|
|
||||||
}
|
|
||||||
return $response;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that handles request redirects.
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
*/
|
|
||||||
public static function redirect()
|
|
||||||
{
|
|
||||||
return function (callable $handler) {
|
|
||||||
return new RedirectMiddleware($handler);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that retries requests based on the boolean result of
|
|
||||||
* invoking the provided "decider" function.
|
|
||||||
*
|
|
||||||
* If no delay function is provided, a simple implementation of exponential
|
|
||||||
* backoff will be utilized.
|
|
||||||
*
|
|
||||||
* @param callable $decider Function that accepts the number of retries,
|
|
||||||
* a request, [response], and [exception] and
|
|
||||||
* returns true if the request is to be retried.
|
|
||||||
* @param callable $delay Function that accepts the number of retries and
|
|
||||||
* returns the number of milliseconds to delay.
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
*/
|
|
||||||
public static function retry(callable $decider, callable $delay = null)
|
|
||||||
{
|
|
||||||
return function (callable $handler) use ($decider, $delay) {
|
|
||||||
return new RetryMiddleware($decider, $handler, $delay);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that logs requests, responses, and errors using a message
|
|
||||||
* formatter.
|
|
||||||
*
|
|
||||||
* @param LoggerInterface $logger Logs messages.
|
|
||||||
* @param MessageFormatter $formatter Formatter used to create message strings.
|
|
||||||
* @param string $logLevel Level at which to log requests.
|
|
||||||
*
|
|
||||||
* @return callable Returns a function that accepts the next handler.
|
|
||||||
*/
|
|
||||||
public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = 'info' /* \Psr\Log\LogLevel::INFO */)
|
|
||||||
{
|
|
||||||
return function (callable $handler) use ($logger, $formatter, $logLevel) {
|
|
||||||
return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
|
|
||||||
return $handler($request, $options)->then(
|
|
||||||
function ($response) use ($logger, $request, $formatter, $logLevel) {
|
|
||||||
$message = $formatter->format($request, $response);
|
|
||||||
$logger->log($logLevel, $message);
|
|
||||||
return $response;
|
|
||||||
},
|
|
||||||
function ($reason) use ($logger, $request, $formatter) {
|
|
||||||
$response = $reason instanceof RequestException
|
|
||||||
? $reason->getResponse()
|
|
||||||
: null;
|
|
||||||
$message = $formatter->format($request, $response, $reason);
|
|
||||||
$logger->notice($message);
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This middleware adds a default content-type if possible, a default
|
|
||||||
* content-length or transfer-encoding header, and the expect header.
|
|
||||||
*
|
|
||||||
* @return callable
|
|
||||||
*/
|
|
||||||
public static function prepareBody()
|
|
||||||
{
|
|
||||||
return function (callable $handler) {
|
|
||||||
return new PrepareBodyMiddleware($handler);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that applies a map function to the request before passing to
|
|
||||||
* the next handler.
|
|
||||||
*
|
|
||||||
* @param callable $fn Function that accepts a RequestInterface and returns
|
|
||||||
* a RequestInterface.
|
|
||||||
* @return callable
|
|
||||||
*/
|
|
||||||
public static function mapRequest(callable $fn)
|
|
||||||
{
|
|
||||||
return function (callable $handler) use ($fn) {
|
|
||||||
return function ($request, array $options) use ($handler, $fn) {
|
|
||||||
return $handler($fn($request), $options);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that applies a map function to the resolved promise's
|
|
||||||
* response.
|
|
||||||
*
|
|
||||||
* @param callable $fn Function that accepts a ResponseInterface and
|
|
||||||
* returns a ResponseInterface.
|
|
||||||
* @return callable
|
|
||||||
*/
|
|
||||||
public static function mapResponse(callable $fn)
|
|
||||||
{
|
|
||||||
return function (callable $handler) use ($fn) {
|
|
||||||
return function ($request, array $options) use ($handler, $fn) {
|
|
||||||
return $handler($request, $options)->then($fn);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
134
vendor/guzzlehttp/guzzle/src/Pool.php
vendored
134
vendor/guzzlehttp/guzzle/src/Pool.php
vendored
@@ -1,134 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise\EachPromise;
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use GuzzleHttp\Promise\PromisorInterface;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends an iterator of requests concurrently using a capped pool size.
|
|
||||||
*
|
|
||||||
* The pool will read from an iterator until it is cancelled or until the
|
|
||||||
* iterator is consumed. When a request is yielded, the request is sent after
|
|
||||||
* applying the "request_options" request options (if provided in the ctor).
|
|
||||||
*
|
|
||||||
* When a function is yielded by the iterator, the function is provided the
|
|
||||||
* "request_options" array that should be merged on top of any existing
|
|
||||||
* options, and the function MUST then return a wait-able promise.
|
|
||||||
*/
|
|
||||||
class Pool implements PromisorInterface
|
|
||||||
{
|
|
||||||
/** @var EachPromise */
|
|
||||||
private $each;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ClientInterface $client Client used to send the requests.
|
|
||||||
* @param array|\Iterator $requests Requests or functions that return
|
|
||||||
* requests to send concurrently.
|
|
||||||
* @param array $config Associative array of options
|
|
||||||
* - concurrency: (int) Maximum number of requests to send concurrently
|
|
||||||
* - options: Array of request options to apply to each request.
|
|
||||||
* - fulfilled: (callable) Function to invoke when a request completes.
|
|
||||||
* - rejected: (callable) Function to invoke when a request is rejected.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
ClientInterface $client,
|
|
||||||
$requests,
|
|
||||||
array $config = []
|
|
||||||
) {
|
|
||||||
// Backwards compatibility.
|
|
||||||
if (isset($config['pool_size'])) {
|
|
||||||
$config['concurrency'] = $config['pool_size'];
|
|
||||||
} elseif (!isset($config['concurrency'])) {
|
|
||||||
$config['concurrency'] = 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['options'])) {
|
|
||||||
$opts = $config['options'];
|
|
||||||
unset($config['options']);
|
|
||||||
} else {
|
|
||||||
$opts = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$iterable = \GuzzleHttp\Promise\iter_for($requests);
|
|
||||||
$requests = function () use ($iterable, $client, $opts) {
|
|
||||||
foreach ($iterable as $key => $rfn) {
|
|
||||||
if ($rfn instanceof RequestInterface) {
|
|
||||||
yield $key => $client->sendAsync($rfn, $opts);
|
|
||||||
} elseif (is_callable($rfn)) {
|
|
||||||
yield $key => $rfn($opts);
|
|
||||||
} else {
|
|
||||||
throw new \InvalidArgumentException('Each value yielded by '
|
|
||||||
. 'the iterator must be a Psr7\Http\Message\RequestInterface '
|
|
||||||
. 'or a callable that returns a promise that fulfills '
|
|
||||||
. 'with a Psr7\Message\Http\ResponseInterface object.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$this->each = new EachPromise($requests(), $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get promise
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function promise()
|
|
||||||
{
|
|
||||||
return $this->each->promise();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends multiple requests concurrently and returns an array of responses
|
|
||||||
* and exceptions that uses the same ordering as the provided requests.
|
|
||||||
*
|
|
||||||
* IMPORTANT: This method keeps every request and response in memory, and
|
|
||||||
* as such, is NOT recommended when sending a large number or an
|
|
||||||
* indeterminate number of requests concurrently.
|
|
||||||
*
|
|
||||||
* @param ClientInterface $client Client used to send the requests
|
|
||||||
* @param array|\Iterator $requests Requests to send concurrently.
|
|
||||||
* @param array $options Passes through the options available in
|
|
||||||
* {@see GuzzleHttp\Pool::__construct}
|
|
||||||
*
|
|
||||||
* @return array Returns an array containing the response or an exception
|
|
||||||
* in the same order that the requests were sent.
|
|
||||||
* @throws \InvalidArgumentException if the event format is incorrect.
|
|
||||||
*/
|
|
||||||
public static function batch(
|
|
||||||
ClientInterface $client,
|
|
||||||
$requests,
|
|
||||||
array $options = []
|
|
||||||
) {
|
|
||||||
$res = [];
|
|
||||||
self::cmpCallback($options, 'fulfilled', $res);
|
|
||||||
self::cmpCallback($options, 'rejected', $res);
|
|
||||||
$pool = new static($client, $requests, $options);
|
|
||||||
$pool->promise()->wait();
|
|
||||||
ksort($res);
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute callback(s)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function cmpCallback(array &$options, $name, array &$results)
|
|
||||||
{
|
|
||||||
if (!isset($options[$name])) {
|
|
||||||
$options[$name] = function ($v, $k) use (&$results) {
|
|
||||||
$results[$k] = $v;
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
$currentFn = $options[$name];
|
|
||||||
$options[$name] = function ($v, $k) use (&$results, $currentFn) {
|
|
||||||
$currentFn($v, $k);
|
|
||||||
$results[$k] = $v;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares requests that contain a body, adding the Content-Length,
|
|
||||||
* Content-Type, and Expect headers.
|
|
||||||
*/
|
|
||||||
class PrepareBodyMiddleware
|
|
||||||
{
|
|
||||||
/** @var callable */
|
|
||||||
private $nextHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $nextHandler Next handler to invoke.
|
|
||||||
*/
|
|
||||||
public function __construct(callable $nextHandler)
|
|
||||||
{
|
|
||||||
$this->nextHandler = $nextHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
$fn = $this->nextHandler;
|
|
||||||
|
|
||||||
// Don't do anything if the request has no body.
|
|
||||||
if ($request->getBody()->getSize() === 0) {
|
|
||||||
return $fn($request, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
$modify = [];
|
|
||||||
|
|
||||||
// Add a default content-type if possible.
|
|
||||||
if (!$request->hasHeader('Content-Type')) {
|
|
||||||
if ($uri = $request->getBody()->getMetadata('uri')) {
|
|
||||||
if ($type = Psr7\mimetype_from_filename($uri)) {
|
|
||||||
$modify['set_headers']['Content-Type'] = $type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a default content-length or transfer-encoding header.
|
|
||||||
if (!$request->hasHeader('Content-Length')
|
|
||||||
&& !$request->hasHeader('Transfer-Encoding')
|
|
||||||
) {
|
|
||||||
$size = $request->getBody()->getSize();
|
|
||||||
if ($size !== null) {
|
|
||||||
$modify['set_headers']['Content-Length'] = $size;
|
|
||||||
} else {
|
|
||||||
$modify['set_headers']['Transfer-Encoding'] = 'chunked';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the expect header if needed.
|
|
||||||
$this->addExpectHeader($request, $options, $modify);
|
|
||||||
|
|
||||||
return $fn(Psr7\modify_request($request, $modify), $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add expect header
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function addExpectHeader(
|
|
||||||
RequestInterface $request,
|
|
||||||
array $options,
|
|
||||||
array &$modify
|
|
||||||
) {
|
|
||||||
// Determine if the Expect header should be used
|
|
||||||
if ($request->hasHeader('Expect')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$expect = isset($options['expect']) ? $options['expect'] : null;
|
|
||||||
|
|
||||||
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
|
|
||||||
if ($expect === false || $request->getProtocolVersion() < 1.1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The expect header is unconditionally enabled
|
|
||||||
if ($expect === true) {
|
|
||||||
$modify['set_headers']['Expect'] = '100-Continue';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// By default, send the expect header when the payload is > 1mb
|
|
||||||
if ($expect === null) {
|
|
||||||
$expect = 1048576;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always add if the body cannot be rewound, the size cannot be
|
|
||||||
// determined, or the size is greater than the cutoff threshold
|
|
||||||
$body = $request->getBody();
|
|
||||||
$size = $body->getSize();
|
|
||||||
|
|
||||||
if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
|
|
||||||
$modify['set_headers']['Expect'] = '100-Continue';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
255
vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
vendored
255
vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
vendored
@@ -1,255 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\BadResponseException;
|
|
||||||
use GuzzleHttp\Exception\TooManyRedirectsException;
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\UriInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request redirect middleware.
|
|
||||||
*
|
|
||||||
* Apply this middleware like other middleware using
|
|
||||||
* {@see \GuzzleHttp\Middleware::redirect()}.
|
|
||||||
*/
|
|
||||||
class RedirectMiddleware
|
|
||||||
{
|
|
||||||
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
|
||||||
|
|
||||||
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
|
||||||
|
|
||||||
public static $defaultSettings = [
|
|
||||||
'max' => 5,
|
|
||||||
'protocols' => ['http', 'https'],
|
|
||||||
'strict' => false,
|
|
||||||
'referer' => false,
|
|
||||||
'track_redirects' => false,
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @var callable */
|
|
||||||
private $nextHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $nextHandler Next handler to invoke.
|
|
||||||
*/
|
|
||||||
public function __construct(callable $nextHandler)
|
|
||||||
{
|
|
||||||
$this->nextHandler = $nextHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
$fn = $this->nextHandler;
|
|
||||||
|
|
||||||
if (empty($options['allow_redirects'])) {
|
|
||||||
return $fn($request, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($options['allow_redirects'] === true) {
|
|
||||||
$options['allow_redirects'] = self::$defaultSettings;
|
|
||||||
} elseif (!is_array($options['allow_redirects'])) {
|
|
||||||
throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
|
|
||||||
} else {
|
|
||||||
// Merge the default settings with the provided settings
|
|
||||||
$options['allow_redirects'] += self::$defaultSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($options['allow_redirects']['max'])) {
|
|
||||||
return $fn($request, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $fn($request, $options)
|
|
||||||
->then(function (ResponseInterface $response) use ($request, $options) {
|
|
||||||
return $this->checkRedirect($request, $options, $response);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
*
|
|
||||||
* @return ResponseInterface|PromiseInterface
|
|
||||||
*/
|
|
||||||
public function checkRedirect(
|
|
||||||
RequestInterface $request,
|
|
||||||
array $options,
|
|
||||||
ResponseInterface $response
|
|
||||||
) {
|
|
||||||
if (substr($response->getStatusCode(), 0, 1) != '3'
|
|
||||||
|| !$response->hasHeader('Location')
|
|
||||||
) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->guardMax($request, $options);
|
|
||||||
$nextRequest = $this->modifyRequest($request, $options, $response);
|
|
||||||
|
|
||||||
if (isset($options['allow_redirects']['on_redirect'])) {
|
|
||||||
call_user_func(
|
|
||||||
$options['allow_redirects']['on_redirect'],
|
|
||||||
$request,
|
|
||||||
$response,
|
|
||||||
$nextRequest->getUri()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var PromiseInterface|ResponseInterface $promise */
|
|
||||||
$promise = $this($nextRequest, $options);
|
|
||||||
|
|
||||||
// Add headers to be able to track history of redirects.
|
|
||||||
if (!empty($options['allow_redirects']['track_redirects'])) {
|
|
||||||
return $this->withTracking(
|
|
||||||
$promise,
|
|
||||||
(string) $nextRequest->getUri(),
|
|
||||||
$response->getStatusCode()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable tracking on promise.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
private function withTracking(PromiseInterface $promise, $uri, $statusCode)
|
|
||||||
{
|
|
||||||
return $promise->then(
|
|
||||||
function (ResponseInterface $response) use ($uri, $statusCode) {
|
|
||||||
// Note that we are pushing to the front of the list as this
|
|
||||||
// would be an earlier response than what is currently present
|
|
||||||
// in the history header.
|
|
||||||
$historyHeader = $response->getHeader(self::HISTORY_HEADER);
|
|
||||||
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
|
|
||||||
array_unshift($historyHeader, $uri);
|
|
||||||
array_unshift($statusHeader, $statusCode);
|
|
||||||
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
|
|
||||||
->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for too many redirects
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @throws TooManyRedirectsException Too many redirects.
|
|
||||||
*/
|
|
||||||
private function guardMax(RequestInterface $request, array &$options)
|
|
||||||
{
|
|
||||||
$current = isset($options['__redirect_count'])
|
|
||||||
? $options['__redirect_count']
|
|
||||||
: 0;
|
|
||||||
$options['__redirect_count'] = $current + 1;
|
|
||||||
$max = $options['allow_redirects']['max'];
|
|
||||||
|
|
||||||
if ($options['__redirect_count'] > $max) {
|
|
||||||
throw new TooManyRedirectsException(
|
|
||||||
"Will not follow more than {$max} redirects",
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
*
|
|
||||||
* @return RequestInterface
|
|
||||||
*/
|
|
||||||
public function modifyRequest(
|
|
||||||
RequestInterface $request,
|
|
||||||
array $options,
|
|
||||||
ResponseInterface $response
|
|
||||||
) {
|
|
||||||
// Request modifications to apply.
|
|
||||||
$modify = [];
|
|
||||||
$protocols = $options['allow_redirects']['protocols'];
|
|
||||||
|
|
||||||
// Use a GET request if this is an entity enclosing request and we are
|
|
||||||
// not forcing RFC compliance, but rather emulating what all browsers
|
|
||||||
// would do.
|
|
||||||
$statusCode = $response->getStatusCode();
|
|
||||||
if ($statusCode == 303 ||
|
|
||||||
($statusCode <= 302 && !$options['allow_redirects']['strict'])
|
|
||||||
) {
|
|
||||||
$modify['method'] = 'GET';
|
|
||||||
$modify['body'] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = $this->redirectUri($request, $response, $protocols);
|
|
||||||
if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {
|
|
||||||
$idnOptions = ($options['idn_conversion'] === true) ? IDNA_DEFAULT : $options['idn_conversion'];
|
|
||||||
$uri = Utils::idnUriConvert($uri, $idnOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
$modify['uri'] = $uri;
|
|
||||||
Psr7\rewind_body($request);
|
|
||||||
|
|
||||||
// Add the Referer header if it is told to do so and only
|
|
||||||
// add the header if we are not redirecting from https to http.
|
|
||||||
if ($options['allow_redirects']['referer']
|
|
||||||
&& $modify['uri']->getScheme() === $request->getUri()->getScheme()
|
|
||||||
) {
|
|
||||||
$uri = $request->getUri()->withUserInfo('');
|
|
||||||
$modify['set_headers']['Referer'] = (string) $uri;
|
|
||||||
} else {
|
|
||||||
$modify['remove_headers'][] = 'Referer';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove Authorization header if host is different.
|
|
||||||
if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
|
|
||||||
$modify['remove_headers'][] = 'Authorization';
|
|
||||||
}
|
|
||||||
|
|
||||||
return Psr7\modify_request($request, $modify);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the appropriate URL on the request based on the location header
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @param array $protocols
|
|
||||||
*
|
|
||||||
* @return UriInterface
|
|
||||||
*/
|
|
||||||
private function redirectUri(
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response,
|
|
||||||
array $protocols
|
|
||||||
) {
|
|
||||||
$location = Psr7\UriResolver::resolve(
|
|
||||||
$request->getUri(),
|
|
||||||
new Psr7\Uri($response->getHeaderLine('Location'))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ensure that the redirect URI is allowed based on the protocols.
|
|
||||||
if (!in_array($location->getScheme(), $protocols)) {
|
|
||||||
throw new BadResponseException(
|
|
||||||
sprintf(
|
|
||||||
'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
|
|
||||||
$location,
|
|
||||||
implode(', ', $protocols)
|
|
||||||
),
|
|
||||||
$request,
|
|
||||||
$response
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
263
vendor/guzzlehttp/guzzle/src/RequestOptions.php
vendored
263
vendor/guzzlehttp/guzzle/src/RequestOptions.php
vendored
@@ -1,263 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains a list of built-in Guzzle request options.
|
|
||||||
*
|
|
||||||
* More documentation for each option can be found at http://guzzlephp.org/.
|
|
||||||
*
|
|
||||||
* @link http://docs.guzzlephp.org/en/v6/request-options.html
|
|
||||||
*/
|
|
||||||
final class RequestOptions
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* allow_redirects: (bool|array) Controls redirect behavior. Pass false
|
|
||||||
* to disable redirects, pass true to enable redirects, pass an
|
|
||||||
* associative to provide custom redirect settings. Defaults to "false".
|
|
||||||
* This option only works if your handler has the RedirectMiddleware. When
|
|
||||||
* passing an associative array, you can provide the following key value
|
|
||||||
* pairs:
|
|
||||||
*
|
|
||||||
* - max: (int, default=5) maximum number of allowed redirects.
|
|
||||||
* - strict: (bool, default=false) Set to true to use strict redirects
|
|
||||||
* meaning redirect POST requests with POST requests vs. doing what most
|
|
||||||
* browsers do which is redirect POST requests with GET requests
|
|
||||||
* - referer: (bool, default=false) Set to true to enable the Referer
|
|
||||||
* header.
|
|
||||||
* - protocols: (array, default=['http', 'https']) Allowed redirect
|
|
||||||
* protocols.
|
|
||||||
* - on_redirect: (callable) PHP callable that is invoked when a redirect
|
|
||||||
* is encountered. The callable is invoked with the request, the redirect
|
|
||||||
* response that was received, and the effective URI. Any return value
|
|
||||||
* from the on_redirect function is ignored.
|
|
||||||
*/
|
|
||||||
const ALLOW_REDIRECTS = 'allow_redirects';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* auth: (array) Pass an array of HTTP authentication parameters to use
|
|
||||||
* with the request. The array must contain the username in index [0],
|
|
||||||
* the password in index [1], and you can optionally provide a built-in
|
|
||||||
* authentication type in index [2]. Pass null to disable authentication
|
|
||||||
* for a request.
|
|
||||||
*/
|
|
||||||
const AUTH = 'auth';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
|
||||||
* Body to send in the request.
|
|
||||||
*/
|
|
||||||
const BODY = 'body';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cert: (string|array) Set to a string to specify the path to a file
|
|
||||||
* containing a PEM formatted SSL client side certificate. If a password
|
|
||||||
* is required, then set cert to an array containing the path to the PEM
|
|
||||||
* file in the first array element followed by the certificate password
|
|
||||||
* in the second array element.
|
|
||||||
*/
|
|
||||||
const CERT = 'cert';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
|
|
||||||
* Specifies whether or not cookies are used in a request or what cookie
|
|
||||||
* jar to use or what cookies to send. This option only works if your
|
|
||||||
* handler has the `cookie` middleware. Valid values are `false` and
|
|
||||||
* an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
|
|
||||||
*/
|
|
||||||
const COOKIES = 'cookies';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* connect_timeout: (float, default=0) Float describing the number of
|
|
||||||
* seconds to wait while trying to connect to a server. Use 0 to wait
|
|
||||||
* indefinitely (the default behavior).
|
|
||||||
*/
|
|
||||||
const CONNECT_TIMEOUT = 'connect_timeout';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* debug: (bool|resource) Set to true or set to a PHP stream returned by
|
|
||||||
* fopen() enable debug output with the HTTP handler used to send a
|
|
||||||
* request.
|
|
||||||
*/
|
|
||||||
const DEBUG = 'debug';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decode_content: (bool, default=true) Specify whether or not
|
|
||||||
* Content-Encoding responses (gzip, deflate, etc.) are automatically
|
|
||||||
* decoded.
|
|
||||||
*/
|
|
||||||
const DECODE_CONTENT = 'decode_content';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* delay: (int) The amount of time to delay before sending in milliseconds.
|
|
||||||
*/
|
|
||||||
const DELAY = 'delay';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* expect: (bool|integer) Controls the behavior of the
|
|
||||||
* "Expect: 100-Continue" header.
|
|
||||||
*
|
|
||||||
* Set to `true` to enable the "Expect: 100-Continue" header for all
|
|
||||||
* requests that sends a body. Set to `false` to disable the
|
|
||||||
* "Expect: 100-Continue" header for all requests. Set to a number so that
|
|
||||||
* the size of the payload must be greater than the number in order to send
|
|
||||||
* the Expect header. Setting to a number will send the Expect header for
|
|
||||||
* all requests in which the size of the payload cannot be determined or
|
|
||||||
* where the body is not rewindable.
|
|
||||||
*
|
|
||||||
* By default, Guzzle will add the "Expect: 100-Continue" header when the
|
|
||||||
* size of the body of a request is greater than 1 MB and a request is
|
|
||||||
* using HTTP/1.1.
|
|
||||||
*/
|
|
||||||
const EXPECT = 'expect';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* form_params: (array) Associative array of form field names to values
|
|
||||||
* where each value is a string or array of strings. Sets the Content-Type
|
|
||||||
* header to application/x-www-form-urlencoded when no Content-Type header
|
|
||||||
* is already present.
|
|
||||||
*/
|
|
||||||
const FORM_PARAMS = 'form_params';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* headers: (array) Associative array of HTTP headers. Each value MUST be
|
|
||||||
* a string or array of strings.
|
|
||||||
*/
|
|
||||||
const HEADERS = 'headers';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* http_errors: (bool, default=true) Set to false to disable exceptions
|
|
||||||
* when a non- successful HTTP response is received. By default,
|
|
||||||
* exceptions will be thrown for 4xx and 5xx responses. This option only
|
|
||||||
* works if your handler has the `httpErrors` middleware.
|
|
||||||
*/
|
|
||||||
const HTTP_ERRORS = 'http_errors';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* idn: (bool|int, default=true) A combination of IDNA_* constants for
|
|
||||||
* idn_to_ascii() PHP's function (see "options" parameter). Set to false to
|
|
||||||
* disable IDN support completely, or to true to use the default
|
|
||||||
* configuration (IDNA_DEFAULT constant).
|
|
||||||
*/
|
|
||||||
const IDN_CONVERSION = 'idn_conversion';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* json: (mixed) Adds JSON data to a request. The provided value is JSON
|
|
||||||
* encoded and a Content-Type header of application/json will be added to
|
|
||||||
* the request if no Content-Type header is already present.
|
|
||||||
*/
|
|
||||||
const JSON = 'json';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* multipart: (array) Array of associative arrays, each containing a
|
|
||||||
* required "name" key mapping to the form field, name, a required
|
|
||||||
* "contents" key mapping to a StreamInterface|resource|string, an
|
|
||||||
* optional "headers" associative array of custom headers, and an
|
|
||||||
* optional "filename" key mapping to a string to send as the filename in
|
|
||||||
* the part. If no "filename" key is present, then no "filename" attribute
|
|
||||||
* will be added to the part.
|
|
||||||
*/
|
|
||||||
const MULTIPART = 'multipart';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* on_headers: (callable) A callable that is invoked when the HTTP headers
|
|
||||||
* of the response have been received but the body has not yet begun to
|
|
||||||
* download.
|
|
||||||
*/
|
|
||||||
const ON_HEADERS = 'on_headers';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* on_stats: (callable) allows you to get access to transfer statistics of
|
|
||||||
* a request and access the lower level transfer details of the handler
|
|
||||||
* associated with your client. ``on_stats`` is a callable that is invoked
|
|
||||||
* when a handler has finished sending a request. The callback is invoked
|
|
||||||
* with transfer statistics about the request, the response received, or
|
|
||||||
* the error encountered. Included in the data is the total amount of time
|
|
||||||
* taken to send the request.
|
|
||||||
*/
|
|
||||||
const ON_STATS = 'on_stats';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* progress: (callable) Defines a function to invoke when transfer
|
|
||||||
* progress is made. The function accepts the following positional
|
|
||||||
* arguments: the total number of bytes expected to be downloaded, the
|
|
||||||
* number of bytes downloaded so far, the number of bytes expected to be
|
|
||||||
* uploaded, the number of bytes uploaded so far.
|
|
||||||
*/
|
|
||||||
const PROGRESS = 'progress';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* proxy: (string|array) Pass a string to specify an HTTP proxy, or an
|
|
||||||
* array to specify different proxies for different protocols (where the
|
|
||||||
* key is the protocol and the value is a proxy string).
|
|
||||||
*/
|
|
||||||
const PROXY = 'proxy';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* query: (array|string) Associative array of query string values to add
|
|
||||||
* to the request. This option uses PHP's http_build_query() to create
|
|
||||||
* the string representation. Pass a string value if you need more
|
|
||||||
* control than what this method provides
|
|
||||||
*/
|
|
||||||
const QUERY = 'query';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sink: (resource|string|StreamInterface) Where the data of the
|
|
||||||
* response is written to. Defaults to a PHP temp stream. Providing a
|
|
||||||
* string will write data to a file by the given name.
|
|
||||||
*/
|
|
||||||
const SINK = 'sink';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* synchronous: (bool) Set to true to inform HTTP handlers that you intend
|
|
||||||
* on waiting on the response. This can be useful for optimizations. Note
|
|
||||||
* that a promise is still returned if you are using one of the async
|
|
||||||
* client methods.
|
|
||||||
*/
|
|
||||||
const SYNCHRONOUS = 'synchronous';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ssl_key: (array|string) Specify the path to a file containing a private
|
|
||||||
* SSL key in PEM format. If a password is required, then set to an array
|
|
||||||
* containing the path to the SSL key in the first array element followed
|
|
||||||
* by the password required for the certificate in the second element.
|
|
||||||
*/
|
|
||||||
const SSL_KEY = 'ssl_key';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* stream: Set to true to attempt to stream a response rather than
|
|
||||||
* download it all up-front.
|
|
||||||
*/
|
|
||||||
const STREAM = 'stream';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify: (bool|string, default=true) Describes the SSL certificate
|
|
||||||
* verification behavior of a request. Set to true to enable SSL
|
|
||||||
* certificate verification using the system CA bundle when available
|
|
||||||
* (the default). Set to false to disable certificate verification (this
|
|
||||||
* is insecure!). Set to a string to provide the path to a CA bundle on
|
|
||||||
* disk to enable verification using a custom certificate.
|
|
||||||
*/
|
|
||||||
const VERIFY = 'verify';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* timeout: (float, default=0) Float describing the timeout of the
|
|
||||||
* request in seconds. Use 0 to wait indefinitely (the default behavior).
|
|
||||||
*/
|
|
||||||
const TIMEOUT = 'timeout';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* read_timeout: (float, default=default_socket_timeout ini setting) Float describing
|
|
||||||
* the body read timeout, for stream requests.
|
|
||||||
*/
|
|
||||||
const READ_TIMEOUT = 'read_timeout';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* version: (float) Specifies the HTTP protocol version to attempt to use.
|
|
||||||
*/
|
|
||||||
const VERSION = 'version';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
|
|
||||||
*/
|
|
||||||
const FORCE_IP_RESOLVE = 'force_ip_resolve';
|
|
||||||
}
|
|
||||||
128
vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
vendored
128
vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
vendored
@@ -1,128 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise\PromiseInterface;
|
|
||||||
use GuzzleHttp\Promise\RejectedPromise;
|
|
||||||
use GuzzleHttp\Psr7;
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware that retries requests based on the boolean result of
|
|
||||||
* invoking the provided "decider" function.
|
|
||||||
*/
|
|
||||||
class RetryMiddleware
|
|
||||||
{
|
|
||||||
/** @var callable */
|
|
||||||
private $nextHandler;
|
|
||||||
|
|
||||||
/** @var callable */
|
|
||||||
private $decider;
|
|
||||||
|
|
||||||
/** @var callable */
|
|
||||||
private $delay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $decider Function that accepts the number of retries,
|
|
||||||
* a request, [response], and [exception] and
|
|
||||||
* returns true if the request is to be
|
|
||||||
* retried.
|
|
||||||
* @param callable $nextHandler Next handler to invoke.
|
|
||||||
* @param callable $delay Function that accepts the number of retries
|
|
||||||
* and [response] and returns the number of
|
|
||||||
* milliseconds to delay.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
callable $decider,
|
|
||||||
callable $nextHandler,
|
|
||||||
callable $delay = null
|
|
||||||
) {
|
|
||||||
$this->decider = $decider;
|
|
||||||
$this->nextHandler = $nextHandler;
|
|
||||||
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default exponential backoff delay function.
|
|
||||||
*
|
|
||||||
* @param int $retries
|
|
||||||
*
|
|
||||||
* @return int milliseconds.
|
|
||||||
*/
|
|
||||||
public static function exponentialDelay($retries)
|
|
||||||
{
|
|
||||||
return (int) pow(2, $retries - 1) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function __invoke(RequestInterface $request, array $options)
|
|
||||||
{
|
|
||||||
if (!isset($options['retries'])) {
|
|
||||||
$options['retries'] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fn = $this->nextHandler;
|
|
||||||
return $fn($request, $options)
|
|
||||||
->then(
|
|
||||||
$this->onFulfilled($request, $options),
|
|
||||||
$this->onRejected($request, $options)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute fulfilled closure
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
private function onFulfilled(RequestInterface $req, array $options)
|
|
||||||
{
|
|
||||||
return function ($value) use ($req, $options) {
|
|
||||||
if (!call_user_func(
|
|
||||||
$this->decider,
|
|
||||||
$options['retries'],
|
|
||||||
$req,
|
|
||||||
$value,
|
|
||||||
null
|
|
||||||
)) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
return $this->doRetry($req, $options, $value);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute rejected closure
|
|
||||||
*
|
|
||||||
* @return callable
|
|
||||||
*/
|
|
||||||
private function onRejected(RequestInterface $req, array $options)
|
|
||||||
{
|
|
||||||
return function ($reason) use ($req, $options) {
|
|
||||||
if (!call_user_func(
|
|
||||||
$this->decider,
|
|
||||||
$options['retries'],
|
|
||||||
$req,
|
|
||||||
null,
|
|
||||||
$reason
|
|
||||||
)) {
|
|
||||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
|
||||||
}
|
|
||||||
return $this->doRetry($req, $options);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
|
|
||||||
{
|
|
||||||
$options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
|
|
||||||
|
|
||||||
return $this($request, $options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
126
vendor/guzzlehttp/guzzle/src/TransferStats.php
vendored
126
vendor/guzzlehttp/guzzle/src/TransferStats.php
vendored
@@ -1,126 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\UriInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data at the point after it was transferred either successfully
|
|
||||||
* or after a network error.
|
|
||||||
*/
|
|
||||||
final class TransferStats
|
|
||||||
{
|
|
||||||
private $request;
|
|
||||||
private $response;
|
|
||||||
private $transferTime;
|
|
||||||
private $handlerStats;
|
|
||||||
private $handlerErrorData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RequestInterface $request Request that was sent.
|
|
||||||
* @param ResponseInterface|null $response Response received (if any)
|
|
||||||
* @param float|null $transferTime Total handler transfer time.
|
|
||||||
* @param mixed $handlerErrorData Handler error data.
|
|
||||||
* @param array $handlerStats Handler specific stats.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
RequestInterface $request,
|
|
||||||
ResponseInterface $response = null,
|
|
||||||
$transferTime = null,
|
|
||||||
$handlerErrorData = null,
|
|
||||||
$handlerStats = []
|
|
||||||
) {
|
|
||||||
$this->request = $request;
|
|
||||||
$this->response = $response;
|
|
||||||
$this->transferTime = $transferTime;
|
|
||||||
$this->handlerErrorData = $handlerErrorData;
|
|
||||||
$this->handlerStats = $handlerStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return RequestInterface
|
|
||||||
*/
|
|
||||||
public function getRequest()
|
|
||||||
{
|
|
||||||
return $this->request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the response that was received (if any).
|
|
||||||
*
|
|
||||||
* @return ResponseInterface|null
|
|
||||||
*/
|
|
||||||
public function getResponse()
|
|
||||||
{
|
|
||||||
return $this->response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a response was received.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasResponse()
|
|
||||||
{
|
|
||||||
return $this->response !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets handler specific error data.
|
|
||||||
*
|
|
||||||
* This might be an exception, a integer representing an error code, or
|
|
||||||
* anything else. Relying on this value assumes that you know what handler
|
|
||||||
* you are using.
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getHandlerErrorData()
|
|
||||||
{
|
|
||||||
return $this->handlerErrorData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the effective URI the request was sent to.
|
|
||||||
*
|
|
||||||
* @return UriInterface
|
|
||||||
*/
|
|
||||||
public function getEffectiveUri()
|
|
||||||
{
|
|
||||||
return $this->request->getUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the estimated time the request was being transferred by the handler.
|
|
||||||
*
|
|
||||||
* @return float|null Time in seconds.
|
|
||||||
*/
|
|
||||||
public function getTransferTime()
|
|
||||||
{
|
|
||||||
return $this->transferTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an array of all of the handler specific transfer data.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getHandlerStats()
|
|
||||||
{
|
|
||||||
return $this->handlerStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a specific handler statistic from the handler by name.
|
|
||||||
*
|
|
||||||
* @param string $stat Handler specific transfer stat to retrieve.
|
|
||||||
*
|
|
||||||
* @return mixed|null
|
|
||||||
*/
|
|
||||||
public function getHandlerStat($stat)
|
|
||||||
{
|
|
||||||
return isset($this->handlerStats[$stat])
|
|
||||||
? $this->handlerStats[$stat]
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
237
vendor/guzzlehttp/guzzle/src/UriTemplate.php
vendored
237
vendor/guzzlehttp/guzzle/src/UriTemplate.php
vendored
@@ -1,237 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expands URI templates. Userland implementation of PECL uri_template.
|
|
||||||
*
|
|
||||||
* @link http://tools.ietf.org/html/rfc6570
|
|
||||||
*/
|
|
||||||
class UriTemplate
|
|
||||||
{
|
|
||||||
/** @var string URI template */
|
|
||||||
private $template;
|
|
||||||
|
|
||||||
/** @var array Variables to use in the template expansion */
|
|
||||||
private $variables;
|
|
||||||
|
|
||||||
/** @var array Hash for quick operator lookups */
|
|
||||||
private static $operatorHash = [
|
|
||||||
'' => ['prefix' => '', 'joiner' => ',', 'query' => false],
|
|
||||||
'+' => ['prefix' => '', 'joiner' => ',', 'query' => false],
|
|
||||||
'#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
|
|
||||||
'.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
|
|
||||||
'/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
|
|
||||||
';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
|
|
||||||
'?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
|
|
||||||
'&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @var array Delimiters */
|
|
||||||
private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
|
|
||||||
'&', '\'', '(', ')', '*', '+', ',', ';', '='];
|
|
||||||
|
|
||||||
/** @var array Percent encoded delimiters */
|
|
||||||
private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
|
|
||||||
'%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
|
|
||||||
'%3B', '%3D'];
|
|
||||||
|
|
||||||
public function expand($template, array $variables)
|
|
||||||
{
|
|
||||||
if (false === strpos($template, '{')) {
|
|
||||||
return $template;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->template = $template;
|
|
||||||
$this->variables = $variables;
|
|
||||||
|
|
||||||
return preg_replace_callback(
|
|
||||||
'/\{([^\}]+)\}/',
|
|
||||||
[$this, 'expandMatch'],
|
|
||||||
$this->template
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse an expression into parts
|
|
||||||
*
|
|
||||||
* @param string $expression Expression to parse
|
|
||||||
*
|
|
||||||
* @return array Returns an associative array of parts
|
|
||||||
*/
|
|
||||||
private function parseExpression($expression)
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
|
|
||||||
if (isset(self::$operatorHash[$expression[0]])) {
|
|
||||||
$result['operator'] = $expression[0];
|
|
||||||
$expression = substr($expression, 1);
|
|
||||||
} else {
|
|
||||||
$result['operator'] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (explode(',', $expression) as $value) {
|
|
||||||
$value = trim($value);
|
|
||||||
$varspec = [];
|
|
||||||
if ($colonPos = strpos($value, ':')) {
|
|
||||||
$varspec['value'] = substr($value, 0, $colonPos);
|
|
||||||
$varspec['modifier'] = ':';
|
|
||||||
$varspec['position'] = (int) substr($value, $colonPos + 1);
|
|
||||||
} elseif (substr($value, -1) === '*') {
|
|
||||||
$varspec['modifier'] = '*';
|
|
||||||
$varspec['value'] = substr($value, 0, -1);
|
|
||||||
} else {
|
|
||||||
$varspec['value'] = (string) $value;
|
|
||||||
$varspec['modifier'] = '';
|
|
||||||
}
|
|
||||||
$result['values'][] = $varspec;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an expansion
|
|
||||||
*
|
|
||||||
* @param array $matches Matches met in the preg_replace_callback
|
|
||||||
*
|
|
||||||
* @return string Returns the replacement string
|
|
||||||
*/
|
|
||||||
private function expandMatch(array $matches)
|
|
||||||
{
|
|
||||||
static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
|
|
||||||
|
|
||||||
$replacements = [];
|
|
||||||
$parsed = self::parseExpression($matches[1]);
|
|
||||||
$prefix = self::$operatorHash[$parsed['operator']]['prefix'];
|
|
||||||
$joiner = self::$operatorHash[$parsed['operator']]['joiner'];
|
|
||||||
$useQuery = self::$operatorHash[$parsed['operator']]['query'];
|
|
||||||
|
|
||||||
foreach ($parsed['values'] as $value) {
|
|
||||||
if (!isset($this->variables[$value['value']])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$variable = $this->variables[$value['value']];
|
|
||||||
$actuallyUseQuery = $useQuery;
|
|
||||||
$expanded = '';
|
|
||||||
|
|
||||||
if (is_array($variable)) {
|
|
||||||
$isAssoc = $this->isAssoc($variable);
|
|
||||||
$kvp = [];
|
|
||||||
foreach ($variable as $key => $var) {
|
|
||||||
if ($isAssoc) {
|
|
||||||
$key = rawurlencode($key);
|
|
||||||
$isNestedArray = is_array($var);
|
|
||||||
} else {
|
|
||||||
$isNestedArray = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$isNestedArray) {
|
|
||||||
$var = rawurlencode($var);
|
|
||||||
if ($parsed['operator'] === '+' ||
|
|
||||||
$parsed['operator'] === '#'
|
|
||||||
) {
|
|
||||||
$var = $this->decodeReserved($var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value['modifier'] === '*') {
|
|
||||||
if ($isAssoc) {
|
|
||||||
if ($isNestedArray) {
|
|
||||||
// Nested arrays must allow for deeply nested
|
|
||||||
// structures.
|
|
||||||
$var = strtr(
|
|
||||||
http_build_query([$key => $var]),
|
|
||||||
$rfc1738to3986
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$var = $key . '=' . $var;
|
|
||||||
}
|
|
||||||
} elseif ($key > 0 && $actuallyUseQuery) {
|
|
||||||
$var = $value['value'] . '=' . $var;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$kvp[$key] = $var;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($variable)) {
|
|
||||||
$actuallyUseQuery = false;
|
|
||||||
} elseif ($value['modifier'] === '*') {
|
|
||||||
$expanded = implode($joiner, $kvp);
|
|
||||||
if ($isAssoc) {
|
|
||||||
// Don't prepend the value name when using the explode
|
|
||||||
// modifier with an associative array.
|
|
||||||
$actuallyUseQuery = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($isAssoc) {
|
|
||||||
// When an associative array is encountered and the
|
|
||||||
// explode modifier is not set, then the result must be
|
|
||||||
// a comma separated list of keys followed by their
|
|
||||||
// respective values.
|
|
||||||
foreach ($kvp as $k => &$v) {
|
|
||||||
$v = $k . ',' . $v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$expanded = implode(',', $kvp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($value['modifier'] === ':') {
|
|
||||||
$variable = substr($variable, 0, $value['position']);
|
|
||||||
}
|
|
||||||
$expanded = rawurlencode($variable);
|
|
||||||
if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
|
|
||||||
$expanded = $this->decodeReserved($expanded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($actuallyUseQuery) {
|
|
||||||
if (!$expanded && $joiner !== '&') {
|
|
||||||
$expanded = $value['value'];
|
|
||||||
} else {
|
|
||||||
$expanded = $value['value'] . '=' . $expanded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$replacements[] = $expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret = implode($joiner, $replacements);
|
|
||||||
if ($ret && $prefix) {
|
|
||||||
return $prefix . $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if an array is associative.
|
|
||||||
*
|
|
||||||
* This makes the assumption that input arrays are sequences or hashes.
|
|
||||||
* This assumption is a tradeoff for accuracy in favor of speed, but it
|
|
||||||
* should work in almost every case where input is supplied for a URI
|
|
||||||
* template.
|
|
||||||
*
|
|
||||||
* @param array $array Array to check
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function isAssoc(array $array)
|
|
||||||
{
|
|
||||||
return $array && array_keys($array)[0] !== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes percent encoding on reserved characters (used with + and #
|
|
||||||
* modifiers).
|
|
||||||
*
|
|
||||||
* @param string $string String to fix
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function decodeReserved($string)
|
|
||||||
{
|
|
||||||
return str_replace(self::$delimsPct, self::$delims, $string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
92
vendor/guzzlehttp/guzzle/src/Utils.php
vendored
92
vendor/guzzlehttp/guzzle/src/Utils.php
vendored
@@ -1,92 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\InvalidArgumentException;
|
|
||||||
use Psr\Http\Message\UriInterface;
|
|
||||||
use Symfony\Polyfill\Intl\Idn\Idn;
|
|
||||||
|
|
||||||
final class Utils
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Wrapper for the hrtime() or microtime() functions
|
|
||||||
* (depending on the PHP version, one of the two is used)
|
|
||||||
*
|
|
||||||
* @return float|mixed UNIX timestamp
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public static function currentTime()
|
|
||||||
{
|
|
||||||
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $options
|
|
||||||
*
|
|
||||||
* @return UriInterface
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public static function idnUriConvert(UriInterface $uri, $options = 0)
|
|
||||||
{
|
|
||||||
if ($uri->getHost()) {
|
|
||||||
$asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
|
|
||||||
if ($asciiHost === false) {
|
|
||||||
$errorBitSet = isset($info['errors']) ? $info['errors'] : 0;
|
|
||||||
|
|
||||||
$errorConstants = array_filter(array_keys(get_defined_constants()), function ($name) {
|
|
||||||
return substr($name, 0, 11) === 'IDNA_ERROR_';
|
|
||||||
});
|
|
||||||
|
|
||||||
$errors = [];
|
|
||||||
foreach ($errorConstants as $errorConstant) {
|
|
||||||
if ($errorBitSet & constant($errorConstant)) {
|
|
||||||
$errors[] = $errorConstant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$errorMessage = 'IDN conversion failed';
|
|
||||||
if ($errors) {
|
|
||||||
$errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidArgumentException($errorMessage);
|
|
||||||
} else {
|
|
||||||
if ($uri->getHost() !== $asciiHost) {
|
|
||||||
// Replace URI only if the ASCII version is different
|
|
||||||
$uri = $uri->withHost($asciiHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $domain
|
|
||||||
* @param int $options
|
|
||||||
* @param array $info
|
|
||||||
*
|
|
||||||
* @return string|false
|
|
||||||
*/
|
|
||||||
private static function idnToAsci($domain, $options, &$info = [])
|
|
||||||
{
|
|
||||||
if (\preg_match('%^[ -~]+$%', $domain) === 1) {
|
|
||||||
return $domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\extension_loaded('intl') && defined('INTL_IDNA_VARIANT_UTS46')) {
|
|
||||||
return \idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Idn class is marked as @internal. Verify that class and method exists.
|
|
||||||
*/
|
|
||||||
if (method_exists(Idn::class, 'idn_to_ascii')) {
|
|
||||||
return Idn::idn_to_ascii($domain, $options, Idn::INTL_IDNA_VARIANT_UTS46, $info);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \RuntimeException('ext-intl or symfony/polyfill-intl-idn not loaded or too old');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
334
vendor/guzzlehttp/guzzle/src/functions.php
vendored
334
vendor/guzzlehttp/guzzle/src/functions.php
vendored
@@ -1,334 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp;
|
|
||||||
|
|
||||||
use GuzzleHttp\Handler\CurlHandler;
|
|
||||||
use GuzzleHttp\Handler\CurlMultiHandler;
|
|
||||||
use GuzzleHttp\Handler\Proxy;
|
|
||||||
use GuzzleHttp\Handler\StreamHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expands a URI template
|
|
||||||
*
|
|
||||||
* @param string $template URI template
|
|
||||||
* @param array $variables Template variables
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function uri_template($template, array $variables)
|
|
||||||
{
|
|
||||||
if (extension_loaded('uri_template')) {
|
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
return \uri_template($template, $variables);
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
static $uriTemplate;
|
|
||||||
if (!$uriTemplate) {
|
|
||||||
$uriTemplate = new UriTemplate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uriTemplate->expand($template, $variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Debug function used to describe the provided value type and class.
|
|
||||||
*
|
|
||||||
* @param mixed $input
|
|
||||||
*
|
|
||||||
* @return string Returns a string containing the type of the variable and
|
|
||||||
* if a class is provided, the class name.
|
|
||||||
*/
|
|
||||||
function describe_type($input)
|
|
||||||
{
|
|
||||||
switch (gettype($input)) {
|
|
||||||
case 'object':
|
|
||||||
return 'object(' . get_class($input) . ')';
|
|
||||||
case 'array':
|
|
||||||
return 'array(' . count($input) . ')';
|
|
||||||
default:
|
|
||||||
ob_start();
|
|
||||||
var_dump($input);
|
|
||||||
// normalize float vs double
|
|
||||||
return str_replace('double(', 'float(', rtrim(ob_get_clean()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an array of header lines into an associative array of headers.
|
|
||||||
*
|
|
||||||
* @param iterable $lines Header lines array of strings in the following
|
|
||||||
* format: "Name: Value"
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function headers_from_lines($lines)
|
|
||||||
{
|
|
||||||
$headers = [];
|
|
||||||
|
|
||||||
foreach ($lines as $line) {
|
|
||||||
$parts = explode(':', $line, 2);
|
|
||||||
$headers[trim($parts[0])][] = isset($parts[1])
|
|
||||||
? trim($parts[1])
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a debug stream based on the provided variable.
|
|
||||||
*
|
|
||||||
* @param mixed $value Optional value
|
|
||||||
*
|
|
||||||
* @return resource
|
|
||||||
*/
|
|
||||||
function debug_resource($value = null)
|
|
||||||
{
|
|
||||||
if (is_resource($value)) {
|
|
||||||
return $value;
|
|
||||||
} elseif (defined('STDOUT')) {
|
|
||||||
return STDOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fopen('php://output', 'w');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chooses and creates a default handler to use based on the environment.
|
|
||||||
*
|
|
||||||
* The returned handler is not wrapped by any default middlewares.
|
|
||||||
*
|
|
||||||
* @return callable Returns the best handler for the given system.
|
|
||||||
* @throws \RuntimeException if no viable Handler is available.
|
|
||||||
*/
|
|
||||||
function choose_handler()
|
|
||||||
{
|
|
||||||
$handler = null;
|
|
||||||
if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
|
|
||||||
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
|
|
||||||
} elseif (function_exists('curl_exec')) {
|
|
||||||
$handler = new CurlHandler();
|
|
||||||
} elseif (function_exists('curl_multi_exec')) {
|
|
||||||
$handler = new CurlMultiHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ini_get('allow_url_fopen')) {
|
|
||||||
$handler = $handler
|
|
||||||
? Proxy::wrapStreaming($handler, new StreamHandler())
|
|
||||||
: new StreamHandler();
|
|
||||||
} elseif (!$handler) {
|
|
||||||
throw new \RuntimeException('GuzzleHttp requires cURL, the '
|
|
||||||
. 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the default User-Agent string to use with Guzzle
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function default_user_agent()
|
|
||||||
{
|
|
||||||
static $defaultAgent = '';
|
|
||||||
|
|
||||||
if (!$defaultAgent) {
|
|
||||||
$defaultAgent = 'GuzzleHttp/' . Client::VERSION;
|
|
||||||
if (extension_loaded('curl') && function_exists('curl_version')) {
|
|
||||||
$defaultAgent .= ' curl/' . \curl_version()['version'];
|
|
||||||
}
|
|
||||||
$defaultAgent .= ' PHP/' . PHP_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $defaultAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the default cacert bundle for the current system.
|
|
||||||
*
|
|
||||||
* First, the openssl.cafile and curl.cainfo php.ini settings are checked.
|
|
||||||
* If those settings are not configured, then the common locations for
|
|
||||||
* bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
|
|
||||||
* and Windows are checked. If any of these file locations are found on
|
|
||||||
* disk, they will be utilized.
|
|
||||||
*
|
|
||||||
* Note: the result of this function is cached for subsequent calls.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws \RuntimeException if no bundle can be found.
|
|
||||||
*/
|
|
||||||
function default_ca_bundle()
|
|
||||||
{
|
|
||||||
static $cached = null;
|
|
||||||
static $cafiles = [
|
|
||||||
// Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
|
||||||
'/etc/pki/tls/certs/ca-bundle.crt',
|
|
||||||
// Ubuntu, Debian (provided by the ca-certificates package)
|
|
||||||
'/etc/ssl/certs/ca-certificates.crt',
|
|
||||||
// FreeBSD (provided by the ca_root_nss package)
|
|
||||||
'/usr/local/share/certs/ca-root-nss.crt',
|
|
||||||
// SLES 12 (provided by the ca-certificates package)
|
|
||||||
'/var/lib/ca-certificates/ca-bundle.pem',
|
|
||||||
// OS X provided by homebrew (using the default path)
|
|
||||||
'/usr/local/etc/openssl/cert.pem',
|
|
||||||
// Google app engine
|
|
||||||
'/etc/ca-certificates.crt',
|
|
||||||
// Windows?
|
|
||||||
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
|
||||||
'C:\\windows\\curl-ca-bundle.crt',
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($cached) {
|
|
||||||
return $cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ca = ini_get('openssl.cafile')) {
|
|
||||||
return $cached = $ca;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ca = ini_get('curl.cainfo')) {
|
|
||||||
return $cached = $ca;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($cafiles as $filename) {
|
|
||||||
if (file_exists($filename)) {
|
|
||||||
return $cached = $filename;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \RuntimeException(
|
|
||||||
<<< EOT
|
|
||||||
No system CA bundle could be found in any of the the common system locations.
|
|
||||||
PHP versions earlier than 5.6 are not properly configured to use the system's
|
|
||||||
CA bundle by default. In order to verify peer certificates, you will need to
|
|
||||||
supply the path on disk to a certificate bundle to the 'verify' request
|
|
||||||
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
|
|
||||||
need a specific certificate bundle, then Mozilla provides a commonly used CA
|
|
||||||
bundle which can be downloaded here (provided by the maintainer of cURL):
|
|
||||||
https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
|
|
||||||
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
|
|
||||||
ini setting to point to the path to the file, allowing you to omit the 'verify'
|
|
||||||
request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
|
||||||
information.
|
|
||||||
EOT
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an associative array of lowercase header names to the actual
|
|
||||||
* header casing.
|
|
||||||
*
|
|
||||||
* @param array $headers
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function normalize_header_keys(array $headers)
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
foreach (array_keys($headers) as $key) {
|
|
||||||
$result[strtolower($key)] = $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the provided host matches any of the no proxy areas.
|
|
||||||
*
|
|
||||||
* This method will strip a port from the host if it is present. Each pattern
|
|
||||||
* can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
|
|
||||||
* partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
|
|
||||||
* "baz.foo.com", but ".foo.com" != "foo.com").
|
|
||||||
*
|
|
||||||
* Areas are matched in the following cases:
|
|
||||||
* 1. "*" (without quotes) always matches any hosts.
|
|
||||||
* 2. An exact match.
|
|
||||||
* 3. The area starts with "." and the area is the last part of the host. e.g.
|
|
||||||
* '.mit.edu' will match any host that ends with '.mit.edu'.
|
|
||||||
*
|
|
||||||
* @param string $host Host to check against the patterns.
|
|
||||||
* @param array $noProxyArray An array of host patterns.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function is_host_in_noproxy($host, array $noProxyArray)
|
|
||||||
{
|
|
||||||
if (strlen($host) === 0) {
|
|
||||||
throw new \InvalidArgumentException('Empty host provided');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip port if present.
|
|
||||||
if (strpos($host, ':')) {
|
|
||||||
$host = explode($host, ':', 2)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($noProxyArray as $area) {
|
|
||||||
// Always match on wildcards.
|
|
||||||
if ($area === '*') {
|
|
||||||
return true;
|
|
||||||
} elseif (empty($area)) {
|
|
||||||
// Don't match on empty values.
|
|
||||||
continue;
|
|
||||||
} elseif ($area === $host) {
|
|
||||||
// Exact matches.
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// 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) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for json_decode that throws when an error occurs.
|
|
||||||
*
|
|
||||||
* @param string $json JSON data to parse
|
|
||||||
* @param bool $assoc When true, returned objects will be converted
|
|
||||||
* into associative arrays.
|
|
||||||
* @param int $depth User specified recursion depth.
|
|
||||||
* @param int $options Bitmask of JSON decode options.
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
* @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
|
|
||||||
* @link http://www.php.net/manual/en/function.json-decode.php
|
|
||||||
*/
|
|
||||||
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
|
|
||||||
{
|
|
||||||
$data = \json_decode($json, $assoc, $depth, $options);
|
|
||||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
|
||||||
throw new Exception\InvalidArgumentException(
|
|
||||||
'json_decode error: ' . json_last_error_msg()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for JSON encoding that throws when an error occurs.
|
|
||||||
*
|
|
||||||
* @param mixed $value The value being encoded
|
|
||||||
* @param int $options JSON encode option bitmask
|
|
||||||
* @param int $depth Set the maximum depth. Must be greater than zero.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
|
|
||||||
* @link http://www.php.net/manual/en/function.json-encode.php
|
|
||||||
*/
|
|
||||||
function json_encode($value, $options = 0, $depth = 512)
|
|
||||||
{
|
|
||||||
$json = \json_encode($value, $options, $depth);
|
|
||||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
|
||||||
throw new Exception\InvalidArgumentException(
|
|
||||||
'json_encode error: ' . json_last_error_msg()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $json;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// Don't redefine the functions if included multiple times.
|
|
||||||
if (!function_exists('GuzzleHttp\uri_template')) {
|
|
||||||
require __DIR__ . '/functions.php';
|
|
||||||
}
|
|
||||||
65
vendor/guzzlehttp/promises/CHANGELOG.md
vendored
65
vendor/guzzlehttp/promises/CHANGELOG.md
vendored
@@ -1,65 +0,0 @@
|
|||||||
# CHANGELOG
|
|
||||||
|
|
||||||
|
|
||||||
## 1.3.1 - 2016-12-20
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- `wait()` foreign promise compatibility
|
|
||||||
|
|
||||||
|
|
||||||
## 1.3.0 - 2016-11-18
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Adds support for custom task queues.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fixed coroutine promise memory leak.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.2.0 - 2016-05-18
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Update to now catch `\Throwable` on PHP 7+
|
|
||||||
|
|
||||||
|
|
||||||
## 1.1.0 - 2016-03-07
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Update EachPromise to prevent recurring on a iterator when advancing, as this
|
|
||||||
could trigger fatal generator errors.
|
|
||||||
- Update Promise to allow recursive waiting without unwrapping exceptions.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.0.3 - 2015-10-15
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Update EachPromise to immediately resolve when the underlying promise iterator
|
|
||||||
is empty. Previously, such a promise would throw an exception when its `wait`
|
|
||||||
function was called.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.0.2 - 2015-05-15
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Conditionally require functions.php.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.0.1 - 2015-06-24
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Updating EachPromise to call next on the underlying promise iterator as late
|
|
||||||
as possible to ensure that generators that generate new requests based on
|
|
||||||
callbacks are not iterated until after callbacks are invoked.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.0.0 - 2015-05-12
|
|
||||||
|
|
||||||
- Initial release
|
|
||||||
19
vendor/guzzlehttp/promises/LICENSE
vendored
19
vendor/guzzlehttp/promises/LICENSE
vendored
@@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2015-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
13
vendor/guzzlehttp/promises/Makefile
vendored
13
vendor/guzzlehttp/promises/Makefile
vendored
@@ -1,13 +0,0 @@
|
|||||||
all: clean test
|
|
||||||
|
|
||||||
test:
|
|
||||||
vendor/bin/phpunit
|
|
||||||
|
|
||||||
coverage:
|
|
||||||
vendor/bin/phpunit --coverage-html=artifacts/coverage
|
|
||||||
|
|
||||||
view-coverage:
|
|
||||||
open artifacts/coverage/index.html
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf artifacts/*
|
|
||||||
504
vendor/guzzlehttp/promises/README.md
vendored
504
vendor/guzzlehttp/promises/README.md
vendored
@@ -1,504 +0,0 @@
|
|||||||
# Guzzle Promises
|
|
||||||
|
|
||||||
[Promises/A+](https://promisesaplus.com/) implementation that handles promise
|
|
||||||
chaining and resolution iteratively, allowing for "infinite" promise chaining
|
|
||||||
while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)
|
|
||||||
for a general introduction to promises.
|
|
||||||
|
|
||||||
- [Features](#features)
|
|
||||||
- [Quick start](#quick-start)
|
|
||||||
- [Synchronous wait](#synchronous-wait)
|
|
||||||
- [Cancellation](#cancellation)
|
|
||||||
- [API](#api)
|
|
||||||
- [Promise](#promise)
|
|
||||||
- [FulfilledPromise](#fulfilledpromise)
|
|
||||||
- [RejectedPromise](#rejectedpromise)
|
|
||||||
- [Promise interop](#promise-interop)
|
|
||||||
- [Implementation notes](#implementation-notes)
|
|
||||||
|
|
||||||
|
|
||||||
# Features
|
|
||||||
|
|
||||||
- [Promises/A+](https://promisesaplus.com/) implementation.
|
|
||||||
- Promise resolution and chaining is handled iteratively, allowing for
|
|
||||||
"infinite" promise chaining.
|
|
||||||
- Promises have a synchronous `wait` method.
|
|
||||||
- Promises can be cancelled.
|
|
||||||
- Works with any object that has a `then` function.
|
|
||||||
- C# style async/await coroutine promises using
|
|
||||||
`GuzzleHttp\Promise\coroutine()`.
|
|
||||||
|
|
||||||
|
|
||||||
# Quick start
|
|
||||||
|
|
||||||
A *promise* represents the eventual result of an asynchronous operation. The
|
|
||||||
primary way of interacting with a promise is through its `then` method, which
|
|
||||||
registers callbacks to receive either a promise's eventual value or the reason
|
|
||||||
why the promise cannot be fulfilled.
|
|
||||||
|
|
||||||
|
|
||||||
## Callbacks
|
|
||||||
|
|
||||||
Callbacks are registered with the `then` method by providing an optional
|
|
||||||
`$onFulfilled` followed by an optional `$onRejected` function.
|
|
||||||
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->then(
|
|
||||||
// $onFulfilled
|
|
||||||
function ($value) {
|
|
||||||
echo 'The promise was fulfilled.';
|
|
||||||
},
|
|
||||||
// $onRejected
|
|
||||||
function ($reason) {
|
|
||||||
echo 'The promise was rejected.';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
*Resolving* a promise means that you either fulfill a promise with a *value* or
|
|
||||||
reject a promise with a *reason*. Resolving a promises triggers callbacks
|
|
||||||
registered with the promises's `then` method. These callbacks are triggered
|
|
||||||
only once and in the order in which they were added.
|
|
||||||
|
|
||||||
|
|
||||||
## Resolving a promise
|
|
||||||
|
|
||||||
Promises are fulfilled using the `resolve($value)` method. Resolving a promise
|
|
||||||
with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger
|
|
||||||
all of the onFulfilled callbacks (resolving a promise with a rejected promise
|
|
||||||
will reject the promise and trigger the `$onRejected` callbacks).
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise
|
|
||||||
->then(function ($value) {
|
|
||||||
// Return a value and don't break the chain
|
|
||||||
return "Hello, " . $value;
|
|
||||||
})
|
|
||||||
// This then is executed after the first then and receives the value
|
|
||||||
// returned from the first then.
|
|
||||||
->then(function ($value) {
|
|
||||||
echo $value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Resolving the promise triggers the $onFulfilled callbacks and outputs
|
|
||||||
// "Hello, reader".
|
|
||||||
$promise->resolve('reader.');
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Promise forwarding
|
|
||||||
|
|
||||||
Promises can be chained one after the other. Each then in the chain is a new
|
|
||||||
promise. The return value of a promise is what's forwarded to the next
|
|
||||||
promise in the chain. Returning a promise in a `then` callback will cause the
|
|
||||||
subsequent promises in the chain to only be fulfilled when the returned promise
|
|
||||||
has been fulfilled. The next promise in the chain will be invoked with the
|
|
||||||
resolved value of the promise.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$nextPromise = new Promise();
|
|
||||||
|
|
||||||
$promise
|
|
||||||
->then(function ($value) use ($nextPromise) {
|
|
||||||
echo $value;
|
|
||||||
return $nextPromise;
|
|
||||||
})
|
|
||||||
->then(function ($value) {
|
|
||||||
echo $value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Triggers the first callback and outputs "A"
|
|
||||||
$promise->resolve('A');
|
|
||||||
// Triggers the second callback and outputs "B"
|
|
||||||
$nextPromise->resolve('B');
|
|
||||||
```
|
|
||||||
|
|
||||||
## Promise rejection
|
|
||||||
|
|
||||||
When a promise is rejected, the `$onRejected` callbacks are invoked with the
|
|
||||||
rejection reason.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->then(null, function ($reason) {
|
|
||||||
echo $reason;
|
|
||||||
});
|
|
||||||
|
|
||||||
$promise->reject('Error!');
|
|
||||||
// Outputs "Error!"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Rejection forwarding
|
|
||||||
|
|
||||||
If an exception is thrown in an `$onRejected` callback, subsequent
|
|
||||||
`$onRejected` callbacks are invoked with the thrown exception as the reason.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->then(null, function ($reason) {
|
|
||||||
throw new \Exception($reason);
|
|
||||||
})->then(null, function ($reason) {
|
|
||||||
assert($reason->getMessage() === 'Error!');
|
|
||||||
});
|
|
||||||
|
|
||||||
$promise->reject('Error!');
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also forward a rejection down the promise chain by returning a
|
|
||||||
`GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
|
|
||||||
`$onRejected` callback.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
use GuzzleHttp\Promise\RejectedPromise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->then(null, function ($reason) {
|
|
||||||
return new RejectedPromise($reason);
|
|
||||||
})->then(null, function ($reason) {
|
|
||||||
assert($reason === 'Error!');
|
|
||||||
});
|
|
||||||
|
|
||||||
$promise->reject('Error!');
|
|
||||||
```
|
|
||||||
|
|
||||||
If an exception is not thrown in a `$onRejected` callback and the callback
|
|
||||||
does not return a rejected promise, downstream `$onFulfilled` callbacks are
|
|
||||||
invoked using the value returned from the `$onRejected` callback.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
use GuzzleHttp\Promise\RejectedPromise;
|
|
||||||
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise
|
|
||||||
->then(null, function ($reason) {
|
|
||||||
return "It's ok";
|
|
||||||
})
|
|
||||||
->then(function ($value) {
|
|
||||||
assert($value === "It's ok");
|
|
||||||
});
|
|
||||||
|
|
||||||
$promise->reject('Error!');
|
|
||||||
```
|
|
||||||
|
|
||||||
# Synchronous wait
|
|
||||||
|
|
||||||
You can synchronously force promises to complete using a promise's `wait`
|
|
||||||
method. When creating a promise, you can provide a wait function that is used
|
|
||||||
to synchronously force a promise to complete. When a wait function is invoked
|
|
||||||
it is expected to deliver a value to the promise or reject the promise. If the
|
|
||||||
wait function does not deliver a value, then an exception is thrown. The wait
|
|
||||||
function provided to a promise constructor is invoked when the `wait` function
|
|
||||||
of the promise is called.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$promise = new Promise(function () use (&$promise) {
|
|
||||||
$promise->resolve('foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Calling wait will return the value of the promise.
|
|
||||||
echo $promise->wait(); // outputs "foo"
|
|
||||||
```
|
|
||||||
|
|
||||||
If an exception is encountered while invoking the wait function of a promise,
|
|
||||||
the promise is rejected with the exception and the exception is thrown.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$promise = new Promise(function () use (&$promise) {
|
|
||||||
throw new \Exception('foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
$promise->wait(); // throws the exception.
|
|
||||||
```
|
|
||||||
|
|
||||||
Calling `wait` on a promise that has been fulfilled will not trigger the wait
|
|
||||||
function. It will simply return the previously resolved value.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$promise = new Promise(function () { die('this is not called!'); });
|
|
||||||
$promise->resolve('foo');
|
|
||||||
echo $promise->wait(); // outputs "foo"
|
|
||||||
```
|
|
||||||
|
|
||||||
Calling `wait` on a promise that has been rejected will throw an exception. If
|
|
||||||
the rejection reason is an instance of `\Exception` the reason is thrown.
|
|
||||||
Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason
|
|
||||||
can be obtained by calling the `getReason` method of the exception.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->reject('foo');
|
|
||||||
$promise->wait();
|
|
||||||
```
|
|
||||||
|
|
||||||
> PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
|
|
||||||
|
|
||||||
|
|
||||||
## Unwrapping a promise
|
|
||||||
|
|
||||||
When synchronously waiting on a promise, you are joining the state of the
|
|
||||||
promise into the current state of execution (i.e., return the value of the
|
|
||||||
promise if it was fulfilled or throw an exception if it was rejected). This is
|
|
||||||
called "unwrapping" the promise. Waiting on a promise will by default unwrap
|
|
||||||
the promise state.
|
|
||||||
|
|
||||||
You can force a promise to resolve and *not* unwrap the state of the promise
|
|
||||||
by passing `false` to the first argument of the `wait` function:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->reject('foo');
|
|
||||||
// This will not throw an exception. It simply ensures the promise has
|
|
||||||
// been resolved.
|
|
||||||
$promise->wait(false);
|
|
||||||
```
|
|
||||||
|
|
||||||
When unwrapping a promise, the resolved value of the promise will be waited
|
|
||||||
upon until the unwrapped value is not a promise. This means that if you resolve
|
|
||||||
promise A with a promise B and unwrap promise A, the value returned by the
|
|
||||||
wait function will be the value delivered to promise B.
|
|
||||||
|
|
||||||
**Note**: when you do not unwrap the promise, no value is returned.
|
|
||||||
|
|
||||||
|
|
||||||
# Cancellation
|
|
||||||
|
|
||||||
You can cancel a promise that has not yet been fulfilled using the `cancel()`
|
|
||||||
method of a promise. When creating a promise you can provide an optional
|
|
||||||
cancel function that when invoked cancels the action of computing a resolution
|
|
||||||
of the promise.
|
|
||||||
|
|
||||||
|
|
||||||
# API
|
|
||||||
|
|
||||||
|
|
||||||
## Promise
|
|
||||||
|
|
||||||
When creating a promise object, you can provide an optional `$waitFn` and
|
|
||||||
`$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is
|
|
||||||
expected to resolve the promise. `$cancelFn` is a function with no arguments
|
|
||||||
that is expected to cancel the computation of a promise. It is invoked when the
|
|
||||||
`cancel()` method of a promise is called.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$promise = new Promise(
|
|
||||||
function () use (&$promise) {
|
|
||||||
$promise->resolve('waited');
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
// do something that will cancel the promise computation (e.g., close
|
|
||||||
// a socket, cancel a database query, etc...)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assert('waited' === $promise->wait());
|
|
||||||
```
|
|
||||||
|
|
||||||
A promise has the following methods:
|
|
||||||
|
|
||||||
- `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`
|
|
||||||
|
|
||||||
Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.
|
|
||||||
|
|
||||||
- `otherwise(callable $onRejected) : PromiseInterface`
|
|
||||||
|
|
||||||
Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
|
|
||||||
|
|
||||||
- `wait($unwrap = true) : mixed`
|
|
||||||
|
|
||||||
Synchronously waits on the promise to complete.
|
|
||||||
|
|
||||||
`$unwrap` controls whether or not the value of the promise is returned for a
|
|
||||||
fulfilled promise or if an exception is thrown if the promise is rejected.
|
|
||||||
This is set to `true` by default.
|
|
||||||
|
|
||||||
- `cancel()`
|
|
||||||
|
|
||||||
Attempts to cancel the promise if possible. The promise being cancelled and
|
|
||||||
the parent most ancestor that has not yet been resolved will also be
|
|
||||||
cancelled. Any promises waiting on the cancelled promise to resolve will also
|
|
||||||
be cancelled.
|
|
||||||
|
|
||||||
- `getState() : string`
|
|
||||||
|
|
||||||
Returns the state of the promise. One of `pending`, `fulfilled`, or
|
|
||||||
`rejected`.
|
|
||||||
|
|
||||||
- `resolve($value)`
|
|
||||||
|
|
||||||
Fulfills the promise with the given `$value`.
|
|
||||||
|
|
||||||
- `reject($reason)`
|
|
||||||
|
|
||||||
Rejects the promise with the given `$reason`.
|
|
||||||
|
|
||||||
|
|
||||||
## FulfilledPromise
|
|
||||||
|
|
||||||
A fulfilled promise can be created to represent a promise that has been
|
|
||||||
fulfilled.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\FulfilledPromise;
|
|
||||||
|
|
||||||
$promise = new FulfilledPromise('value');
|
|
||||||
|
|
||||||
// Fulfilled callbacks are immediately invoked.
|
|
||||||
$promise->then(function ($value) {
|
|
||||||
echo $value;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## RejectedPromise
|
|
||||||
|
|
||||||
A rejected promise can be created to represent a promise that has been
|
|
||||||
rejected.
|
|
||||||
|
|
||||||
```php
|
|
||||||
use GuzzleHttp\Promise\RejectedPromise;
|
|
||||||
|
|
||||||
$promise = new RejectedPromise('Error');
|
|
||||||
|
|
||||||
// Rejected callbacks are immediately invoked.
|
|
||||||
$promise->then(null, function ($reason) {
|
|
||||||
echo $reason;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# Promise interop
|
|
||||||
|
|
||||||
This library works with foreign promises that have a `then` method. This means
|
|
||||||
you can use Guzzle promises with [React promises](https://github.com/reactphp/promise)
|
|
||||||
for example. When a foreign promise is returned inside of a then method
|
|
||||||
callback, promise resolution will occur recursively.
|
|
||||||
|
|
||||||
```php
|
|
||||||
// Create a React promise
|
|
||||||
$deferred = new React\Promise\Deferred();
|
|
||||||
$reactPromise = $deferred->promise();
|
|
||||||
|
|
||||||
// Create a Guzzle promise that is fulfilled with a React promise.
|
|
||||||
$guzzlePromise = new \GuzzleHttp\Promise\Promise();
|
|
||||||
$guzzlePromise->then(function ($value) use ($reactPromise) {
|
|
||||||
// Do something something with the value...
|
|
||||||
// Return the React promise
|
|
||||||
return $reactPromise;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Please note that wait and cancel chaining is no longer possible when forwarding
|
|
||||||
a foreign promise. You will need to wrap a third-party promise with a Guzzle
|
|
||||||
promise in order to utilize wait and cancel functions with foreign promises.
|
|
||||||
|
|
||||||
|
|
||||||
## Event Loop Integration
|
|
||||||
|
|
||||||
In order to keep the stack size constant, Guzzle promises are resolved
|
|
||||||
asynchronously using a task queue. When waiting on promises synchronously, the
|
|
||||||
task queue will be automatically run to ensure that the blocking promise and
|
|
||||||
any forwarded promises are resolved. When using promises asynchronously in an
|
|
||||||
event loop, you will need to run the task queue on each tick of the loop. If
|
|
||||||
you do not run the task queue, then promises will not be resolved.
|
|
||||||
|
|
||||||
You can run the task queue using the `run()` method of the global task queue
|
|
||||||
instance.
|
|
||||||
|
|
||||||
```php
|
|
||||||
// Get the global task queue
|
|
||||||
$queue = \GuzzleHttp\Promise\queue();
|
|
||||||
$queue->run();
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, you could use Guzzle promises with React using a periodic timer:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$loop = React\EventLoop\Factory::create();
|
|
||||||
$loop->addPeriodicTimer(0, [$queue, 'run']);
|
|
||||||
```
|
|
||||||
|
|
||||||
*TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
|
|
||||||
|
|
||||||
|
|
||||||
# Implementation notes
|
|
||||||
|
|
||||||
|
|
||||||
## Promise resolution and chaining is handled iteratively
|
|
||||||
|
|
||||||
By shuffling pending handlers from one owner to another, promises are
|
|
||||||
resolved iteratively, allowing for "infinite" then chaining.
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
require 'vendor/autoload.php';
|
|
||||||
|
|
||||||
use GuzzleHttp\Promise\Promise;
|
|
||||||
|
|
||||||
$parent = new Promise();
|
|
||||||
$p = $parent;
|
|
||||||
|
|
||||||
for ($i = 0; $i < 1000; $i++) {
|
|
||||||
$p = $p->then(function ($v) {
|
|
||||||
// The stack size remains constant (a good thing)
|
|
||||||
echo xdebug_get_stack_depth() . ', ';
|
|
||||||
return $v + 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$parent->resolve(0);
|
|
||||||
var_dump($p->wait()); // int(1000)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
When a promise is fulfilled or rejected with a non-promise value, the promise
|
|
||||||
then takes ownership of the handlers of each child promise and delivers values
|
|
||||||
down the chain without using recursion.
|
|
||||||
|
|
||||||
When a promise is resolved with another promise, the original promise transfers
|
|
||||||
all of its pending handlers to the new promise. When the new promise is
|
|
||||||
eventually resolved, all of the pending handlers are delivered the forwarded
|
|
||||||
value.
|
|
||||||
|
|
||||||
|
|
||||||
## A promise is the deferred.
|
|
||||||
|
|
||||||
Some promise libraries implement promises using a deferred object to represent
|
|
||||||
a computation and a promise object to represent the delivery of the result of
|
|
||||||
the computation. This is a nice separation of computation and delivery because
|
|
||||||
consumers of the promise cannot modify the value that will be eventually
|
|
||||||
delivered.
|
|
||||||
|
|
||||||
One side effect of being able to implement promise resolution and chaining
|
|
||||||
iteratively is that you need to be able for one promise to reach into the state
|
|
||||||
of another promise to shuffle around ownership of handlers. In order to achieve
|
|
||||||
this without making the handlers of a promise publicly mutable, a promise is
|
|
||||||
also the deferred value, allowing promises of the same parent class to reach
|
|
||||||
into and modify the private properties of promises of the same type. While this
|
|
||||||
does allow consumers of the value to modify the resolution or rejection of the
|
|
||||||
deferred, it is a small price to pay for keeping the stack size constant.
|
|
||||||
|
|
||||||
```php
|
|
||||||
$promise = new Promise();
|
|
||||||
$promise->then(function ($value) { echo $value; });
|
|
||||||
// The promise is the deferred value, so you can deliver a value to it.
|
|
||||||
$promise->resolve('foo');
|
|
||||||
// prints "foo"
|
|
||||||
```
|
|
||||||
34
vendor/guzzlehttp/promises/composer.json
vendored
34
vendor/guzzlehttp/promises/composer.json
vendored
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "guzzlehttp/promises",
|
|
||||||
"description": "Guzzle promises library",
|
|
||||||
"keywords": ["promise"],
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Michael Dowling",
|
|
||||||
"email": "mtdowling@gmail.com",
|
|
||||||
"homepage": "https://github.com/mtdowling"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.5.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^4.0"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\Promise\\": "src/"
|
|
||||||
},
|
|
||||||
"files": ["src/functions_include.php"]
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "vendor/bin/phpunit",
|
|
||||||
"test-ci": "vendor/bin/phpunit --coverage-text"
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.4-dev"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when too many errors occur in the some() or any() methods.
|
|
||||||
*/
|
|
||||||
class AggregateException extends RejectionException
|
|
||||||
{
|
|
||||||
public function __construct($msg, array $reasons)
|
|
||||||
{
|
|
||||||
parent::__construct(
|
|
||||||
$reasons,
|
|
||||||
sprintf('%s; %d rejected promises', $msg, count($reasons))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception that is set as the reason for a promise that has been cancelled.
|
|
||||||
*/
|
|
||||||
class CancellationException extends RejectionException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
151
vendor/guzzlehttp/promises/src/Coroutine.php
vendored
151
vendor/guzzlehttp/promises/src/Coroutine.php
vendored
@@ -1,151 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Generator;
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a promise that is resolved using a generator that yields values or
|
|
||||||
* promises (somewhat similar to C#'s async keyword).
|
|
||||||
*
|
|
||||||
* When called, the coroutine function will start an instance of the generator
|
|
||||||
* and returns a promise that is fulfilled with its final yielded value.
|
|
||||||
*
|
|
||||||
* Control is returned back to the generator when the yielded promise settles.
|
|
||||||
* This can lead to less verbose code when doing lots of sequential async calls
|
|
||||||
* with minimal processing in between.
|
|
||||||
*
|
|
||||||
* use GuzzleHttp\Promise;
|
|
||||||
*
|
|
||||||
* function createPromise($value) {
|
|
||||||
* return new Promise\FulfilledPromise($value);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* $promise = Promise\coroutine(function () {
|
|
||||||
* $value = (yield createPromise('a'));
|
|
||||||
* try {
|
|
||||||
* $value = (yield createPromise($value . 'b'));
|
|
||||||
* } catch (\Exception $e) {
|
|
||||||
* // The promise was rejected.
|
|
||||||
* }
|
|
||||||
* yield $value . 'c';
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* // Outputs "abc"
|
|
||||||
* $promise->then(function ($v) { echo $v; });
|
|
||||||
*
|
|
||||||
* @param callable $generatorFn Generator function to wrap into a promise.
|
|
||||||
*
|
|
||||||
* @return Promise
|
|
||||||
* @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
|
|
||||||
*/
|
|
||||||
final class Coroutine implements PromiseInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var PromiseInterface|null
|
|
||||||
*/
|
|
||||||
private $currentPromise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Generator
|
|
||||||
*/
|
|
||||||
private $generator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Promise
|
|
||||||
*/
|
|
||||||
private $result;
|
|
||||||
|
|
||||||
public function __construct(callable $generatorFn)
|
|
||||||
{
|
|
||||||
$this->generator = $generatorFn();
|
|
||||||
$this->result = new Promise(function () {
|
|
||||||
while (isset($this->currentPromise)) {
|
|
||||||
$this->currentPromise->wait();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$this->nextCoroutine($this->generator->current());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function then(
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
return $this->result->then($onFulfilled, $onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function otherwise(callable $onRejected)
|
|
||||||
{
|
|
||||||
return $this->result->otherwise($onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function wait($unwrap = true)
|
|
||||||
{
|
|
||||||
return $this->result->wait($unwrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getState()
|
|
||||||
{
|
|
||||||
return $this->result->getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resolve($value)
|
|
||||||
{
|
|
||||||
$this->result->resolve($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reject($reason)
|
|
||||||
{
|
|
||||||
$this->result->reject($reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cancel()
|
|
||||||
{
|
|
||||||
$this->currentPromise->cancel();
|
|
||||||
$this->result->cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function nextCoroutine($yielded)
|
|
||||||
{
|
|
||||||
$this->currentPromise = promise_for($yielded)
|
|
||||||
->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public function _handleSuccess($value)
|
|
||||||
{
|
|
||||||
unset($this->currentPromise);
|
|
||||||
try {
|
|
||||||
$next = $this->generator->send($value);
|
|
||||||
if ($this->generator->valid()) {
|
|
||||||
$this->nextCoroutine($next);
|
|
||||||
} else {
|
|
||||||
$this->result->resolve($value);
|
|
||||||
}
|
|
||||||
} catch (Exception $exception) {
|
|
||||||
$this->result->reject($exception);
|
|
||||||
} catch (Throwable $throwable) {
|
|
||||||
$this->result->reject($throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public function _handleFailure($reason)
|
|
||||||
{
|
|
||||||
unset($this->currentPromise);
|
|
||||||
try {
|
|
||||||
$nextYield = $this->generator->throw(exception_for($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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
229
vendor/guzzlehttp/promises/src/EachPromise.php
vendored
229
vendor/guzzlehttp/promises/src/EachPromise.php
vendored
@@ -1,229 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a promise that iterates over many promises and invokes
|
|
||||||
* side-effect functions in the process.
|
|
||||||
*/
|
|
||||||
class EachPromise implements PromisorInterface
|
|
||||||
{
|
|
||||||
private $pending = [];
|
|
||||||
|
|
||||||
/** @var \Iterator */
|
|
||||||
private $iterable;
|
|
||||||
|
|
||||||
/** @var callable|int */
|
|
||||||
private $concurrency;
|
|
||||||
|
|
||||||
/** @var callable */
|
|
||||||
private $onFulfilled;
|
|
||||||
|
|
||||||
/** @var callable */
|
|
||||||
private $onRejected;
|
|
||||||
|
|
||||||
/** @var Promise */
|
|
||||||
private $aggregate;
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $mutex;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration hash can include the following key value pairs:
|
|
||||||
*
|
|
||||||
* - fulfilled: (callable) Invoked when a promise fulfills. The function
|
|
||||||
* is invoked with three arguments: the fulfillment value, the index
|
|
||||||
* position from the iterable list of the promise, and the aggregate
|
|
||||||
* promise that manages all of the promises. The aggregate promise may
|
|
||||||
* be resolved from within the callback to short-circuit the promise.
|
|
||||||
* - rejected: (callable) Invoked when a promise is rejected. The
|
|
||||||
* function is invoked with three arguments: the rejection reason, the
|
|
||||||
* index position from the iterable list of the promise, and the
|
|
||||||
* aggregate promise that manages all of the promises. The aggregate
|
|
||||||
* promise may be resolved from within the callback to short-circuit
|
|
||||||
* the promise.
|
|
||||||
* - concurrency: (integer) Pass this configuration option to limit the
|
|
||||||
* allowed number of outstanding concurrently executing promises,
|
|
||||||
* creating a capped pool of promises. There is no limit by default.
|
|
||||||
*
|
|
||||||
* @param mixed $iterable Promises or values to iterate.
|
|
||||||
* @param array $config Configuration options
|
|
||||||
*/
|
|
||||||
public function __construct($iterable, array $config = [])
|
|
||||||
{
|
|
||||||
$this->iterable = iter_for($iterable);
|
|
||||||
|
|
||||||
if (isset($config['concurrency'])) {
|
|
||||||
$this->concurrency = $config['concurrency'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['fulfilled'])) {
|
|
||||||
$this->onFulfilled = $config['fulfilled'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['rejected'])) {
|
|
||||||
$this->onRejected = $config['rejected'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function promise()
|
|
||||||
{
|
|
||||||
if ($this->aggregate) {
|
|
||||||
return $this->aggregate;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->createPromise();
|
|
||||||
$this->iterable->rewind();
|
|
||||||
$this->refillPending();
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
$this->aggregate->reject($e);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->aggregate->reject($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->aggregate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createPromise()
|
|
||||||
{
|
|
||||||
$this->mutex = false;
|
|
||||||
$this->aggregate = new Promise(function () {
|
|
||||||
reset($this->pending);
|
|
||||||
if (empty($this->pending) && !$this->iterable->valid()) {
|
|
||||||
$this->aggregate->resolve(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume a potentially fluctuating list of promises while
|
|
||||||
// ensuring that indexes are maintained (precluding array_shift).
|
|
||||||
while ($promise = current($this->pending)) {
|
|
||||||
next($this->pending);
|
|
||||||
$promise->wait();
|
|
||||||
if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear the references when the promise is resolved.
|
|
||||||
$clearFn = function () {
|
|
||||||
$this->iterable = $this->concurrency = $this->pending = null;
|
|
||||||
$this->onFulfilled = $this->onRejected = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
$this->aggregate->then($clearFn, $clearFn);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function refillPending()
|
|
||||||
{
|
|
||||||
if (!$this->concurrency) {
|
|
||||||
// Add all pending promises.
|
|
||||||
while ($this->addPending() && $this->advanceIterator());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add only up to N pending promises.
|
|
||||||
$concurrency = is_callable($this->concurrency)
|
|
||||||
? call_user_func($this->concurrency, count($this->pending))
|
|
||||||
: $this->concurrency;
|
|
||||||
$concurrency = max($concurrency - count($this->pending), 0);
|
|
||||||
// Concurrency may be set to 0 to disallow new promises.
|
|
||||||
if (!$concurrency) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Add the first pending promise.
|
|
||||||
$this->addPending();
|
|
||||||
// Note this is special handling for concurrency=1 so that we do
|
|
||||||
// not advance the iterator after adding the first promise. This
|
|
||||||
// helps work around issues with generators that might not have the
|
|
||||||
// next value to yield until promise callbacks are called.
|
|
||||||
while (--$concurrency
|
|
||||||
&& $this->advanceIterator()
|
|
||||||
&& $this->addPending());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function addPending()
|
|
||||||
{
|
|
||||||
if (!$this->iterable || !$this->iterable->valid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$promise = promise_for($this->iterable->current());
|
|
||||||
$idx = $this->iterable->key();
|
|
||||||
|
|
||||||
$this->pending[$idx] = $promise->then(
|
|
||||||
function ($value) use ($idx) {
|
|
||||||
if ($this->onFulfilled) {
|
|
||||||
call_user_func(
|
|
||||||
$this->onFulfilled, $value, $idx, $this->aggregate
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$this->step($idx);
|
|
||||||
},
|
|
||||||
function ($reason) use ($idx) {
|
|
||||||
if ($this->onRejected) {
|
|
||||||
call_user_func(
|
|
||||||
$this->onRejected, $reason, $idx, $this->aggregate
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$this->step($idx);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function advanceIterator()
|
|
||||||
{
|
|
||||||
// Place a lock on the iterator so that we ensure to not recurse,
|
|
||||||
// preventing fatal generator errors.
|
|
||||||
if ($this->mutex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->mutex = true;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// If the promise was already resolved, then ignore this step.
|
|
||||||
if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($this->pending[$idx]);
|
|
||||||
|
|
||||||
// Only refill pending promises if we are not locked, preventing the
|
|
||||||
// EachPromise to recursively invoke the provided iterator, which
|
|
||||||
// cause a fatal error: "Cannot resume an already running generator"
|
|
||||||
if ($this->advanceIterator() && !$this->checkIfFinished()) {
|
|
||||||
// Add more pending promises if possible.
|
|
||||||
$this->refillPending();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkIfFinished()
|
|
||||||
{
|
|
||||||
if (!$this->pending && !$this->iterable->valid()) {
|
|
||||||
// Resolve the promise if there's nothing left to do.
|
|
||||||
$this->aggregate->resolve(null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A promise that has been fulfilled.
|
|
||||||
*
|
|
||||||
* Thenning off of this promise will invoke the onFulfilled callback
|
|
||||||
* immediately and ignore other callbacks.
|
|
||||||
*/
|
|
||||||
class FulfilledPromise implements PromiseInterface
|
|
||||||
{
|
|
||||||
private $value;
|
|
||||||
|
|
||||||
public function __construct($value)
|
|
||||||
{
|
|
||||||
if (method_exists($value, 'then')) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
'You cannot create a FulfilledPromise with a promise.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->value = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function then(
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
// Return itself if there is no onFulfilled function.
|
|
||||||
if (!$onFulfilled) {
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
$queue = queue();
|
|
||||||
$p = new Promise([$queue, 'run']);
|
|
||||||
$value = $this->value;
|
|
||||||
$queue->add(static function () use ($p, $value, $onFulfilled) {
|
|
||||||
if ($p->getState() === self::PENDING) {
|
|
||||||
try {
|
|
||||||
$p->resolve($onFulfilled($value));
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
$p->reject($e);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$p->reject($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return $p;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function otherwise(callable $onRejected)
|
|
||||||
{
|
|
||||||
return $this->then(null, $onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function wait($unwrap = true, $defaultDelivery = null)
|
|
||||||
{
|
|
||||||
return $unwrap ? $this->value : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getState()
|
|
||||||
{
|
|
||||||
return self::FULFILLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resolve($value)
|
|
||||||
{
|
|
||||||
if ($value !== $this->value) {
|
|
||||||
throw new \LogicException("Cannot resolve a fulfilled promise");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reject($reason)
|
|
||||||
{
|
|
||||||
throw new \LogicException("Cannot reject a fulfilled promise");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cancel()
|
|
||||||
{
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
280
vendor/guzzlehttp/promises/src/Promise.php
vendored
280
vendor/guzzlehttp/promises/src/Promise.php
vendored
@@ -1,280 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Promises/A+ implementation that avoids recursion when possible.
|
|
||||||
*
|
|
||||||
* @link https://promisesaplus.com/
|
|
||||||
*/
|
|
||||||
class Promise implements PromiseInterface
|
|
||||||
{
|
|
||||||
private $state = self::PENDING;
|
|
||||||
private $result;
|
|
||||||
private $cancelFn;
|
|
||||||
private $waitFn;
|
|
||||||
private $waitList;
|
|
||||||
private $handlers = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $waitFn Fn that when invoked resolves the promise.
|
|
||||||
* @param callable $cancelFn Fn that when invoked cancels the promise.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
callable $waitFn = null,
|
|
||||||
callable $cancelFn = null
|
|
||||||
) {
|
|
||||||
$this->waitFn = $waitFn;
|
|
||||||
$this->cancelFn = $cancelFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function then(
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
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) {
|
|
||||||
return $onFulfilled
|
|
||||||
? promise_for($this->result)->then($onFulfilled)
|
|
||||||
: promise_for($this->result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's either cancelled or rejected, so return a rejected promise
|
|
||||||
// and immediately invoke any callbacks.
|
|
||||||
$rejection = rejection_for($this->result);
|
|
||||||
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function otherwise(callable $onRejected)
|
|
||||||
{
|
|
||||||
return $this->then(null, $onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function wait($unwrap = true)
|
|
||||||
{
|
|
||||||
$this->waitIfPending();
|
|
||||||
|
|
||||||
$inner = $this->result instanceof PromiseInterface
|
|
||||||
? $this->result->wait($unwrap)
|
|
||||||
: $this->result;
|
|
||||||
|
|
||||||
if ($unwrap) {
|
|
||||||
if ($this->result instanceof PromiseInterface
|
|
||||||
|| $this->state === self::FULFILLED
|
|
||||||
) {
|
|
||||||
return $inner;
|
|
||||||
} else {
|
|
||||||
// It's rejected so "unwrap" and throw an exception.
|
|
||||||
throw exception_for($inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getState()
|
|
||||||
{
|
|
||||||
return $this->state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cancel()
|
|
||||||
{
|
|
||||||
if ($this->state !== self::PENDING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->waitFn = $this->waitList = null;
|
|
||||||
|
|
||||||
if ($this->cancelFn) {
|
|
||||||
$fn = $this->cancelFn;
|
|
||||||
$this->cancelFn = null;
|
|
||||||
try {
|
|
||||||
$fn();
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
$this->reject($e);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->reject($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reject the promise only if it wasn't rejected in a then callback.
|
|
||||||
if ($this->state === self::PENDING) {
|
|
||||||
$this->reject(new CancellationException('Promise has been cancelled'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resolve($value)
|
|
||||||
{
|
|
||||||
$this->settle(self::FULFILLED, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reject($reason)
|
|
||||||
{
|
|
||||||
$this->settle(self::REJECTED, $reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function settle($state, $value)
|
|
||||||
{
|
|
||||||
if ($this->state !== self::PENDING) {
|
|
||||||
// Ignore calls with the same resolution.
|
|
||||||
if ($state === $this->state && $value === $this->result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw $this->state === $state
|
|
||||||
? new \LogicException("The promise is already {$state}.")
|
|
||||||
: new \LogicException("Cannot change a {$this->state} promise to {$state}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value === $this) {
|
|
||||||
throw new \LogicException('Cannot fulfill or reject a promise with itself');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear out the state of the promise but stash the handlers.
|
|
||||||
$this->state = $state;
|
|
||||||
$this->result = $value;
|
|
||||||
$handlers = $this->handlers;
|
|
||||||
$this->handlers = null;
|
|
||||||
$this->waitList = $this->waitFn = null;
|
|
||||||
$this->cancelFn = null;
|
|
||||||
|
|
||||||
if (!$handlers) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the value was not a settled promise or a thenable, then resolve
|
|
||||||
// it in the task queue using the correct ID.
|
|
||||||
if (!method_exists($value, 'then')) {
|
|
||||||
$id = $state === self::FULFILLED ? 1 : 2;
|
|
||||||
// It's a success, so resolve the handlers in the queue.
|
|
||||||
queue()->add(static function () use ($id, $value, $handlers) {
|
|
||||||
foreach ($handlers as $handler) {
|
|
||||||
self::callHandler($id, $value, $handler);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} elseif ($value instanceof Promise
|
|
||||||
&& $value->getState() === self::PENDING
|
|
||||||
) {
|
|
||||||
// We can just merge our handlers onto the next promise.
|
|
||||||
$value->handlers = array_merge($value->handlers, $handlers);
|
|
||||||
} else {
|
|
||||||
// Resolve the handlers when the forwarded promise is resolved.
|
|
||||||
$value->then(
|
|
||||||
static function ($value) use ($handlers) {
|
|
||||||
foreach ($handlers as $handler) {
|
|
||||||
self::callHandler(1, $value, $handler);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
static function ($reason) use ($handlers) {
|
|
||||||
foreach ($handlers as $handler) {
|
|
||||||
self::callHandler(2, $reason, $handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call a stack of handlers using a specific callback index and value.
|
|
||||||
*
|
|
||||||
* @param int $index 1 (resolve) or 2 (reject).
|
|
||||||
* @param mixed $value Value to pass to the callback.
|
|
||||||
* @param array $handler Array of handler data (promise and callbacks).
|
|
||||||
*
|
|
||||||
* @return array Returns the next group to resolve.
|
|
||||||
*/
|
|
||||||
private static function callHandler($index, $value, array $handler)
|
|
||||||
{
|
|
||||||
/** @var PromiseInterface $promise */
|
|
||||||
$promise = $handler[0];
|
|
||||||
|
|
||||||
// The promise may have been cancelled or resolved before placing
|
|
||||||
// this thunk in the queue.
|
|
||||||
if ($promise->getState() !== self::PENDING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (isset($handler[$index])) {
|
|
||||||
$promise->resolve($handler[$index]($value));
|
|
||||||
} elseif ($index === 1) {
|
|
||||||
// Forward resolution values as-is.
|
|
||||||
$promise->resolve($value);
|
|
||||||
} else {
|
|
||||||
// Forward rejections down the chain.
|
|
||||||
$promise->reject($value);
|
|
||||||
}
|
|
||||||
} catch (\Throwable $reason) {
|
|
||||||
$promise->reject($reason);
|
|
||||||
} catch (\Exception $reason) {
|
|
||||||
$promise->reject($reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function waitIfPending()
|
|
||||||
{
|
|
||||||
if ($this->state !== self::PENDING) {
|
|
||||||
return;
|
|
||||||
} elseif ($this->waitFn) {
|
|
||||||
$this->invokeWaitFn();
|
|
||||||
} elseif ($this->waitList) {
|
|
||||||
$this->invokeWaitList();
|
|
||||||
} else {
|
|
||||||
// If there's not 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.');
|
|
||||||
}
|
|
||||||
|
|
||||||
queue()->run();
|
|
||||||
|
|
||||||
if ($this->state === self::PENDING) {
|
|
||||||
$this->reject('Invoking the wait callback did not resolve the promise');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function invokeWaitFn()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$wfn = $this->waitFn;
|
|
||||||
$this->waitFn = null;
|
|
||||||
$wfn(true);
|
|
||||||
} catch (\Exception $reason) {
|
|
||||||
if ($this->state === self::PENDING) {
|
|
||||||
// The promise has not been resolved yet, so reject the promise
|
|
||||||
// with the exception.
|
|
||||||
$this->reject($reason);
|
|
||||||
} else {
|
|
||||||
// The promise was already resolved, so there's a problem in
|
|
||||||
// the application.
|
|
||||||
throw $reason;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function invokeWaitList()
|
|
||||||
{
|
|
||||||
$waitList = $this->waitList;
|
|
||||||
$this->waitList = null;
|
|
||||||
|
|
||||||
foreach ($waitList as $result) {
|
|
||||||
while (true) {
|
|
||||||
$result->waitIfPending();
|
|
||||||
|
|
||||||
if ($result->result instanceof Promise) {
|
|
||||||
$result = $result->result;
|
|
||||||
} else {
|
|
||||||
if ($result->result instanceof PromiseInterface) {
|
|
||||||
$result->result->wait(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A promise represents the eventual result of an asynchronous operation.
|
|
||||||
*
|
|
||||||
* The primary way of interacting with a promise is through its then method,
|
|
||||||
* which registers callbacks to receive either a promise’s eventual value or
|
|
||||||
* the reason why the promise cannot be fulfilled.
|
|
||||||
*
|
|
||||||
* @link https://promisesaplus.com/
|
|
||||||
*/
|
|
||||||
interface PromiseInterface
|
|
||||||
{
|
|
||||||
const PENDING = 'pending';
|
|
||||||
const FULFILLED = 'fulfilled';
|
|
||||||
const REJECTED = 'rejected';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends fulfillment and rejection handlers to the promise, and returns
|
|
||||||
* a new promise resolving to the return value of the called handler.
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends a rejection handler callback to the promise, and returns a new
|
|
||||||
* promise resolving to the return value of the callback if it is called,
|
|
||||||
* or to its original fulfillment value if the promise is instead
|
|
||||||
* fulfilled.
|
|
||||||
*
|
|
||||||
* @param callable $onRejected Invoked when the promise is rejected.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function otherwise(callable $onRejected);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve the promise with the given value.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @throws \RuntimeException if the promise is already resolved.
|
|
||||||
*/
|
|
||||||
public function resolve($value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reject the promise with the given reason.
|
|
||||||
*
|
|
||||||
* @param mixed $reason
|
|
||||||
* @throws \RuntimeException if the promise is already resolved.
|
|
||||||
*/
|
|
||||||
public function reject($reason);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels the promise if possible.
|
|
||||||
*
|
|
||||||
* @link https://github.com/promises-aplus/cancellation-spec/issues/7
|
|
||||||
*/
|
|
||||||
public function cancel();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits until the promise completes if possible.
|
|
||||||
*
|
|
||||||
* Pass $unwrap as true to unwrap the result of the promise, either
|
|
||||||
* returning the resolved value or throwing the rejected exception.
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface used with classes that return a promise.
|
|
||||||
*/
|
|
||||||
interface PromisorInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns a promise.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
public function promise();
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A promise that has been rejected.
|
|
||||||
*
|
|
||||||
* Thenning off of this promise will invoke the onRejected callback
|
|
||||||
* immediately and ignore other callbacks.
|
|
||||||
*/
|
|
||||||
class RejectedPromise implements PromiseInterface
|
|
||||||
{
|
|
||||||
private $reason;
|
|
||||||
|
|
||||||
public function __construct($reason)
|
|
||||||
{
|
|
||||||
if (method_exists($reason, 'then')) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
'You cannot create a RejectedPromise with a promise.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->reason = $reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function then(
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
// If there's no onRejected callback then just return self.
|
|
||||||
if (!$onRejected) {
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
$queue = queue();
|
|
||||||
$reason = $this->reason;
|
|
||||||
$p = new Promise([$queue, 'run']);
|
|
||||||
$queue->add(static function () use ($p, $reason, $onRejected) {
|
|
||||||
if ($p->getState() === self::PENDING) {
|
|
||||||
try {
|
|
||||||
// Return a resolved promise if onRejected does not throw.
|
|
||||||
$p->resolve($onRejected($reason));
|
|
||||||
} 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)
|
|
||||||
{
|
|
||||||
return $this->then(null, $onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function wait($unwrap = true, $defaultDelivery = null)
|
|
||||||
{
|
|
||||||
if ($unwrap) {
|
|
||||||
throw exception_for($this->reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getState()
|
|
||||||
{
|
|
||||||
return self::REJECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resolve($value)
|
|
||||||
{
|
|
||||||
throw new \LogicException("Cannot resolve a rejected promise");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reject($reason)
|
|
||||||
{
|
|
||||||
if ($reason !== $this->reason) {
|
|
||||||
throw new \LogicException("Cannot reject a rejected promise");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cancel()
|
|
||||||
{
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A special exception that is thrown when waiting on a rejected promise.
|
|
||||||
*
|
|
||||||
* The reason value is available via the getReason() method.
|
|
||||||
*/
|
|
||||||
class RejectionException extends \RuntimeException
|
|
||||||
{
|
|
||||||
/** @var mixed Rejection reason. */
|
|
||||||
private $reason;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $reason Rejection reason.
|
|
||||||
* @param string $description Optional description
|
|
||||||
*/
|
|
||||||
public function __construct($reason, $description = null)
|
|
||||||
{
|
|
||||||
$this->reason = $reason;
|
|
||||||
|
|
||||||
$message = 'The promise was rejected';
|
|
||||||
|
|
||||||
if ($description) {
|
|
||||||
$message .= ' with reason: ' . $description;
|
|
||||||
} elseif (is_string($reason)
|
|
||||||
|| (is_object($reason) && method_exists($reason, '__toString'))
|
|
||||||
) {
|
|
||||||
$message .= ' with reason: ' . $this->reason;
|
|
||||||
} elseif ($reason instanceof \JsonSerializable) {
|
|
||||||
$message .= ' with reason: '
|
|
||||||
. json_encode($this->reason, JSON_PRETTY_PRINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the rejection reason.
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getReason()
|
|
||||||
{
|
|
||||||
return $this->reason;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
66
vendor/guzzlehttp/promises/src/TaskQueue.php
vendored
66
vendor/guzzlehttp/promises/src/TaskQueue.php
vendored
@@ -1,66 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A task queue that executes tasks in a FIFO order.
|
|
||||||
*
|
|
||||||
* This task queue class is used to settle promises asynchronously and
|
|
||||||
* maintains a constant stack size. You can use the task queue asynchronously
|
|
||||||
* by calling the `run()` function of the global task queue in an event loop.
|
|
||||||
*
|
|
||||||
* GuzzleHttp\Promise\queue()->run();
|
|
||||||
*/
|
|
||||||
class TaskQueue implements TaskQueueInterface
|
|
||||||
{
|
|
||||||
private $enableShutdown = true;
|
|
||||||
private $queue = [];
|
|
||||||
|
|
||||||
public function __construct($withShutdown = true)
|
|
||||||
{
|
|
||||||
if ($withShutdown) {
|
|
||||||
register_shutdown_function(function () {
|
|
||||||
if ($this->enableShutdown) {
|
|
||||||
// Only run the tasks if an E_ERROR didn't occur.
|
|
||||||
$err = error_get_last();
|
|
||||||
if (!$err || ($err['type'] ^ E_ERROR)) {
|
|
||||||
$this->run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isEmpty()
|
|
||||||
{
|
|
||||||
return !$this->queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add(callable $task)
|
|
||||||
{
|
|
||||||
$this->queue[] = $task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run()
|
|
||||||
{
|
|
||||||
/** @var callable $task */
|
|
||||||
while ($task = array_shift($this->queue)) {
|
|
||||||
$task();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The task queue will be run and exhausted by default when the process
|
|
||||||
* exits IFF the exit is not the result of a PHP E_ERROR error.
|
|
||||||
*
|
|
||||||
* You can disable running the automatic shutdown of the queue by calling
|
|
||||||
* this function. If you disable the task queue shutdown process, then you
|
|
||||||
* MUST either run the task queue (as a result of running your event loop
|
|
||||||
* or manually using the run() method) or wait on each outstanding promise.
|
|
||||||
*
|
|
||||||
* Note: This shutdown will occur before any destructors are triggered.
|
|
||||||
*/
|
|
||||||
public function disableShutdown()
|
|
||||||
{
|
|
||||||
$this->enableShutdown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GuzzleHttp\Promise;
|
|
||||||
|
|
||||||
interface TaskQueueInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns true if the queue is empty.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isEmpty();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a task to the queue that will be executed the next time run is
|
|
||||||
* called.
|
|
||||||
*
|
|
||||||
* @param callable $task
|
|
||||||
*/
|
|
||||||
public function add(callable $task);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute all of the pending task in the queue.
|
|
||||||
*/
|
|
||||||
public function run();
|
|
||||||
}
|
|
||||||
457
vendor/guzzlehttp/promises/src/functions.php
vendored
457
vendor/guzzlehttp/promises/src/functions.php
vendored
@@ -1,457 +0,0 @@
|
|||||||
<?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
|
|
||||||
*/
|
|
||||||
function queue(TaskQueueInterface $assign = null)
|
|
||||||
{
|
|
||||||
static $queue;
|
|
||||||
|
|
||||||
if ($assign) {
|
|
||||||
$queue = $assign;
|
|
||||||
} elseif (!$queue) {
|
|
||||||
$queue = new TaskQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
function task(callable $task)
|
|
||||||
{
|
|
||||||
$queue = queue();
|
|
||||||
$promise = new Promise([$queue, 'run']);
|
|
||||||
$queue->add(function () use ($task, $promise) {
|
|
||||||
try {
|
|
||||||
$promise->resolve($task());
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
$promise->reject($e);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$promise->reject($e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return $promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a promise for a value if the value is not a promise.
|
|
||||||
*
|
|
||||||
* @param mixed $value Promise or value.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
function promise_for($value)
|
|
||||||
{
|
|
||||||
if ($value instanceof PromiseInterface) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a Guzzle promise that shadows the given promise.
|
|
||||||
if (method_exists($value, 'then')) {
|
|
||||||
$wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
|
|
||||||
$cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
|
|
||||||
$promise = new Promise($wfn, $cfn);
|
|
||||||
$value->then([$promise, 'resolve'], [$promise, 'reject']);
|
|
||||||
return $promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FulfilledPromise($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
|
|
||||||
*/
|
|
||||||
function rejection_for($reason)
|
|
||||||
{
|
|
||||||
if ($reason instanceof PromiseInterface) {
|
|
||||||
return $reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RejectedPromise($reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an exception for a rejected promise value.
|
|
||||||
*
|
|
||||||
* @param mixed $reason
|
|
||||||
*
|
|
||||||
* @return \Exception|\Throwable
|
|
||||||
*/
|
|
||||||
function exception_for($reason)
|
|
||||||
{
|
|
||||||
return $reason instanceof \Exception || $reason instanceof \Throwable
|
|
||||||
? $reason
|
|
||||||
: new RejectionException($reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator for the given value.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return \Iterator
|
|
||||||
*/
|
|
||||||
function iter_for($value)
|
|
||||||
{
|
|
||||||
if ($value instanceof \Iterator) {
|
|
||||||
return $value;
|
|
||||||
} elseif (is_array($value)) {
|
|
||||||
return new \ArrayIterator($value);
|
|
||||||
} else {
|
|
||||||
return new \ArrayIterator([$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
|
|
||||||
*/
|
|
||||||
function inspect(PromiseInterface $promise)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return [
|
|
||||||
'state' => PromiseInterface::FULFILLED,
|
|
||||||
'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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits on all of the provided promises, but does not unwrap rejected promises
|
|
||||||
* as thrown exception.
|
|
||||||
*
|
|
||||||
* Returns an array of inspection state arrays.
|
|
||||||
*
|
|
||||||
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @see GuzzleHttp\Promise\inspect for the inspection state array format.
|
|
||||||
*/
|
|
||||||
function inspect_all($promises)
|
|
||||||
{
|
|
||||||
$results = [];
|
|
||||||
foreach ($promises as $key => $promise) {
|
|
||||||
$results[$key] = inspect($promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 mixed $promises Iterable of PromiseInterface objects to wait on.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @throws \Exception on error
|
|
||||||
* @throws \Throwable on error in PHP >=7
|
|
||||||
*/
|
|
||||||
function unwrap($promises)
|
|
||||||
{
|
|
||||||
$results = [];
|
|
||||||
foreach ($promises as $key => $promise) {
|
|
||||||
$results[$key] = $promise->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
function all($promises)
|
|
||||||
{
|
|
||||||
$results = [];
|
|
||||||
return each(
|
|
||||||
$promises,
|
|
||||||
function ($value, $idx) use (&$results) {
|
|
||||||
$results[$idx] = $value;
|
|
||||||
},
|
|
||||||
function ($reason, $idx, Promise $aggregate) {
|
|
||||||
$aggregate->reject($reason);
|
|
||||||
}
|
|
||||||
)->then(function () use (&$results) {
|
|
||||||
ksort($results);
|
|
||||||
return $results;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 prommise is rejected with a {@see GuzzleHttp\Promise\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
|
|
||||||
*/
|
|
||||||
function some($count, $promises)
|
|
||||||
{
|
|
||||||
$results = [];
|
|
||||||
$rejections = [];
|
|
||||||
|
|
||||||
return each(
|
|
||||||
$promises,
|
|
||||||
function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
|
|
||||||
if ($p->getState() !== PromiseInterface::PENDING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$results[$idx] = $value;
|
|
||||||
if (count($results) >= $count) {
|
|
||||||
$p->resolve(null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function ($reason) use (&$rejections) {
|
|
||||||
$rejections[] = $reason;
|
|
||||||
}
|
|
||||||
)->then(
|
|
||||||
function () use (&$results, &$rejections, $count) {
|
|
||||||
if (count($results) !== $count) {
|
|
||||||
throw new AggregateException(
|
|
||||||
'Not enough promises to fulfill count',
|
|
||||||
$rejections
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ksort($results);
|
|
||||||
return array_values($results);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
function any($promises)
|
|
||||||
{
|
|
||||||
return some(1, $promises)->then(function ($values) { return $values[0]; });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* @param mixed $promises Promises or values.
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
* @see GuzzleHttp\Promise\inspect for the inspection state array format.
|
|
||||||
*/
|
|
||||||
function settle($promises)
|
|
||||||
{
|
|
||||||
$results = [];
|
|
||||||
|
|
||||||
return each(
|
|
||||||
$promises,
|
|
||||||
function ($value, $idx) use (&$results) {
|
|
||||||
$results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
|
|
||||||
},
|
|
||||||
function ($reason, $idx) use (&$results) {
|
|
||||||
$results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
|
|
||||||
}
|
|
||||||
)->then(function () use (&$results) {
|
|
||||||
ksort($results);
|
|
||||||
return $results;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 promise 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 promise if needed.
|
|
||||||
*
|
|
||||||
* @param mixed $iterable Iterator or array to iterate over.
|
|
||||||
* @param callable $onFulfilled
|
|
||||||
* @param callable $onRejected
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
function each(
|
|
||||||
$iterable,
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
return (new EachPromise($iterable, [
|
|
||||||
'fulfilled' => $onFulfilled,
|
|
||||||
'rejected' => $onRejected
|
|
||||||
]))->promise();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
function each_limit(
|
|
||||||
$iterable,
|
|
||||||
$concurrency,
|
|
||||||
callable $onFulfilled = null,
|
|
||||||
callable $onRejected = null
|
|
||||||
) {
|
|
||||||
return (new EachPromise($iterable, [
|
|
||||||
'fulfilled' => $onFulfilled,
|
|
||||||
'rejected' => $onRejected,
|
|
||||||
'concurrency' => $concurrency
|
|
||||||
]))->promise();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
function each_limit_all(
|
|
||||||
$iterable,
|
|
||||||
$concurrency,
|
|
||||||
callable $onFulfilled = null
|
|
||||||
) {
|
|
||||||
return each_limit(
|
|
||||||
$iterable,
|
|
||||||
$concurrency,
|
|
||||||
$onFulfilled,
|
|
||||||
function ($reason, $idx, PromiseInterface $aggregate) {
|
|
||||||
$aggregate->reject($reason);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a promise is fulfilled.
|
|
||||||
*
|
|
||||||
* @param PromiseInterface $promise
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function is_fulfilled(PromiseInterface $promise)
|
|
||||||
{
|
|
||||||
return $promise->getState() === PromiseInterface::FULFILLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a promise is rejected.
|
|
||||||
*
|
|
||||||
* @param PromiseInterface $promise
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function is_rejected(PromiseInterface $promise)
|
|
||||||
{
|
|
||||||
return $promise->getState() === PromiseInterface::REJECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a promise is fulfilled or rejected.
|
|
||||||
*
|
|
||||||
* @param PromiseInterface $promise
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function is_settled(PromiseInterface $promise)
|
|
||||||
{
|
|
||||||
return $promise->getState() !== PromiseInterface::PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Coroutine
|
|
||||||
*
|
|
||||||
* @param callable $generatorFn
|
|
||||||
*
|
|
||||||
* @return PromiseInterface
|
|
||||||
*/
|
|
||||||
function coroutine(callable $generatorFn)
|
|
||||||
{
|
|
||||||
return new Coroutine($generatorFn);
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// Don't redefine the functions if included multiple times.
|
|
||||||
if (!function_exists('GuzzleHttp\Promise\promise_for')) {
|
|
||||||
require __DIR__ . '/functions.php';
|
|
||||||
}
|
|
||||||
246
vendor/guzzlehttp/psr7/CHANGELOG.md
vendored
246
vendor/guzzlehttp/psr7/CHANGELOG.md
vendored
@@ -1,246 +0,0 @@
|
|||||||
# Change Log
|
|
||||||
|
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
|
|
||||||
## [Unreleased]
|
|
||||||
|
|
||||||
|
|
||||||
## [1.6.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244)
|
|
||||||
- Added MIME type for WEBP image format (#246)
|
|
||||||
- Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262)
|
|
||||||
- Accept port number 0 to be valid (#270)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fixed subsequent reads from `php://input` in ServerRequest (#247)
|
|
||||||
- Fixed readable/writable detection for certain stream modes (#248)
|
|
||||||
- Fixed encoding of special characters in the `userInfo` component of an URI (#253)
|
|
||||||
|
|
||||||
|
|
||||||
## [1.5.2] - 2018-12-04
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Check body size when getting the message summary
|
|
||||||
|
|
||||||
|
|
||||||
## [1.5.1] - 2018-12-04
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Get the summary of a body only if it is readable
|
|
||||||
|
|
||||||
|
|
||||||
## [1.5.0] - 2018-12-03
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Response first-line to response string exception (fixes #145)
|
|
||||||
- A test for #129 behavior
|
|
||||||
- `get_message_body_summary` function in order to get the message summary
|
|
||||||
- `3gp` and `mkv` mime types
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Clarify exception message when stream is detached
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
- Deprecated parsing folded header lines as per RFC 7230
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix `AppendStream::detach` to not close streams
|
|
||||||
- `InflateStream` preserves `isSeekable` attribute of the underlying stream
|
|
||||||
- `ServerRequest::getUriFromGlobals` to support URLs in query parameters
|
|
||||||
|
|
||||||
|
|
||||||
Several other fixes and improvements.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.4.2] - 2017-03-20
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing
|
|
||||||
calls to `trigger_error` when deprecated methods are invoked.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.4.1] - 2017-02-27
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Rriggering of silenced deprecation warnings.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Reverted BC break by reintroducing behavior to automagically fix a URI with a
|
|
||||||
relative path and an authority by adding a leading slash to the path. It's only
|
|
||||||
deprecated now.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.4.0] - 2017-02-21
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Added common URI utility methods based on RFC 3986 (see documentation in the readme):
|
|
||||||
- `Uri::isDefaultPort`
|
|
||||||
- `Uri::isAbsolute`
|
|
||||||
- `Uri::isNetworkPathReference`
|
|
||||||
- `Uri::isAbsolutePathReference`
|
|
||||||
- `Uri::isRelativePathReference`
|
|
||||||
- `Uri::isSameDocumentReference`
|
|
||||||
- `Uri::composeComponents`
|
|
||||||
- `UriNormalizer::normalize`
|
|
||||||
- `UriNormalizer::isEquivalent`
|
|
||||||
- `UriResolver::relativize`
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
|
|
||||||
- Allow `parse_response` to parse a response without delimiting space and reason.
|
|
||||||
- Ensure each URI modification results in a valid URI according to PSR-7 discussions.
|
|
||||||
Invalid modifications will throw an exception instead of returning a wrong URI or
|
|
||||||
doing some magic.
|
|
||||||
- `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
|
|
||||||
because the path of a URI with an authority must start with a slash "/" or be empty
|
|
||||||
- `(new Uri())->withScheme('http')` will return `'http://localhost'`
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
- `Uri::resolve` in favor of `UriResolver::resolve`
|
|
||||||
- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- `Stream::read` when length parameter <= 0.
|
|
||||||
- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
|
|
||||||
- `ServerRequest::getUriFromGlobals` when `Host` header contains port.
|
|
||||||
- Compatibility of URIs with `file` scheme and empty host.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.3.1] - 2016-06-25
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- `Uri::__toString` for network path references, e.g. `//example.org`.
|
|
||||||
- Missing lowercase normalization for host.
|
|
||||||
- Handling of URI components in case they are `'0'` in a lot of places,
|
|
||||||
e.g. as a user info password.
|
|
||||||
- `Uri::withAddedHeader` to correctly merge headers with different case.
|
|
||||||
- Trimming of header values in `Uri::withAddedHeader`. Header values may
|
|
||||||
be surrounded by whitespace which should be ignored according to RFC 7230
|
|
||||||
Section 3.2.4. This does not apply to header names.
|
|
||||||
- `Uri::withAddedHeader` with an array of header values.
|
|
||||||
- `Uri::resolve` when base path has no slash and handling of fragment.
|
|
||||||
- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the
|
|
||||||
key/value both in encoded as well as decoded form to those methods. This is
|
|
||||||
consistent with withPath, withQuery etc.
|
|
||||||
- `ServerRequest::withoutAttribute` when attribute value is null.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.3.0] - 2016-04-13
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Remaining interfaces needed for full PSR7 compatibility
|
|
||||||
(ServerRequestInterface, UploadedFileInterface, etc.).
|
|
||||||
- Support for stream_for from scalars.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Can now extend Uri.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- A bug in validating request methods by making it more permissive.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.3] - 2016-02-18
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
|
|
||||||
streams, which can sometimes return fewer bytes than requested with `fread`.
|
|
||||||
- Handling of gzipped responses with FNAME headers.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.2] - 2016-01-22
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Support for URIs without any authority.
|
|
||||||
- Support for HTTP 451 'Unavailable For Legal Reasons.'
|
|
||||||
- Support for using '0' as a filename.
|
|
||||||
- Support for including non-standard ports in Host headers.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.1] - 2015-11-02
|
|
||||||
|
|
||||||
### Changes
|
|
||||||
|
|
||||||
- Now supporting negative offsets when seeking to SEEK_END.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.0] - 2015-08-15
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Body as `"0"` is now properly added to a response.
|
|
||||||
- Now allowing forward seeking in CachingStream.
|
|
||||||
- Now properly parsing HTTP requests that contain proxy targets in
|
|
||||||
`parse_request`.
|
|
||||||
- functions.php is now conditionally required.
|
|
||||||
- user-info is no longer dropped when resolving URIs.
|
|
||||||
|
|
||||||
|
|
||||||
## [1.1.0] - 2015-06-24
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- URIs can now be relative.
|
|
||||||
- `multipart/form-data` headers are now overridden case-insensitively.
|
|
||||||
- URI paths no longer encode the following characters because they are allowed
|
|
||||||
in URIs: "(", ")", "*", "!", "'"
|
|
||||||
- A port is no longer added to a URI when the scheme is missing and no port is
|
|
||||||
present.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.0.0 - 2015-05-19
|
|
||||||
|
|
||||||
Initial release.
|
|
||||||
|
|
||||||
Currently unsupported:
|
|
||||||
|
|
||||||
- `Psr\Http\Message\ServerRequestInterface`
|
|
||||||
- `Psr\Http\Message\UploadedFileInterface`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Unreleased]: https://github.com/guzzle/psr7/compare/1.6.0...HEAD
|
|
||||||
[1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0
|
|
||||||
[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2
|
|
||||||
[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1
|
|
||||||
[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0
|
|
||||||
[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2
|
|
||||||
[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1
|
|
||||||
[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0
|
|
||||||
[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1
|
|
||||||
[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0
|
|
||||||
[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3
|
|
||||||
[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2
|
|
||||||
[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1
|
|
||||||
[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0
|
|
||||||
[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user