Passed
Pull Request — master (#88)
by Adam
03:01
created

Client::getUserAgent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
     * @var array User agent strings to be concatenated and added to each request.
34
     */
35
    protected $userAgent = [];
36
37
    /**
38
     * Client constructor.
39
     *
40
     * @param ConnectorInterface $connector
41
     */
42
    public function __construct(ConnectorInterface $connector)
43
    {
44
        $this->connector = $connector;
45
46
        $this->setUserAgent(
47
            sprintf(
48
                "%s/%s (https://github.com/typhonius/acquia-php-sdk-v2)",
49
                'acquia-php-sdk-v2',
50
                $this->getVersion()
51
            )
52
        );
53
    }
54
55
    /**
56
     * Client factory method for instantiating.
57
     *
58
     * @param ConnectorInterface $connector
59
     *
60
     * @return static
61
     */
62
    public static function factory(ConnectorInterface $connector)
63
    {
64
        $client = new static(
65
            $connector
66
        );
67
68
        return $client;
69
    }
70
71
    /**
72
     * Returns the current version of the library.
73
     *
74
     * @return string
75
     * @throws \Exception
76
     */
77
    public function getVersion()
78
    {
79
        if ($file = @file_get_contents(dirname(dirname(__DIR__)) . '/VERSION')) {
80
            return trim($file);
81
        } else {
82
            throw new \Exception('No VERSION file');
83
        }
84
    }
85
86
    /**
87
     * Allows the library to modify the request prior to making the call to the API.
88
     */
89
    public function modifyOptions($options = []): array
90
    {
91
        // Combine options set globally e.g. headers with options set by individual API calls e.g. form_params.
92
        $options = $this->options + $options;
93
94
        // This library can be standalone or as a dependency. Dependent libraries may also set their own user agent
95
        // which will make $options['headers']['User-Agent'] an array.
96
        // We need to array_unique() the array of User-Agent headers as multiple calls may include multiple of the same header.
97
        // We also use array_unshift() to place this library's user agent first to order to have it appear at the beginning of log files.
98
        // As Guzzle joins arrays with a comma, we must implode with a space here to pass Guzzle a string.
99
        $userAgent = sprintf(
100
            "%s/%s (https://github.com/typhonius/acquia-php-sdk-v2)",
101
            'acquia-php-sdk-v2',
102
            $this->getVersion()
103
        );
104
        if (isset($options['headers']['User-Agent']) && is_array($options['headers']['User-Agent'])) {
105
            array_unshift($options['headers']['User-Agent'], $userAgent);
106
            $options['headers']['User-Agent'] = implode(' ', array_unique($options['headers']['User-Agent']));
107
        } else {
108
            $options['headers']['User-Agent'] = $userAgent;
109
        }
110
111
        $options['query'] = $this->query;
112
        if (!empty($options['query']['filter']) && is_array($options['query']['filter'])) {
113
            // Default to an OR filter to increase returned responses.
114
            $options['query']['filter'] = implode(',', $options['query']['filter']);
115
        }
116
117
        return $options;
118
    }
119
120
    /**
121
     * @inheritdoc
122
     */
123
    public function request(string $verb, string $path, array $options = [])
124
    {
125
        // @TODO follow this up by removing $options from the parameters able
126
        // to be passed into this function and instead solely relying on the
127
        // addOption() method as this can then be tested.
128
        $options = $this->modifyOptions($options);
129
130
        $response = $this->makeRequest($verb, $path, $options);
131
132
        return $this->processResponse($response);
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138
    public function makeRequest(string $verb, string $path, array $options = []): ResponseInterface
139
    {
140
        try {
141
            $response = $this->connector->sendRequest($verb, $path, $options);
142
        } catch (BadResponseException $e) {
143
            $response = $e->getResponse();
144
        }
145
146
        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...
147
    }
148
149
    /**
150
     * @inheritdoc
151
     */
152
    public function processResponse(ResponseInterface $response)
153
    {
154
155
        $body_json = $response->getBody();
156
        $body = json_decode($body_json);
157
        if (json_last_error() !== JSON_ERROR_NONE) {
158
            return $body_json;
159
        }
160
161
        if (property_exists($body, '_embedded') && property_exists($body->_embedded, 'items')) {
162
            return $body->_embedded->items;
163
        }
164
165
        if (property_exists($body, 'error') && property_exists($body, 'message')) {
166
            throw new ApiErrorException($body);
167
        }
168
169
        return $body;
170
    }
171
172
    /**
173
     * @inheritdoc
174
     */
175
    public function getQuery(): array
176
    {
177
        return $this->query;
178
    }
179
180
    /**
181
     * @inheritdoc
182
     */
183
    public function clearQuery(): void
184
    {
185
        $this->query = [];
186
    }
187
188
    /**
189
     * @inheritdoc
190
     */
191
    public function addQuery($name, $value): void
192
    {
193
        $this->query = array_merge_recursive($this->query, [$name => $value]);
194
    }
195
196
    /**
197
     * @inheritdoc
198
     */
199
    public function getOptions(): array
200
    {
201
        return $this->options;
202
    }
203
204
    /**
205
     * @inheritdoc
206
     */
207
    public function clearOptions(): void
208
    {
209
        $this->options = [];
210
    }
211
212
    /**
213
     * @inheritdoc
214
     */
215
    public function addOption($name, $value): void
216
    {
217
        $this->options = array_merge_recursive($this->options, [$name => $value]);
218
    }
219
220
    /**
221
     * @inheritdoc
222
     */
223
    public function setUserAgent($name): void
224
    {
225
        $this->userAgent[] = $name;
226
    }
227
228
    /**
229
     * @inheritdoc
230
     */
231
    public function getUserAgent(): array
232
    {
233
        return array_unique($this->userAgent);
234
    }
235
}
236