Completed
Pull Request — master (#42)
by Stéphane
04:50 queued 03:33
created

Promise::doResolve()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
rs 10
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
58
    /**
59
     * ReactPHP LoopInterface
60
     *
61
     * @var LoopInterface
62
     */
63
    private $loop;
64
65 110
    public function __construct(PromiseInterface $promise, LoopInterface $loop, RequestInterface $request)
66
    {
67 110
        $this->state = self::PENDING;
68
69 110
        $this->request = $request;
70 110
        $this->loop    = $loop;
71 110
        $this->promise = $promise->then(
72
            /**
73
             * @param ResponseInterface|null $response
74
             */
75
            function (?ResponseInterface $response): ResponseInterface {
76 102
                $this->response = $response;
77 102
                $this->state = self::FULFILLED;
78
79 102
                return $response;
80 110
            },
81
            /**
82
             * @param mixed $reason
83
             */
84
            function ($reason): void {
85 8
                $this->state = self::REJECTED;
86
87 8
                if ($reason instanceof HttplugException) {
88 4
                    $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 6
                } elseif ($reason instanceof RuntimeException) {
90 4
                    $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 2
                } elseif ($reason instanceof \Throwable) {
92 1
                    $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 1
                    $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
                }
96
97 8
                throw $this->exception;
98 110
            });
99 110
    }
100
101 54
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null)
102
    {
103 54
        return new self($this->promise->then($onFulfilled, $onRejected), $this->loop, $this->request);
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 110
    public function getState()
110
    {
111 110
        return $this->state;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 110
    public function wait($unwrap = true)
118
    {
119 110
        $loop = $this->loop;
120 110
        while (HttpPromise::PENDING === $this->getState()) {
121
            $loop->futureTick(function () use ($loop) {
122 104
                $loop->stop();
123 104
            });
124 104
            $loop->run();
125
        }
126
127 110
        if ($unwrap) {
128 107
            if (HttpPromise::REJECTED == $this->getState()) {
129 6
                throw $this->exception;
130
            }
131
132 101
            return $this->response;
133
        }
134 3
    }
135
}
136