Completed
Push — master ( e37e46...c75450 )
by David
01:07
created

src/Deferred.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Http\Client\Common;
6
7
use Http\Promise\Promise;
8
use Psr\Http\Client\ClientExceptionInterface;
9
use Psr\Http\Message\ResponseInterface;
10
11
/**
12
 * A deferred allow to return a promise which has not been resolved yet.
13
 */
14
final class Deferred implements Promise
15
{
16
    /**
17
     * @var ResponseInterface|null
18
     */
19
    private $value;
20
21
    /**
22
     * @var ClientExceptionInterface|null
23
     */
24
    private $failure;
25
26
    /**
27
     * @var string
28
     */
29
    private $state;
30
31
    /**
32
     * @var callable
33
     */
34
    private $waitCallback;
35
36
    /**
37
     * @var callable[]
38
     */
39
    private $onFulfilledCallbacks;
40
41
    /**
42
     * @var callable[]
43
     */
44
    private $onRejectedCallbacks;
45
46
    public function __construct(callable $waitCallback)
47
    {
48
        $this->waitCallback = $waitCallback;
49
        $this->state = Promise::PENDING;
50
        $this->onFulfilledCallbacks = [];
51
        $this->onRejectedCallbacks = [];
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function then(callable $onFulfilled = null, callable $onRejected = null): Promise
58
    {
59
        $deferred = new self($this->waitCallback);
60
61 View Code Duplication
        $this->onFulfilledCallbacks[] = function (ResponseInterface $response) use ($onFulfilled, $deferred) {
62
            try {
63
                if (null !== $onFulfilled) {
64
                    $response = $onFulfilled($response);
65
                }
66
                $deferred->resolve($response);
67
            } catch (ClientExceptionInterface $exception) {
68
                $deferred->reject($exception);
69
            }
70
        };
71
72 View Code Duplication
        $this->onRejectedCallbacks[] = function (ClientExceptionInterface $exception) use ($onRejected, $deferred) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
73
            try {
74
                if (null !== $onRejected) {
75
                    $response = $onRejected($exception);
76
                    $deferred->resolve($response);
77
78
                    return;
79
                }
80
                $deferred->reject($exception);
81
            } catch (ClientExceptionInterface $newException) {
82
                $deferred->reject($newException);
83
            }
84
        };
85
86
        return $deferred;
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function getState(): string
93
    {
94
        return $this->state;
95
    }
96
97
    /**
98
     * Resolve this deferred with a Response.
99
     */
100
    public function resolve(ResponseInterface $response): void
101
    {
102
        if (Promise::PENDING !== $this->state) {
103
            return;
104
        }
105
106
        $this->value = $response;
107
        $this->state = Promise::FULFILLED;
108
109
        foreach ($this->onFulfilledCallbacks as $onFulfilledCallback) {
110
            $onFulfilledCallback($response);
111
        }
112
    }
113
114
    /**
115
     * Reject this deferred with an Exception.
116
     */
117
    public function reject(ClientExceptionInterface $exception): void
118
    {
119
        if (Promise::PENDING !== $this->state) {
120
            return;
121
        }
122
123
        $this->failure = $exception;
124
        $this->state = Promise::REJECTED;
125
126
        foreach ($this->onRejectedCallbacks as $onRejectedCallback) {
127
            $onRejectedCallback($exception);
128
        }
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function wait($unwrap = true)
135
    {
136
        if (Promise::PENDING === $this->state) {
137
            $callback = $this->waitCallback;
138
            $callback();
139
        }
140
141
        if (!$unwrap) {
142
            return null;
143
        }
144
145
        if (Promise::FULFILLED === $this->state) {
146
            return $this->value;
147
        }
148
149
        /** @var ClientExceptionInterface */
150
        throw $this->failure;
151
    }
152
}
153