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