Init Server Composer Components
This commit is contained in:
parent
35db27b0e6
commit
a44cc1d2e3
177 changed files with 24745 additions and 0 deletions
11
server/vendor/guzzlehttp/promises/.gitignore
vendored
Normal file
11
server/vendor/guzzlehttp/promises/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
phpunit.xml
|
||||
composer.phar
|
||||
composer.lock
|
||||
composer-test.lock
|
||||
vendor/
|
||||
build/artifacts/
|
||||
artifacts/
|
||||
docs/_build
|
||||
docs/*.pyc
|
||||
.idea
|
||||
.DS_STORE
|
19
server/vendor/guzzlehttp/promises/.travis.yml
vendored
Normal file
19
server/vendor/guzzlehttp/promises/.travis.yml
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
sudo: false
|
||||
|
||||
install:
|
||||
- travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script: make test
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
fast_finish: true
|
21
server/vendor/guzzlehttp/promises/CHANGELOG.md
vendored
Normal file
21
server/vendor/guzzlehttp/promises/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 1.0.3 - 2015-10-15
|
||||
|
||||
* 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
|
||||
|
||||
* Conditionally require functions.php.
|
||||
|
||||
## 1.0.1 - 2015-06-24
|
||||
|
||||
* 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
server/vendor/guzzlehttp/promises/LICENSE
vendored
Normal file
19
server/vendor/guzzlehttp/promises/LICENSE
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2015 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
server/vendor/guzzlehttp/promises/Makefile
vendored
Normal file
13
server/vendor/guzzlehttp/promises/Makefile
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
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/*
|
501
server/vendor/guzzlehttp/promises/README.md
vendored
Normal file
501
server/vendor/guzzlehttp/promises/README.md
vendored
Normal file
|
@ -0,0 +1,501 @@
|
|||
# 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 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->deliver('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 delivered value.
|
||||
|
||||
```php
|
||||
$promise = new Promise(function () { die('this is not called!'); });
|
||||
$promise->deliver('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 delivered 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`
|
||||
|
||||
Creates a new promise that is fulfilled or rejected when the promise is
|
||||
resolved.
|
||||
|
||||
- `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->deliver('foo');
|
||||
// prints "foo"
|
||||
```
|
31
server/vendor/guzzlehttp/promises/composer.json
vendored
Normal file
31
server/vendor/guzzlehttp/promises/composer.json
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"type": "library",
|
||||
"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"]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
17
server/vendor/guzzlehttp/promises/phpunit.xml.dist
vendored
Normal file
17
server/vendor/guzzlehttp/promises/phpunit.xml.dist
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="./tests/bootstrap.php"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite>
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
<exclude>
|
||||
<directory suffix="Interface.php">src/</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
16
server/vendor/guzzlehttp/promises/src/AggregateException.php
vendored
Normal file
16
server/vendor/guzzlehttp/promises/src/AggregateException.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?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))
|
||||
);
|
||||
}
|
||||
}
|
9
server/vendor/guzzlehttp/promises/src/CancellationException.php
vendored
Normal file
9
server/vendor/guzzlehttp/promises/src/CancellationException.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
* Exception that is set as the reason for a promise that has been cancelled.
|
||||
*/
|
||||
class CancellationException extends RejectionException
|
||||
{
|
||||
}
|
207
server/vendor/guzzlehttp/promises/src/EachPromise.php
vendored
Normal file
207
server/vendor/guzzlehttp/promises/src/EachPromise.php
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* 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 (\Exception $e) {
|
||||
$this->aggregate->reject($e);
|
||||
}
|
||||
|
||||
return $this->aggregate;
|
||||
}
|
||||
|
||||
private function createPromise()
|
||||
{
|
||||
$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()
|
||||
{
|
||||
try {
|
||||
$this->iterable->next();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$this->aggregate->reject($e);
|
||||
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]);
|
||||
$this->advanceIterator();
|
||||
|
||||
if (!$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;
|
||||
}
|
||||
}
|
80
server/vendor/guzzlehttp/promises/src/FulfilledPromise.php
vendored
Normal file
80
server/vendor/guzzlehttp/promises/src/FulfilledPromise.php
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?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 (\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
|
||||
}
|
||||
}
|
268
server/vendor/guzzlehttp/promises/src/Promise.php
vendored
Normal file
268
server/vendor/guzzlehttp/promises/src/Promise.php
vendored
Normal file
|
@ -0,0 +1,268 @@
|
|||
<?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();
|
||||
|
||||
if (!$unwrap) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->result instanceof PromiseInterface) {
|
||||
return $this->result->wait($unwrap);
|
||||
} elseif ($this->state === self::FULFILLED) {
|
||||
return $this->result;
|
||||
} else {
|
||||
// It's rejected so "unwrap" and throw an exception.
|
||||
throw exception_for($this->result);
|
||||
}
|
||||
}
|
||||
|
||||
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 (\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 (\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) {
|
||||
descend:
|
||||
$result->waitIfPending();
|
||||
if ($result->result instanceof Promise) {
|
||||
$result = $result->result;
|
||||
goto descend;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
93
server/vendor/guzzlehttp/promises/src/PromiseInterface.php
vendored
Normal file
93
server/vendor/guzzlehttp/promises/src/PromiseInterface.php
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?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);
|
||||
}
|
15
server/vendor/guzzlehttp/promises/src/PromisorInterface.php
vendored
Normal file
15
server/vendor/guzzlehttp/promises/src/PromisorInterface.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
* Interface used with classes that return a promise.
|
||||
*/
|
||||
interface PromisorInterface
|
||||
{
|
||||
/**
|
||||
* Returns a promise.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function promise();
|
||||
}
|
84
server/vendor/guzzlehttp/promises/src/RejectedPromise.php
vendored
Normal file
84
server/vendor/guzzlehttp/promises/src/RejectedPromise.php
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?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 (\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
|
||||
}
|
||||
}
|
47
server/vendor/guzzlehttp/promises/src/RejectionException.php
vendored
Normal file
47
server/vendor/guzzlehttp/promises/src/RejectionException.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
79
server/vendor/guzzlehttp/promises/src/TaskQueue.php
vendored
Normal file
79
server/vendor/guzzlehttp/promises/src/TaskQueue.php
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?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
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the queue is empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return !$this->queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a task to the queue that will be executed the next time run is
|
||||
* called.
|
||||
*
|
||||
* @param callable $task
|
||||
*/
|
||||
public function add(callable $task)
|
||||
{
|
||||
$this->queue[] = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all of the pending task in the queue.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
495
server/vendor/guzzlehttp/promises/src/functions.php
vendored
Normal file
495
server/vendor/guzzlehttp/promises/src/functions.php
vendored
Normal file
|
@ -0,0 +1,495 @@
|
|||
<?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>
|
||||
*
|
||||
* @return TaskQueue
|
||||
*/
|
||||
function queue()
|
||||
{
|
||||
static $queue;
|
||||
|
||||
if (!$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 (\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
|
||||
*/
|
||||
function exception_for($reason)
|
||||
{
|
||||
return $reason instanceof \Exception
|
||||
? $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' => 'rejected', 'reason' => $e->getReason()];
|
||||
} catch (\Exception $e) {
|
||||
return ['state' => '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
|
||||
*/
|
||||
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 Promise
|
||||
*/
|
||||
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 Promise
|
||||
*/
|
||||
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 Promise
|
||||
* @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' => 'fulfilled', 'value' => $value];
|
||||
},
|
||||
function ($reason, $idx) use (&$results) {
|
||||
$results[$idx] = ['state' => '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 Promise
|
||||
*/
|
||||
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 mixed
|
||||
*/
|
||||
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 mixed
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function coroutine(callable $generatorFn)
|
||||
{
|
||||
$generator = $generatorFn();
|
||||
return __next_coroutine($generator->current(), $generator)->then();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function __next_coroutine($yielded, \Generator $generator)
|
||||
{
|
||||
return promise_for($yielded)->then(
|
||||
function ($value) use ($generator) {
|
||||
$nextYield = $generator->send($value);
|
||||
return $generator->valid()
|
||||
? __next_coroutine($nextYield, $generator)
|
||||
: $value;
|
||||
},
|
||||
function ($reason) use ($generator) {
|
||||
$nextYield = $generator->throw(exception_for($reason));
|
||||
// The throw was caught, so keep iterating on the coroutine
|
||||
return __next_coroutine($nextYield, $generator);
|
||||
}
|
||||
);
|
||||
}
|
6
server/vendor/guzzlehttp/promises/src/functions_include.php
vendored
Normal file
6
server/vendor/guzzlehttp/promises/src/functions_include.php
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
// Don't redefine the functions if included multiple times.
|
||||
if (!function_exists('GuzzleHttp\Promise\promise_for')) {
|
||||
require __DIR__ . '/functions.php';
|
||||
}
|
14
server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php
vendored
Normal file
14
server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\AggregateException;
|
||||
|
||||
class AggregateExceptionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testHasReason()
|
||||
{
|
||||
$e = new AggregateException('foo', ['baz', 'bar']);
|
||||
$this->assertContains('foo', $e->getMessage());
|
||||
$this->assertEquals(['baz', 'bar'], $e->getReason());
|
||||
}
|
||||
}
|
294
server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
vendored
Normal file
294
server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
vendored
Normal file
|
@ -0,0 +1,294 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use GuzzleHttp\Promise\EachPromise;
|
||||
use GuzzleHttp\Promise as P;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Promise\EachPromise
|
||||
*/
|
||||
class EachPromiseTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testReturnsSameInstance()
|
||||
{
|
||||
$each = new EachPromise([], ['concurrency' => 100]);
|
||||
$this->assertSame($each->promise(), $each->promise());
|
||||
}
|
||||
|
||||
public function testInvokesAllPromises()
|
||||
{
|
||||
$promises = [new Promise(), new Promise(), new Promise()];
|
||||
$called = [];
|
||||
$each = new EachPromise($promises, [
|
||||
'fulfilled' => function ($value) use (&$called) {
|
||||
$called[] = $value;
|
||||
}
|
||||
]);
|
||||
$p = $each->promise();
|
||||
$promises[0]->resolve('a');
|
||||
$promises[1]->resolve('c');
|
||||
$promises[2]->resolve('b');
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['a', 'c', 'b'], $called);
|
||||
$this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
|
||||
}
|
||||
|
||||
public function testIsWaitable()
|
||||
{
|
||||
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
|
||||
$b = new Promise(function () use (&$b) { $b->resolve('b'); });
|
||||
$called = [];
|
||||
$each = new EachPromise([$a, $b], [
|
||||
'fulfilled' => function ($value) use (&$called) { $called[] = $value; }
|
||||
]);
|
||||
$p = $each->promise();
|
||||
$this->assertNull($p->wait());
|
||||
$this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
|
||||
$this->assertEquals(['a', 'b'], $called);
|
||||
}
|
||||
|
||||
public function testCanResolveBeforeConsumingAll()
|
||||
{
|
||||
$called = 0;
|
||||
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
|
||||
$b = new Promise(function () { $this->fail(); });
|
||||
$each = new EachPromise([$a, $b], [
|
||||
'fulfilled' => function ($value, $idx, Promise $aggregate) use (&$called) {
|
||||
$this->assertSame($idx, 0);
|
||||
$this->assertEquals('a', $value);
|
||||
$aggregate->resolve(null);
|
||||
$called++;
|
||||
},
|
||||
'rejected' => function (\Exception $reason) {
|
||||
$this->fail($reason->getMessage());
|
||||
}
|
||||
]);
|
||||
$p = $each->promise();
|
||||
$p->wait();
|
||||
$this->assertNull($p->wait());
|
||||
$this->assertEquals(1, $called);
|
||||
$this->assertEquals(PromiseInterface::FULFILLED, $a->getState());
|
||||
$this->assertEquals(PromiseInterface::PENDING, $b->getState());
|
||||
// Resolving $b has no effect on the aggregate promise.
|
||||
$b->resolve('foo');
|
||||
$this->assertEquals(1, $called);
|
||||
}
|
||||
|
||||
public function testLimitsPendingPromises()
|
||||
{
|
||||
$pending = [new Promise(), new Promise(), new Promise(), new Promise()];
|
||||
$promises = new \ArrayIterator($pending);
|
||||
$each = new EachPromise($promises, ['concurrency' => 2]);
|
||||
$p = $each->promise();
|
||||
$this->assertCount(2, $this->readAttribute($each, 'pending'));
|
||||
$pending[0]->resolve('a');
|
||||
$this->assertCount(2, $this->readAttribute($each, 'pending'));
|
||||
$this->assertTrue($promises->valid());
|
||||
$pending[1]->resolve('b');
|
||||
P\queue()->run();
|
||||
$this->assertCount(2, $this->readAttribute($each, 'pending'));
|
||||
$this->assertTrue($promises->valid());
|
||||
$promises[2]->resolve('c');
|
||||
P\queue()->run();
|
||||
$this->assertCount(1, $this->readAttribute($each, 'pending'));
|
||||
$this->assertEquals(PromiseInterface::PENDING, $p->getState());
|
||||
$promises[3]->resolve('d');
|
||||
P\queue()->run();
|
||||
$this->assertNull($this->readAttribute($each, 'pending'));
|
||||
$this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
|
||||
$this->assertFalse($promises->valid());
|
||||
}
|
||||
|
||||
public function testDynamicallyLimitsPendingPromises()
|
||||
{
|
||||
$calls = [];
|
||||
$pendingFn = function ($count) use (&$calls) {
|
||||
$calls[] = $count;
|
||||
return 2;
|
||||
};
|
||||
$pending = [new Promise(), new Promise(), new Promise(), new Promise()];
|
||||
$promises = new \ArrayIterator($pending);
|
||||
$each = new EachPromise($promises, ['concurrency' => $pendingFn]);
|
||||
$p = $each->promise();
|
||||
$this->assertCount(2, $this->readAttribute($each, 'pending'));
|
||||
$pending[0]->resolve('a');
|
||||
$this->assertCount(2, $this->readAttribute($each, 'pending'));
|
||||
$this->assertTrue($promises->valid());
|
||||
$pending[1]->resolve('b');
|
||||
$this->assertCount(2, $this->readAttribute($each, 'pending'));
|
||||
P\queue()->run();
|
||||
$this->assertTrue($promises->valid());
|
||||
$promises[2]->resolve('c');
|
||||
P\queue()->run();
|
||||
$this->assertCount(1, $this->readAttribute($each, 'pending'));
|
||||
$this->assertEquals(PromiseInterface::PENDING, $p->getState());
|
||||
$promises[3]->resolve('d');
|
||||
P\queue()->run();
|
||||
$this->assertNull($this->readAttribute($each, 'pending'));
|
||||
$this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
|
||||
$this->assertEquals([0, 1, 1, 1], $calls);
|
||||
$this->assertFalse($promises->valid());
|
||||
}
|
||||
|
||||
public function testClearsReferencesWhenResolved()
|
||||
{
|
||||
$called = false;
|
||||
$a = new Promise(function () use (&$a, &$called) {
|
||||
$a->resolve('a');
|
||||
$called = true;
|
||||
});
|
||||
$each = new EachPromise([$a], [
|
||||
'concurrency' => function () { return 1; },
|
||||
'fulfilled' => function () {},
|
||||
'rejected' => function () {}
|
||||
]);
|
||||
$each->promise()->wait();
|
||||
$this->assertNull($this->readAttribute($each, 'onFulfilled'));
|
||||
$this->assertNull($this->readAttribute($each, 'onRejected'));
|
||||
$this->assertNull($this->readAttribute($each, 'iterable'));
|
||||
$this->assertNull($this->readAttribute($each, 'pending'));
|
||||
$this->assertNull($this->readAttribute($each, 'concurrency'));
|
||||
$this->assertTrue($called);
|
||||
}
|
||||
|
||||
public function testCanBeCancelled()
|
||||
{
|
||||
$this->markTestIncomplete();
|
||||
}
|
||||
|
||||
public function testFulfillsImmediatelyWhenGivenAnEmptyIterator()
|
||||
{
|
||||
$each = new EachPromise(new \ArrayIterator([]));
|
||||
$result = $each->promise()->wait();
|
||||
}
|
||||
|
||||
public function testDoesNotBlowStackWithFulfilledPromises()
|
||||
{
|
||||
$pending = [];
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$pending[] = new FulfilledPromise($i);
|
||||
}
|
||||
$values = [];
|
||||
$each = new EachPromise($pending, [
|
||||
'fulfilled' => function ($value) use (&$values) {
|
||||
$values[] = $value;
|
||||
}
|
||||
]);
|
||||
$called = false;
|
||||
$each->promise()->then(function () use (&$called) {
|
||||
$called = true;
|
||||
});
|
||||
$this->assertFalse($called);
|
||||
P\queue()->run();
|
||||
$this->assertTrue($called);
|
||||
$this->assertEquals(range(0, 99), $values);
|
||||
}
|
||||
|
||||
public function testDoesNotBlowStackWithRejectedPromises()
|
||||
{
|
||||
$pending = [];
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$pending[] = new RejectedPromise($i);
|
||||
}
|
||||
$values = [];
|
||||
$each = new EachPromise($pending, [
|
||||
'rejected' => function ($value) use (&$values) {
|
||||
$values[] = $value;
|
||||
}
|
||||
]);
|
||||
$called = false;
|
||||
$each->promise()->then(
|
||||
function () use (&$called) { $called = true; },
|
||||
function () { $this->fail('Should not have rejected.'); }
|
||||
);
|
||||
$this->assertFalse($called);
|
||||
P\queue()->run();
|
||||
$this->assertTrue($called);
|
||||
$this->assertEquals(range(0, 99), $values);
|
||||
}
|
||||
|
||||
public function testReturnsPromiseForWhatever()
|
||||
{
|
||||
$called = [];
|
||||
$arr = ['a', 'b'];
|
||||
$each = new EachPromise($arr, [
|
||||
'fulfilled' => function ($v) use (&$called) { $called[] = $v; }
|
||||
]);
|
||||
$p = $each->promise();
|
||||
$this->assertNull($p->wait());
|
||||
$this->assertEquals(['a', 'b'], $called);
|
||||
}
|
||||
|
||||
public function testRejectsAggregateWhenNextThrows()
|
||||
{
|
||||
$iter = function () {
|
||||
yield 'a';
|
||||
throw new \Exception('Failure');
|
||||
};
|
||||
$each = new EachPromise($iter());
|
||||
$p = $each->promise();
|
||||
$e = null;
|
||||
$received = null;
|
||||
$p->then(null, function ($reason) use (&$e) { $e = $reason; });
|
||||
P\queue()->run();
|
||||
$this->assertInstanceOf('Exception', $e);
|
||||
$this->assertEquals('Failure', $e->getMessage());
|
||||
}
|
||||
|
||||
public function testDoesNotCallNextOnIteratorUntilNeededWhenWaiting()
|
||||
{
|
||||
$results = [];
|
||||
$values = [10];
|
||||
$remaining = 9;
|
||||
$iter = function () use (&$values) {
|
||||
while ($value = array_pop($values)) {
|
||||
yield $value;
|
||||
}
|
||||
};
|
||||
$each = new EachPromise($iter(), [
|
||||
'concurrency' => 1,
|
||||
'fulfilled' => function ($r) use (&$results, &$values, &$remaining) {
|
||||
$results[] = $r;
|
||||
if ($remaining > 0) {
|
||||
$values[] = $remaining--;
|
||||
}
|
||||
}
|
||||
]);
|
||||
$each->promise()->wait();
|
||||
$this->assertEquals(range(10, 1), $results);
|
||||
}
|
||||
|
||||
public function testDoesNotCallNextOnIteratorUntilNeededWhenAsync()
|
||||
{
|
||||
$firstPromise = new Promise();
|
||||
$pending = [$firstPromise];
|
||||
$values = [$firstPromise];
|
||||
$results = [];
|
||||
$remaining = 9;
|
||||
$iter = function () use (&$values) {
|
||||
while ($value = array_pop($values)) {
|
||||
yield $value;
|
||||
}
|
||||
};
|
||||
$each = new EachPromise($iter(), [
|
||||
'concurrency' => 1,
|
||||
'fulfilled' => function ($r) use (&$results, &$values, &$remaining, &$pending) {
|
||||
$results[] = $r;
|
||||
if ($remaining-- > 0) {
|
||||
$pending[] = $values[] = new Promise();
|
||||
}
|
||||
}
|
||||
]);
|
||||
$i = 0;
|
||||
$each->promise();
|
||||
while ($promise = array_pop($pending)) {
|
||||
$promise->resolve($i++);
|
||||
P\queue()->run();
|
||||
}
|
||||
$this->assertEquals(range(0, 9), $results);
|
||||
}
|
||||
}
|
108
server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php
vendored
Normal file
108
server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Promise;
|
||||
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Promise\FulfilledPromise
|
||||
*/
|
||||
class FulfilledPromiseTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testReturnsValueWhenWaitedUpon()
|
||||
{
|
||||
$p = new FulfilledPromise('foo');
|
||||
$this->assertEquals('fulfilled', $p->getState());
|
||||
$this->assertEquals('foo', $p->wait(true));
|
||||
}
|
||||
|
||||
public function testCannotCancel()
|
||||
{
|
||||
$p = new FulfilledPromise('foo');
|
||||
$this->assertEquals('fulfilled', $p->getState());
|
||||
$p->cancel();
|
||||
$this->assertEquals('foo', $p->wait());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @exepctedExceptionMessage Cannot resolve a fulfilled promise
|
||||
*/
|
||||
public function testCannotResolve()
|
||||
{
|
||||
$p = new FulfilledPromise('foo');
|
||||
$p->resolve('bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @exepctedExceptionMessage Cannot reject a fulfilled promise
|
||||
*/
|
||||
public function testCannotReject()
|
||||
{
|
||||
$p = new FulfilledPromise('foo');
|
||||
$p->reject('bar');
|
||||
}
|
||||
|
||||
public function testCanResolveWithSameValue()
|
||||
{
|
||||
$p = new FulfilledPromise('foo');
|
||||
$p->resolve('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCannotResolveWithPromise()
|
||||
{
|
||||
new FulfilledPromise(new Promise());
|
||||
}
|
||||
|
||||
public function testReturnsSelfWhenNoOnFulfilled()
|
||||
{
|
||||
$p = new FulfilledPromise('a');
|
||||
$this->assertSame($p, $p->then());
|
||||
}
|
||||
|
||||
public function testAsynchronouslyInvokesOnFulfilled()
|
||||
{
|
||||
$p = new FulfilledPromise('a');
|
||||
$r = null;
|
||||
$f = function ($d) use (&$r) { $r = $d; };
|
||||
$p2 = $p->then($f);
|
||||
$this->assertNotSame($p, $p2);
|
||||
$this->assertNull($r);
|
||||
\GuzzleHttp\Promise\queue()->run();
|
||||
$this->assertEquals('a', $r);
|
||||
}
|
||||
|
||||
public function testReturnsNewRejectedWhenOnFulfilledFails()
|
||||
{
|
||||
$p = new FulfilledPromise('a');
|
||||
$f = function () { throw new \Exception('b'); };
|
||||
$p2 = $p->then($f);
|
||||
$this->assertNotSame($p, $p2);
|
||||
try {
|
||||
$p2->wait();
|
||||
$this->fail();
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals('b', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testOtherwiseIsSugarForRejections()
|
||||
{
|
||||
$c = null;
|
||||
$p = new FulfilledPromise('foo');
|
||||
$p->otherwise(function ($v) use (&$c) { $c = $v; });
|
||||
$this->assertNull($c);
|
||||
}
|
||||
|
||||
public function testDoesNotTryToFulfillTwiceDuringTrampoline()
|
||||
{
|
||||
$fp = new FulfilledPromise('a');
|
||||
$t1 = $fp->then(function ($v) { return $v . ' b'; });
|
||||
$t1->resolve('why!');
|
||||
$this->assertEquals('why!', $t1->wait());
|
||||
}
|
||||
}
|
50
server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php
vendored
Normal file
50
server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
|
||||
class NotPromiseInstance extends Thennable implements PromiseInterface
|
||||
{
|
||||
private $nextPromise = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->nextPromise = new Promise();
|
||||
}
|
||||
|
||||
public function then(callable $res = null, callable $rej = null)
|
||||
{
|
||||
return $this->nextPromise->then($res, $rej);
|
||||
}
|
||||
|
||||
public function otherwise(callable $onRejected)
|
||||
{
|
||||
return $this->then($onRejected);
|
||||
}
|
||||
|
||||
public function resolve($value)
|
||||
{
|
||||
$this->nextPromise->resolve($value);
|
||||
}
|
||||
|
||||
public function reject($reason)
|
||||
{
|
||||
$this->nextPromise->reject($reason);
|
||||
}
|
||||
|
||||
public function wait($unwrap = true, $defaultResolution = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function cancel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getState()
|
||||
{
|
||||
return $this->nextPromise->getState();
|
||||
}
|
||||
}
|
579
server/vendor/guzzlehttp/promises/tests/PromiseTest.php
vendored
Normal file
579
server/vendor/guzzlehttp/promises/tests/PromiseTest.php
vendored
Normal file
|
@ -0,0 +1,579 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\CancellationException;
|
||||
use GuzzleHttp\Promise as P;
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Promise\RejectionException;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Promise\Promise
|
||||
*/
|
||||
class PromiseTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The promise is already fulfilled
|
||||
*/
|
||||
public function testCannotResolveNonPendingPromise()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$p->resolve('bar');
|
||||
$this->assertEquals('foo', $p->wait());
|
||||
}
|
||||
|
||||
public function testCanResolveWithSameValue()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$p->resolve('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage Cannot change a fulfilled promise to rejected
|
||||
*/
|
||||
public function testCannotRejectNonPendingPromise()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$p->reject('bar');
|
||||
$this->assertEquals('foo', $p->wait());
|
||||
}
|
||||
|
||||
public function testCanRejectWithSameValue()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->reject('foo');
|
||||
$p->reject('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage Cannot change a fulfilled promise to rejected
|
||||
*/
|
||||
public function testCannotRejectResolveWithSameValue()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$p->reject('foo');
|
||||
}
|
||||
|
||||
public function testInvokesWaitFunction()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) { $p->resolve('10'); });
|
||||
$this->assertEquals('10', $p->wait());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\RejectionException
|
||||
*/
|
||||
public function testRejectsAndThrowsWhenWaitFailsToResolve()
|
||||
{
|
||||
$p = new Promise(function () {});
|
||||
$p->wait();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\RejectionException
|
||||
* @expectedExceptionMessage The promise was rejected with reason: foo
|
||||
*/
|
||||
public function testThrowsWhenUnwrapIsRejectedWithNonException()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) { $p->reject('foo'); });
|
||||
$p->wait();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \UnexpectedValueException
|
||||
* @expectedExceptionMessage foo
|
||||
*/
|
||||
public function testThrowsWhenUnwrapIsRejectedWithException()
|
||||
{
|
||||
$e = new \UnexpectedValueException('foo');
|
||||
$p = new Promise(function () use (&$p, $e) { $p->reject($e); });
|
||||
$p->wait();
|
||||
}
|
||||
|
||||
public function testDoesNotUnwrapExceptionsWhenDisabled()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) { $p->reject('foo'); });
|
||||
$this->assertEquals('pending', $p->getState());
|
||||
$p->wait(false);
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
}
|
||||
|
||||
public function testRejectsSelfWhenWaitThrows()
|
||||
{
|
||||
$e = new \UnexpectedValueException('foo');
|
||||
$p = new Promise(function () use ($e) { throw $e; });
|
||||
try {
|
||||
$p->wait();
|
||||
$this->fail();
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
}
|
||||
}
|
||||
|
||||
public function testWaitsOnNestedPromises()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) { $p->resolve('_'); });
|
||||
$p2 = new Promise(function () use (&$p2) { $p2->resolve('foo'); });
|
||||
$p3 = $p->then(function () use ($p2) { return $p2; });
|
||||
$this->assertSame('foo', $p3->wait());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\RejectionException
|
||||
*/
|
||||
public function testThrowsWhenWaitingOnPromiseWithNoWaitFunction()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->wait();
|
||||
}
|
||||
|
||||
public function testThrowsWaitExceptionAfterPromiseIsResolved()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) {
|
||||
$p->reject('Foo!');
|
||||
throw new \Exception('Bar?');
|
||||
});
|
||||
|
||||
try {
|
||||
$p->wait();
|
||||
$this->fail();
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals('Bar?', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetsActualWaitValueFromThen()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) { $p->reject('Foo!'); });
|
||||
$p2 = $p->then(null, function ($reason) {
|
||||
return new RejectedPromise([$reason]);
|
||||
});
|
||||
|
||||
try {
|
||||
$p2->wait();
|
||||
$this->fail('Should have thrown');
|
||||
} catch (RejectionException $e) {
|
||||
$this->assertEquals(['Foo!'], $e->getReason());
|
||||
}
|
||||
}
|
||||
|
||||
public function testWaitBehaviorIsBasedOnLastPromiseInChain()
|
||||
{
|
||||
$p3 = new Promise(function () use (&$p3) { $p3->resolve('Whoop'); });
|
||||
$p2 = new Promise(function () use (&$p2, $p3) { $p2->reject($p3); });
|
||||
$p = new Promise(function () use (&$p, $p2) { $p->reject($p2); });
|
||||
$this->assertEquals('Whoop', $p->wait());
|
||||
}
|
||||
|
||||
public function testCannotCancelNonPending()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$p->cancel();
|
||||
$this->assertEquals('fulfilled', $p->getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\CancellationException
|
||||
*/
|
||||
public function testCancelsPromiseWhenNoCancelFunction()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->cancel();
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
$p->wait();
|
||||
}
|
||||
|
||||
public function testCancelsPromiseWithCancelFunction()
|
||||
{
|
||||
$called = false;
|
||||
$p = new Promise(null, function () use (&$called) { $called = true; });
|
||||
$p->cancel();
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
$this->assertTrue($called);
|
||||
}
|
||||
|
||||
public function testCancelsUppermostPendingPromise()
|
||||
{
|
||||
$called = false;
|
||||
$p1 = new Promise(null, function () use (&$called) { $called = true; });
|
||||
$p2 = $p1->then(function () {});
|
||||
$p3 = $p2->then(function () {});
|
||||
$p4 = $p3->then(function () {});
|
||||
$p3->cancel();
|
||||
$this->assertEquals('rejected', $p1->getState());
|
||||
$this->assertEquals('rejected', $p2->getState());
|
||||
$this->assertEquals('rejected', $p3->getState());
|
||||
$this->assertEquals('pending', $p4->getState());
|
||||
$this->assertTrue($called);
|
||||
|
||||
try {
|
||||
$p3->wait();
|
||||
$this->fail();
|
||||
} catch (CancellationException $e) {
|
||||
$this->assertContains('cancelled', $e->getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
$p4->wait();
|
||||
$this->fail();
|
||||
} catch (CancellationException $e) {
|
||||
$this->assertContains('cancelled', $e->getMessage());
|
||||
}
|
||||
|
||||
$this->assertEquals('rejected', $p4->getState());
|
||||
}
|
||||
|
||||
public function testCancelsChildPromises()
|
||||
{
|
||||
$called1 = $called2 = $called3 = false;
|
||||
$p1 = new Promise(null, function () use (&$called1) { $called1 = true; });
|
||||
$p2 = new Promise(null, function () use (&$called2) { $called2 = true; });
|
||||
$p3 = new Promise(null, function () use (&$called3) { $called3 = true; });
|
||||
$p4 = $p2->then(function () use ($p3) { return $p3; });
|
||||
$p5 = $p4->then(function () { $this->fail(); });
|
||||
$p4->cancel();
|
||||
$this->assertEquals('pending', $p1->getState());
|
||||
$this->assertEquals('rejected', $p2->getState());
|
||||
$this->assertEquals('rejected', $p4->getState());
|
||||
$this->assertEquals('pending', $p5->getState());
|
||||
$this->assertFalse($called1);
|
||||
$this->assertTrue($called2);
|
||||
$this->assertFalse($called3);
|
||||
}
|
||||
|
||||
public function testRejectsPromiseWhenCancelFails()
|
||||
{
|
||||
$called = false;
|
||||
$p = new Promise(null, function () use (&$called) {
|
||||
$called = true;
|
||||
throw new \Exception('e');
|
||||
});
|
||||
$p->cancel();
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
$this->assertTrue($called);
|
||||
try {
|
||||
$p->wait();
|
||||
$this->fail();
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals('e', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreatesPromiseWhenFulfilledAfterThen()
|
||||
{
|
||||
$p = new Promise();
|
||||
$carry = null;
|
||||
$p2 = $p->then(function ($v) use (&$carry) { $carry = $v; });
|
||||
$this->assertNotSame($p, $p2);
|
||||
$p->resolve('foo');
|
||||
P\queue()->run();
|
||||
|
||||
$this->assertEquals('foo', $carry);
|
||||
}
|
||||
|
||||
public function testCreatesPromiseWhenFulfilledBeforeThen()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$carry = null;
|
||||
$p2 = $p->then(function ($v) use (&$carry) { $carry = $v; });
|
||||
$this->assertNotSame($p, $p2);
|
||||
$this->assertNull($carry);
|
||||
\GuzzleHttp\Promise\queue()->run();
|
||||
$this->assertEquals('foo', $carry);
|
||||
}
|
||||
|
||||
public function testCreatesPromiseWhenFulfilledWithNoCallback()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve('foo');
|
||||
$p2 = $p->then();
|
||||
$this->assertNotSame($p, $p2);
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p2);
|
||||
}
|
||||
|
||||
public function testCreatesPromiseWhenRejectedAfterThen()
|
||||
{
|
||||
$p = new Promise();
|
||||
$carry = null;
|
||||
$p2 = $p->then(null, function ($v) use (&$carry) { $carry = $v; });
|
||||
$this->assertNotSame($p, $p2);
|
||||
$p->reject('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $carry);
|
||||
}
|
||||
|
||||
public function testCreatesPromiseWhenRejectedBeforeThen()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->reject('foo');
|
||||
$carry = null;
|
||||
$p2 = $p->then(null, function ($v) use (&$carry) { $carry = $v; });
|
||||
$this->assertNotSame($p, $p2);
|
||||
$this->assertNull($carry);
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $carry);
|
||||
}
|
||||
|
||||
public function testCreatesPromiseWhenRejectedWithNoCallback()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->reject('foo');
|
||||
$p2 = $p->then();
|
||||
$this->assertNotSame($p, $p2);
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p2);
|
||||
}
|
||||
|
||||
public function testInvokesWaitFnsForThens()
|
||||
{
|
||||
$p = new Promise(function () use (&$p) { $p->resolve('a'); });
|
||||
$p2 = $p
|
||||
->then(function ($v) { return $v . '-1-'; })
|
||||
->then(function ($v) { return $v . '2'; });
|
||||
$this->assertEquals('a-1-2', $p2->wait());
|
||||
}
|
||||
|
||||
public function testStacksThenWaitFunctions()
|
||||
{
|
||||
$p1 = new Promise(function () use (&$p1) { $p1->resolve('a'); });
|
||||
$p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); });
|
||||
$p3 = new Promise(function () use (&$p3) { $p3->resolve('c'); });
|
||||
$p4 = $p1
|
||||
->then(function () use ($p2) { return $p2; })
|
||||
->then(function () use ($p3) { return $p3; });
|
||||
$this->assertEquals('c', $p4->wait());
|
||||
}
|
||||
|
||||
public function testForwardsFulfilledDownChainBetweenGaps()
|
||||
{
|
||||
$p = new Promise();
|
||||
$r = $r2 = null;
|
||||
$p->then(null, null)
|
||||
->then(function ($v) use (&$r) { $r = $v; return $v . '2'; })
|
||||
->then(function ($v) use (&$r2) { $r2 = $v; });
|
||||
$p->resolve('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $r);
|
||||
$this->assertEquals('foo2', $r2);
|
||||
}
|
||||
|
||||
public function testForwardsRejectedPromisesDownChainBetweenGaps()
|
||||
{
|
||||
$p = new Promise();
|
||||
$r = $r2 = null;
|
||||
$p->then(null, null)
|
||||
->then(null, function ($v) use (&$r) { $r = $v; return $v . '2'; })
|
||||
->then(function ($v) use (&$r2) { $r2 = $v; });
|
||||
$p->reject('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $r);
|
||||
$this->assertEquals('foo2', $r2);
|
||||
}
|
||||
|
||||
public function testForwardsThrownPromisesDownChainBetweenGaps()
|
||||
{
|
||||
$e = new \Exception();
|
||||
$p = new Promise();
|
||||
$r = $r2 = null;
|
||||
$p->then(null, null)
|
||||
->then(null, function ($v) use (&$r, $e) {
|
||||
$r = $v;
|
||||
throw $e;
|
||||
})
|
||||
->then(
|
||||
null,
|
||||
function ($v) use (&$r2) { $r2 = $v; }
|
||||
);
|
||||
$p->reject('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $r);
|
||||
$this->assertSame($e, $r2);
|
||||
}
|
||||
|
||||
public function testForwardsReturnedRejectedPromisesDownChainBetweenGaps()
|
||||
{
|
||||
$p = new Promise();
|
||||
$rejected = new RejectedPromise('bar');
|
||||
$r = $r2 = null;
|
||||
$p->then(null, null)
|
||||
->then(null, function ($v) use (&$r, $rejected) {
|
||||
$r = $v;
|
||||
return $rejected;
|
||||
})
|
||||
->then(
|
||||
null,
|
||||
function ($v) use (&$r2) { $r2 = $v; }
|
||||
);
|
||||
$p->reject('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $r);
|
||||
$this->assertEquals('bar', $r2);
|
||||
try {
|
||||
$p->wait();
|
||||
} catch (RejectionException $e) {
|
||||
$this->assertEquals('foo', $e->getReason());
|
||||
}
|
||||
}
|
||||
|
||||
public function testForwardsHandlersToNextPromise()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p2 = new Promise();
|
||||
$resolved = null;
|
||||
$p
|
||||
->then(function ($v) use ($p2) { return $p2; })
|
||||
->then(function ($value) use (&$resolved) { $resolved = $value; });
|
||||
$p->resolve('a');
|
||||
$p2->resolve('b');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('b', $resolved);
|
||||
}
|
||||
|
||||
public function testRemovesReferenceFromChildWhenParentWaitedUpon()
|
||||
{
|
||||
$r = null;
|
||||
$p = new Promise(function () use (&$p) { $p->resolve('a'); });
|
||||
$p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); });
|
||||
$pb = $p->then(
|
||||
function ($v) use ($p2, &$r) {
|
||||
$r = $v;
|
||||
return $p2;
|
||||
})
|
||||
->then(function ($v) { return $v . '.'; });
|
||||
$this->assertEquals('a', $p->wait());
|
||||
$this->assertEquals('b', $p2->wait());
|
||||
$this->assertEquals('b.', $pb->wait());
|
||||
$this->assertEquals('a', $r);
|
||||
}
|
||||
|
||||
public function testForwardsHandlersWhenFulfilledPromiseIsReturned()
|
||||
{
|
||||
$res = [];
|
||||
$p = new Promise();
|
||||
$p2 = new Promise();
|
||||
$p2->resolve('foo');
|
||||
$p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; });
|
||||
// $res is A:foo
|
||||
$p
|
||||
->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
|
||||
->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
|
||||
$p->resolve('a');
|
||||
$p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res);
|
||||
}
|
||||
|
||||
public function testForwardsHandlersWhenRejectedPromiseIsReturned()
|
||||
{
|
||||
$res = [];
|
||||
$p = new Promise();
|
||||
$p2 = new Promise();
|
||||
$p2->reject('foo');
|
||||
$p2->then(null, function ($v) use (&$res) { $res[] = 'A:' . $v; });
|
||||
$p->then(null, function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
|
||||
->then(null, function ($v) use (&$res) { $res[] = 'C:' . $v; });
|
||||
$p->reject('a');
|
||||
$p->then(null, function ($v) use (&$res) { $res[] = 'D:' . $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res);
|
||||
}
|
||||
|
||||
public function testDoesNotForwardRejectedPromise()
|
||||
{
|
||||
$res = [];
|
||||
$p = new Promise();
|
||||
$p2 = new Promise();
|
||||
$p2->cancel();
|
||||
$p2->then(function ($v) use (&$res) { $res[] = "B:$v"; return $v; });
|
||||
$p->then(function ($v) use ($p2, &$res) { $res[] = "B:$v"; return $p2; })
|
||||
->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
|
||||
$p->resolve('a');
|
||||
$p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['B:a', 'D:a'], $res);
|
||||
}
|
||||
|
||||
public function testRecursivelyForwardsWhenOnlyThennable()
|
||||
{
|
||||
$res = [];
|
||||
$p = new Promise();
|
||||
$p2 = new Thennable();
|
||||
$p2->resolve('foo');
|
||||
$p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; });
|
||||
$p->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
|
||||
->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
|
||||
$p->resolve('a');
|
||||
$p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res);
|
||||
}
|
||||
|
||||
public function testRecursivelyForwardsWhenNotInstanceOfPromise()
|
||||
{
|
||||
$res = [];
|
||||
$p = new Promise();
|
||||
$p2 = new NotPromiseInstance();
|
||||
$p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; });
|
||||
$p->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
|
||||
->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
|
||||
$p->resolve('a');
|
||||
$p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['B', 'D:a'], $res);
|
||||
$p2->resolve('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['B', 'D:a', 'A:foo', 'C:foo'], $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage Cannot fulfill or reject a promise with itself
|
||||
*/
|
||||
public function testCannotResolveWithSelf()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->resolve($p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage Cannot fulfill or reject a promise with itself
|
||||
*/
|
||||
public function testCannotRejectWithSelf()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->reject($p);
|
||||
}
|
||||
|
||||
public function testDoesNotBlowStackWhenWaitingOnNestedThens()
|
||||
{
|
||||
$inner = new Promise(function () use (&$inner) { $inner->resolve(0); });
|
||||
$prev = $inner;
|
||||
for ($i = 1; $i < 100; $i++) {
|
||||
$prev = $prev->then(function ($i) { return $i + 1; });
|
||||
}
|
||||
|
||||
$parent = new Promise(function () use (&$parent, $prev) {
|
||||
$parent->resolve($prev);
|
||||
});
|
||||
|
||||
$this->assertEquals(99, $parent->wait());
|
||||
}
|
||||
|
||||
public function testOtherwiseIsSugarForRejections()
|
||||
{
|
||||
$p = new Promise();
|
||||
$p->reject('foo');
|
||||
$p->otherwise(function ($v) use (&$c) { $c = $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals($c, 'foo');
|
||||
}
|
||||
}
|
143
server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php
vendored
Normal file
143
server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Promise\RejectedPromise
|
||||
*/
|
||||
class RejectedPromiseTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testThrowsReasonWhenWaitedUpon()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
try {
|
||||
$p->wait(true);
|
||||
$this->fail();
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
$this->assertContains('foo', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testCannotCancel()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$p->cancel();
|
||||
$this->assertEquals('rejected', $p->getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @exepctedExceptionMessage Cannot resolve a rejected promise
|
||||
*/
|
||||
public function testCannotResolve()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$p->resolve('bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @exepctedExceptionMessage Cannot reject a rejected promise
|
||||
*/
|
||||
public function testCannotReject()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$p->reject('bar');
|
||||
}
|
||||
|
||||
public function testCanRejectWithSameValue()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$p->reject('foo');
|
||||
}
|
||||
|
||||
public function testThrowsSpecificException()
|
||||
{
|
||||
$e = new \Exception();
|
||||
$p = new RejectedPromise($e);
|
||||
try {
|
||||
$p->wait(true);
|
||||
$this->fail();
|
||||
} catch (\Exception $e2) {
|
||||
$this->assertSame($e, $e2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCannotResolveWithPromise()
|
||||
{
|
||||
new RejectedPromise(new Promise());
|
||||
}
|
||||
|
||||
public function testReturnsSelfWhenNoOnReject()
|
||||
{
|
||||
$p = new RejectedPromise('a');
|
||||
$this->assertSame($p, $p->then());
|
||||
}
|
||||
|
||||
public function testInvokesOnRejectedAsynchronously()
|
||||
{
|
||||
$p = new RejectedPromise('a');
|
||||
$r = null;
|
||||
$f = function ($reason) use (&$r) { $r = $reason; };
|
||||
$p->then(null, $f);
|
||||
$this->assertNull($r);
|
||||
\GuzzleHttp\Promise\queue()->run();
|
||||
$this->assertEquals('a', $r);
|
||||
}
|
||||
|
||||
public function testReturnsNewRejectedWhenOnRejectedFails()
|
||||
{
|
||||
$p = new RejectedPromise('a');
|
||||
$f = function () { throw new \Exception('b'); };
|
||||
$p2 = $p->then(null, $f);
|
||||
$this->assertNotSame($p, $p2);
|
||||
try {
|
||||
$p2->wait();
|
||||
$this->fail();
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals('b', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testWaitingIsNoOp()
|
||||
{
|
||||
$p = new RejectedPromise('a');
|
||||
$p->wait(false);
|
||||
}
|
||||
|
||||
public function testOtherwiseIsSugarForRejections()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$p->otherwise(function ($v) use (&$c) { $c = $v; });
|
||||
\GuzzleHttp\Promise\queue()->run();
|
||||
$this->assertSame('foo', $c);
|
||||
}
|
||||
|
||||
public function testCanResolveThenWithSuccess()
|
||||
{
|
||||
$actual = null;
|
||||
$p = new RejectedPromise('foo');
|
||||
$p->otherwise(function ($v) {
|
||||
return $v . ' bar';
|
||||
})->then(function ($v) use (&$actual) {
|
||||
$actual = $v;
|
||||
});
|
||||
\GuzzleHttp\Promise\queue()->run();
|
||||
$this->assertEquals('foo bar', $actual);
|
||||
}
|
||||
|
||||
public function testDoesNotTryToRejectTwiceDuringTrampoline()
|
||||
{
|
||||
$fp = new RejectedPromise('a');
|
||||
$t1 = $fp->then(null, function ($v) { return $v . ' b'; });
|
||||
$t1->resolve('why!');
|
||||
$this->assertEquals('why!', $t1->wait());
|
||||
}
|
||||
}
|
47
server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php
vendored
Normal file
47
server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\RejectionException;
|
||||
|
||||
class Thing1
|
||||
{
|
||||
public function __construct($message)
|
||||
{
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
}
|
||||
|
||||
class Thing2 implements \JsonSerializable
|
||||
{
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return '{}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Promise\RejectionException
|
||||
*/
|
||||
class RejectionExceptionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCanGetReasonFromException()
|
||||
{
|
||||
$thing = new Thing1('foo');
|
||||
$e = new RejectionException($thing);
|
||||
|
||||
$this->assertSame($thing, $e->getReason());
|
||||
$this->assertEquals('The promise was rejected with reason: foo', $e->getMessage());
|
||||
}
|
||||
|
||||
public function testCanGetReasonMessageFromJson()
|
||||
{
|
||||
$reason = new Thing2();
|
||||
$e = new RejectionException($reason);
|
||||
$this->assertContains("{}", $e->getMessage());
|
||||
}
|
||||
}
|
31
server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php
vendored
Normal file
31
server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Test;
|
||||
|
||||
use GuzzleHttp\Promise\TaskQueue;
|
||||
|
||||
class TaskQueueTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testKnowsIfEmpty()
|
||||
{
|
||||
$tq = new TaskQueue(false);
|
||||
$this->assertTrue($tq->isEmpty());
|
||||
}
|
||||
|
||||
public function testKnowsIfFull()
|
||||
{
|
||||
$tq = new TaskQueue(false);
|
||||
$tq->add(function () {});
|
||||
$this->assertFalse($tq->isEmpty());
|
||||
}
|
||||
|
||||
public function testExecutesTasksInOrder()
|
||||
{
|
||||
$tq = new TaskQueue(false);
|
||||
$called = [];
|
||||
$tq->add(function () use (&$called) { $called[] = 'a'; });
|
||||
$tq->add(function () use (&$called) { $called[] = 'b'; });
|
||||
$tq->add(function () use (&$called) { $called[] = 'c'; });
|
||||
$tq->run();
|
||||
$this->assertEquals(['a', 'b', 'c'], $called);
|
||||
}
|
||||
}
|
24
server/vendor/guzzlehttp/promises/tests/Thennable.php
vendored
Normal file
24
server/vendor/guzzlehttp/promises/tests/Thennable.php
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
|
||||
class Thennable
|
||||
{
|
||||
private $nextPromise = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->nextPromise = new Promise();
|
||||
}
|
||||
|
||||
public function then(callable $res = null, callable $rej = null)
|
||||
{
|
||||
return $this->nextPromise->then($res, $rej);
|
||||
}
|
||||
|
||||
public function resolve($value)
|
||||
{
|
||||
$this->nextPromise->resolve($value);
|
||||
}
|
||||
}
|
4
server/vendor/guzzlehttp/promises/tests/bootstrap.php
vendored
Normal file
4
server/vendor/guzzlehttp/promises/tests/bootstrap.php
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
require __DIR__ . '/Thennable.php';
|
||||
require __DIR__ . '/NotPromiseInstance.php';
|
694
server/vendor/guzzlehttp/promises/tests/functionsTest.php
vendored
Normal file
694
server/vendor/guzzlehttp/promises/tests/functionsTest.php
vendored
Normal file
|
@ -0,0 +1,694 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Promise\Tests;
|
||||
|
||||
use GuzzleHttp\Promise as P;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
|
||||
class FunctionsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreatesPromiseForValue()
|
||||
{
|
||||
$p = \GuzzleHttp\Promise\promise_for('foo');
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p);
|
||||
}
|
||||
|
||||
public function testReturnsPromiseForPromise()
|
||||
{
|
||||
$p = new Promise();
|
||||
$this->assertSame($p, \GuzzleHttp\Promise\promise_for($p));
|
||||
}
|
||||
|
||||
public function testReturnsPromiseForThennable()
|
||||
{
|
||||
$p = new Thennable();
|
||||
$wrapped = \GuzzleHttp\Promise\promise_for($p);
|
||||
$this->assertNotSame($p, $wrapped);
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\PromiseInterface', $wrapped);
|
||||
$p->resolve('foo');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('foo', $wrapped->wait());
|
||||
}
|
||||
|
||||
public function testReturnsRejection()
|
||||
{
|
||||
$p = \GuzzleHttp\Promise\rejection_for('fail');
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p);
|
||||
$this->assertEquals('fail', $this->readAttribute($p, 'reason'));
|
||||
}
|
||||
|
||||
public function testReturnsPromisesAsIsInRejectionFor()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = \GuzzleHttp\Promise\rejection_for($a);
|
||||
$this->assertSame($a, $b);
|
||||
}
|
||||
|
||||
public function testWaitsOnAllPromisesIntoArray()
|
||||
{
|
||||
$e = new \Exception();
|
||||
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
|
||||
$b = new Promise(function () use (&$b) { $b->reject('b'); });
|
||||
$c = new Promise(function () use (&$c, $e) { $c->reject($e); });
|
||||
$results = \GuzzleHttp\Promise\inspect_all([$a, $b, $c]);
|
||||
$this->assertEquals([
|
||||
['state' => 'fulfilled', 'value' => 'a'],
|
||||
['state' => 'rejected', 'reason' => 'b'],
|
||||
['state' => 'rejected', 'reason' => $e]
|
||||
], $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\RejectionException
|
||||
*/
|
||||
public function testUnwrapsPromisesWithNoDefaultAndFailure()
|
||||
{
|
||||
$promises = [new FulfilledPromise('a'), new Promise()];
|
||||
\GuzzleHttp\Promise\unwrap($promises);
|
||||
}
|
||||
|
||||
public function testUnwrapsPromisesWithNoDefault()
|
||||
{
|
||||
$promises = [new FulfilledPromise('a')];
|
||||
$this->assertEquals(['a'], \GuzzleHttp\Promise\unwrap($promises));
|
||||
}
|
||||
|
||||
public function testUnwrapsPromisesWithKeys()
|
||||
{
|
||||
$promises = [
|
||||
'foo' => new FulfilledPromise('a'),
|
||||
'bar' => new FulfilledPromise('b'),
|
||||
];
|
||||
$this->assertEquals([
|
||||
'foo' => 'a',
|
||||
'bar' => 'b'
|
||||
], \GuzzleHttp\Promise\unwrap($promises));
|
||||
}
|
||||
|
||||
public function testAllAggregatesSortedArray()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$c = new Promise();
|
||||
$d = \GuzzleHttp\Promise\all([$a, $b, $c]);
|
||||
$b->resolve('b');
|
||||
$a->resolve('a');
|
||||
$c->resolve('c');
|
||||
$d->then(
|
||||
function ($value) use (&$result) { $result = $value; },
|
||||
function ($reason) use (&$result) { $result = $reason; }
|
||||
);
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['a', 'b', 'c'], $result);
|
||||
}
|
||||
|
||||
public function testAllThrowsWhenAnyRejected()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$c = new Promise();
|
||||
$d = \GuzzleHttp\Promise\all([$a, $b, $c]);
|
||||
$b->resolve('b');
|
||||
$a->reject('fail');
|
||||
$c->resolve('c');
|
||||
$d->then(
|
||||
function ($value) use (&$result) { $result = $value; },
|
||||
function ($reason) use (&$result) { $result = $reason; }
|
||||
);
|
||||
P\queue()->run();
|
||||
$this->assertEquals('fail', $result);
|
||||
}
|
||||
|
||||
public function testSomeAggregatesSortedArrayWithMax()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$c = new Promise();
|
||||
$d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]);
|
||||
$b->resolve('b');
|
||||
$c->resolve('c');
|
||||
$a->resolve('a');
|
||||
$d->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(['b', 'c'], $result);
|
||||
}
|
||||
|
||||
public function testSomeRejectsWhenTooManyRejections()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$d = \GuzzleHttp\Promise\some(2, [$a, $b]);
|
||||
$a->reject('bad');
|
||||
$b->resolve('good');
|
||||
P\queue()->run();
|
||||
$this->assertEquals($a::REJECTED, $d->getState());
|
||||
$d->then(null, function ($reason) use (&$called) {
|
||||
$called = $reason;
|
||||
});
|
||||
P\queue()->run();
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\AggregateException', $called);
|
||||
$this->assertContains('bad', $called->getReason());
|
||||
}
|
||||
|
||||
public function testCanWaitUntilSomeCountIsSatisfied()
|
||||
{
|
||||
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
|
||||
$b = new Promise(function () use (&$b) { $b->resolve('b'); });
|
||||
$c = new Promise(function () use (&$c) { $c->resolve('c'); });
|
||||
$d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]);
|
||||
$this->assertEquals(['a', 'b'], $d->wait());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\AggregateException
|
||||
* @expectedExceptionMessage Not enough promises to fulfill count
|
||||
*/
|
||||
public function testThrowsIfImpossibleToWaitForSomeCount()
|
||||
{
|
||||
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
|
||||
$d = \GuzzleHttp\Promise\some(2, [$a]);
|
||||
$d->wait();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \GuzzleHttp\Promise\AggregateException
|
||||
* @expectedExceptionMessage Not enough promises to fulfill count
|
||||
*/
|
||||
public function testThrowsIfResolvedWithoutCountTotalResults()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$d = \GuzzleHttp\Promise\some(3, [$a, $b]);
|
||||
$a->resolve('a');
|
||||
$b->resolve('b');
|
||||
$d->wait();
|
||||
}
|
||||
|
||||
public function testAnyReturnsFirstMatch()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$c = \GuzzleHttp\Promise\any([$a, $b]);
|
||||
$b->resolve('b');
|
||||
$a->resolve('a');
|
||||
//P\queue()->run();
|
||||
//$this->assertEquals('fulfilled', $c->getState());
|
||||
$c->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals('b', $result);
|
||||
}
|
||||
|
||||
public function testSettleFulfillsWithFulfilledAndRejected()
|
||||
{
|
||||
$a = new Promise();
|
||||
$b = new Promise();
|
||||
$c = new Promise();
|
||||
$d = \GuzzleHttp\Promise\settle([$a, $b, $c]);
|
||||
$b->resolve('b');
|
||||
$c->resolve('c');
|
||||
$a->reject('a');
|
||||
P\queue()->run();
|
||||
$this->assertEquals('fulfilled', $d->getState());
|
||||
$d->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals([
|
||||
['state' => 'rejected', 'reason' => 'a'],
|
||||
['state' => 'fulfilled', 'value' => 'b'],
|
||||
['state' => 'fulfilled', 'value' => 'c']
|
||||
], $result);
|
||||
}
|
||||
|
||||
public function testCanInspectFulfilledPromise()
|
||||
{
|
||||
$p = new FulfilledPromise('foo');
|
||||
$this->assertEquals([
|
||||
'state' => 'fulfilled',
|
||||
'value' => 'foo'
|
||||
], \GuzzleHttp\Promise\inspect($p));
|
||||
}
|
||||
|
||||
public function testCanInspectRejectedPromise()
|
||||
{
|
||||
$p = new RejectedPromise('foo');
|
||||
$this->assertEquals([
|
||||
'state' => 'rejected',
|
||||
'reason' => 'foo'
|
||||
], \GuzzleHttp\Promise\inspect($p));
|
||||
}
|
||||
|
||||
public function testCanInspectRejectedPromiseWithNormalException()
|
||||
{
|
||||
$e = new \Exception('foo');
|
||||
$p = new RejectedPromise($e);
|
||||
$this->assertEquals([
|
||||
'state' => 'rejected',
|
||||
'reason' => $e
|
||||
], \GuzzleHttp\Promise\inspect($p));
|
||||
}
|
||||
|
||||
public function testCallsEachLimit()
|
||||
{
|
||||
$p = new Promise();
|
||||
$aggregate = \GuzzleHttp\Promise\each_limit($p, 2);
|
||||
$p->resolve('a');
|
||||
P\queue()->run();
|
||||
$this->assertEquals($p::FULFILLED, $aggregate->getState());
|
||||
}
|
||||
|
||||
public function testEachLimitAllRejectsOnFailure()
|
||||
{
|
||||
$p = [new FulfilledPromise('a'), new RejectedPromise('b')];
|
||||
$aggregate = \GuzzleHttp\Promise\each_limit_all($p, 2);
|
||||
P\queue()->run();
|
||||
$this->assertEquals(P\PromiseInterface::REJECTED, $aggregate->getState());
|
||||
$result = \GuzzleHttp\Promise\inspect($aggregate);
|
||||
$this->assertEquals('b', $result['reason']);
|
||||
}
|
||||
|
||||
public function testIterForReturnsIterator()
|
||||
{
|
||||
$iter = new \ArrayIterator();
|
||||
$this->assertSame($iter, \GuzzleHttp\Promise\iter_for($iter));
|
||||
}
|
||||
|
||||
public function testKnowsIfFulfilled()
|
||||
{
|
||||
$p = new FulfilledPromise(null);
|
||||
$this->assertTrue(P\is_fulfilled($p));
|
||||
$this->assertFalse(P\is_rejected($p));
|
||||
}
|
||||
|
||||
public function testKnowsIfRejected()
|
||||
{
|
||||
$p = new RejectedPromise(null);
|
||||
$this->assertTrue(P\is_rejected($p));
|
||||
$this->assertFalse(P\is_fulfilled($p));
|
||||
}
|
||||
|
||||
public function testKnowsIfSettled()
|
||||
{
|
||||
$p = new RejectedPromise(null);
|
||||
$this->assertTrue(P\is_settled($p));
|
||||
$p = new Promise();
|
||||
$this->assertFalse(P\is_settled($p));
|
||||
}
|
||||
|
||||
public function testReturnsTrampoline()
|
||||
{
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\TaskQueue', P\queue());
|
||||
$this->assertSame(P\queue(), P\queue());
|
||||
}
|
||||
|
||||
public function testCanScheduleThunk()
|
||||
{
|
||||
$tramp = P\queue();
|
||||
$promise = P\task(function () { return 'Hi!'; });
|
||||
$c = null;
|
||||
$promise->then(function ($v) use (&$c) { $c = $v; });
|
||||
$this->assertNull($c);
|
||||
$tramp->run();
|
||||
$this->assertEquals('Hi!', $c);
|
||||
}
|
||||
|
||||
public function testCanScheduleThunkWithRejection()
|
||||
{
|
||||
$tramp = P\queue();
|
||||
$promise = P\task(function () { throw new \Exception('Hi!'); });
|
||||
$c = null;
|
||||
$promise->otherwise(function ($v) use (&$c) { $c = $v; });
|
||||
$this->assertNull($c);
|
||||
$tramp->run();
|
||||
$this->assertEquals('Hi!', $c->getMessage());
|
||||
}
|
||||
|
||||
public function testCanScheduleThunkWithWait()
|
||||
{
|
||||
$tramp = P\queue();
|
||||
$promise = P\task(function () { return 'a'; });
|
||||
$this->assertEquals('a', $promise->wait());
|
||||
$tramp->run();
|
||||
}
|
||||
|
||||
public function testYieldsFromCoroutine()
|
||||
{
|
||||
$promise = P\coroutine(function () {
|
||||
$value = (yield new P\FulfilledPromise('a'));
|
||||
yield $value . 'b';
|
||||
});
|
||||
$promise->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals('ab', $result);
|
||||
}
|
||||
|
||||
public function testCanCatchExceptionsInCoroutine()
|
||||
{
|
||||
$promise = P\coroutine(function () {
|
||||
try {
|
||||
yield new P\RejectedPromise('a');
|
||||
$this->fail('Should have thrown into the coroutine!');
|
||||
} catch (P\RejectionException $e) {
|
||||
$value = (yield new P\FulfilledPromise($e->getReason()));
|
||||
yield $value . 'b';
|
||||
}
|
||||
});
|
||||
$promise->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(P\PromiseInterface::FULFILLED, $promise->getState());
|
||||
$this->assertEquals('ab', $result);
|
||||
}
|
||||
|
||||
public function testRejectsParentExceptionWhenException()
|
||||
{
|
||||
$promise = P\coroutine(function () {
|
||||
yield new P\FulfilledPromise(0);
|
||||
throw new \Exception('a');
|
||||
});
|
||||
$promise->then(
|
||||
function () { $this->fail(); },
|
||||
function ($reason) use (&$result) { $result = $reason; }
|
||||
);
|
||||
P\queue()->run();
|
||||
$this->assertInstanceOf('Exception', $result);
|
||||
$this->assertEquals('a', $result->getMessage());
|
||||
}
|
||||
|
||||
public function testCanRejectFromRejectionCallback()
|
||||
{
|
||||
$promise = P\coroutine(function () {
|
||||
yield new P\FulfilledPromise(0);
|
||||
yield new P\RejectedPromise('no!');
|
||||
});
|
||||
$promise->then(
|
||||
function () { $this->fail(); },
|
||||
function ($reason) use (&$result) { $result = $reason; }
|
||||
);
|
||||
P\queue()->run();
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result);
|
||||
$this->assertEquals('no!', $result->getReason());
|
||||
}
|
||||
|
||||
public function testCanAsyncReject()
|
||||
{
|
||||
$rej = new P\Promise();
|
||||
$promise = P\coroutine(function () use ($rej) {
|
||||
yield new P\FulfilledPromise(0);
|
||||
yield $rej;
|
||||
});
|
||||
$promise->then(
|
||||
function () { $this->fail(); },
|
||||
function ($reason) use (&$result) { $result = $reason; }
|
||||
);
|
||||
$rej->reject('no!');
|
||||
P\queue()->run();
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result);
|
||||
$this->assertEquals('no!', $result->getReason());
|
||||
}
|
||||
|
||||
public function testCanCatchAndThrowOtherException()
|
||||
{
|
||||
$promise = P\coroutine(function () {
|
||||
try {
|
||||
yield new P\RejectedPromise('a');
|
||||
$this->fail('Should have thrown into the coroutine!');
|
||||
} catch (P\RejectionException $e) {
|
||||
throw new \Exception('foo');
|
||||
}
|
||||
});
|
||||
$promise->otherwise(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState());
|
||||
$this->assertContains('foo', $result->getMessage());
|
||||
}
|
||||
|
||||
public function testCanCatchAndYieldOtherException()
|
||||
{
|
||||
$promise = P\coroutine(function () {
|
||||
try {
|
||||
yield new P\RejectedPromise('a');
|
||||
$this->fail('Should have thrown into the coroutine!');
|
||||
} catch (P\RejectionException $e) {
|
||||
yield new P\RejectedPromise('foo');
|
||||
}
|
||||
});
|
||||
$promise->otherwise(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState());
|
||||
$this->assertContains('foo', $result->getMessage());
|
||||
}
|
||||
|
||||
public function createLotsOfSynchronousPromise()
|
||||
{
|
||||
return P\coroutine(function () {
|
||||
$value = 0;
|
||||
for ($i = 0; $i < 1000; $i++) {
|
||||
$value = (yield new P\FulfilledPromise($i));
|
||||
}
|
||||
yield $value;
|
||||
});
|
||||
}
|
||||
|
||||
public function testLotsOfSynchronousDoesNotBlowStack()
|
||||
{
|
||||
$promise = $this->createLotsOfSynchronousPromise();
|
||||
$promise->then(function ($v) use (&$r) { $r = $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(999, $r);
|
||||
}
|
||||
|
||||
public function testLotsOfSynchronousWaitDoesNotBlowStack()
|
||||
{
|
||||
$promise = $this->createLotsOfSynchronousPromise();
|
||||
$promise->then(function ($v) use (&$r) { $r = $v; });
|
||||
$this->assertEquals(999, $promise->wait());
|
||||
$this->assertEquals(999, $r);
|
||||
}
|
||||
|
||||
private function createLotsOfFlappingPromise()
|
||||
{
|
||||
return P\coroutine(function () {
|
||||
$value = 0;
|
||||
for ($i = 0; $i < 1000; $i++) {
|
||||
try {
|
||||
if ($i % 2) {
|
||||
$value = (yield new P\FulfilledPromise($i));
|
||||
} else {
|
||||
$value = (yield new P\RejectedPromise($i));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$value = (yield new P\FulfilledPromise($i));
|
||||
}
|
||||
}
|
||||
yield $value;
|
||||
});
|
||||
}
|
||||
|
||||
public function testLotsOfTryCatchingDoesNotBlowStack()
|
||||
{
|
||||
$promise = $this->createLotsOfFlappingPromise();
|
||||
$promise->then(function ($v) use (&$r) { $r = $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(999, $r);
|
||||
}
|
||||
|
||||
public function testLotsOfTryCatchingWaitingDoesNotBlowStack()
|
||||
{
|
||||
$promise = $this->createLotsOfFlappingPromise();
|
||||
$promise->then(function ($v) use (&$r) { $r = $v; });
|
||||
$this->assertEquals(999, $promise->wait());
|
||||
$this->assertEquals(999, $r);
|
||||
}
|
||||
|
||||
public function testAsyncPromisesWithCorrectlyYieldedValues()
|
||||
{
|
||||
$promises = [
|
||||
new P\Promise(),
|
||||
new P\Promise(),
|
||||
new P\Promise()
|
||||
];
|
||||
|
||||
$promise = P\coroutine(function () use ($promises) {
|
||||
$value = null;
|
||||
$this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
|
||||
foreach ($promises as $idx => $p) {
|
||||
$value = (yield $p);
|
||||
$this->assertEquals($value, $idx);
|
||||
$this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
|
||||
}
|
||||
$this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
|
||||
yield $value;
|
||||
});
|
||||
|
||||
$promises[0]->resolve(0);
|
||||
$promises[1]->resolve(1);
|
||||
$promises[2]->resolve(2);
|
||||
|
||||
$promise->then(function ($v) use (&$r) { $r = $v; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals(2, $r);
|
||||
}
|
||||
|
||||
public function testYieldFinalWaitablePromise()
|
||||
{
|
||||
$p1 = new P\Promise(function () use (&$p1) {
|
||||
$p1->resolve('skip me');
|
||||
});
|
||||
$p2 = new P\Promise(function () use (&$p2) {
|
||||
$p2->resolve('hello!');
|
||||
});
|
||||
$co = P\coroutine(function() use ($p1, $p2) {
|
||||
yield $p1;
|
||||
yield $p2;
|
||||
});
|
||||
P\queue()->run();
|
||||
$this->assertEquals('hello!', $co->wait());
|
||||
}
|
||||
|
||||
public function testCanYieldFinalPendingPromise()
|
||||
{
|
||||
$p1 = new P\Promise();
|
||||
$p2 = new P\Promise();
|
||||
$co = P\coroutine(function() use ($p1, $p2) {
|
||||
yield $p1;
|
||||
yield $p2;
|
||||
});
|
||||
$p1->resolve('a');
|
||||
$p2->resolve('b');
|
||||
$co->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals('b', $result);
|
||||
}
|
||||
|
||||
public function testCanNestYieldsAndFailures()
|
||||
{
|
||||
$p1 = new P\Promise();
|
||||
$p2 = new P\Promise();
|
||||
$p3 = new P\Promise();
|
||||
$p4 = new P\Promise();
|
||||
$p5 = new P\Promise();
|
||||
$co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5) {
|
||||
try {
|
||||
yield $p1;
|
||||
} catch (\Exception $e) {
|
||||
yield $p2;
|
||||
try {
|
||||
yield $p3;
|
||||
yield $p4;
|
||||
} catch (\Exception $e) {
|
||||
yield $p5;
|
||||
}
|
||||
}
|
||||
});
|
||||
$p1->reject('a');
|
||||
$p2->resolve('b');
|
||||
$p3->resolve('c');
|
||||
$p4->reject('d');
|
||||
$p5->resolve('e');
|
||||
$co->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals('e', $result);
|
||||
}
|
||||
|
||||
public function testCanYieldErrorsAndSuccessesWithoutRecursion()
|
||||
{
|
||||
$promises = [];
|
||||
for ($i = 0; $i < 20; $i++) {
|
||||
$promises[] = new P\Promise();
|
||||
}
|
||||
|
||||
$co = P\coroutine(function() use ($promises) {
|
||||
for ($i = 0; $i < 20; $i += 4) {
|
||||
try {
|
||||
yield $promises[$i];
|
||||
yield $promises[$i + 1];
|
||||
} catch (\Exception $e) {
|
||||
yield $promises[$i + 2];
|
||||
yield $promises[$i + 3];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for ($i = 0; $i < 20; $i += 4) {
|
||||
$promises[$i]->resolve($i);
|
||||
$promises[$i + 1]->reject($i + 1);
|
||||
$promises[$i + 2]->resolve($i + 2);
|
||||
$promises[$i + 3]->resolve($i + 3);
|
||||
}
|
||||
|
||||
$co->then(function ($value) use (&$result) { $result = $value; });
|
||||
P\queue()->run();
|
||||
$this->assertEquals('19', $result);
|
||||
}
|
||||
|
||||
public function testCanWaitOnPromiseAfterFulfilled()
|
||||
{
|
||||
$f = function () {
|
||||
static $i = 0;
|
||||
$i++;
|
||||
return $p = new P\Promise(function () use (&$p, $i) {
|
||||
$p->resolve($i . '-bar');
|
||||
});
|
||||
};
|
||||
|
||||
$promises = [];
|
||||
for ($i = 0; $i < 20; $i++) {
|
||||
$promises[] = $f();
|
||||
}
|
||||
|
||||
$p = P\coroutine(function () use ($promises) {
|
||||
yield new P\FulfilledPromise('foo!');
|
||||
foreach ($promises as $promise) {
|
||||
yield $promise;
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertEquals('20-bar', $p->wait());
|
||||
}
|
||||
|
||||
public function testCanWaitOnErroredPromises()
|
||||
{
|
||||
$p1 = new P\Promise(function () use (&$p1) { $p1->reject('a'); });
|
||||
$p2 = new P\Promise(function () use (&$p2) { $p2->resolve('b'); });
|
||||
$p3 = new P\Promise(function () use (&$p3) { $p3->resolve('c'); });
|
||||
$p4 = new P\Promise(function () use (&$p4) { $p4->reject('d'); });
|
||||
$p5 = new P\Promise(function () use (&$p5) { $p5->resolve('e'); });
|
||||
$p6 = new P\Promise(function () use (&$p6) { $p6->reject('f'); });
|
||||
|
||||
$co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5, $p6) {
|
||||
try {
|
||||
yield $p1;
|
||||
} catch (\Exception $e) {
|
||||
yield $p2;
|
||||
try {
|
||||
yield $p3;
|
||||
yield $p4;
|
||||
} catch (\Exception $e) {
|
||||
yield $p5;
|
||||
yield $p6;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$res = P\inspect($co);
|
||||
$this->assertEquals('f', $res['reason']);
|
||||
}
|
||||
|
||||
public function testCoroutineOtherwiseIntegrationTest()
|
||||
{
|
||||
$a = new P\Promise();
|
||||
$b = new P\Promise();
|
||||
$promise = P\coroutine(function () use ($a, $b) {
|
||||
// Execute the pool of commands concurrently, and process errors.
|
||||
yield $a;
|
||||
yield $b;
|
||||
})->otherwise(function (\Exception $e) {
|
||||
// Throw errors from the operations as a specific Multipart error.
|
||||
throw new \OutOfBoundsException('a', 0, $e);
|
||||
});
|
||||
$a->resolve('a');
|
||||
$b->reject('b');
|
||||
$reason = P\inspect($promise)['reason'];
|
||||
$this->assertInstanceOf('OutOfBoundsException', $reason);
|
||||
$this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $reason->getPrevious());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue