Completed
Pull Request — master (#42)
by Stéphane
07:54
created

Promise::reject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 10
ccs 6
cts 7
cp 0.8571
crap 2.0116
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace Http\Adapter\React;
4
5
use Http\Client\Exception as HttplugException;
6
use Http\Promise\Promise as HttpPromise;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use React\EventLoop\LoopInterface;
10
use React\Promise\PromiseInterface;
11
use RuntimeException;
12
use UnexpectedValueException;
13
14
/**
15
 * React promise adapter implementation.
16
 *
17
 * @author Stéphane Hulard <[email protected]>
18
 *
19
 * @internal
20
 */
21
final class Promise implements HttpPromise
22
{
23
    /**
24
     * Promise status.
25
     *
26
     * @var string
27
     */
28
    private $state = HttpPromise::PENDING;
29
30
    /**
31
     * PSR7 received response.
32
     *
33
     * @var ResponseInterface
34
     */
35
    private $response;
36
37
    /**
38
     * Execution error.
39
     *
40
     * @var Exception
41
     */
42
    private $exception;
43
44
    /**
45
     * HTTP Request
46
     *
47
     * @var RequestInterface
48
     */
49
    private $request;
50
51
    /**
52
     * Adapted ReactPHP promise
53
     *
54
     * @var PromiseInterface
55
     */
56
    private $promise;
57 106
58
    /**
59 106
     * ReactPHP LoopInterface
60 106
     *
61
     * @var LoopInterface
62
     */
63
    private $loop;
64
65
    public function __construct(PromiseInterface $promise, LoopInterface $loop, RequestInterface $request)
66
    {
67
        $this->state = self::PENDING;
68
69
        $this->request = $request;
70 55
        $this->loop    = $loop;
71
        $this->promise = $promise->then(
72 55
            /**
73
             * @param ResponseInterface|null $response
74
             */
75 1
            function (?ResponseInterface $response): ResponseInterface {
76 55
                $this->response = $response;
77
                $this->state = self::FULFILLED;
78
79 1
                return $response;
80 55
            },
81
            /**
82
             * @param mixed $reason
83
             */
84 53
            function ($reason): void {
85
                $this->state = self::REJECTED;
86 53
87
                if ($reason instanceof HttplugException) {
88
                    $this->exception = $reason;
0 ignored issues
show
Documentation Bug introduced by
It seems like $reason of type object<Http\Client\Exception> is incompatible with the declared type object<Http\Adapter\React\Exception> of property $exception.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
89
                } elseif ($reason instanceof RuntimeException) {
90 53
                    $this->exception = new HttplugException\NetworkException($reason->getMessage(), $this->request, $reason);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Http\Client\Excepti...this->request, $reason) of type object<Http\Client\Exception\NetworkException> is incompatible with the declared type object<Http\Adapter\React\Exception> of property $exception.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
91
                } elseif ($reason instanceof \Throwable) {
92
                    $this->exception = new HttplugException\TransferException('Invalid exception returned from ReactPHP', 0, $reason);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Http\Client\Excepti... ReactPHP', 0, $reason) of type object<Http\Client\Exception\TransferException> is incompatible with the declared type object<Http\Adapter\React\Exception> of property $exception.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
93
                } else {
94 2
                    $this->exception = new UnexpectedValueException('Reason returned from ReactPHP must be an Exception');
0 ignored issues
show
Documentation Bug introduced by
It seems like new \UnexpectedValueExce... must be an Exception') of type object<UnexpectedValueException> is incompatible with the declared type object<Http\Adapter\React\Exception> of property $exception.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
95 2
                }
96 2
97
                throw $this->exception;
98 2
            });
99
    }
100 55
101
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null)
102
    {
103
        return new self($this->promise->then($onFulfilled, $onRejected), $this->loop, $this->request);
104 55
    }
105
106
    /**
107
     * {@inheritdoc}
108 55
     */
109
    public function getState()
110
    {
111
        return $this->state;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function wait($unwrap = true)
118 103
    {
119
        $loop = $this->loop;
120 103
        while (HttpPromise::PENDING === $this->getState()) {
121
            $loop->futureTick(function () use ($loop) {
122
                $loop->stop();
123
            });
124 103
            $loop->run();
125 103
        }
126 103
127 103
        if ($unwrap) {
128
            if (HttpPromise::REJECTED == $this->getState()) {
129 103
                throw $this->exception;
130
            }
131 103
132
            return $this->response;
133 103
        }
134 53
    }
135
}
136