Completed
Pull Request — master (#8)
by Tomáš
03:09
created

Requester::validateStatus()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
rs 9.8666
ccs 6
cts 6
cp 1
cc 4
nc 3
nop 2
crap 4
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 324
    public function __construct(string $apiUser, string $apiKey)
43
    {
44 324
        $this->apiUser = $apiUser;
45 324
        $this->apiKey  = $apiKey;
46
47 324
        $this->validator = new Validator();
48 324
    }
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 313
    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 313
        $path = trim($shipper . '/' . $request, '/');
72 313
        $path = str_replace('//', '/', $path);
73 313
        $host = $this->resolveHostName($version);
74
75
        // call API server and get response
76 313
        $response = $this->request($host . $path, $data);
77
78
        // get status code and content
79 313
        $statusCode = $response->getStatusCode();
80 313
        $content    = $response->getBody()->getContents();
81
82
        // parse response content to assoc array
83 313
        $content = json_decode($content, true);
84
85
        // return empty array when json_decode fails
86 313
        if ($content === null) {
87 1
            $content = [];
88
        }
89
90
        // validate response status code
91 313
        $this->validateResponse($statusCode, $content, $shouldHaveStatus);
92
93
        // return response
94 210
        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 50
    public function request(string $url, array $data = []): ResponseInterface
106
    {
107
        // init curl
108 50
        $ch = curl_init();
109
110
        // set headers
111 50
        curl_setopt($ch, CURLOPT_URL, $url);
112 50
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
113 50
        curl_setopt($ch, CURLOPT_HEADER, false);
114 50
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
115 50
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
116
117
        // set data
118 50
        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 50
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
125 50
            'Authorization: Basic ' . base64_encode($this->apiUser . ':' . $this->apiKey),
126 50
            'Content-Type: application/json',
127
        ]);
128
129
        // execute curl
130 50
        $response   = curl_exec($ch);
131 50
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
132
133
        // check for errors.
134 50
        if ($response === false) {
135 1
            throw new RuntimeException(curl_error($ch), curl_errno($ch));
136
        }
137
138
        // close curl
139 49
        curl_close($ch);
140
141 49
        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 313
    private function resolveHostName(string $version): string
152
    {
153 313
        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 313
    private function validateResponse(int $statusCode, array $response, bool $shouldHaveStatus): void
166
    {
167 313
        $this->validator->validateStatus($statusCode, $response);
168
169 271
        $this->validator->validateResponseStatus($response, null, $shouldHaveStatus);
170 210
    }
171
}
172