Passed
Branch master (837a03)
by Tomáš
02:48
created

Requester   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 39
c 5
b 0
f 0
dl 0
loc 157
ccs 41
cts 41
cp 1
rs 10
wmc 8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A validateResponse() 0 5 1
A call() 0 32 2
A request() 0 37 3
A __construct() 0 6 1
A resolveHostName() 0 3 1
1
<?php
2
3
namespace Inspirum\Balikobot\Services;
4
5
use GuzzleHttp\Psr7\Response;
6
use Inspirum\Balikobot\Contracts\RequesterInterface;
7
use Inspirum\Balikobot\Definitions\API;
8
use Inspirum\Balikobot\Exceptions\BadRequestException;
9
use Inspirum\Balikobot\Exceptions\UnauthorizedException;
10
use Psr\Http\Message\ResponseInterface;
11
use RuntimeException;
12
13
class Requester implements RequesterInterface
14
{
15
    /**
16
     * API User
17
     *
18
     * @var string
19
     */
20
    private $apiUser;
21
22
    /**
23
     * API key
24
     *
25
     * @var string
26
     */
27
    private $apiKey;
28
29
    /**
30
     * Response validator
31
     *
32
     * @var \Inspirum\Balikobot\Services\Validator
33
     */
34
    private $validator;
35
36
    /**
37
     * Balikobot API client
38
     *
39
     * @param string $apiUser
40
     * @param string $apiKey
41
     */
42 349
    public function __construct(string $apiUser, string $apiKey)
43
    {
44 349
        $this->apiUser = $apiUser;
45 349
        $this->apiKey  = $apiKey;
46
47 349
        $this->validator = new Validator();
48 349
    }
49
50
    /**
51
     * Call API
52
     *
53
     * @param string             $version
54
     * @param string             $request
55
     * @param string             $shipper
56
     * @param array<mixed,mixed> $data
57
     * @param bool               $shouldHaveStatus
58
     *
59
     * @return array<mixed,mixed>
60
     *
61
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
62
     */
63 337
    public function call(
64
        string $version,
65
        string $shipper,
66
        string $request,
67
        array $data = [],
68
        bool $shouldHaveStatus = true
69
    ): array {
70
        // resolve url
71 337
        $path = trim($shipper . '/' . $request, '/');
72 337
        $path = str_replace('//', '/', $path);
73 337
        $host = $this->resolveHostName($version);
74
75
        // call API server and get response
76 337
        $response = $this->request($host . $path, $data);
77
78
        // get status code and content
79 337
        $statusCode = $response->getStatusCode();
80 337
        $content    = $response->getBody()->getContents();
81
82
        // parse response content to assoc array
83 337
        $content = json_decode($content, true);
84
85
        // return empty array when json_decode fails
86 337
        if ($content === null) {
87 1
            $content = [];
88
        }
89
90
        // validate response status code
91 337
        $this->validateResponse($statusCode, $content, $shouldHaveStatus);
92
93
        // return response
94 228
        return $content;
95
    }
96
97
    /**
98
     * Get API response
99
     *
100
     * @param string             $url
101
     * @param array<mixed,mixed> $data
102
     *
103
     * @return \Psr\Http\Message\ResponseInterface
104
     */
105 55
    public function request(string $url, array $data = []): ResponseInterface
106
    {
107
        // init curl
108 55
        $ch = curl_init();
109
110
        // set headers
111 55
        curl_setopt($ch, CURLOPT_URL, $url);
112 55
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
113 55
        curl_setopt($ch, CURLOPT_HEADER, false);
114 55
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
115 55
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
116
117
        // set data
118 55
        if (count($data) > 0) {
119 23
            curl_setopt($ch, CURLOPT_POST, true);
120 23
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
121
        }
122
123
        // set auth
124 55
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
125 55
            'Authorization: Basic ' . base64_encode($this->apiUser . ':' . $this->apiKey),
126 55
            'Content-Type: application/json',
127
        ]);
128
129
        // execute curl
130 55
        $response   = curl_exec($ch);
131 55
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
132
133
        // check for errors.
134 55
        if ($response === false) {
135 1
            throw new RuntimeException(curl_error($ch), curl_errno($ch));
136
        }
137
138
        // close curl
139 54
        curl_close($ch);
140
141 54
        return new Response((int) $statusCode, [], (string) $response);
142
    }
143
144
    /**
145
     * Get API url for given version
146
     *
147
     * @param string $version
148
     *
149
     * @return string
150
     */
151 337
    private function resolveHostName(string $version): string
152
    {
153 337
        return API::URL[$version] ?? API::URL[API::V2V1];
154
    }
155
156
    /**
157
     * Validate response
158
     *
159
     * @param int                $statusCode
160
     * @param array<mixed,mixed> $response
161
     * @param bool               $shouldHaveStatus
162
     *
163
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
164
     */
165 337
    private function validateResponse(int $statusCode, array $response, bool $shouldHaveStatus): void
166
    {
167 337
        $this->validator->validateStatus($statusCode, $response);
168
169 294
        $this->validator->validateResponseStatus($response, null, $shouldHaveStatus);
170 228
    }
171
}
172