Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
69 / 69 |
|
100.00% |
26 / 26 |
CRAP | |
100.00% |
1 / 1 |
AbstractPromise | |
100.00% |
69 / 69 |
|
100.00% |
26 / 26 |
54 | |
100.00% |
1 / 1 |
setPromiser | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getPromiser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasPromiser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setSuccess | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
getSuccess | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
hasSuccess | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
setFailure | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
getFailure | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasFailure | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setCancel | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
getCancel | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasCancel | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setFinally | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
getFinally | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasFinally | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setState | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
5 | |||
getState | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasState | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isPending | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isFulfilled | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isRejected | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isCancelled | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
then | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
catch | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
finally | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
forward | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
wait | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
resolve | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
cancel | n/a |
0 / 0 |
n/a |
0 / 0 |
0 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Http\Promise; |
15 | |
16 | use Pop\Http\Client; |
17 | use Pop\Http\Client\Response; |
18 | use Pop\Http\Client\Handler\CurlMulti; |
19 | use Pop\Utils\CallableObject; |
20 | |
21 | /** |
22 | * Abstract HTTP promise class |
23 | * |
24 | * @category Pop |
25 | * @package Pop\Http |
26 | * @author Nick Sagona, III <dev@nolainteractive.com> |
27 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
28 | * @license http://www.popphp.org/license New BSD License |
29 | * @version 5.2.0 |
30 | */ |
31 | abstract class AbstractPromise implements PromiseInterface |
32 | { |
33 | |
34 | /** |
35 | * Status constants |
36 | * @var string |
37 | */ |
38 | const PENDING = 'PENDING'; |
39 | const FULFILLED = 'FULFILLED'; |
40 | const REJECTED = 'REJECTED'; |
41 | const CANCELLED = 'CANCELLED'; |
42 | |
43 | /** |
44 | * Client Promiser |
45 | * @var Client|CurlMulti|null |
46 | */ |
47 | protected Client|CurlMulti|null $promiser = null; |
48 | |
49 | /** |
50 | * Success callables |
51 | * @var array |
52 | */ |
53 | protected array $success = []; |
54 | |
55 | /** |
56 | * Failure callable |
57 | * @var ?CallableObject |
58 | */ |
59 | protected ?CallableObject $failure = null; |
60 | |
61 | /** |
62 | * Cancel callable |
63 | * @var ?CallableObject |
64 | */ |
65 | protected ?CallableObject $cancel = null; |
66 | |
67 | /** |
68 | * Cancel callable |
69 | * @var ?CallableObject |
70 | */ |
71 | protected ?CallableObject $finally = null; |
72 | |
73 | /** |
74 | * Current state |
75 | * @var string |
76 | */ |
77 | protected string $state = self::PENDING; |
78 | |
79 | /** |
80 | * Method to set client promiser |
81 | * |
82 | * @param Client|CurlMulti $promiser |
83 | * @return PromiseInterface |
84 | */ |
85 | public function setPromiser(Client|CurlMulti $promiser): AbstractPromise |
86 | { |
87 | $this->promiser = $promiser; |
88 | return $this; |
89 | } |
90 | |
91 | /** |
92 | * Method to get client promiser |
93 | * |
94 | * @return Client|CurlMulti |
95 | */ |
96 | public function getPromiser(): Client|CurlMulti |
97 | { |
98 | return $this->promiser; |
99 | } |
100 | |
101 | /** |
102 | * Method to check client promiser |
103 | * |
104 | * @return bool |
105 | */ |
106 | public function hasPromiser(): bool |
107 | { |
108 | return ($this->promiser !== null); |
109 | } |
110 | |
111 | /** |
112 | * Method to set success callable |
113 | * |
114 | * @param mixed $success |
115 | * @throws Exception |
116 | * @return AbstractPromise |
117 | */ |
118 | public function setSuccess(mixed $success): AbstractPromise |
119 | { |
120 | if (!($success instanceof CallableObject) && !is_callable($success)) { |
121 | throw new Exception('Error: The success callback must be an instance of CallableObject or a callable'); |
122 | } |
123 | if (!($success instanceof CallableObject) && is_callable($success)) { |
124 | $success = new CallableObject($success); |
125 | } |
126 | |
127 | $this->success[] = $success; |
128 | return $this; |
129 | } |
130 | |
131 | /** |
132 | * Method to get success callable |
133 | * |
134 | * @param ?int $i |
135 | * @return array|CallableObject|null |
136 | */ |
137 | public function getSuccess(?int $i = null): array|CallableObject|null |
138 | { |
139 | if ($i !== null) { |
140 | return $this->success[$i] ?? null; |
141 | } else { |
142 | return $this->success; |
143 | } |
144 | } |
145 | |
146 | /** |
147 | * Method to check success callable |
148 | * |
149 | * @param ?int $i |
150 | * @return bool |
151 | */ |
152 | public function hasSuccess(?int $i = null): bool |
153 | { |
154 | if ($i !== null) { |
155 | return (isset($this->success[$i])); |
156 | } else { |
157 | return (!empty($this->success)); |
158 | } |
159 | } |
160 | |
161 | /** |
162 | * Method to set failure callable |
163 | * |
164 | * @param mixed $failure |
165 | * @return AbstractPromise |
166 | */ |
167 | public function setFailure(mixed $failure): AbstractPromise |
168 | { |
169 | if (!($failure instanceof CallableObject) && !is_callable($failure)) { |
170 | throw new Exception('Error: The failure callback must be an instance of CallableObject or a callable'); |
171 | } |
172 | if (!($failure instanceof CallableObject) && is_callable($failure)) { |
173 | $failure = new CallableObject($failure); |
174 | } |
175 | |
176 | $this->failure = $failure; |
177 | return $this; |
178 | } |
179 | |
180 | /** |
181 | * Method to get failure callable |
182 | * |
183 | * @return CallableObject|null |
184 | */ |
185 | public function getFailure(): CallableObject|null |
186 | { |
187 | return $this->failure; |
188 | } |
189 | |
190 | /** |
191 | * Method to check failure callable |
192 | * |
193 | * @return bool |
194 | */ |
195 | public function hasFailure(): bool |
196 | { |
197 | return ($this->failure !== null); |
198 | } |
199 | |
200 | /** |
201 | * Method to set cancel callable |
202 | * |
203 | * @param mixed $cancel |
204 | * @return AbstractPromise |
205 | */ |
206 | public function setCancel(mixed $cancel): AbstractPromise |
207 | { |
208 | if (!($cancel instanceof CallableObject) && !is_callable($cancel)) { |
209 | throw new Exception('Error: The cancel callback must be an instance of CallableObject or a callable'); |
210 | } |
211 | if (!($cancel instanceof CallableObject) && is_callable($cancel)) { |
212 | $cancel = new CallableObject($cancel); |
213 | } |
214 | |
215 | $this->cancel = $cancel; |
216 | return $this; |
217 | } |
218 | |
219 | /** |
220 | * Method to get cancel callable |
221 | * |
222 | * @return CallableObject|null |
223 | */ |
224 | public function getCancel(): CallableObject|null |
225 | { |
226 | return $this->cancel; |
227 | } |
228 | |
229 | /** |
230 | * Method to check cancel callable |
231 | * |
232 | * @return bool |
233 | */ |
234 | public function hasCancel(): bool |
235 | { |
236 | return ($this->cancel !== null); |
237 | } |
238 | |
239 | /** |
240 | * Method to set finally callable |
241 | * |
242 | * @param mixed $finally |
243 | * @return PromiseInterface |
244 | */ |
245 | public function setFinally(mixed $finally): AbstractPromise |
246 | { |
247 | if (!($finally instanceof CallableObject) && !is_callable($finally)) { |
248 | throw new Exception('Error: The cancel callback must be an instance of CallableObject or a callable'); |
249 | } |
250 | if (!($finally instanceof CallableObject) && is_callable($finally)) { |
251 | $finally = new CallableObject($finally); |
252 | } |
253 | |
254 | $this->finally = $finally; |
255 | return $this; |
256 | } |
257 | |
258 | /** |
259 | * Method to get finally callable |
260 | * |
261 | * @return CallableObject|null |
262 | */ |
263 | public function getFinally(): CallableObject|null |
264 | { |
265 | return $this->finally; |
266 | } |
267 | |
268 | /** |
269 | * Method to check finally callable |
270 | * |
271 | * @return bool |
272 | */ |
273 | public function hasFinally(): bool |
274 | { |
275 | return ($this->finally !== null); |
276 | } |
277 | |
278 | /** |
279 | * Method to set current state |
280 | * |
281 | * @param string $state |
282 | * @throws Exception |
283 | * @return AbstractPromise |
284 | */ |
285 | public function setState(string $state): AbstractPromise |
286 | { |
287 | if (($state !== static::PENDING) && ($state !== static::FULFILLED) && ($state !== static::REJECTED) && ($state !== static::CANCELLED)) { |
288 | throw new Exception('Error: That state is not allowed.'); |
289 | } |
290 | $this->state = $state; |
291 | return $this; |
292 | } |
293 | |
294 | /** |
295 | * Method to get current state |
296 | * |
297 | * @return string |
298 | */ |
299 | public function getState(): string |
300 | { |
301 | return $this->state; |
302 | } |
303 | |
304 | /** |
305 | * Method to check current state |
306 | * |
307 | * @return bool |
308 | */ |
309 | public function hasState(): bool |
310 | { |
311 | return ($this->state !== null); |
312 | } |
313 | |
314 | /** |
315 | * Determine is the promise is pending |
316 | * |
317 | * @return bool |
318 | */ |
319 | public function isPending(): bool |
320 | { |
321 | return ($this->state == static::PENDING); |
322 | } |
323 | |
324 | /** |
325 | * Determine is the promise is fulfilled |
326 | * |
327 | * @return bool |
328 | */ |
329 | public function isFulfilled(): bool |
330 | { |
331 | return ($this->state == static::FULFILLED); |
332 | } |
333 | |
334 | /** |
335 | * Determine is the promise is rejected |
336 | * |
337 | * @return bool |
338 | */ |
339 | public function isRejected(): bool |
340 | { |
341 | return ($this->state == static::REJECTED); |
342 | } |
343 | |
344 | /** |
345 | * Determine is the promise is cancelled |
346 | * |
347 | * @return bool |
348 | */ |
349 | public function isCancelled(): bool |
350 | { |
351 | return ($this->state == static::CANCELLED); |
352 | } |
353 | |
354 | /** |
355 | * Then method |
356 | * |
357 | * @param mixed $success |
358 | * @param bool $resolve |
359 | * @return AbstractPromise |
360 | */ |
361 | public function then(mixed $success, bool $resolve = false): AbstractPromise |
362 | { |
363 | $this->setSuccess($success); |
364 | |
365 | if ($resolve) { |
366 | $this->resolve(); |
367 | } |
368 | |
369 | return $this; |
370 | } |
371 | |
372 | /** |
373 | * Method to set failure callable (alias) |
374 | * |
375 | * @param mixed $failure |
376 | * @param bool $resolve |
377 | * @return AbstractPromise |
378 | */ |
379 | public function catch(mixed $failure, bool $resolve = false): AbstractPromise |
380 | { |
381 | $this->setFailure($failure); |
382 | |
383 | if ($resolve) { |
384 | $this->resolve(); |
385 | } |
386 | |
387 | return $this; |
388 | } |
389 | |
390 | /** |
391 | * Method to set finally callable (alias) |
392 | * |
393 | * @param mixed $finally |
394 | * @return AbstractPromise |
395 | */ |
396 | public function finally(mixed $finally, bool $resolve = false): AbstractPromise |
397 | { |
398 | $this->setFinally($finally); |
399 | |
400 | if ($resolve) { |
401 | $this->resolve(); |
402 | } |
403 | |
404 | return $this; |
405 | } |
406 | |
407 | /** |
408 | * Forward method |
409 | * |
410 | * @param PromiseInterface $nextPromise |
411 | * @param int $i |
412 | * @return AbstractPromise |
413 | */ |
414 | public function forward(PromiseInterface $nextPromise, int $i = 0): AbstractPromise |
415 | { |
416 | for ($j = $i; $j < count($this->success); $j++) { |
417 | $nextPromise->then($this->success[$j]); |
418 | } |
419 | if ($this->hasFailure()) { |
420 | $nextPromise->setFailure($this->failure); |
421 | } |
422 | if ($this->hasCancel()) { |
423 | $nextPromise->setCancel($this->cancel); |
424 | } |
425 | |
426 | return $nextPromise; |
427 | } |
428 | |
429 | /** |
430 | * Wait method |
431 | * |
432 | * @param bool $unwrap |
433 | * @return Response|array|null |
434 | */ |
435 | abstract public function wait(bool $unwrap = true): Response|array|null; |
436 | |
437 | /** |
438 | * Resolve method |
439 | * |
440 | * @return void |
441 | */ |
442 | abstract public function resolve(): void; |
443 | |
444 | /** |
445 | * Cancel method |
446 | * |
447 | * @return void |
448 | */ |
449 | abstract public function cancel(): void; |
450 | |
451 | } |