Completed
Pull Request — master (#105)
by Ambroise
03:37
created

RestClient::executeRequest()   B

Complexity

Conditions 8
Paths 24

Size

Total Lines 57
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 8.0439

Importance

Changes 9
Bugs 0 Features 2
Metric Value
cc 8
eloc 38
c 9
b 0
f 2
nc 24
nop 3
dl 0
loc 57
ccs 31
cts 34
cp 0.9118
crap 8.0439
rs 8.0675

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Mapado\RestClientSdk;
6
7
use GuzzleHttp\ClientInterface;
8
use GuzzleHttp\Exception\ClientException;
9
use GuzzleHttp\Exception\RequestException;
10
use GuzzleHttp\Exception\TransferException;
11
use Mapado\RestClientSdk\Exception\RestClientException;
12
use Mapado\RestClientSdk\Exception\RestException;
13
use Psr\Http\Message\ResponseInterface;
14
use Symfony\Component\HttpFoundation\Request;
15
16
/**
17
 * Class RestClient
18
 *
19
 * @author Julien Deniau <[email protected]>
20
 */
21
class RestClient
22
{
23
    /**
24
     * @var ClientInterface
25
     */
26
    private $httpClient;
27
28
    /**
29
     * @var ?string
30
     */
31
    private $baseUrl;
32
33
    /**
34
     * @var bool
35
     */
36
    private $logHistory;
37
38
    /**
39
     * @var array
40
     */
41
    private $requestHistory;
42
43
    /**
44
     * @var ?Request
45
     */
46
    private $currentRequest;
47
48
    public function __construct(
49
        ClientInterface $httpClient,
50
        ?string $baseUrl = null
51
    ) {
52 1
        $this->httpClient = $httpClient;
53 1
        $this->baseUrl =
54 1
            null !== $baseUrl && '/' === mb_substr($baseUrl, -1)
55
                ? mb_substr($baseUrl, 0, -1)
56 1
                : $baseUrl;
57 1
        $this->logHistory = false;
58 1
        $this->requestHistory = [];
59 1
    }
60
61
    public function isHistoryLogged(): bool
62
    {
63 1
        return $this->logHistory;
64
    }
65
66
    public function setCurrentRequest(Request $currentRequest): self
67
    {
68
        $this->currentRequest = $currentRequest;
69
70
        return $this;
71
    }
72
73
    public function setLogHistory(bool $logHistory): self
74
    {
75 1
        $this->logHistory = $logHistory;
76
77 1
        return $this;
78
    }
79
80
    public function getRequestHistory(): array
81
    {
82 1
        return $this->requestHistory;
83
    }
84
85
    /**
86
     * get a path
87
     *
88
     * @return array|ResponseInterface|null
89
     *
90
     * @throws RestException
91
     */
92
    public function get(string $path, array $parameters = [])
93
    {
94 1
        $requestUrl = $this->baseUrl . $path;
95
        try {
96 1
            return $this->executeRequest('GET', $requestUrl, $parameters);
97 1
        } catch (ClientException $e) {
98 1
            $response = $e->getResponse();
99 1
            if (null !== $response && 404 === $response->getStatusCode()) {
100 1
                return null;
101
            }
102 1
            throw new RestClientException('Error while getting resource', $path, [], 7, $e);
103 1
        } catch (TransferException $e) {
104 1
            throw new RestException('Error while getting resource', $path, [], 1, $e);
105
        }
106
    }
107
108
    /**
109
     * @throws RestException
110
     */
111
    public function delete(string $path): void
112
    {
113
        try {
114 1
            $this->executeRequest('DELETE', $this->baseUrl . $path);
115 1
        } catch (ClientException $e) {
116 1
            return;
117 1
        } catch (TransferException $e) {
118 1
            throw new RestException('Error while deleting resource', $path, [], 2, $e);
119
        }
120 1
    }
121
122
    /**
123
     * @return array|ResponseInterface
124
     *
125
     * @throws RestClientException
126
     * @throws RestException
127
     */
128
    public function post(string $path, array $data, array $parameters = [])
129
    {
130 1
        $parameters['json'] = $data;
131
        try {
132 1
            return $this->executeRequest(
133 1
                'POST',
134 1
                $this->baseUrl . $path,
135 1
                $parameters
136
            );
137 1
        } catch (ClientException $e) {
138 1
            throw new RestClientException('Cannot create resource', $path, [], 3, $e);
139 1
        } catch (TransferException $e) {
140 1
            throw new RestException('Error while posting resource', $path, [], 4, $e);
141
        }
142
    }
143
144
    /**
145
     * @return array|ResponseInterface
146
     *
147
     * @throws RestClientException
148
     * @throws RestException
149
     */
150
    public function put(string $path, array $data, array $parameters = [])
151
    {
152 1
        $parameters['json'] = $data;
153
154
        try {
155 1
            return $this->executeRequest(
156 1
                'PUT',
157 1
                $this->baseUrl . $path,
158 1
                $parameters
159
            );
160 1
        } catch (ClientException $e) {
161 1
            throw new RestClientException('Cannot update resource', $path, [], 5, $e);
162 1
        } catch (TransferException $e) {
163 1
            throw new RestException('Error while puting resource', $path, [], 6, $e);
164
        }
165
    }
166
167
    /**
168
     * Merge default parameters.
169
     */
170
    protected function mergeDefaultParameters(array $parameters): array
171
    {
172 1
        $request = $this->getCurrentRequest();
173
174 1
        $defaultParameters = ['version' => '1.0'];
175 1
        if (null !== $request) {
176
            $defaultParameters['headers'] = ['Referer' => $request->getUri()];
177
        }
178
179
        /** @var array|null $out */
180 1
        $out = array_replace_recursive($defaultParameters, $parameters);
181
182 1
        if (null === $out) {
183
            throw new \RuntimeException(sprintf('Error while calling array_replace_recursive in %s. This should not happen.', __METHOD__));
184
        }
185
186 1
        return $out;
187
    }
188
189
    protected function getCurrentRequest(): ?Request
190
    {
191 1
        if ('cli' === \PHP_SAPI) {
192
            // we are in cli mode, do not bother to get request
193 1
            return null;
194
        }
195
196
        if (!$this->currentRequest) {
197
            $this->currentRequest = Request::createFromGlobals();
198
        }
199
200
        return $this->currentRequest;
201
    }
202
203
    /**
204
     * Executes request.
205
     *
206
     * @return ResponseInterface|array
207
     *
208
     * @throws TransferException
209
     */
210
    private function executeRequest(
211
        string $method,
212
        string $url,
213
        array $parameters = []
214
    ) {
215 1
        $parameters = $this->mergeDefaultParameters($parameters);
216
217 1
        $startTime = null;
218 1
        if ($this->isHistoryLogged()) {
219 1
            $startTime = microtime(true);
220
        }
221
222
        try {
223 1
            $response = $this->httpClient->request($method, $url, $parameters);
224 1
            $this->logRequest(
225 1
                $startTime,
226 1
                $method,
227 1
                $url,
228 1
                $parameters,
229 1
                $response
230
            );
231 1
        } catch (RequestException $e) {
232 1
            $this->logRequest(
233 1
                $startTime,
234 1
                $method,
235 1
                $url,
236 1
                $parameters,
237 1
                $e->getResponse()
238
            );
239 1
            throw $e;
240
        } catch (TransferException $e) {
241
            $this->logRequest($startTime, $method, $url, $parameters);
242
            throw $e;
243
        }
244
245 1
        $headers = $response->getHeaders();
246 1
        $jsonContentTypeList = ['application/ld+json', 'application/json'];
247
248 1
        $requestIsJson = false;
249
250
        $responseContentType =
251 1
            $headers['Content-Type'] ?? $headers['content-type'] ?? null;
252 1
        if ($responseContentType) {
253 1
            foreach ($jsonContentTypeList as $contentType) {
254
                if (
255 1
                    false !== mb_stripos($responseContentType[0], $contentType)
256
                ) {
257 1
                    $requestIsJson = true;
258 1
                    break;
259
                }
260
            }
261
        }
262
263 1
        if ($requestIsJson) {
264 1
            return json_decode((string) $response->getBody(), true);
265
        } else {
266 1
            return $response;
267
        }
268
    }
269
270
    private function logRequest(
271
        ?float $startTime,
272
        string $method,
273
        string $url,
274
        array $parameters,
275
        ?ResponseInterface $response = null
276
    ): void {
277 1
        if ($this->isHistoryLogged()) {
278 1
            $queryTime = microtime(true) - $startTime;
279
280 1
            $this->requestHistory[] = [
281 1
                'method' => $method,
282 1
                'url' => $url,
283 1
                'parameters' => $parameters,
284 1
                'response' => $response,
285 1
                'responseBody' => $response
286 1
                    ? json_decode((string) $response->getBody(), true)
287
                    : null,
288 1
                'queryTime' => $queryTime,
289 1
                'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),
290
            ];
291
        }
292 1
    }
293
}
294