Completed
Push — master ( 3f7c36...9787b3 )
by Paweł
03:09
created

DefaultApiClient::addDefaultHeaders()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 10
rs 9.4286
cc 3
eloc 5
nc 3
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);
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)
120
    {
121
        return $this->client->makeCall(
122
            $request->getFullUrl(),
123
            $this->addDefaultHeaders($request->getHeaders()),
124
            $request->getOptions()
125
        );
126
    }
127
128
    /**
129
     * Refreshes the token via then authenticator.
130
     *
131
     * @param  RequestInterface $request
132
     *
133
     * @return void
134
     */
135
    protected function getNewToken(RequestInterface $request)
136
    {
137
        try {
138
            $this->authenticator->setBaseUrl($request->getBaseUrl());
139
            $this->authenticator->getAuthenticationTokens();
140
        } catch (AuthenticationException $e) {
141
            throw new AccessDeniedException('Could not authenticate against API.', $e->getCode(), $e);
142
        }
143
144
        return;
145
    }
146
147
    /**
148
     * Adds default headers to the headers per request, only if the key
149
     * cannot not be found in the headers per request.
150
     *
151
     * @param array $headers
152
     *
153
     * @return array
154
     */
155
    protected function addDefaultHeaders($headers)
156
    {
157
        foreach ($this->headers as $key => $value) {
158
            if (!isset($headers[$key])) {
159
                $headers[$key] = $value;
160
            }
161
        }
162
163
        return $headers;
164
    }
165
}
166