Completed
Push — master ( ef7341...b49dc7 )
by Graham
740:05 queued 675:04
created

GuzzleHttpAdapter::handleResponse()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4286
cc 3
eloc 5
nc 2
nop 1
1
<?php
2
3
namespace DigitalOceanV2\Adapter;
4
5
use DigitalOceanV2\Exception\ExceptionInterface;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\ClientInterface;
8
use GuzzleHttp\Event\CompleteEvent;
9
use GuzzleHttp\Exception\RequestException;
10
use GuzzleHttp\Message\ResponseInterface;
11
use GuzzleHttp\Psr7\Response;
12
13
class GuzzleHttpAdapter extends AbstractAdapter implements AdapterInterface
14
{
15
    /**
16
     * @var ClientInterface
17
     */
18
    protected $client;
19
20
    /**
21
     * @var Response|ResponseInterface
22
     */
23
    protected $response;
24
25
    /**
26
     * @var ExceptionInterface
27
     */
28
    protected $exception;
29
30
    /**
31
     * @param string             $accessToken
32
     * @param ClientInterface    $client      (optional)
33
     * @param ExceptionInterface $exception   (optional)
34
     */
35
    public function __construct($accessToken, ClientInterface $client = null, ExceptionInterface $exception = null)
36
    {
37
        if (version_compare(ClientInterface::VERSION, '6') === 1) {
38
            $this->client = $client ?: new Client(['headers' => ['Authorization' => sprintf('Bearer %s', $accessToken)]]);
39
        } else {
40
            $this->client = $client ?: new Client();
41
42
            $this->client->setDefaultOption('headers/Authorization', sprintf('Bearer %s', $accessToken));
0 ignored issues
show
Bug introduced by
The method setDefaultOption() does not seem to exist on object<GuzzleHttp\ClientInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
43
44
            $this->client->getEmitter()->on('complete', function (CompleteEvent $e) {
0 ignored issues
show
Bug introduced by
The method getEmitter() does not seem to exist on object<GuzzleHttp\ClientInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
45
                $this->handleResponse($e);
46
                $e->stopPropagation();
47
            });
48
        }
49
50
        $this->exception = $exception;
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function get($url)
57
    {
58
        try {
59
            $this->response = $this->client->get($url);
60
        } catch (RequestException $e) {
61
            $this->response = $e->getResponse();
0 ignored issues
show
Documentation Bug introduced by
It seems like $e->getResponse() of type object<Psr\Http\Message\ResponseInterface> is incompatible with the declared type object<GuzzleHttp\Psr7\R...sage\ResponseInterface> of property $response.

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...
62
            $this->handleException();
63
        }
64
65
        return $this->response->getBody();
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function delete($url, array $headers = [])
72
    {
73
        try {
74
            $options = ['headers' => $headers];
75
            $this->response = $this->client->delete($url, $options);
76
        } catch (RequestException $e) {
77
            $this->response = $e->getResponse();
0 ignored issues
show
Documentation Bug introduced by
It seems like $e->getResponse() of type object<Psr\Http\Message\ResponseInterface> is incompatible with the declared type object<GuzzleHttp\Psr7\R...sage\ResponseInterface> of property $response.

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...
78
            $this->handleException();
79
        }
80
81
        return $this->response->getBody();
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function put($url, array $headers = [], $content = '')
88
    {
89
        try {
90
            $options = version_compare(ClientInterface::VERSION, '6') === 1 && ($json = json_decode($content, true)) ?
91
                ['headers' => $headers, 'json' => $json] :
0 ignored issues
show
Bug introduced by
The variable $json does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
92
                ['headers' => $headers, 'body' => $content];
93
94
            $this->response = $this->client->put($url, $options);
95
        } catch (RequestException $e) {
96
            $this->response = $e->getResponse();
0 ignored issues
show
Documentation Bug introduced by
It seems like $e->getResponse() of type object<Psr\Http\Message\ResponseInterface> is incompatible with the declared type object<GuzzleHttp\Psr7\R...sage\ResponseInterface> of property $response.

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...
97
            $this->handleException();
98
        }
99
100
        return $this->response->getBody();
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function post($url, array $headers = [], $content = '')
107
    {
108
        try {
109
            $options = version_compare(ClientInterface::VERSION, '6') === 1 && ($json = json_decode($content, true)) ?
110
                ['headers' => $headers, 'json' => $json] :
0 ignored issues
show
Bug introduced by
The variable $json does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
111
                ['headers' => $headers, 'body' => $content];
112
113
            $this->response = $this->client->post($url, $options);
114
        } catch (RequestException $e) {
115
            $this->response = $e->getResponse();
0 ignored issues
show
Documentation Bug introduced by
It seems like $e->getResponse() of type object<Psr\Http\Message\ResponseInterface> is incompatible with the declared type object<GuzzleHttp\Psr7\R...sage\ResponseInterface> of property $response.

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...
116
            $this->handleException();
117
        }
118
119
        return $this->response->getBody();
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function getLatestResponseHeaders()
126
    {
127
        if (null === $this->response) {
128
            return;
129
        }
130
131
        return [
132
            'reset' => (int) (string) $this->response->getHeader('RateLimit-Reset'),
133
            'remaining' => (int) (string) $this->response->getHeader('RateLimit-Remaining'),
134
            'limit' => (int) (string) $this->response->getHeader('RateLimit-Limit'),
135
        ];
136
    }
137
138
    /**
139
     * @param CompleteEvent $event
140
     *
141
     * @throws \RuntimeException|ExceptionInterface
142
     */
143
    protected function handleResponse(CompleteEvent $event)
144
    {
145
        $this->response = $event->getResponse();
146
147
        if ($this->response->getStatusCode() >= 200 && $this->response->getStatusCode() <= 299) {
148
            return;
149
        }
150
151
        $this->handleException();
152
    }
153
154
    /**
155
     * @throws \RuntimeException|ExceptionInterface
156
     */
157
    protected function handleException()
158
    {
159
        $body = (string) $this->response->getBody();
160
        $code = (int) $this->response->getStatusCode();
161
162
        if ($this->exception) {
163
            return $this->exception->create($body, $code);
164
        }
165
166
        $content = json_decode($body);
167
168
        throw new \RuntimeException(sprintf('[%d] %s (%s)', $code, $content->message, $content->id), $code);
169
    }
170
}
171