Completed
Push — master ( 993800...e13cda )
by Steven
04:02
created

Http::putAsBody()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
crap 1
1
<?php namespace Stevenmaguire\Services\Trello;
2
3
use GuzzleHttp\Client as HttpClient;
4
use GuzzleHttp\ClientInterface as HttpClientInterface;
5
use GuzzleHttp\Exception\RequestException;
6
use GuzzleHttp\Psr7;
7
use GuzzleHttp\Psr7\Request;
8
use Psr\Http\Message\RequestInterface;
9
10
class Http
11
{
12
    const HTTP_DELETE = 'DELETE';
13
    const HTTP_GET = 'GET';
14
    const HTTP_POST = 'POST';
15
    const HTTP_PUT = 'PUT';
16
17
    /**
18
     * Multipart resources to include in next request.
19
     *
20
     * @var array
21
     */
22
    protected $multipartResources = [];
23
24
    /**
25
     * Http client
26
     *
27
     * @var HttpClientInterface
28
     */
29
    protected $httpClient;
30
31
    /**
32
     * Creates a new http broker.
33
     */
34 702
    public function __construct()
35
    {
36 702
        $this->httpClient = new HttpClient;
37 702
    }
38
39
    /**
40
     * Adds authentication credentials to given request.
41
     *
42
     * @param  RequestInterface  $request
43
     *
44
     * @return RequestInterface
45
     */
46 682
    protected function authenticateRequest(RequestInterface $request)
47
    {
48 682
        $uri = $request->getUri();
49 682
        parse_str($uri->getQuery(), $query);
50
51 682
        $query['key'] = Configuration::get('key');
52 682
        $query['token'] = Configuration::get('token');
53
54 682
        $uri = $uri->withQuery(http_build_query($query));
55
56 682
        return $request->withUri($uri);
57
    }
58
59
    /**
60
     * Creates a request.
61
     *
62
     * @param  string $verb
63
     * @param  string $path
64
     * @param  array  $parameters
65
     *
66
     * @return Request
67
     */
68 684
    protected function createRequest($verb, $path, $parameters = [])
69
    {
70 684
        if (isset($parameters['file'])) {
71 2
            $this->queueResourceAs(
72 2
                'file',
73 2
                Psr7\stream_for($parameters['file'])
74 1
            );
75 2
            unset($parameters['file']);
76 1
        }
77
78 684
        $request = new Request(
79 684
            $verb,
80 684
            $this->getUrlFromPath($path),
81 684
            $this->getHeaders()
82 342
        );
83
84 684
        return $request->withUri(
85 684
            $request->getUri()->withQuery(
86 684
                http_build_query($parameters)
87 342
            )
88 342
        );
89
    }
90
91
    /**
92
     * Retrieves http response for a request with the delete method.
93
     *
94
     * @param  string $path
95
     * @param  array  $parameters
96
     *
97
     * @return object
98
     */
99 62
    public function delete($path, $parameters = [])
100
    {
101 62
        $request = $this->getRequest(static::HTTP_DELETE, $path, $parameters);
102
103 62
        return $this->sendRequest($request);
104
    }
105
106
    /**
107
     * Retrieves http response for a request with the get method.
108
     *
109
     * @param  string $path
110
     * @param  array  $parameters
111
     *
112
     * @return object
113
     */
114 312
    public function get($path, $parameters = [])
115
    {
116 312
        $request = $this->getRequest(static::HTTP_GET, $path, $parameters);
117
118 312
        return $this->sendRequest($request);
119
    }
120
121
    /**
122
     * Creates and returns a request.
123
     *
124
     * @param  string $method
125
     * @param  string $path
126
     * @param  array  $parameters
127
     *
128
     * @return RequestInterface
129
     */
130 684
    public function getRequest($method, $path, $parameters = [], $authenticated = true)
131
    {
132 684
        $request = $this->createRequest($method, $path, $parameters);
133
134 684
        if ($authenticated) {
135 682
            $request = $this->authenticateRequest($request);
136 341
        }
137
138 684
        return $request;
139
    }
140
141
    /**
142
     * Retrieves default headers.
143
     *
144
     * @return array
145
     */
146 684
    protected function getHeaders()
147
    {
148 684
        return [];
149
    }
150
151
    /**
152
     * Prepares an array of important exception parts based on composition of a
153
     * given exception.
154
     *
155
     * @param  RequestException  $requestException
156
     *
157
     * @return array
158
     */
159 8
    private function getRequestExceptionParts(RequestException $requestException)
160
    {
161 8
        $response = $requestException->getResponse();
162 8
        $parts = [];
163 8
        $parts['reason'] = $response ? $response->getReasonPhrase() : $requestException->getMessage();
164 8
        $parts['code'] = $response ? $response->getStatusCode() : $requestException->getCode();
165 8
        $parts['body'] = $response ? $response->getBody() : null;
166
167 8
        return $parts;
168
    }
169
170
    /**
171
     * Creates an array of request options based on the current status of the
172
     * http client.
173
     *
174
     * @return array
175
     */
176 680
    protected function getRequestOptions()
177
    {
178
        $options = [
179 680
            'proxy' => Configuration::get('proxy')
180 340
        ];
181
182 680
        if (!empty(array_filter($this->multipartResources))) {
183 2
            $options['multipart'] = $this->multipartResources;
184 1
        }
185
186 680
        return $options;
187
    }
188
189
    /**
190
     * Creates fully qualified domain from given path.
191
     *
192
     * @param  string  $path
193
     *
194
     * @return string
195
     */
196 684
    protected function getUrlFromPath($path = '/')
197
    {
198 684
        return Configuration::get('domain').'/'.Configuration::get('version').'/'.ltrim($path, '/');
199
    }
200
201
    /**
202
     * Retrieves http response for a request with the post method.
203
     *
204
     * @param  string $path
205
     * @param  array  $parameters
206
     *
207
     * @return object
208
     */
209 86
    public function post($path, $parameters)
210
    {
211 86
        $request = $this->getRequest(static::HTTP_POST, $path, $parameters);
212
213 86
        return $this->sendRequest($request);
214
    }
215
216
    /**
217
     * Retrieves http response for a request with the put method.
218
     *
219
     * @param  string $path
220
     * @param  array  $parameters
221
     *
222
     * @return object
223
     */
224 218
    public function put($path, $parameters)
225
    {
226 218
        $request = $this->getRequest(static::HTTP_PUT, $path, $parameters);
227
228 218
        return $this->sendRequest($request);
229
    }
230
231
    /**
232
     * Retrieves http response for a request with the put method,
233
     * ensuring parameters are passed as body.
234
     *
235
     * @param  string $path
236
     * @param  array  $parameters
237
     *
238
     * @return object
239
     */
240 2
    public function putAsBody($path, $parameters)
241
    {
242 2
        $request = $this->getRequest(static::HTTP_PUT, $path)
243 2
            ->withBody(Psr7\stream_for(json_encode($parameters)));
244
245 2
        return $this->sendRequest($request);
246
    }
247
248
    /**
249
     * Adds a given resource to multipart stream collection, to be processed by next request.
250
     *
251
     * @param  string                                           $name
252
     * @param  resource|string|Psr\Http\Message\StreamInterface $resource
253
     *
254
     * @return void
255
     */
256 2
    protected function queueResourceAs($name, $resource)
257
    {
258 2
        array_push($this->multipartResources, [
259 2
            'name' => $name,
260 2
            'contents' => $resource,
261 1
        ]);
262 2
    }
263
264
    /**
265
     * Retrieves http response for a given request.
266
     *
267
     * @param  RequestInterface $request
268
     *
269
     * @return object
270
     * @throws Exceptions\Exception
271
     */
272 680
    protected function sendRequest(RequestInterface $request)
273
    {
274
        try {
275 680
            $response = $this->httpClient->send(
276 680
                $request,
277 680
                $this->getRequestOptions()
278 340
            );
279
280 672
            $this->multipartResources = [];
281
282 672
            return json_decode($response->getBody());
283 8
        } catch (RequestException $e) {
284 8
            $this->throwRequestException($e);
285
        }
286
    } // @codeCoverageIgnore
287
288
    /**
289
     * Updates the http client.
290
     *
291
     * @param HttpClientInterface  $httpClient
292
     *
293
     * @return Http
294
     */
295 680
    public function setClient(HttpClientInterface $httpClient)
296
    {
297 680
        $this->httpClient = $httpClient;
298
299 680
        return $this;
300
    }
301
302
    /**
303
     * Creates local exception from guzzle request exception, which includes
304
     * response body.
305
     *
306
     * @param  RequestException  $requestException
307
     *
308
     * @return void
309
     * @throws Exceptions\Exception
310
     */
311 8
    protected function throwRequestException(RequestException $requestException)
312
    {
313 8
        $exceptionParts = $this->getRequestExceptionParts($requestException);
314
315 8
        $exception = new Exceptions\Exception(
316 8
            $exceptionParts['reason'],
317 8
            $exceptionParts['code'],
318 4
            $requestException
319 4
        );
320
321 8
        $body = $exceptionParts['body'];
322 8
        $json = json_decode($body);
323
324 8
        if (json_last_error() == JSON_ERROR_NONE) {
325 5
            throw $exception->setResponseBody($json);
326
        }
327
328 3
        throw $exception->setResponseBody($body);
329
    }
330
}
331