DefaultApiClient::makeApiCall()   B
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 2 Features 1
Metric Value
c 4
b 2
f 1
dl 0
loc 30
rs 8.439
cc 5
eloc 15
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
        switch ($response['status']) {
53
            case 200:
54
                $this->resetAuthenticationRetryAttempt();
55
56
                return $this->createResponseObject($response);
57
            case 401:
58
                $this->incrementAuthenticationRetryAttempt();
59
60
                if ($this->isAuthenticationRetryLimitReached()) {
61
                    throw new AccessDeniedException('Authentication retry limit reached.');
62
                }
63
64
                // Once SD-3820 is fixed, implement SWP-92 branch, it will use
65
                // the refresh token functionality, instead of request a new token
66
                // each time this method is called.
67
                $this->getNewToken($request);
68
69
                return $this->makeApiCall($request);
70
        }
71
72
        throw new ClientException(sprintf('The server returned an error with status %s.', $response['status']), $response['status']);
73
    }
74
75
    /**
76
     * Creates response object from response array.
77
     *
78
     * @param  array $response
79
     *
80
     * @return Response API Response object
81
     *
82
     * @throws ClientException Thrown when response object could not be created
83
     */
84
    protected function createResponseObject(array $response)
85
    {
86
        try {
87
            return new Response($response['body'], $response['headers']);
88
        } catch (ResponseException $e) {
89
            throw new ClientException($e->getMessage(), $e->getCode(), $e);
90
        }
91
    }
92
93
    /**
94
     * Adds authentication details to request with OAuth decorator.
95
     *
96
     * @param  RequestInterface $request
97
     *
98
     * @return OAuthDecorator OAuth ready decorated Request
99
     */
100
    protected function authenticateRequest(RequestInterface $request)
101
    {
102
        $authenticatedRequest = new OAuthDecorator($request);
103
        $authenticatedRequest->setAccessToken($this->authenticator->getAccessToken());
104
        $authenticatedRequest->addAuthentication();
105
106
        return $authenticatedRequest;
107
    }
108
109
    /**
110
     * Sends the actual request.
111
     *
112
     * @param  RequestInterface $request
113
     *
114
     * @return Response Response object created from raw response
115
     *
116
     * @throws ClientException Thrown when response could not be created.
117
     */
118
    protected function sendRequest(RequestInterface $request)
119
    {
120
        return $this->client->makeCall(
121
            $request->getFullUrl(),
122
            $this->addDefaultHeaders($request->getHeaders()),
123
            $request->getOptions()
124
        );
125
    }
126
127
    /**
128
     * Refreshes the token via then authenticator.
129
     *
130
     * @param  RequestInterface $request
131
     *
132
     * @return void
133
     */
134
    protected function getNewToken(RequestInterface $request)
135
    {
136
        try {
137
            $this->authenticator->setBaseUrl($request->getBaseUrl());
138
            $this->authenticator->getAuthenticationTokens();
139
        } catch (AuthenticationException $e) {
140
            throw new AccessDeniedException('Could not authenticate against API.', $e->getCode(), $e);
141
        }
142
143
        return;
144
    }
145
146
    /**
147
     * Adds default headers to the headers per request, only if the key
148
     * cannot not be found in the headers per request.
149
     *
150
     * @param array $headers
151
     *
152
     * @return array
153
     */
154
    protected function addDefaultHeaders($headers)
155
    {
156
        foreach ($this->headers as $key => $value) {
157
            if (!isset($headers[$key])) {
158
                $headers[$key] = $value;
159
            }
160
        }
161
162
        return $headers;
163
    }
164
}
165