Completed
Push — master ( b83b4d...175f97 )
by Joel
11s
created

Promise::doResolve()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
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
    public function __construct(LoopInterface $loop)
58 108
    {
59
        $this->loop = $loop;
60 108
    }
61
62 105
    /**
63 105
     * Allow to apply callable when the promise resolve.
64 108
     *
65
     * @param callable|null $onFulfilled
66 3
     * @param callable|null $onRejected
67 3
     *
68 3
     * @return Promise
69 108
     */
70 108
    public function then(callable $onFulfilled = null, callable $onRejected = null)
71 108
    {
72
        $newPromise = new self($this->loop);
73
74
        $onFulfilled = $onFulfilled !== null ? $onFulfilled : function (ResponseInterface $response) {
75
            return $response;
76
        };
77
78
        $onRejected = $onRejected !== null ? $onRejected : function (Exception $exception) {
79
            throw $exception;
80
        };
81 55
82
        $this->onFulfilled = function (ResponseInterface $response) use ($onFulfilled, $newPromise) {
83
            try {
84 53
                $newPromise->resolve($onFulfilled($response));
85 53
            } catch (Exception $exception) {
86 53
                $newPromise->reject($exception);
87 55
            }
88 2
        };
89 2
90
        $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...
91 55
            try {
92
                $newPromise->resolve($onRejected($exception));
93 55
            } catch (Exception $exception) {
94
                $newPromise->reject($exception);
95
            }
96
        };
97
98
        if ($this->state === HttpPromise::FULFILLED) {
99 108
            $this->doResolve($this->response);
100
        }
101 108
102
        if ($this->state === HttpPromise::REJECTED) {
103
            $this->doReject($this->exception);
104
        }
105
106
        return $newPromise;
107
    }
108
109
    /**
110
     * Resolve this promise.
111 108
     *
112
     * @param ResponseInterface $response
113 108
     *
114
     * @internal
115 108
     */
116
    public function resolve(ResponseInterface $response)
117
    {
118
        if ($this->state !== HttpPromise::PENDING) {
119
            throw new \RuntimeException('Promise is already resolved');
120
        }
121 108
122
        $this->state = HttpPromise::FULFILLED;
123 108
        $this->response = $response;
124
        $this->doResolve($response);
125
    }
126 108
127 108
    private function doResolve(ResponseInterface $response)
128 108
    {
129
        $onFulfilled = $this->onFulfilled;
130 108
131 105
        if (null !== $onFulfilled) {
132 1
            $onFulfilled($response);
133
        }
134
    }
135 104
136
    /**
137 3
     * Reject this promise.
138
     *
139
     * @param Exception $exception
140
     *
141
     * @internal
142
     */
143
    public function reject(Exception $exception)
144
    {
145
        if ($this->state !== HttpPromise::PENDING) {
146
            throw new \RuntimeException('Promise is already resolved');
147
        }
148
149
        $this->state = HttpPromise::REJECTED;
150
        $this->exception = $exception;
151
        $this->doReject($exception);
152
    }
153
154
    private function doReject(Exception $exception)
155
    {
156
        $onRejected = $this->onRejected;
157
158
        if (null !== $onRejected) {
159
            $onRejected($exception);
160
        }
161
    }
162
163
    /**
164
     * {@inheritdoc}
165
     */
166
    public function getState()
167
    {
168
        return $this->state;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function wait($unwrap = true)
175
    {
176
        while (HttpPromise::PENDING === $this->getState()) {
177
            $this->loop->tick();
178
        }
179
180
        if ($unwrap) {
181
            if (HttpPromise::REJECTED == $this->getState()) {
182
                throw $this->exception;
183
            }
184
185
            return $this->response;
186
        }
187
    }
188
}
189