[Web] Update composer libraries

This commit is contained in:
FreddleSpl0it committed 2026-10-28 11:56:29 +01:00
1 parent 9cc8ac2908
commit bd8c784118
1297 files changed
+71585 -24460

No files matched your search

@@ -0,0 +1,72 @@
# Implementation Notes
This document describes implementation details that explain observable behavior
in `guzzlehttp/promises`, especially queue-based callback execution, iterative
resolution, and why `Promise` also acts as the deferred value. Application code
usually only needs the [Promise Quick Start](promise-quick-start.md) and
[Promise API](promise-api.md).
## Iterative Resolution and Chaining
Promises are resolved iteratively by moving pending handlers between promises.
This keeps stack size constant even for very long `then()` chains.
```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.
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
takes ownership of each child promise's handlers and delivers values down the
chain without 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 pending handlers receive 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. That separation prevents consumers from modifying the value
that will eventually be delivered.
Iterative resolution requires one promise to move handlers from another promise.
To do that without making handlers publicly mutable, `Promise` is also the
deferred value. Promises of the same class can modify each other's private
state, including handler ownership. This means a consumer that receives a
`Promise` can also resolve or reject it, but it keeps chaining efficient and
stack safe.
```php
$promise = new Promise();
$promise->then(function ($value) { echo $value; });
// The promise is the deferred value, so you can deliver a value to it.
$promise->resolve('foo');
GuzzleHttp\Promise\Utils::queue()->run();
// Prints "foo"
```
## Related
- [Quick Start](promise-quick-start.md)
- [Promise API](promise-api.md)
- [Promise Interoperability](promise-interoperability.md)
@@ -0,0 +1,177 @@
# Promise API
This reference summarizes the public API provided by `guzzlehttp/promises`.
Promise APIs are documented for static analysis as
`PromiseInterface<TValue, TReason>`. `TValue` is the fulfillment value type and
`TReason` is the rejection reason type. This typing is PHPDoc-only and does not
change runtime behavior.
Callbacks registered with `then()` are queued. They are invoked when the global
task queue runs, when a returned promise is waited on, or when the queue is
drained by the default shutdown handler.
## PromiseInterface and Promise
`PromiseInterface` defines the common promise contract and the states
`pending`, `fulfilled`, and `rejected`.
When creating a `Promise`, you can provide an optional `$waitFn` and
`$cancelFn`. `$waitFn` receives a boolean argument and is expected to resolve or
reject the promise. `$cancelFn` receives no arguments and is invoked when
`cancel()` is called.
```php
use GuzzleHttp\Promise\Promise;
$promise = new Promise(
function (bool $recursive) use (&$promise) {
$promise->resolve('waited');
},
function () {
// Cancel the underlying operation, such as closing a socket.
}
);
assert('waited' === $promise->wait());
```
A promise has the following methods:
- `then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface` appends fulfillment and rejection handlers and returns a new promise resolving to the return value of the called handler. If a handler is omitted, the original fulfillment value or rejection reason is forwarded.
- `otherwise(callable $onRejected) : PromiseInterface` appends a rejection handler and returns a new promise resolving to the callback result if called, or to the original fulfillment value if the promise is fulfilled.
- `wait(bool $unwrap = true) : mixed` synchronously waits on the promise. When `$unwrap` is `true`, fulfilled values are returned and rejected reasons are thrown. When `$unwrap` is `false`, the promise is settled without returning or throwing its result.
- `cancel() : void` attempts to cancel the promise and dependent promises.
- `getState() : string` returns `pending`, `fulfilled`, or `rejected`.
- `resolve($value = null) : void` fulfills the promise with `$value`, or with `null` if no value is given.
- `reject($reason) : void` rejects the promise with `$reason`.
## Settled Promises
`FulfilledPromise` represents an already fulfilled promise. Fulfillment
callbacks are still queued and run when the task queue runs or the returned
promise is waited on.
```php
use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Promise\Utils;
$promise = new FulfilledPromise('value');
$promise->then(function ($value) {
echo $value;
});
Utils::queue()->run();
```
`RejectedPromise` represents an already rejected promise. Rejection callbacks
are also queued and run when the queue is drained or the returned promise is
waited on.
```php
use GuzzleHttp\Promise\RejectedPromise;
use GuzzleHttp\Promise\Utils;
$promise = new RejectedPromise('Error');
$promise->then(null, function ($reason) {
echo $reason;
});
Utils::queue()->run();
```
## Utils
`GuzzleHttp\Promise\Utils` provides helpers for inspecting, aggregating, and
queuing promise work.
- `Utils::queue(?TaskQueueInterface $assign = null) : TaskQueueInterface` returns the global task queue, or assigns a replacement queue when `$assign` is provided.
- `Utils::task(callable $task) : PromiseInterface` adds a task to the global queue and returns a promise that is fulfilled or rejected with the task result.
- `Utils::inspect(PromiseInterface $promise) : array` waits for one promise to settle and returns an inspection array with `state` and either `value` or `reason`.
- `Utils::inspectAll(iterable $promises) : array` inspects each promise and returns inspection arrays keyed like the input iterable.
- `Utils::unwrap(iterable $promises) : array` waits on all promises and returns fulfilled values, throwing if any promise rejects.
- `Utils::all(iterable $promises, bool $recursive = false, array $config = []) : PromiseInterface` returns a promise fulfilled with all values, or rejected when any input rejects.
- `Utils::settle(iterable $promises, bool $recursive = false, array $config = []) : PromiseInterface` returns a promise fulfilled with inspection arrays after all inputs settle.
- `Utils::some(int $count, iterable $promises) : PromiseInterface` fulfills with the values of the first `$count` promises to fulfill, in the order they appear in the input, or rejects with `AggregateException` if too few fulfill.
- `Utils::any(iterable $promises) : PromiseInterface` fulfills with the first fulfilled value, or rejects with `AggregateException` if none fulfill.
`Utils::all()` and `Utils::settle()` accept `['concurrency' => 5]` or
`['concurrency' => callable]` for lazy iterables. This limits how many items are
pulled from the iterable at one time; it does not throttle promises that have
already been created or started.
```php
use GuzzleHttp\Promise\Utils;
$promise = Utils::all($promises, false, ['concurrency' => 5]);
```
## Create
`GuzzleHttp\Promise\Create` provides factories used by the promise
implementation and by callers that need to normalize values.
- `Create::promiseFor($value) : PromiseInterface` returns `$value` when it is already a Guzzle promise, wraps foreign thenables in a Guzzle promise, or returns a fulfilled promise for plain values.
- `Create::rejectionFor($reason) : PromiseInterface` returns `$reason` when it is already a promise, or returns a rejected promise for plain reasons.
- `Create::exceptionFor($reason) : Throwable` returns throwable reasons as-is, or wraps non-throwable reasons in `RejectionException`.
- `Create::iterFor(iterable $value) : Iterator` returns an iterator for arrays, iterators, iterator aggregates, and traversables.
## State
`GuzzleHttp\Promise\State` provides readable state checks:
- `State::isPending(PromiseInterface $promise) : bool`
- `State::isSettled(PromiseInterface $promise) : bool`
- `State::isFulfilled(PromiseInterface $promise) : bool`
- `State::isRejected(PromiseInterface $promise) : bool`
`GuzzleHttp\Promise\Is` is deprecated because PHP 8.6 deprecates `is` as a class
name, and will be removed in Guzzle Promises 4.0. Replace `Is::pending()`,
`Is::settled()`, `Is::fulfilled()`, and `Is::rejected()` with the matching
`State` methods.
## Each and EachPromise
`Each::of()` consumes an iterable of promises or values and invokes callbacks as
items settle. Fulfillment callbacks receive the fulfilled value, iterable key,
and aggregate promise. Rejection callbacks receive the rejection reason,
iterable key, and aggregate promise. Callback return values are ignored.
```php
use GuzzleHttp\Promise\Each;
$promise = Each::of($promises, $onFulfilled, $onRejected, ['concurrency' => 5]);
```
- `Each::of(iterable $iterable, ?callable $onFulfilled = null, ?callable $onRejected = null, array $config = []) : PromiseInterface` consumes the iterable and optionally limits lazy iteration with `concurrency`.
- `Each::ofLimit(iterable $iterable, $concurrency, ?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface` is a convenience wrapper for `Each::of()` with a concurrency limit.
- `Each::ofLimitAll(iterable $iterable, $concurrency, ?callable $onFulfilled = null) : PromiseInterface` is like `ofLimit()`, but rejects the aggregate promise on the first rejection.
- `EachPromise` is the configurable class behind `Each`; use it directly when you need `fulfilled`, `rejected`, and `concurrency` keys in one configuration array.
The concurrency options limit lazy promise creation. For HTTP request
concurrency, use `GuzzleHttp\Pool` from `guzzlehttp/guzzle`.
## Coroutine
`Coroutine::of(callable $generatorFn) : Coroutine` creates a promise resolved by
a generator that yields values or promises. The generator resumes with each
fulfilled value, and rejections are thrown into the generator.
## Task Queue
`TaskQueueInterface` exposes `isEmpty()`, `add(callable $task)`, and `run()`.
`TaskQueue` executes queued tasks in FIFO order. The default queue runs at
process shutdown unless disabled, and `wait()` drains the queue while resolving
the promise being waited on.
## Exceptions
- `RejectionException` is thrown by `wait()` when a rejected promise has a non-throwable reason. The original reason is available through `getReason()`.
- `AggregateException` extends `RejectionException` and is used by `Utils::some()` and `Utils::any()` when too few promises fulfill.
- `CancellationException` extends `RejectionException` and is used as the rejection reason for cancelled promises.
## Related
- [Quick Start](promise-quick-start.md)
- [Promise Interoperability](promise-interoperability.md)
- [Implementation Notes](implementation-notes.md)
- [Upgrade Guide](../UPGRADING.md)
@@ -0,0 +1,78 @@
# Promise Interoperability
This guide explains how Guzzle promises interact with foreign promise
implementations. A foreign promise is any object with a `then` method, such as a
[React promise](https://github.com/reactphp/promise). When a foreign promise is
returned from a `then` callback, Guzzle forwards resolution to that promise.
## Foreign Promises
Capture the promise returned from `then()`. That chained promise is the Guzzle
promise that follows the foreign promise's eventual result.
```php
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\Utils;
$deferred = new React\Promise\Deferred();
$reactPromise = $deferred->promise();
$guzzlePromise = new Promise();
$chained = $guzzlePromise->then(function ($value) use ($reactPromise) {
// Use the Guzzle value, then continue with the React promise.
return $reactPromise;
});
$chained->then(function ($value) {
echo $value;
});
$guzzlePromise->resolve('start');
Utils::queue()->run();
$deferred->resolve('done');
Utils::queue()->run();
```
Forwarding a foreign promise does not make Guzzle able to synchronously wait on
or cancel the foreign operation. The chained Guzzle promise settles only after
the foreign implementation invokes the callbacks registered through `then()`.
If the foreign promise has no compatible `wait()` or `cancel()` behavior, Guzzle
cannot invent that behavior.
Use `Create::promiseFor($foreignPromise)` to shadow a foreign thenable as a
Guzzle promise. If the foreign object exposes `wait()` or `cancel()` methods,
the wrapper uses them. Otherwise, use the foreign implementation's event loop or
completion mechanism and drain Guzzle's task queue when callbacks need to run.
## Event Loop Integration
Guzzle promises use a task queue to keep stack size constant and to run promise
callbacks asynchronously. When waiting on promises synchronously, the task queue
is automatically run while resolving the blocking promise and forwarded Guzzle
promises.
When using promises asynchronously in an event loop, run the task queue on loop
ticks. If you do not run the task queue, Guzzle promise callbacks may remain
queued.
```php
$queue = GuzzleHttp\Promise\Utils::queue();
$queue->run();
```
For example, you could use Guzzle promises with React using a short periodic
timer. Avoid zero-interval timers because they may keep the loop busy even when
there is no promise work to run.
```php
$queue = GuzzleHttp\Promise\Utils::queue();
$loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(0.01, [$queue, 'run']);
```
## Related
- [Quick Start](promise-quick-start.md)
- [Promise API](promise-api.md)
- [Implementation Notes](implementation-notes.md)
@@ -0,0 +1,319 @@
# Promise Quick Start
This guide covers the common promise operations needed when using
`guzzlehttp/promises` directly: registering callbacks, resolving or rejecting
promises, waiting synchronously, composing chains, and using generator-based
flows. For the full public surface, see the [Promise API](promise-api.md).
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 the eventual value or the reason why the
promise cannot be fulfilled.
Guzzle promise callbacks are queued. They run when the task queue is drained,
for example by `Utils::queue()->run()`, by waiting on a returned promise, or by
the default shutdown handler at the end of the PHP process. Examples that show
callback output drain the queue explicitly.
## 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*. Callbacks registered with `then` are invoked
only once and in the order in which they were added when the queue is drained.
## Resolving a Promise
Promises are fulfilled using the `resolve($value = null)` method. Calling
`resolve()` without an argument fulfills the promise with `null`. Resolving a
promise with any value other than a `GuzzleHttp\Promise\RejectedPromise` queues
the `$onFulfilled` callbacks. Resolving with a rejected promise rejects the
promise and queues the `$onRejected` callbacks.
```php
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\Utils;
$promise = new Promise();
$promise
->then(function ($value) {
return 'Hello, ' . $value;
})
->then(function ($value) {
echo $value;
});
$promise->resolve('reader.');
Utils::queue()->run();
// Outputs "Hello, reader."
```
## Promise Forwarding
Promises can be chained one after the other. Each `then` call returns a new
promise. The return value of a callback is forwarded to the next promise in the
chain. Returning a promise from a callback makes the next promise wait for that
returned promise to settle.
```php
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\Utils;
$promise = new Promise();
$nextPromise = new Promise();
$promise
->then(function ($value) use ($nextPromise) {
echo $value;
return $nextPromise;
})
->then(function ($value) {
echo $value;
});
$promise->resolve('A');
Utils::queue()->run();
// Outputs "A"
$nextPromise->resolve('B');
Utils::queue()->run();
// Outputs "B"
```
## Promise Rejection
When a promise is rejected, the `$onRejected` callbacks are invoked with the
rejection reason when the queue is drained.
```php
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\Utils;
$promise = new Promise();
$promise->then(null, function ($reason) {
echo $reason;
});
$promise->reject('Error!');
Utils::queue()->run();
// Outputs "Error!"
```
## Rejection Forwarding
If an exception is thrown in an `$onRejected` callback, subsequent
`$onRejected` callbacks receive the thrown exception as the reason.
```php
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\Utils;
$promise = new Promise();
$promise->then(null, function ($reason) {
throw new Exception($reason);
})->then(null, function ($reason) {
assert($reason->getMessage() === 'Error!');
});
$promise->reject('Error!');
Utils::queue()->run();
```
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;
use GuzzleHttp\Promise\Utils;
$promise = new Promise();
$promise->then(null, function ($reason) {
return new RejectedPromise($reason);
})->then(null, function ($reason) {
assert($reason === 'Error!');
});
$promise->reject('Error!');
Utils::queue()->run();
```
If an exception is not thrown in an `$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\Utils;
$promise = new Promise();
$promise
->then(null, function ($reason) {
return "It's ok";
})
->then(function ($value) {
assert($value === "It's ok");
});
$promise->reject('Error!');
Utils::queue()->run();
```
## 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 complete the promise. The wait function receives a boolean
argument and is expected to resolve or reject the promise. If the wait function
does not settle the promise, an exception is thrown.
```php
use GuzzleHttp\Promise\Promise;
$promise = new Promise(function (bool $recursive) use (&$promise) {
$promise->resolve('foo');
});
echo $promise->wait();
// Outputs "foo"
```
If a throwable is encountered while invoking the wait function of a promise,
the promise is rejected with the throwable and the throwable is thrown.
```php
$promise = new Promise(function (bool $recursive) use (&$promise) {
throw new Exception('foo');
});
$promise->wait(); // Throws the exception.
```
Calling `wait` on a promise that has been fulfilled will not trigger the wait
function. It will simply return the previously resolved value.
```php
$promise = new Promise(function (bool $recursive) { die('this is not called!'); });
$promise->resolve('foo');
echo $promise->wait();
// Outputs "foo"
```
Calling `wait` on a promise that has been rejected will throw. If the rejection
reason is an instance of `\Throwable`, the reason is thrown. Otherwise, a
`GuzzleHttp\Promise\RejectionException` is thrown and the reason can be
obtained by calling `getReason()` on 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 reason: foo'
## Unwrapping a Promise
When synchronously waiting on a promise, you are joining the state of the
promise into the current execution: the fulfilled value is returned, or the
rejection reason is thrown. This is called "unwrapping" the promise. Waiting on
a promise unwraps by default.
You can force a promise to resolve and *not* unwrap its state by passing
`false` to `wait()`:
```php
$promise = new Promise();
$promise->reject('foo');
// This does not throw. It only ensures the promise has been resolved.
$promise->wait(false);
```
When unwrapping a promise, the resolved value of the promise will be waited on
until the unwrapped value is not a promise. This means that if promise A is
resolved with promise B, unwrapping promise A returns the value delivered to
promise B.
When you do not unwrap the promise, no value is returned.
## Inspecting a Promise
`Utils::inspect($promise)` waits for a promise to settle and returns an array
describing its final state. For rejected promises, the `reason` entry is the
actual rejection reason delivered to rejection callbacks.
This means `RejectionException` and subclasses are not unwrapped by
`inspect()`. For example, cancelled promises inspect with a
`CancellationException` reason.
## Generator-Based Async
`Coroutine::of()` creates a promise from a generator that yields values or
promises. The generator resumes each time the yielded value settles, which can
make sequential asynchronous flows easier to read.
```php
use GuzzleHttp\Promise\Coroutine;
use GuzzleHttp\Promise\FulfilledPromise;
$promise = Coroutine::of(function () {
$first = yield new FulfilledPromise('A');
$second = yield new FulfilledPromise($first . 'B');
yield $second . 'C';
});
echo $promise->wait();
// Outputs "ABC"
```
If a yielded promise rejects, the rejection is thrown into the generator. Catch
it inside the generator to recover, or let it reject the coroutine promise.
## Cancellation
You can cancel a promise that has not yet been fulfilled using `cancel()`. When
creating a promise, you can provide an optional cancel function that cancels the
underlying operation, such as closing a socket or aborting a query.
```php
use GuzzleHttp\Promise\Promise;
$promise = new Promise(null, function () {
// Cancel the underlying operation.
});
$promise->cancel();
```
Cancellation rejects the promise with a `CancellationException` unless the
cancel function settles the promise first.
## Related
- [Promise API](promise-api.md)
- [Promise Interoperability](promise-interoperability.md)
- [Implementation Notes](implementation-notes.md)
- [Upgrade Guide](../UPGRADING.md)