RestRequest   B
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 378
Duplicated Lines 0 %

Test Coverage

Coverage 91.26%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 39
c 1
b 1
f 0
dl 0
loc 378
ccs 94
cts 103
cp 0.9126
rs 8.2857

21 Methods

Rating   Name   Duplication   Size   Complexity  
A setFileParameters() 0 4 2
B createRequest() 0 25 5
A __construct() 0 4 2
A rawPut() 0 3 1
A rawPost() 0 3 1
A setModelProperties() 0 11 4
A addQueryResultOrder() 0 3 1
A setTransportLanguage() 0 4 1
A rawGet() 0 3 1
A getClient() 0 3 1
A setHeaders() 0 4 2
A sendRequest() 0 9 2
A addQueryCondition() 0 3 1
A setGetParameters() 0 5 2
A rawPatch() 0 3 1
A addErrorHandler() 0 14 4
A setPostParameters() 0 4 2
A rawDelete() 0 3 1
A setBody() 0 4 2
A authenticate() 0 3 1
B rawRequest() 0 30 2
1
<?php
2
3
namespace Trucker\Requests;
4
5
use Guzzle\Common\Event;
6
use Guzzle\Http\Client;
7
use Guzzle\Http\Exception\BadResponseException;
8
use Guzzle\Http\Message\Request;
9
use Illuminate\Container\Container;
10
use Trucker\Facades\Config;
11
use Trucker\Facades\ErrorHandlerFactory;
12
use Trucker\Facades\ResponseInterpreterFactory;
13
use Trucker\Facades\TransporterFactory;
14
use Trucker\Finders\Conditions\QueryConditionInterface;
15
use Trucker\Finders\Conditions\QueryResultOrderInterface;
16
use Trucker\Requests\Auth\AuthenticationInterface;
17
use Trucker\Resource\Model;
18
use Trucker\Responses\RawResponse;
19
20
class RestRequest implements RequestableInterface
21
{
22
    /**
23
     * The IoC Container.
24
     *
25
     * @var Container
26
     */
27
    protected $app;
28
29
    /**
30
     * Request client.
31
     *
32
     * @var \Guzzle\Http\Client
33
     */
34
    protected $client;
35
36
    /**
37
     * Request object managed by this
38
     * class.
39
     *
40
     * @var Request
41
     */
42
    protected $request;
43
44
    /**
45
     * Build a new RestRequest.
46
     *
47
     * @param Container $app
48
     * @param Client    $client
49
     *
50
     * @throws \Guzzle\Common\Exception\RuntimeException
51
     */
52 38
    public function __construct(Container $app, $client = null)
53
    {
54 38
        $this->app = $app;
55 38
        $this->client = null == $client ? new Client() : $client;
56 38
    }
57
58
    /**
59
     * Getter function to access the HTTP Client.
60
     *
61
     * @return Client
62
     */
63
    public function getClient()
64
    {
65
        return $this->client;
66
    }
67
68
    /**
69
     * Function to create a Guzzle HTTP request.
70
     *
71
     * @param string $baseUri         The protocol + host
72
     * @param string $path            The URI path after the host
73
     * @param string $httpMethod      The HTTP method to use for the request (GET, PUT, POST, DELTE etc.)
74
     * @param array  $requestHeaders  Any additional headers for the request
75
     * @param string $httpMethodParam Post parameter to set with a string that
76
     *                                contains the HTTP method type sent with a POST
77
     *
78
     * @return Request
79
     *
80
     * @throws \Exception
81
     */
82 36
    public function createRequest($baseUri, $path, $httpMethod = 'GET', array $requestHeaders = [], $httpMethodParam = null)
83
    {
84 36
        $this->client->setBaseUrl($baseUri);
85
86 36
        if (!in_array(strtolower($httpMethod), ['get', 'put', 'post', 'patch', 'delete', 'head'], true)) {
87
            throw new \Exception('Invalid HTTP method');
88
        }
89
90 36
        $method = strtolower($httpMethod);
91 36
        $method = 'patch' === $method ? 'put' : $method; //override patch calls with put
92
93 36
        if (null != $httpMethodParam && in_array($method, ['put', 'post', 'patch', 'delete'], true)) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $httpMethodParam of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
94 4
            $this->request = $this->client->post($path);
95 4
            $this->request->setPostField($httpMethodParam, strtoupper($method));
0 ignored issues
show
Bug introduced by
The method setPostField() does not exist on Guzzle\Http\Message\RequestInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Guzzle\Http\Message\Request. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
            $this->request->/** @scrutinizer ignore-call */ 
96
                            setPostField($httpMethodParam, strtoupper($method));
Loading history...
96
        } else {
97 32
            $this->request = $this->client->{$method}($path);
98
        }
99
100
        //set any additional headers on the request
101 36
        $this->setHeaders($requestHeaders);
102
103
        //setup how we get data back (xml, json etc)
104 36
        $this->setTransportLanguage();
105
106 36
        return $this->request;
107
    }
