Passed
Pull Request — master (#74)
by Adam
02:21
created

Client::modifyOptions()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 29
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 29
rs 9.8666
1
<?php
2
3
namespace AcquiaCloudApi\Connector;
4
5
use Psr\Http\Message\ResponseInterface;
6
use GuzzleHttp\Exception\BadResponseException;
7
use AcquiaCloudApi\Exception\ApiErrorException;
8
use Psr\Http\Message\StreamInterface;
9
10
/**
11
 * Class Client
12
 *
13
 * @package AcquiaCloudApi\CloudApi
14
 */
15
class Client implements ClientInterface
16
{
17
    /**
18
     * @var ConnectorInterface The API connector.
19
     */
20
    protected $connector;
21
22
    /**
23
     * @var array Query strings to be applied to the request.
24
     */
25
    protected $query = [];
26
27
    /**
28
     * @var array Guzzle options to be applied to the request.
29
     */
30
    protected $options = [];
31
32
    /**
33
     * Client constructor.
34
     *
35
     * @param ConnectorInterface $connector
36
     */
37
    public function __construct(ConnectorInterface $connector)
38
    {
39
        $this->connector = $connector;
40
    }
41
42
    /**
43
     * Client factory method for instantiating.
44
     *
45
     * @param ConnectorInterface $connector
46
     *
47
     * @return static
48
     */
49
    public static function factory(ConnectorInterface $connector)
50
    {
51
        $client = new static(
52
            $connector
53
        );
54
55
        return $client;
56
    }
57
58
    /**
59
     * Returns the current version of the library.
60
     *
61
     * @return string
62
     * @throws \Exception
63
     */
64
    public function getVersion()
65
    {
66
        if ($file = @file_get_contents(dirname(dirname(__DIR__)) . '/VERSION')) {
67
            return trim($file);
68
        } else {
69
            throw new \Exception('No VERSION file');
70
        }
71
    }
72
73
    /**
74
     * Allows the library to modify the request prior to making the call to the API.
75
     */
76
    public function modifyOptions($options = []): array
77
    {
78
        // Add the user agent header here so it can't be removed by other libraries.
79
        $this->addOption('headers', [
80
            'User-Agent' => sprintf(
81
                "%s/%s (https://github.com/typhonius/acquia-php-sdk-v2)",
82
                'acquia-php-sdk-v2',
83
                $this->getVersion()
84
            )
85
        ]);
86
87
        // Combine options set globally e.g. headers with options set by individual API calls e.g. form_params.
88
        $options = $this->options + $options;
89
90
        // This library can be standalone or as a dependency. Dependent libraries may also set their own user agent
91
        // which will make $options['headers']['User-Agent'] an array.
92
        // We need to reverse the array of User-Agent headers to order this library's header first in log files.
93
        // As Guzzle joins arrays with a comma, we must implode with a space here to pass Guzzle a string.
94
        if (is_array($options['headers']['User-Agent'])) {
95
            $options['headers']['User-Agent'] = implode(' ', array_reverse($options['headers']['User-Agent']));
96
        }
97
98
        $options['query'] = $this->query;
99
        if (!empty($options['query']['filter']) && is_array($options['query']['filter'])) {
100
            // Default to an AND filter.
101
            $options['query']['filter'] = implode(',', $options['query']['filter']);
102
        }
103
104
        return $options;
105
    }
106
107
    /**
108
     * @inheritdoc
109
     */
110
    public function request(string $verb, string $path, array $options = [])
111
    {
112
        // @TODO follow this up by removing $options from the parameters able
113
        // to be passed into this function and instead solely relying on the
114
        // addOption() method as this can then be tested.
115
        $options = $this->modifyOptions($options);
116
117
        $response = $this->makeRequest($verb, $path, $options);
118
119
        return $this->processResponse($response);
120
    }
121
122
    /**
123
     * @inheritdoc
124
     */
125
    public function makeRequest(string $verb, string $path, array $options = []): ResponseInterface
126
    {
127
        try {
128
            $response = $this->connector->sendRequest($verb, $path, $options);
129
        } catch (BadResponseException $e) {
130
            $response = $e->getResponse();
131
        }
132
133
        return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response could return the type null which is incompatible with the type-hinted return Psr\Http\Message\ResponseInterface. Consider adding an additional type-check to rule them out.
Loading history...
134
    }
135
136
    /**
137
     * @inheritdoc
138
     */
139
    public function processResponse(ResponseInterface $response)
140
    {
141
142
        $body = $response->getBody();
143
144
        $object = json_decode($body);
145
        if (json_last_error() !== JSON_ERROR_NONE) {
146
            return $body;
147
        }
148
149
        if (property_exists($object, '_embedded') && property_exists($object->_embedded, 'items')) {
150
            return $object->_embedded->items;
151
        }
152
153
        if (property_exists($object, 'error') && property_exists($object, 'message')) {
154
            throw new ApiErrorException($object);
155
        }
156
157
        return $object;
158
    }
159
160
    /**
161
     * @inheritdoc
162
     */
163
    public function getQuery(): array
164
    {
165
        return $this->query;
166
    }
167
168
    /**
169
     * @inheritdoc
170
     */
171
    public function clearQuery(): void
172
    {
173
        $this->query = [];
174
    }
175
176
    /**
177
     * @inheritdoc
178
     */
179
    public function addQuery($name, $value): void
180
    {
181
        $this->query = array_merge_recursive($this->query, [$name => $value]);
182
    }
183
184
    /**
185
     * @inheritdoc
186
     */
187
    public function getOptions(): array
188
    {
189
        return $this->options;
190
    }
191
192
    /**
193
     * @inheritdoc
194
     */
195
    public function clearOptions(): void
196
    {
197
        $this->options = [];
198
    }
199
200
    /**
201
     * @inheritdoc
202
     */
203
    public function addOption($name, $value): void
204
    {
205
        $this->options = array_merge_recursive($this->options, [$name => $value]);
206
    }
207
}
208