Passed
Push — master ( 49030a...d9cb1c )
by Alex
02:21
created

CustomClient::assertUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 2
nc 2
nop 0
1
<?php
2
namespace Mezon\CustomClient;
3
4
/**
5
 * Class CustomClient
6
 *
7
 * @package Mezon
8
 * @subpackage CustomClient
9
 * @author Dodonov A.A.
10
 * @version v.1.0 (2019/08/07)
11
 * @copyright Copyright (c) 2019, aeon.org
12
 */
13
14
/**
15
 * Custom API client class
16
 */
17
class CustomClient
18
{
19
20
    /**
21
     * Server host
22
     *
23
     * @var string
24
     */
25
    protected $url = false;
26
27
    /**
28
     * Headers
29
     *
30
     * @var array
31
     */
32
    protected $headers = [];
33
34
    /**
35
     * Idempotence key
36
     *
37
     * @var string
38
     */
39
    protected $idempotencyKey = '';
40
41
    /**
42
     * Trait PUT requests as POST
43
     *
44
     * @var boolean
45
     */
46
    private $traitPutAsPost = false;
47
48
    /**
49
     * Trait DELETE requests as POST
50
     *
51
     * @var boolean
52
     */
53
    private $traitDeleteAsPost = false;
54
55
    /**
56
     * Constructor
57
     *
58
     * @param string $url
59
     *            service URL
60
     * @param array $headers
61
     *            HTTP headers
62
     */
63
    public function __construct(string $url = '', array $headers = [])
64
    {
65
        if ($url !== '') {
66
            $this->url = rtrim($url, '/');
67
        } else {
68
            $this->url = '';
69
        }
70
71
        $this->headers = $headers;
72
    }
73
74
    /**
75
     * Method send request to the URL
76
     *
77
     * @param string $url
78
     *            URL
79
     * @param array $headers
80
     *            Headers
81
     * @param string $method
82
     *            Request HTTP Method
83
     * @param array $data
84
     *            Request data
85
     * @return array Response body and HTTP code
86
     * @codeCoverageIgnore
87
     */
88
    protected function sendRequest(string $url, array $headers, string $method, array $data = []): array
89
    {
90
        return CurlWrapper::sendRequest($url, $headers, $method, $data);
91
    }
92
93
    /**
94
     * Method gets result and validates it.
95
     *
96
     * @param string $url
97
     *            request URL
98
     * @param int $code
99
     *            response HTTP code
100
     * @param mixed $body
101
     *            response body
102
     * @return mixed Request result
103
     */
104
    protected function dispatchResult(string $url, int $code, $body)
105
    {
106
        if ($code == 0) {
107
            throw (new \Exception("No response from URL : " . $url));
108
        } elseif ($code == 404) {
109
            throw (new \Exception("URL: $url not found"));
110
        } elseif ($code == 400) {
111
            throw (new \Exception("Bad request on URL $url"));
112
        } elseif ($code == 403) {
113
            throw (new \Exception("Auth error"));
114
        }
115
116
        return $body;
117
    }
118
119
    /**
120
     * Method returns common headers
121
     *
122
     * @return array Headers
123
     */
124
    protected function getCommonHeaders(): array
125
    {
126
        $result = $this->headers;
127
128
        if ($this->idempotencyKey !== '') {
129
            $result[] = 'Idempotency-Key: ' . $this->idempotencyKey;
130
        }
131
132
        $result[] = 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0';
133
134
        return $result;
135
    }
136
137
    /**
138
     * Method compiles post headers
139
     *
140
     * @return array Header
141
     */
142
    protected function getFormHeaders(): array
143
    {
144
        $fullHeaders = $this->getCommonHeaders();
145
146
        $fullHeaders[] = 'Content-type: application/x-www-form-urlencoded';
147
148
        return $fullHeaders;
149
    }
150
151
    /**
152
     * Method asserts that $url is set
153
     */
154
    private function assertUrl(): void
155
    {
156
        if ($this->url == '') {
157
            throw (new \Exception(
158
                'Service URL must be set in class ' . __CLASS__ . ' extended in ' . get_called_class() .
159
                ' and called from ' . ($_SERVER['SERVER_NAME'] ?? 'console') . ($_SERVER['REQUEST_URI'] ?? ''),
160
                - 23));
161
        }
162
    }
163
164
    /**
165
     * Method sends request on server
166
     *
167
     * @param string $method
168
     *            HTTP method (POST|PUT|DELETE)
169
     * @param string $endpoint
170
     *            Calling endpoint
171
     * @param mixed $data
172
     *            Request data
173
     */
174
    protected function sendFormRequest(string $method, string $endpoint, array $data = [])
175
    {
176
        $this->assertUrl();
177
178
        $fullUrl = $this->url . '/' . ltrim($endpoint, '/');
179
180
        list ($body, $code) = $this->sendRequest($fullUrl, $this->getFormHeaders(), $method, $data);
181
182
        return $this->dispatchResult($fullUrl, $code, $body);
183
    }
184
185
    /**
186
     * Method sends POST request to server
187
     *
188
     * @param string $endpoint
189
     *            Calling endpoint
190
     * @param array $data
191
     *            Request data
192
     * @return mixed Result of the request
193
     */
194
    public function sendPostRequest(string $endpoint, array $data = [])
195
    {
196
        return $this->sendFormRequest('POST', $endpoint, $data);
197
    }
198
199
    /**
200
     * Method sends PUT request to server
201
     *
202
     * @param string $endpoint
203
     *            Calling endpoint
204
     * @param array $data
205
     *            Request data
206
     * @return mixed Result of the request
207
     */
208
    public function sendPutRequest(string $endpoint, array $data = [])
209
    {
210
        if ($this->traitPutAsPost) {
211
            return $this->sendPostRequest($endpoint, $data);
212
        } else {
213
            return $this->sendFormRequest('PUT', $endpoint, $data);
214
        }
215
    }
216
217
    /**
218
     * Method sends DELETE request to server
219
     *
220
     * @param string $endpoint
221
     *            Calling endpoint
222
     * @param array $data
223
     *            Request data
224
     * @return mixed Result of the request
225
     */
226
    public function sendDeleteRequest(string $endpoint, array $data = [])
227
    {
228
        if ($this->traitDeleteAsPost) {
229
            return $this->sendPostRequest($endpoint, $data);
230
        } else {
231
            return $this->sendFormRequest('DELETE', $endpoint, $data);
232
        }
233
    }
234
235
    /**
236
     * Method sends GET request to server.
237
     *
238
     * @param string $endpoint
239
     *            Calling endpoint.
240
     * @return mixed Result of the remote call.
241
     */
242
    public function sendGetRequest(string $endpoint)
243
    {
244
        $this->assertUrl();
245
246
        $fullUrl = $this->url . '/' . ltrim($endpoint, '/');
247
248
        $fullUrl = str_replace(' ', '%20', $fullUrl);
249
250
        list ($body, $code) = $this->sendRequest($fullUrl, $this->getCommonHeaders(), 'GET');
251
252
        return $this->dispatchResult($fullUrl, $code, $body);
253
    }
254
255
    /**
256
     * Method sets idempotence key.
257
     * To remove the key just call this method the second time with the '' parameter
258
     *
259
     * @param string $key
260
     *            Idempotence key
261
     */
262
    public function setIdempotencyKey(string $key): void
263
    {
264
        $this->idempotencyKey = $key;
265
    }
266
267
    /**
268
     * Method returns idempotency key
269
     *
270
     * @return string Idempotency key
271
     */
272
    public function getIdempotencyKey(): string
273
    {
274
        return $this->idempotencyKey;
275
    }
276
277
    /**
278
     * Method returns URL
279
     *
280
     * @return string URL
281
     */
282
    public function getUrl(): string
283
    {
284
        return $this->url;
285
    }
286
287
    /**
288
     * Method sets URL
289
     *
290
     * @param string $url
291
     *            URL
292
     */
293
    public function setUrl(string $url): void
294
    {
295
        $this->url = $url;
296
    }
297
298
    /**
299
     * Method returns headers
300
     *
301
     * @return array Headers
302
     */
303
    public function getHeaders(): array
304
    {
305
        return $this->headers;
306
    }
307
308
    /**
309
     * Method traits PUT as POST
310
     *
311
     * @param bool $flag
312
     */
313
    public function setPutTraitMethod(bool $flag): void
314
    {
315
        $this->traitPutAsPost = $flag;
316
    }
317
318
    /**
319
     * Method traits DELETE as POST
320
     *
321
     * @param bool $flag
322
     */
323
    public function setDeleteTraitMethod(bool $flag): void
324
    {
325
        $this->traitDeleteAsPost = $flag;
326
    }
327
}
328