108
109
    /**
110
     * Function to set headers on the request.
111
     *
112
     * @param array $requestHeaders Any additional headers for the request
113
     */
114 36
    public function setHeaders(array $requestHeaders = [])
115
    {
116 36
        foreach ($requestHeaders as $header => $value) {
117 3
            $this->request->setHeader($header, $value);
118
        }
119 36
    }
120
121
    /**
122
     * Function to set given file parameters
123
     * on the request.
124
     *
125
     * @param array $params File parameters to set
126
     */
127 5
    public function setBody($body, $contentType = null)
128
    {
129 5
        if (method_exists($this->request, 'setBody')) {
130 4
            $this->request->setBody($body, $contentType);
131
        }
132 5
    }
133
134
    /**
135
     * Function to set POST parameters onto the request.
136
     *
137
     * @param array $params Key value array of post params
138
     */
139 6
    public function setPostParameters(array $params = [])
140
    {
141 6
        foreach ($params as $key => $value) {
142 4
            $this->request->setPostField($key, $value);
0 ignored issues
show
introduced by
The method setPostField() does not exist on Guzzle\Http\Message\Request. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

142
            $this->request->/** @scrutinizer ignore-call */ 
143
                            setPostField($key, $value);
Loading history...
143
        }
144 6
    }
145
146
    /**
147
     * Functio to set GET parameters onto the
148
     * request.
149
     *
150
     * @param array $params Key value array of get params
151
     */
152 12
    public function setGetParameters(array $params = [])
153
    {
154 12
        $query = $this->request->getQuery();
155 12
        foreach ($params as $key => $val) {
156 8
            $query->add($key, $val);
157
        }
158 12
    }
159
160
    /**
161
     * Function to set given file parameters
162
     * on the request.
163
     *
164
     * @param array $params File parameters to set
165
     */
166 6
    public function setFileParameters(array $params = [])
167
    {
168 6
        foreach ($params as $key => $value) {
169 1
            $this->request->addPostFile($key, $value);
0 ignored issues
show
introduced by
The method addPostFile() does not exist on Guzzle\Http\Message\Request. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

169
            $this->request->/** @scrutinizer ignore-call */ 
170
                            addPostFile($key, $value);
Loading history...
170
        }
171 6
    }
172
173
    /**
174
     * Function to set the entities properties on the
175
     * request object taking into account any properties that
176
     * are read only etc.
177
     *
178
     * @param  \Trucker\Resource\Model
179
     */
180 9
    public function setModelProperties(Model $model)
181
    {
182 9
        $cantSet = $model->getReadOnlyFields();
183
184
        //set the property attributes
185 9
        foreach ($model->attributes() as $key => $value) {
186 9
            if (in_array($key, $model->getFileFields(), true)) {
187 1
                $this->request->addPostFile($key, $value);
188
            } else {
189 9
                if (!in_array($key, $cantSet, true)) {
190 9
                    $this->request->setPostField($key, $value);
191
                }
192
            }
193
        }
194 9
    }
195
196
    /**
197
     * Function to set the language of data transport. Uses
198
     * TransporterFactory to pull a Transportable object
199
     * and set up the request.
200
     */
201 36
    public function setTransportLanguage()
202
    {
203 36
        $transporter = TransporterFactory::build();
0 ignored issues
show
Bug introduced by
The method build() does not exist on Trucker\Facades\TransporterFactory. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

203
        /** @scrutinizer ignore-call */ 
204
        $transporter = TransporterFactory::build();
Loading history...
204 36
        $transporter->setHeaderOnRequest($this->request);
205 36
    }
