Passed
Branch master (0d8fc3)
by Tomáš
12:26
created

DefaultClient   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 28
c 1
b 0
f 0
dl 0
loc 88
ccs 32
cts 32
cp 1
rs 10
wmc 11

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A validateResponse() 0 5 1
A getContents() 0 14 3
A parseContents() 0 10 3
A resolveUrl() 0 10 2
A call() 0 20 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Inspirum\Balikobot\Client;
6
7
use GuzzleHttp\Psr7\InflateStream;
8
use Inspirum\Balikobot\Client\Response\Validator;
9
use Inspirum\Balikobot\Exception\BadRequestException;
10
use JsonException;
11
use Psr\Http\Message\StreamInterface;
12
use Throwable;
13
use function json_decode;
14
use function sprintf;
15
use function str_replace;
16
use function trim;
17
use const JSON_THROW_ON_ERROR;
18
19
final class DefaultClient implements Client
20
{
21 504
    public function __construct(
22
        private Requester $requester,
23
        private Validator $validator,
24
    ) {
25
    }
26
27
    /** @inheritDoc */
28 504
    public function call(
29
        string $baseUrl,
30
        ?string $carrier,
31
        string $method,
32
        array $data = [],
33
        ?string $path = null,
34
        bool $shouldHaveStatus = true,
35
        bool $gzip = false,
36
    ): array {
37 504
        $url = $this->resolveUrl($baseUrl, $carrier, $method, $path, $gzip);
38
39 504
        $response = $this->requester->request($url, $data);
40
41 504
        $statusCode    = $response->getStatusCode();
42 504
        $contents      = $this->getContents($response->getBody(), $gzip);
43 504
        $parsedContent = $this->parseContents($contents, $statusCode < 300);
44
45 503
        $this->validateResponse($statusCode, $parsedContent, $shouldHaveStatus);
46
47 202
        return $parsedContent;
48
    }
49
50 504
    private function resolveUrl(string $baseUrl, ?string $carrier, string $method, ?string $path, bool $gzip): string
51
    {
52 504
        $url = sprintf('%s/%s/%s', $carrier, $method, $path ?? '');
53 504
        $url = trim(str_replace('//', '/', $url), '/');
54
55 504
        if ($gzip) {
56 426
            $url = sprintf('%s?gzip=1', $url);
57
        }
58
59 504
        return sprintf('%s/%s', $baseUrl, $url);
60
    }
61
62
    /**
63
     * @return array<string,mixed>
64
     *
65
     * @throws \Inspirum\Balikobot\Exception\Exception
66
     */
67 504
    private function parseContents(string $content, bool $throwOnError): array
68
    {
69
        try {
70 504
            return json_decode($content, true, flags: JSON_THROW_ON_ERROR);
71 2
        } catch (JsonException $exception) {
72 2
            if ($throwOnError) {
73 1
                throw new BadRequestException([], 400, $exception, 'Cannot parse response data');
74
            }
75
76 1
            return [];
77
        }
78
    }
79
80 504
    private function getContents(StreamInterface $stream, bool $gzip): string
81
    {
82 504
        if ($gzip === false) {
83 78
            return $stream->getContents();
84
        }
85
86
        try {
87 426
            $inflateStream = new InflateStream($stream);
88
89 426
            return $inflateStream->getContents();
90 40
        } catch (Throwable) {
91 40
            $stream->rewind();
92
93 40
            return $stream->getContents();
94
        }
95
    }
96
97
    /**
98
     * @param array<string,mixed> $response
99
     *
100
     * @throws \Inspirum\Balikobot\Exception\Exception
101
     */
102 503
    private function validateResponse(int $statusCode, array $response, bool $shouldHaveStatus): void
103
    {
104 503
        $this->validator->validateStatus($statusCode, $response);
105
106 485
        $this->validator->validateResponseStatus($response, null, $shouldHaveStatus);
107
    }
108
}
109