PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / vendor_prefixed / guzzlehttp / promises / src / Utils.php

Utils.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI trunk, at vendor_prefixed/guzzlehttp/promises/src/Utils.php

250 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace YoastSEO_Vendor\GuzzleHttp\Promise;
5
6 final class Utils
7 {
8 /**
9 * Get the global task queue used for promise resolution.
10 *
11 * This task queue MUST be run in an event loop in order for promises to be
12 * settled asynchronously. It will be automatically run when synchronously
13 * waiting on a promise.
14 *
15 * <code>
16 * while ($eventLoop->isRunning()) {
17 * GuzzleHttp\Promise\Utils::queue()->run();
18 * }
19 * </code>
20 *
21 * @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
22 */
23 public static function queue(?\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface
24 {
25 static $queue;
26 if ($assign) {
27 $queue = $assign;
28 } elseif (!$queue) {
29 $queue = new \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueue();
30 }
31 return $queue;
32 }
33 /**
34 * Adds a function to run in the task queue when it is next `run()` and
35 * returns a promise that is fulfilled or rejected with the result.
36 *
37 * @param callable $task Task function to run.
38 */
39 public static function task(callable $task) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
40 {
41 $queue = self::queue();
42 $promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
43 $queue->add(function () use($task, $promise) : void {
44 try {
45 if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) {
46 $promise->resolve($task());
47 }
48 } catch (\Throwable $e) {
49 $promise->reject($e);
50 }
51 });
52 return $promise;
53 }
54 /**
55 * Synchronously waits on a promise to resolve and returns an inspection
56 * state array.
57 *
58 * Returns a state associative array containing a "state" key mapping to a
59 * valid promise state. If the state of the promise is "fulfilled", the
60 * array will contain a "value" key mapping to the fulfilled value of the
61 * promise. If the promise is rejected, the array will contain a "reason"
62 * key mapping to the rejection reason of the promise.
63 *
64 * @param PromiseInterface $promise Promise or value.
65 */
66 public static function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : array
67 {
68 try {
69 return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $promise->wait()];
70 } catch (\Throwable $e) {
71 if ($e instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\AggregateException) {
72 return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e];
73 }
74 if ($e instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException) {
75 return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()];
76 }
77 return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e];
78 }
79 }
80 /**
81 * Waits on all of the provided promises, but does not unwrap rejected
82 * promises as thrown exception.
83 *
84 * Returns an array of inspection state arrays.
85 *
86 * @see inspect for the inspection state array format.
87 *
88 * @param PromiseInterface[] $promises Traversable of promises to wait upon.
89 */
90 public static function inspectAll($promises) : array
91 {
92 $promises = self::prepareIterable($promises, __FUNCTION__);
93 $results = [];
94 foreach ($promises as $key => $promise) {
95 $results[$key] = self::inspect($promise);
96 }
97 return $results;
98 }
99 /**
100 * Waits on all of the provided promises and returns the fulfilled values.
101 *
102 * Returns an array that contains the value of each promise (in the same
103 * order the promises were provided). An exception is thrown if any of the
104 * promises are rejected.
105 *
106 * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
107 *
108 * @throws \Throwable on error
109 */
110 public static function unwrap($promises) : array
111 {
112 $promises = self::prepareIterable($promises, __FUNCTION__);
113 $results = [];
114 foreach ($promises as $key => $promise) {
115 $results[$key] = $promise->wait();
116 }
117 return $results;
118 }
119 /**
120 * Given an array of promises, return a promise that is fulfilled when all
121 * the items in the array are fulfilled.
122 *
123 * The promise's fulfillment value is an array with fulfillment values at
124 * respective positions to the original array. If any promise in the array
125 * rejects, the returned promise is rejected with the rejection reason.
126 *
127 * @param mixed $promises Promises or values.
128 * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
129 */
130 public static function all($promises, bool $recursive = \false) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
131 {
132 $promises = self::prepareIterable($promises, __FUNCTION__);
133 $results = [];
134 $promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void {
135 $results[$idx] = $value;
136 }, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) : void {
137 if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($aggregate)) {
138 $aggregate->reject($reason);
139 }
140 })->then(function () use(&$results) {
141 \ksort($results);
142 return $results;
143 });
144 if (\true === $recursive) {
145 $promise = $promise->then(function ($results) use($recursive, &$promises) {
146 // A consumed generator cannot be traversed again, so a
147 // recursive pass has nothing further to observe.
148 if ($promises instanceof \Generator) {
149 return $results;
150 }
151 foreach ($promises as $promise) {
152 if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) {
153 return self::all($promises, $recursive);
154 }
155 }
156 return $results;
157 });
158 }
159 return $promise;
160 }
161 /**
162 * Initiate a competitive race between multiple promises or values (values
163 * will become immediately fulfilled promises).
164 *
165 * When count amount of promises have been fulfilled, the returned promise
166 * is fulfilled with an array that contains the fulfillment values of the
167 * winners in order of resolution.
168 *
169 * This promise is rejected with a {@see AggregateException} if the number
170 * of fulfilled promises is less than the desired $count.
171 *
172 * @param int $count Total number of promises.
173 * @param mixed $promises Promises or values.
174 */
175 public static function some(int $count, $promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
176 {
177 $promises = self::prepareIterable($promises, __FUNCTION__);
178 $results = [];
179 $rejections = [];
180 return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) : void {
181 if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($p)) {
182 return;
183 }
184 $results[$idx] = $value;
185 if (\count($results) >= $count) {
186 $p->resolve(null);
187 }
188 }, function ($reason) use(&$rejections) : void {
189 $rejections[] = $reason;
190 })->then(function () use(&$results, &$rejections, $count) {
191 if (\count($results) !== $count) {
192 throw new \YoastSEO_Vendor\GuzzleHttp\Promise\AggregateException('Not enough promises to fulfill count', $rejections);
193 }
194 \ksort($results);
195 return \array_values($results);
196 });
197 }
198 /**
199 * Like some(), with 1 as count. However, if the promise fulfills, the
200 * fulfillment value is not an array of 1 but the value directly.
201 *
202 * @param mixed $promises Promises or values.
203 */
204 public static function any($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
205 {
206 $promises = self::prepareIterable($promises, __FUNCTION__);
207 return self::some(1, $promises)->then(function ($values) {
208 return $values[0];
209 });
210 }
211 /**
212 * Returns a promise that is fulfilled when all of the provided promises have
213 * been fulfilled or rejected.
214 *
215 * The returned promise is fulfilled with an array of inspection state arrays.
216 *
217 * @see inspect for the inspection state array format.
218 *
219 * @param mixed $promises Promises or values.
220 */
221 public static function settle($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
222 {
223 $promises = self::prepareIterable($promises, __FUNCTION__);
224 $results = [];
225 return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void {
226 $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $value];
227 }, function ($reason, $idx) use(&$results) : void {
228 $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $reason];
229 })->then(function () use(&$results) {
230 \ksort($results);
231 return $results;
232 });
233 }
234 private static function prepareIterable($promises, string $method) : iterable
235 {
236 if (\is_iterable($promises)) {
237 return $promises;
238 }
239 self::triggerNonIterableDeprecation($promises, $method);
240 return [$promises];
241 }
242 private static function triggerNonIterableDeprecation($promises, string $method) : void
243 {
244 if (\is_iterable($promises)) {
245 return;
246 }
247 \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/promises', '2.5', 'Passing a non-iterable to %s::%s() is deprecated; guzzlehttp/promises 3.0 will require an iterable.', self::class, $method);
248 }
249 }
250