Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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