Completed
Push — master ( bdb5af...d3c208 )
by David
02:42 queued 10s
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 React\EventLoop\LoopInterface;
6
use Http\Client\Exception;
7
use Http\Promise\Promise as HttpPromise;
8
use Psr\Http\Message\ResponseInterface;
9
10
/**
11
 * React promise adapter implementation.
12
 *
13
 * @author Stéphane Hulard <[email protected]>
14
 *
15
 * @internal
16
 */
17
final class Promise implements HttpPromise
18
{
19
    /**
20
     * Promise status.
21
     *
22
     * @var string
23
     */
24
    private $state = HttpPromise::PENDING;
25
26
    /**
27
     * PSR7 received response.
28
     *
29
     * @var ResponseInterface
30
     */
31
    private $response;
32
33
    /**
34
     * Execution error.
35
     *
36
     * @var Exception
37
     */
38
    private $exception;
39
40
    /**
41
     * @var callable|null
42
     */
43
    private $onFulfilled;
44
45
    /**
46
     * @var callable|null
47
     */
48
    private $onRejected;
49
50
    /**
51
     * React Event Loop used for synchronous processing.
52
     *
53
     * @var LoopInterface
54
     */
55
    private $loop;
56
57 110
    public function __construct(LoopInterface $loop)
58
    {
59 110
        $this->loop = $loop;
60 110
    }
61
62
    /**
63
     * Allow to apply callable when the promise resolve.
64
     *
65
     * @param callable|null $onFulfilled
66
     * @param callable|null $onRejected
67
     *
68
     * @return Promise
69
     */
70 57
    public function then(callable $onFulfilled = null, callable $onRejected = null)
71
    {
72 57
        $newPromise = new self($this->loop);
73
74
        $onFulfilled = null !== $onFulfilled ? $onFulfilled : function (ResponseInterface $response) {
75 1
            return $response;
76 57
        };
77
78
        $onRejected = null !== $onRejected ? $onRejected : function (Exception $exception) {
79 1
            throw $exception;
80 57
        };
81
82
        $this->onFulfilled = function (ResponseInterface $response) use ($onFulfilled, $newPromise) {
83
            try {
84 55
                $return = $onFulfilled($response);
85
86 55
                $newPromise->resolve(null !== $return ? $return : $response);
87
            } catch (Exception $exception) {
88
                $newPromise->reject($exception);
89
            }
90 55
        };
91
92
        $this->onRejected = function (Exception $exception) use ($onRejected, $newPromise) {
0 ignored issues
show
Unused Code introduced by
The parameter $exception is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
93
            try {
94 2
                $newPromise->resolve($onRejected($exception));
95 2
            } catch (Exception $exception) {
96 2
                $newPromise->reject($exception);
97
            }
98 2
        };
99
100 57
        if (HttpPromise::FULFILLED === $this->state) {
101
            $this->doResolve($this->response);
102
        }
103
104 57
        if (HttpPromise::REJECTED === $this->state) {
105
            $this->doReject($this->exception);
106
        }
107
108 57
        return $newPromise;
109
    }
110
111
    /**
112
     * Resolve this promise.
113
     *
114
     * @param ResponseInterface $response
115
     *
116
     * @internal
117
     */
118 107
    public function resolve(ResponseInterface $response)
119
    {
120 107
        if (HttpPromise::PENDING !== $this->state) {
121
            throw new \RuntimeException('Promise is already resolved');
122
        }
123
124 107
        $this->state = HttpPromise::FULFILLED;
125 107
        $this->response = $response;
126 107
        $this->doResolve($response);
127 107
    }
128
129 107
    private function doResolve(ResponseInterface $response)
130
    {
131 107
        $onFulfilled = $this->onFulfilled;
132
133 107
        if (null !== $onFulfilled) {
134 55
            $onFulfilled($response);
135
        }
136 107
    }
137
138
    /**
139
     * Reject this promise.
140
     *
141
     * @param Exception $exception
142
     *
143
     * @internal
144
     */
145 3
    public function reject(Exception $exception)
146
    {
147 3
        if (HttpPromise::PENDING !== $this->state) {
148
            throw new \RuntimeException('Promise is already resolved');
149
        }
150
151 3
        $this->state = HttpPromise::REJECTED;
152 3
        $this->exception = $exception;
153 3
        $this->doReject($exception);
154 3
    }
155
156 3
    private function doReject(Exception $exception)
157
    {
158 3
        $onRejected = $this->onRejected;
159
160 3
        if (null !== $onRejected) {
161 2
            $onRejected($exception);
162
        }
163 3
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168 110
    public function getState()
169
    {
170 110
        return $this->state;
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 110
    public function wait($unwrap = true)
177
    {
178 110
        $loop = $this->loop;
179 110
        while (HttpPromise::PENDING === $this->getState()) {
180 108
            $loop->futureTick(function () use ($loop) {
181 108
                $loop->stop();
182 108
            });
183 108
            $loop->run();
184
        }
185
186 110
        if ($unwrap) {
187 107
            if (HttpPromise::REJECTED == $this->getState()) {
188 1
                throw $this->exception;
189
            }
190
191 106
            return $this->response;
192
        }
193 3
    }
194
}
195