DefaultClient::validateResponse()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
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 569
    public function __construct(
22
        private readonly Requester $requester,
23
        private readonly Validator $validator,
24
    ) {
25 569
    }
26
27
    /** @inheritDoc */
28 569
    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 569
        $url = $this->resolveUrl($baseUrl, $carrier, $method, $path, $gzip);
38
39 569
        $response = $this->requester->request($url, $data);
40
41 569
        $statusCode = $response->getStatusCode();
42 569
        $contents = $this->getContents($response->getBody(), $gzip);
43 569
        $parsedContent = $this->parseContents($contents, $statusCode < 300);
44
45 567
        $this->validateResponse($statusCode, $parsedContent, $shouldHaveStatus);
46
47 266
        return $parsedContent;
48
    }
49
50
    /**
51
     * @return non-empty-string
52
     */
53 569
    private function resolveUrl(string $baseUrl, ?string $carrier, string $method, ?string $path, bool $gzip): string
54
    {
55 569
        $url = sprintf('%s/%s/%s', $carrier, $method, $path ?? '');
56 569
        $url = trim(str_replace('//', '/', $url), '/');
57
58 569
        if ($gzip) {
59 490
            $url = sprintf('%s?gzip=1', $url);
60
        }
61
62 569
        return sprintf('%s/%s', $baseUrl, $url);
63
    }
64
65
    /**
66
     * @return array<string,mixed>
67
     *
68
     * @throws \Inspirum\Balikobot\Exception\Exception
69
     */
70 569
    private function parseContents(string $content, bool $throwOnError): array
71
    {
72
        try {
73 569
            return json_decode($content, true, flags: JSON_THROW_ON_ERROR);
74 3
        } catch (JsonException $exception) {
75 3
            if ($throwOnError) {
76 2
                throw new BadRequestException([], 400, $exception, 'Cannot parse response data');
77
            }
78
79 1
            return [];
80
        }
81
    }
82
83 569
    private function getContents(StreamInterface $stream, bool $gzip): string
84
    {
85 569
        if ($gzip === false) {
86 79
            return $stream->getContents();
87
        }
88
89
        try {
90 490
            $inflateStream = new InflateStream($stream);
91
92 490
            return $inflateStream->getContents();
93 10
        } catch (Throwable) {
94 10
            $stream->rewind();
95
96 10
            return $stream->getContents();
97
        }
98
    }
99
100
    /**
101
     * @param array<string,mixed> $response
102
     *
103
     * @throws \Inspirum\Balikobot\Exception\Exception
104
     */
105 567
    private function validateResponse(int $statusCode, array $response, bool $shouldHaveStatus): void
106
    {
107 567
        $this->validator->validateStatus($statusCode, $response);
108
109 547
        $this->validator->validateResponseStatus($response, null, $shouldHaveStatus);
110
    }
111
}
112