Passed
Pull Request — master (#88)
by Adam
02:08
created

Client::setUserAgent()   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 1
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 reverse the array of User-Agent headers to order this library's header first in log files.
97
        // As Guzzle joins arrays with a comma, we must implode with a space here to pass Guzzle a string.
98
        $userAgent = $this->getUserAgent();
99
100
        if (is_array($userAgent)) {
0 ignored issues
show
introduced by
The condition is_array($userAgent) is always true.
Loading history...
101
            $options['headers']['User-Agent'] = implode(' ', $userAgent);
102
        }
103
104
        $options['query'] = $this->query;
105
        if (!empty($options['query']['filter']) && is_array($options['query']['filter'])) {
106
            // Default to an AND filter.
107
            $options['query']['filter'] = implode(',', $options['query']['filter']);
108
        }
109
110
        return $options;
111
    }
112
113
    /**
114
     * @inheritdoc
115
     */
116
    public function request(string $verb, string $path, array $options = [])
117
    {
118
        // @TODO follow this up by removing $options from the parameters able
119
        // to be passed into this function and instead solely relying on the
120
        // addOption() method as this can then be tested.
121
        $options = $this->modifyOptions($options);
122
123
        $response = $this->makeRequest($verb, $path, $options);
124
125
        return $this->processResponse($response);
126
    }
127
128
    /**
129
     * @inheritdoc
130
     */
131
    public function makeRequest(string $verb, string $path, array $options = []): ResponseInterface
132
    {
133
        try {
134
            $response = $this->connector->sendRequest($verb, $path, $options);
135
        } catch (BadResponseException $e) {
136
            $response = $e->getResponse();
137
        }
138
139
        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...
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145
    public function processResponse(ResponseInterface $response)
146
    {
147
148
        $body_json = $response->getBody();
149
        $body = json_decode($body_json);
150
        if (json_last_error() !== JSON_ERROR_NONE) {
151
            return $body_json;
152
        }
153
154
        if (property_exists($body, '_embedded') && property_exists($body->_embedded, 'items')) {
155
            return $body->_embedded->items;
156
        }
157
158
        if (property_exists($body, 'error') && property_exists($body, 'message')) {
159
            throw new ApiErrorException($body);
160
        }
161
162
        return $body;
163
    }
164
165
    /**
166
     * @inheritdoc
167
     */
168
    public function getQuery(): array
169
    {
170
        return $this->query;
171
    }
172
173
    /**
174
     * @inheritdoc
175
     */
176
    public function clearQuery(): void
177
    {
178
        $this->query = [];
179
    }
180
181
    /**
182
     * @inheritdoc
183
     */
184
    public function addQuery($name, $value): void
185
    {
186
        $this->query = array_merge_recursive($this->query, [$name => $value]);
187
    }
188
189
    /**
190
     * @inheritdoc
191
     */
192
    public function getOptions(): array
193
    {
194
        return $this->options;
195
    }
196
197
    /**
198
     * @inheritdoc
199
     */
200
    public function clearOptions(): void
201
    {
202
        $this->options = [];
203
    }
204
205
    /**
206
     * @inheritdoc
207
     */
208
    public function addOption($name, $value): void
209
    {
210
        $this->options = array_merge_recursive($this->options, [$name => $value]);
211
    }
212
213
    /**
214
     * @inheritdoc
215
     */
216
    public function setUserAgent($name): void
217
    {
218
        $this->userAgent[] = $name;
219
    }
220
221
    /**
222
     * @inheritdoc
223
     */
224
    public function getUserAgent(): array
225
    {
226
        return array_unique($this->userAgent);
227
    }
228
}
229