206
207
    /**
208
     * Function to add an error handler to the request.  This could be used.
209
     *
210
     * @param int      $httpStatus      HTTP status to error handle (-1 matches all)
211
     * @param \Closure $func            Function to call on error
212
     * @param bool     $stopPropagation Boolean as to wether to stop event propagation
213
     */
214 1
    public function addErrorHandler($httpStatus, \Closure $func, $stopPropagation = true)
215
    {
216 1
        $request = $this->request;
217 1
        $this->request->getEventDispatcher()->addListener(
218 1
            'request.error',
219 1
            function (Event $event) use ($httpStatus, $stopPropagation, $func, $request) {
220
                if ($httpStatus == -1 || $event['response']->getStatusCode() == $httpStatus) {
0 ignored issues
show
Bug introduced by
The method getStatusCode() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

220
                if ($httpStatus == -1 || $event['response']->/** @scrutinizer ignore-call */ getStatusCode() == $httpStatus) {

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...
221
                    // Stop other events from firing if needed
222
                    if ($stopPropagation) {
223
                        $event->stopPropagation();
224
                    }
225
226
                    //execute the callback
227
                    $func($event, $request);
228
                }
229 1
            }
230
        );
231 1
    }
232
233
    /**
234
     * Function to add Query conditions to the request.
235
     *
236
     * @param QueryConditionInterface $condition condition to add to the request
237
     */
238 2
    public function addQueryCondition(QueryConditionInterface $condition)
239
    {
240 2
        $condition->addToRequest($this->request);
241 2
    }
242
243
    /**
244
     * Function to add Query result ordering conditions to the request.
245
     *
246
     * @param QueryResultOrderInterface $resultOrder
247
     */
248 2
    public function addQueryResultOrder(QueryResultOrderInterface $resultOrder)
249
    {
250 2
        $resultOrder->addToRequest($this->request);
251 2
    }
252
253
    /**
254
     * Function to add authentication to the request.
255
     *
256
     * @param AuthenticationInterface $auth
257
     */
258 1
    public function authenticate(AuthenticationInterface $auth)
259
    {
260 1
        $auth->authenticateRequest($this->request);
261 1
    }
262
263
    /**
264
     * Function to send the request to the remote API.
265
     *
266
     * @return \Trucker\Responses\Response
267
     */
268 24
    public function sendRequest()
269
    {
270
        try {
271 24
            $response = $this->request->send();
272 6
        } catch (BadResponseException $e) {
273 6
            $response = $e->getResponse();
274
        }
275
276 24
        return $this->app->make('trucker.response')->newInstance($this->app, $response);
277
    }
278
279
    /**
280
     * Function to execute a raw GET request.
281
     *
282
     * @param string $uri     uri to hit (i.e. /users)
283
     * @param array  $params  Querystring parameters to send
284
     * @param array  $headers Optional headers to use
285
     *
286
     * @return \Trucker\Responses\RawResponse
287
     */
288 1
    public function rawGet($uri, array $params = [], array $headers = [])
289
    {
290 1
        return $this->rawRequest($uri, 'GET', [], $params, [], $headers);
291
    }
292
293
    /**
294
     * Function to execute a raw POST request.
295
     *
296
     * @param string $uri       uri to hit (i.e. /users)
297
     * @param array  $params    POST parameters to send
298
     * @param array  $getParams Querystring parameters to send
299
     * @param array  $files     files to send (key = name, value = path)
300
     * @param array  $headers   Optional headers to use
301
     *
302
     * @return \Trucker\Responses\RawResponse
303
     */
304 1
    public function rawPost($uri, array $params = [], array $getParams = [], array $files = [], array $headers = [])
305
    {
306 1
        return $this->rawRequest($uri, 'POST', $params, $getParams, $files, $headers);
307
    }
308
309
    /**
310
     * Function to execute a raw PUT request.
311
     *
312
     * @param string $uri       uri to hit (i.e. /users)
313
     * @param array  $params    PUT parameters to send
314
     * @param array  $getParams Querystring parameters to send
315
     * @param array  $files     files to send (key = name, value = path)
316
     * @param array  $headers   Optional headers to use
317
     *
318
     * @return \Trucker\Responses\RawResponse
319
     */
320 1
    public function rawPut($uri, array $params = [], array $getParams = [], array $files = [], array $headers = [])
321
    {
322 1
        return $this->rawRequest($uri, 'PUT', $params, $getParams, $files, $headers);
323
    }
324
325
    /**
326
     * Function to execute a raw PATCH request.
327
     *
328
     * @param string $uri       uri to hit (i.e. /users)
329
     * @param array  $params    PATCH parameters to send
330
     * @param array  $getParams Querystring parameters to send
331
     * @param array  $files     files to send (key = name, value = path)
332
     * @param array  $headers   Optional headers to use
333
     *
334
     * @return \Trucker\Responses\RawResponse
335
     */
336 1
    public function rawPatch($uri, array $params = [], array $getParams = [], array $files = [], array $headers = [])
337
    {
338 1
        return $this->rawRequest($uri, 'PATCH', $params, $getParams, $files, $headers);
339
    }
340
341
    /**
342
     * Function to execute a raw DELETE request.
343
     *
344
     * @param string $uri     uri to hit (i.e. /users)
345
     * @param array  $params  Querystring parameters to send
346
     * @param array  $headers Optional headers to use
347
     *
348
     * @return \Trucker\Responses\RawResponse
349
     */
350 1
    public function rawDelete($uri, array $params = [], array $headers = [])
351
    {
352 1
        return $this->rawRequest($uri, 'DELETE', [], $params, [], $headers);
353
    }
354
355
    /**
356
     * Function to execute a raw request on the base URI with the given uri path
357
     * and params.
358
     *
359
     * @param string $uri       uri to hit (i.e. /users)
360
     * @param string $method    Request method (GET, PUT, POST, PATCH, DELETE, etc.)
361
     * @param array  $params    PUT or POST parameters to send
362
     * @param array  $getParams Querystring parameters to send
363
     * @param array  $files     PUT or POST files to send (key = name, value = path)
364
     * @param array  $headers   Optional headers to use
365
     *
366
     * @return \Trucker\Responses\RawResponse
367
     */
368 5
    public function rawRequest($uri, $method, array $params = [], array $getParams = [], array $files = [], array $headers = [])
369
    {
370 5
        $this->request = $this->createRequest(
371 5
            Config::get('request.base_uri'),
0 ignored issues
show
Bug introduced by
The method get() does not exist on Trucker\Facades\Config. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

371
            Config::/** @scrutinizer ignore-call */ 
372
                    get('request.base_uri'),
Loading history...
372 5
            $uri,
373 5
            $method
374
        );
375
376 5
        $this->setPostParameters($params);
377 5
        $this->setGetParameters($getParams);
378 5
        $this->setFileParameters($files);
379 5
        $this->setHeaders($headers);
380
381
        //encode the request body
382
        /** @var \Trucker\Transporters\TransporterInterface $transporter */
383 5
        $transporter = TransporterFactory::build();
384 5
        $transporter->setRequestBody($this, $params);
385
386
        // Trucker\Response
387 5
        $response = $this->sendRequest();
388
389
        //handle clean response with errors
390 5
        if (ResponseInterpreterFactory::build()->invalid($response)) {
0 ignored issues
show
Bug introduced by
The method build() does not exist on Trucker\Facades\ResponseInterpreterFactory. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

390
        if (ResponseInterpreterFactory::/** @scrutinizer ignore-call */ build()->invalid($response)) {
Loading history...
391
            //get the errors and set them to our local collection
392
            $errors = (array) ErrorHandlerFactory::build()->parseErrors($response);
0 ignored issues
show
Bug introduced by
The method build() does not exist on Trucker\Facades\ErrorHandlerFactory. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

392
            $errors = (array) ErrorHandlerFactory::/** @scrutinizer ignore-call */ build()->parseErrors($response);
Loading history...
393
394
            return new RawResponse(false, $response, $errors);
395
        }//end if
396
397 5
        return new RawResponse(true, $response);
398
    }
399
400
    //end rawRequest
401
}
402