CustomClient::sendPutRequest()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 2
nc 2
nop 2
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 = '';
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
        // TODO send body in exception because even if the error code was returned the body may not be nulled
107
        if ($code == 0) {
108
            throw (new \Exception("No response from URL : " . $url));
109
        } elseif ($code == 404) {
110
            throw (new \Exception("URL: $url not found"));
111
        } elseif ($code == 400) {
112
            throw (new \Exception("Bad request on URL $url"));
113
        } elseif ($code == 403) {
114
            throw (new \Exception("Auth error"));
115
        }
116
117
        return $body;
118
    }
119
120
    /**
121
     * Method returns common headers
122
     *
123
     * @return array Headers
124
     */
125
    protected function getCommonHeaders(): array
126
    {
127
        $result = $this->headers;
128
129
        if ($this->idempotencyKey !== '') {
130
            $result[] = 'Idempotency-Key: ' . $this->idempotencyKey;
131
        }
132
133
        return $result;
134
    }
135
136
    /**
137
     * Method compiles post headers
138
     *
139
     * @return array Header
140
     */
141
    protected function getFormHeaders(): array
142
    {
143
        $fullHeaders = $this->getCommonHeaders();
144
145
        if (! CurlWrapper::isHeaderExists($this->headers, 'Content-type')) {
146
            $fullHeaders[] = 'Content-type: application/x-www-form-urlencoded';
147
        }
148
149
        return $fullHeaders;
150
    }
151
152
    /**
153
     * Method asserts that $url is set
154
     */
155
    private function assertUrl(): void
156
    {
157
        if ($this->url == '') {
158
            throw (new \Exception('Service URL must be set in class ' . __CLASS__ . ' extended in ' . get_called_class() . ' and called from ' . ($_SERVER['SERVER_NAME'] ?? 'console') . ($_SERVER['REQUEST_URI'] ?? ''), - 23));
159
        }
160
    }
161
162
    /**
163
     * Method sends request on server
164
     *
165
     * @param string $method
166
     *            HTTP method (POST|PUT|DELETE)
167
     * @param string $endpoint
168
     *            Calling endpoint
169
     * @param mixed $data
170
     *            Request data
171
     *            @return mixed request result
172
     */
173
    protected function sendFormRequest(string $method, string $endpoint, array $data = [])
174
    {
175
        $this->assertUrl();
176
177
        $fullUrl = $this->url . '/' . ltrim($endpoint, '/');
178
179
        list ($body, $code) = $this->sendRequest($fullUrl, $this->getFormHeaders(), $method, $data);
180
181
        return $this->dispatchResult($fullUrl, $code, $body);
182
    }
183
184
    /**
185
     * Method sends POST request to server
186
     *
187
     * @param string $endpoint
188
     *            Calling endpoint
189
     * @param array $data
190
     *            Request data
191
     * @return mixed Result of the request
192
     */
193
    public function sendPostRequest(string $endpoint, array $data = [])
194
    {
195
        return $this->sendFormRequest('POST', $endpoint, $data);
196
    }
197
198
    /**
199
     * Method sends PUT request to server
200
     *
201
     * @param string $endpoint
202
     *            Calling endpoint
203
     * @param array $data
204
     *            Request data
205
     * @return mixed Result of the request
206
     */
207
    public function sendPutRequest(string $endpoint, array $data = [])
208
    {
209
        if ($this->traitPutAsPost) {
210
            return $this->sendPostRequest($endpoint, $data);
211
        } else {
212
            return $this->sendFormRequest('PUT', $endpoint, $data);
213
        }
214
    }
215
216
    /**
217
     * Method sends DELETE request to server
218
     *
219
     * @param string $endpoint
220
     *            Calling endpoint
221
     * @param array $data
222
     *            Request data
223
     * @return mixed Result of the request
224
     */
225
    public function sendDeleteRequest(string $endpoint, array $data = [])
226
    {
227
        if ($this->traitDeleteAsPost) {
228
            return $this->sendPostRequest($endpoint, $data);
229
        } else {
230
            return $this->sendFormRequest('DELETE', $endpoint, $data);
231
        }
232
    }
233
234
    /**
235
     * Method sends GET request to server.
236
     *
237
     * @param string $endpoint
238
     *            Calling endpoint.
239
     * @return mixed Result of the remote call.
240
     */
241
    public function sendGetRequest(string $endpoint)
242
    {
243
        $this->assertUrl();
244
245
        $fullUrl = $this->url . '/' . ltrim($endpoint, '/');
246
247
        $fullUrl = str_replace(' ', '%20', $fullUrl);
248
249
        list ($body, $code) = $this->sendRequest($fullUrl, $this->getCommonHeaders(), 'GET');
250
251
        return $this->dispatchResult($fullUrl, $code, $body);
252
    }
253
254
    /**
255
     * Method sets idempotence key.
256
     * To remove the key just call this method the second time with the '' parameter
257
     *
258
     * @param string $key
259
     *            Idempotence key
260
     */
261
    public function setIdempotencyKey(string $key): void
262
    {
263
        $this->idempotencyKey = $key;
264
    }
265
266
    /**
267
     * Method returns idempotency key
268
     *
269
     * @return string Idempotency key
270
     */
271
    public function getIdempotencyKey(): string
272
    {
273
        return $this->idempotencyKey;
274
    }
275
276
    /**
277
     * Method returns URL
278
     *
279
     * @return string URL
280
     */
281
    public function getUrl(): string
282
    {
283
        return $this->url;
284
    }
285
286
    /**
287
     * Method sets URL
288
     *
289
     * @param string $url
290
     *            URL
291
     */
292
    public function setUrl(string $url): void
293
    {
294
        $this->url = $url;
295
    }
296
297
    /**
298
     * Method returns headers
299
     *
300
     * @return array Headers
301
     */
302
    public function getHeaders(): array
303
    {
304
        return $this->headers;
305
    }
306
307
    /**
308
     * Method traits PUT as POST
309
     *
310
     * @param bool $flag
311
     */
312
    public function setPutTraitMethod(bool $flag): void
313
    {
314
        $this->traitPutAsPost = $flag;
315
    }
316
317
    /**
318
     * Method traits DELETE as POST
319
     *
320
     * @param bool $flag
321
     */
322
    public function setDeleteTraitMethod(bool $flag): void
323
    {
324
        $this->traitDeleteAsPost = $flag;
325
    }
326
}
327