Promise   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 1 Features 0
Metric Value
wmc 10
eloc 37
c 5
b 1
f 0
dl 0
loc 110
ccs 34
cts 34
cp 1
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 30 4
A then() 0 3 1
A wait() 0 16 4
A getState() 0 3 1
1
<?php
2
3
namespace Http\Adapter\React;
4
5
use Http\Adapter\React\Exception\UnexpectedValueException;
6
use Http\Client\Exception as HttplugException;
7
use Http\Promise\Promise as HttpPromise;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use React\EventLoop\LoopInterface;
11
use React\Promise\PromiseInterface;
12
use RuntimeException;
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|null
34
     */
35
    private $response;
36
37
    /**
38
     * Execution error.
39
     *
40
     * @var HttplugException
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
            function (?ResponseInterface $response): ?ResponseInterface {
73 102
                $this->response = $response;
74 102
                $this->state = self::FULFILLED;
75
76 102
                return $response;
77 110
            },
78
            /**
79
             * @param mixed $reason
80
             */
81
            function ($reason): void {
82 8
                $this->state = self::REJECTED;
83
84 8
                if ($reason instanceof HttplugException) {
85 4
                    $this->exception = $reason;
86 6
                } elseif ($reason instanceof RuntimeException) {
87 4
                    $this->exception = new HttplugException\NetworkException($reason->getMessage(), $this->request, $reason);
88 2
                } elseif ($reason instanceof \Throwable) {
89 1
                    $this->exception = new HttplugException\TransferException('Invalid exception returned from ReactPHP', 0, $reason);
90
                } else {
91 1
                    $this->exception = new UnexpectedValueException('Reason returned from ReactPHP must be an Exception');
92
                }
93
94 8
                throw $this->exception;
95 110
            }
96 110
        );
97
    }
98 54
99
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null)
100 54
    {
101
        return new self($this->promise->then($onFulfilled, $onRejected), $this->loop, $this->request);
102
    }
103
104
    /**
105
     * {@inheritdoc}
106 110
     */
107
    public function getState()
108 110
    {
109
        return $this->state;
110
    }
111
112
    /**
113
     * {@inheritdoc}
114 110
     */
115
    public function wait($unwrap = true)
116 110
    {
117 110
        $loop = $this->loop;
118
        while (HttpPromise::PENDING === $this->getState()) {
119 104
            $loop->futureTick(function () use ($loop) {
120 104
                $loop->stop();
121 104
            });
122
            $loop->run();
123
        }
124 110
125 107
        if ($unwrap) {
126 6
            if (HttpPromise::REJECTED == $this->getState()) {
127
                throw $this->exception;
128
            }
129 101
130
            return $this->response;
131 3
        }
132
    }
133
}
134