Completed
Push — master ( 9509df...dcc885 )
by David
01:53
created

Promise   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 97.62%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 10
dl 0
loc 124
ccs 41
cts 42
cp 0.9762
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A then() 0 4 1
A getState() 0 4 1
A wait() 0 12 3
A handleException() 0 26 5
A __construct() 0 25 4
1
<?php
2
3
namespace Http\Adapter\Guzzle6;
4
5
use GuzzleHttp\Exception as GuzzleExceptions;
6
use GuzzleHttp\Promise\PromiseInterface;
7
use Http\Adapter\Guzzle6\Exception\UnexpectedValueException;
8
use Http\Client\Exception as HttplugException;
9
use Http\Promise\Promise as HttpPromise;
10
use Psr\Http\Message\RequestInterface;
11
use Psr\Http\Message\ResponseInterface;
12
13
/**
14
 * Wrapper around Guzzle promises.
15
 *
16
 * @author Joel Wurtz <[email protected]>
17
 */
18
final class Promise implements HttpPromise
19
{
20
    /**
21
     * @var PromiseInterface
22
     */
23
    private $promise;
24
25
    /**
26
     * @var string State of the promise
27
     */
28
    private $state;
29
30
    /**
31
     * @var ResponseInterface
32
     */
33
    private $response;
34
35
    /**
36
     * @var HttplugException
37
     */
38
    private $exception;
39
40
    /**
41
     * @var RequestInterface
42
     */
43
    private $request;
44
45
    /**
46
     * @param PromiseInterface $promise
47
     * @param RequestInterface $request
48
     */
49 378
    public function __construct(PromiseInterface $promise, RequestInterface $request)
50
    {
51 378
        $this->request = $request;
52 378
        $this->state = self::PENDING;
53
        $this->promise = $promise->then(function ($response) {
54 353
            $this->response = $response;
55 353
            $this->state = self::FULFILLED;
56
57 353
            return $response;
58
        }, function ($reason) use ($request) {
59 25
            $this->state = self::REJECTED;
60
61 25
            if ($reason instanceof HttplugException) {
62 6
                $this->exception = $reason;
63 25
            } elseif ($reason instanceof GuzzleExceptions\GuzzleException) {
64 21
                $this->exception = $this->handleException($reason, $request);
65 4
            } elseif ($reason instanceof \Throwable) {
66 3
                $this->exception = new HttplugException\TransferException('Invalid exception returned from Guzzle6', 0, $reason);
67
            } else {
68 1
                $this->exception = new UnexpectedValueException('Reason returned from Guzzle6 must be an Exception');
69
            }
70
71 25
            throw $this->exception;
72 378
        });
73 378
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 159
    public function then(callable $onFulfilled = null, callable $onRejected = null)
79
    {
80 159
        return new static($this->promise->then($onFulfilled, $onRejected), $this->request);
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 369
    public function getState()
87
    {
88 369
        return $this->state;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94 378
    public function wait($unwrap = true)
95
    {
96 378
        $this->promise->wait(false);
97
98 378
        if ($unwrap) {
99 369
            if (self::REJECTED == $this->getState()) {
100 19
                throw $this->exception;
101
            }
102
103 350
            return $this->response;
104
        }
105 9
    }
106
107
    /**
108
     * Converts a Guzzle exception into an Httplug exception.
109
     *
110
     * @param GuzzleExceptions\GuzzleException $exception
111
     * @param RequestInterface                 $request
112
     *
113
     * @return HttplugException
114
     */
115 21
    private function handleException(GuzzleExceptions\GuzzleException $exception, RequestInterface $request)
116
    {
117 21
        if ($exception instanceof GuzzleExceptions\SeekException) {
118
            return new HttplugException\RequestException($exception->getMessage(), $request, $exception);
119
        }
120
121 21
        if ($exception instanceof GuzzleExceptions\ConnectException) {
122 11
            return new HttplugException\NetworkException($exception->getMessage(), $exception->getRequest(), $exception);
123
        }
124
125 10
        if ($exception instanceof GuzzleExceptions\RequestException) {
126
            // Make sure we have a response for the HttpException
127 9
            if ($exception->hasResponse()) {
128 4
                return new HttplugException\HttpException(
129 4
                    $exception->getMessage(),
130 4
                    $exception->getRequest(),
131 4
                    $exception->getResponse(),
0 ignored issues
show
Bug introduced by
It seems like $exception->getResponse() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
132 4
                    $exception
133
                );
134
            }
135
136 5
            return new HttplugException\RequestException($exception->getMessage(), $exception->getRequest(), $exception);
137
        }
138
139 1
        return new HttplugException\TransferException($exception->getMessage(), 0, $exception);
140
    }
141
}
142