PluginProbe
Depicter — Popup & Slider Builder / trunk
Depicter — Popup & Slider Builder vtrunk
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / modules / GuzzleHttp / Promise / Utils.php

Utils.php in Depicter — Popup & Slider Builder trunk, at modules/GuzzleHttp/Promise/Utils.php

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