Completed
Pull Request — master (#19)
by Mischa
03:32
created

DefaultApiClient::makeApiCall()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 31
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 31
rs 8.439
cc 5
eloc 14
nc 8
nop 1
1
<?php
2
3
/**
4
 * This file is part of the PHP SDK library for the Superdesk Content API.
5
 *
6
 * Copyright 2015 Sourcefabric z.u. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú.
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace Superdesk\ContentApiSdk\Client;
16
17
use Superdesk\ContentApiSdk\API\Request\RequestInterface;
18
use Superdesk\ContentApiSdk\API\Request\OAuthDecorator;
19
use Superdesk\ContentApiSdk\API\Response;
20
use Superdesk\ContentApiSdk\ContentApiSdk;
21
use Superdesk\ContentApiSdk\Exception\AuthenticationException;
22
use Superdesk\ContentApiSdk\Exception\AccessDeniedException;
23
use Superdesk\ContentApiSdk\Exception\ClientException;
24
use Superdesk\ContentApiSdk\Exception\ResponseException;
25
26
/**
27
 * Request client that implements all methods regarding basic request/response
28
 * handling for the Content API.
29
 */
30
class DefaultApiClient extends AbstractApiClient
31
{
32
    /**
33
     * Default request headers.
34
     *
35
     * @var array
36
     */
37
    protected $headers = array(
38
        'Accept' => 'application/json'
39
    );
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function makeApiCall(RequestInterface $request)
45
    {
46
        if ($this->authenticator->getAccessToken() === null) {
47
            $this->getNewToken($request);
48
        }
49
50
        $response = $this->sendRequest($this->authenticateRequest($request));
51
52
        if ($response['status'] === 200) {
53
54
            $this->resetAuthenticationRetryAttempt();
55
56
            return $this->createResponseObject($response);
0 ignored issues
show
Documentation introduced by
$response is of type object<Superdesk\ContentApiSdk\API\Response>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
57
        } elseif ($response['status'] === 401) {
58
59
            $this->incrementAuthenticationRetryAttempt();
60
61
            if ($this->isAuthenticationRetryLimitReached()) {
62
                throw new AccessDeniedException('Authentication retry limit reached.');
63
            }
64
65
            // Once SD-3820 is fixed, implement SWP-92 branch, it will use
66
            // the refresh token functionality, instead of request a new token
67
            // each time this method is called.
68
            $this->getNewToken($request);
69
70
            return $this->makeApiCall($request);
71
        }
72
73
        throw new ClientException(sprintf('The server returned an error with status %s.', $response['status']), $response['status']);
74
    }
75
76
    /**
77
     * Creates response object from response array.
78
     *
79
     * @param  array $response
80
     *
81
     * @return Response API Response object
82
     *
83
     * @throws ClientException Thrown when response object could not be created
84
     */
85
    protected function createResponseObject(array $response)
86
    {
87
        try {
88
            return new Response($response['body'], $response['headers']);
89
        } catch (ResponseException $e) {
90
            throw new ClientException($e->getMessage(), $e->getCode(), $e);
91
        }
92
    }
93
94
    /**
95
     * Adds authentication details to request with OAuth decorator.
96
     *
97
     * @param  RequestInterface $request
98
     *
99
     * @return OAuthDecorator OAuth ready decorated Request
100
     */
101
    protected function authenticateRequest(RequestInterface $request)
102
    {
103
        $authenticatedRequest = new OAuthDecorator($request);
104
        $authenticatedRequest->setAccessToken($this->authenticator->getAccessToken());
105
        $authenticatedRequest->addAuthentication();
106
107
        return $authenticatedRequest;
108
    }
109
110
    /**
111
     * Sends the actual request.
112
     *
113
     * @param  RequestInterface $request
114
     *
115
     * @return Response Response object created from raw response
116
     *
117
     * @throws ClientException Thrown when response could not be created.
118
     */
119
    protected function sendRequest(RequestInterface $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
120
    {
121
        echo 456; exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method sendRequest() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
122
        return $this->client->makeCall(
0 ignored issues
show
Unused Code introduced by
return $this->client->ma...request->getOptions()); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
123
            $request->getFullUrl(),
124
            $this->addDefaultHeaders($request->getHeaders()),
125
            $request->getOptions()
126
        );
127
    }
128
129
    /**
130
     * Refreshes the token via then authenticator.
131
     *
132
     * @param  RequestInterface $request
133
     *
134
     * @return void
135
     */
136
    protected function getNewToken(RequestInterface $request)
137
    {
138
        try {
139
            $this->authenticator->setBaseUrl($request->getBaseUrl());
140
            $this->authenticator->getAuthenticationTokens();
141
        } catch (AuthenticationException $e) {
142
            throw new AccessDeniedException('Could not authenticate against API.', $e->getCode(), $e);
143
        }
144
145
        return;
146
    }
147
148
    /**
149
     * Adds default headers to the headers per request, only if the key
150
     * cannot not be found in the headers per request.
151
     *
152
     * @param array $headers
153
     *
154
     * @return array
155
     */
156
    protected function addDefaultHeaders($headers)
157
    {
158
        foreach ($this->headers as $key => $value) {
159
            if (!isset($headers[$key])) {
160
                $headers[$key] = $value;
161
            }
162
        }
163
164
        return $headers;
165
    }
166
}
167