1<?php 2 3declare(strict_types=1); 4 5namespace GuzzleHttp\Promise; 6 7/** 8 * A promise that has been rejected. 9 * 10 * Thenning off of this promise will invoke the onRejected callback 11 * immediately and ignore other callbacks. 12 * 13 * @final 14 */ 15class RejectedPromise implements PromiseInterface 16{ 17 private $reason; 18 19 /** 20 * @param mixed $reason 21 */ 22 public function __construct($reason) 23 { 24 if (is_object($reason) && method_exists($reason, 'then')) { 25 throw new \InvalidArgumentException( 26 'You cannot create a RejectedPromise with a promise.' 27 ); 28 } 29 30 $this->reason = $reason; 31 } 32 33 public function then( 34 callable $onFulfilled = null, 35 callable $onRejected = null 36 ): PromiseInterface { 37 // If there's no onRejected callback then just return self. 38 if (!$onRejected) { 39 return $this; 40 } 41 42 $queue = Utils::queue(); 43 $reason = $this->reason; 44 $p = new Promise([$queue, 'run']); 45 $queue->add(static function () use ($p, $reason, $onRejected): void { 46 if (Is::pending($p)) { 47 try { 48 // Return a resolved promise if onRejected does not throw. 49 $p->resolve($onRejected($reason)); 50 } catch (\Throwable $e) { 51 // onRejected threw, so return a rejected promise. 52 $p->reject($e); 53 } 54 } 55 }); 56 57 return $p; 58 } 59 60 public function otherwise(callable $onRejected): PromiseInterface 61 { 62 return $this->then(null, $onRejected); 63 } 64 65 public function wait(bool $unwrap = true) 66 { 67 if ($unwrap) { 68 throw Create::exceptionFor($this->reason); 69 } 70 71 return null; 72 } 73 74 public function getState(): string 75 { 76 return self::REJECTED; 77 } 78 79 public function resolve($value): void 80 { 81 throw new \LogicException('Cannot resolve a rejected promise'); 82 } 83 84 public function reject($reason): void 85 { 86 if ($reason !== $this->reason) { 87 throw new \LogicException('Cannot reject a rejected promise'); 88 } 89 } 90 91 public function cancel(): void 92 { 93 // pass 94 } 95} 96