Options::getBodyFormat()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Gemz\HttpClient\Contracts;
4
5
use Gemz\HttpClient\Exceptions\InvalidArgument;
6
use Symfony\Component\Mime\Part\Multipart\FormDataPart;
7
8
trait Options
9
{
10
    /** @var string */
11
    private static $CONTENT_TYPE_JSON = 'application/json';
12
13
    /** @var string */
14
    private static $CONTENT_TYPE_PLAIN = 'text/plain';
15
16
    /** @var string */
17
    private static $CONTENT_TYPE_MULTIPART = 'multipart/form-data';
18
19
    /** @var string */
20
    private static $CONTENT_TYPE_FORM_PARAMS = 'application/x-www-form-urlencoded';
21
22
    /** @var string */
23
    protected static $CUSTOM_DATA_HEADER = 'X-Custom-Data';
24
25
    /** @var array<mixed> */
26
    protected $options = [];
27
28
    /** @var bool */
29
    protected $throwErrors = false;
30
31
    /** @var array<String> */
32
    protected $bodyFormats = [
33
        'json' => 'json',
34
        'multipart' => 'body',
35
        'form_params' => 'body',
36
        'string' => 'body',
37
    ];
38
39
    /** @var string */
40
    protected $bodyFormat = 'json';
41
42
    /**
43
     * Set authentication auth bearer token
44
     *
45
     * @param string $token
46
     *
47
     * @return $this
48
     */
49
    public function authBearer(string $token): self
50
    {
51
        return $this->option('auth_bearer', $token);
52
    }
53
54
    /**
55
     * Set authentication auth basic. If password is null
56
     * only username will be used
57
     *
58
     * @param string $username
59
     * @param string $password
60
     *
61
     * @return $this
62
     */
63
    public function authBasic(string $username, string $password = ''): self
64
    {
65
        $this->options['auth_basic'] = $username;
66
67
        if ('' !== $password) {
68
            $this->options['auth_basic'] .= ':' . $password;
69
        }
70
71
        return $this;
72
    }
73
74
    /**
75
     * @return $this
76
     */
77
    public function throwErrors(): self
78
    {
79
        $this->throwErrors = true;
80
81
        return $this;
82
    }
83
84
    /**
85
     * @return bool
86
     */
87
    public function shouldThrowErrors(): bool
88
    {
89
        return $this->throwErrors;
90
    }
91
92
    /**
93
     * Values for existing header keys will be replaced
94
     *
95
     * @param string $key
96
     * @param string $value
97
     *
98
     * @return $this
99
     */
100
    public function header(string $key, string $value): self
101
    {
102
        $this->options['headers'][$key] = $value;
103
104
        return $this;
105
    }
106
107
    /**
108
     * Values for existing header keys will be replaced
109
     *
110
     * @param array<String> $headers
111
     *
112
     * @return $this
113
     */
114
    public function headers(array $headers): self
115
    {
116
        foreach ($headers as $key => $value) {
117
            $this->header($key, $value);
118
        }
119
120
        return $this;
121
    }
122
123
    /**
124
     * Set the base uri.
125
     *
126
     * @param string $uri
127
     *
128
     * @return $this
129
     */
130
    public function baseUri(string $uri): self
131
    {
132
        return $this->option('base_uri', $uri);
133
    }
134
135
    /**
136
     * Disallows redirects.
137
     *
138
     * @return $this
139
     */
140
    public function disallowRedirects(): self
141
    {
142
        return $this->option('max_redirects', -1);
143
    }
144
145
    /**
146
     * @param int $max
147
     *
148
     * @return $this
149
     */
150
    public function allowRedirects(int $max = 0): self
151
    {
152
        return $this->option('max_redirects', $max);
153
    }
154
155
    /**
156
     * Float describing the timeout of the request in seconds.
157
     * use 0 to wait indefinitely
158
     *
159
     * @param float $seconds
160
     *
161
     * @return $this
162
     */
163
    public function timeout(float $seconds): self
164
    {
165
        return $this->option('timeout', $seconds);
166
    }
167
168
    /**
169
     * Pass a string to specify an HTTP proxy, or an array to specify different proxies for different protocols.
170
     *
171
     * @param string|array<String> $proxy
172
     *
173
     * @return $this
174
     */
175
    public function useProxy($proxy): self
176
    {
177
        return $this->option('proxy', $proxy);
178
    }
179
180
    /**
181
     * @param float $seconds
182
     *
183
     * @return $this
184
     */
185
    public function maxDuration(float $seconds): self
186
    {
187
        return $this->option('max_duration', $seconds);
188
    }
189
190
    /**
191
     * Does not verify SSL certificates
192
     *
193
     * @return $this
194
     */
195
    public function doNotVerifySsl(): self
196
    {
197
        $this->option('verify_peer', false);
198
        $this->option('verify_host', false);
199
200
        return $this;
201
    }
202
203
    /**
204
     * Does verify SSL certificates
205
     *
206
     * @return $this
207
     */
208
    public function verifySsl(): self
209
    {
210
        $this->option('verify_peer', true);
211
        $this->option('verify_host', true);
212
213
        return $this;
214
    }
215
216
    /**
217
     * Set the content type
218
     *
219
     * @param string $type
220
     *
221
     * @return $this
222
     */
223
    public function contentType(string $type): self
224
    {
225
        return $this->header('Content-Type', $type);
226
    }
227
228
    /**
229
     * Set the clients user agent
230
     *
231
     * @param string $agent
232
     *
233
     * @return $this
234
     */
235
    public function userAgent(string $agent): self
236
    {
237
        return $this->header('User-Agent', $agent);
238
    }
239
240
    /**
241
     * Set accept header
242
     *
243
     * @param string $value
244
     *
245
     * @return $this
246
     */
247
    public function accept(string $value): self
248
    {
249
        return $this->header('Accept', $value);
250
    }
251
252
    /**
253
     * Set option according guzzle request options
254
     *
255
     * @param string $key
256
     * @param mixed $value
257
     *
258
     * @return $this
259
     */
260
    public function option(string $key, $value): self
261
    {
262
        $this->options[$key] = $value;
263
264
        return $this;
265
    }
266
267
    /**
268
     * Set param for the query url
269
     *
270
     * @param string $key
271
     * @param string $value
272
     *
273
     * @return $this
274
     */
275
    public function queryParam(string $key, string $value): self
276
    {
277
        $this->options['query'][$key] = $value;
278
279
        return $this;
280
    }
281
282
    /**
283
     * Set multiple params for query url
284
     * in form of [<key> => <value>, <key2> => <value2>]
285
     *
286
     * @param array<String> $params
287
     *
288
     * @return $this
289
     */
290
    public function queryParams(array $params): self
291
    {
292
        foreach ($params as $key => $value) {
293
            $this->queryParam($key, $value);
294
        }
295
296
        return $this;
297
    }
298
299
    /**
300
     * Any extra data to attach to the response header
301
     * Available in response->customData(). Useful when using asynchronous requests
302
     * to identify the request
303
     *
304
     * @param mixed $data
305
     *
306
     * @return $this
307
     */
308
    public function customData($data): self
309
    {
310
        return $this->option('user_data', $data);
311
    }
312
313
    /**
314
     * @param string $format
315
     *
316
     * @return $this
317
     */
318
    protected function bodyFormat(string $format): self
319
    {
320
        $this->bodyFormat = $format;
321
322
        return $this;
323
    }
324
325
    /**
326
     * Set the content type and body format for strings
327
     * @return $this
328
     */
329
    public function asString()
330
    {
331
        return $this
332
            ->bodyFormat('string')
333
            ->contentType(self::$CONTENT_TYPE_PLAIN);
334
    }
335
336
    /**
337
     * Set the content type and body format json
338
     *
339
     * @return $this
340
     */
341
    public function asJson(): self
342
    {
343
        return $this
344
            ->bodyFormat('json')
345
            ->contentType(self::$CONTENT_TYPE_JSON);
346
    }
347
348
    /**
349
     * Set the content type and body format form params
350
     *
351
     * @return $this
352
     */
353
    public function asFormParams(): self
354
    {
355
        return $this
356
            ->bodyFormat('form_params')
357
            ->contentType(self::$CONTENT_TYPE_FORM_PARAMS);
358
    }
359
360
    /**
361
     * Set the content type and body format multipart form-data
362
     *
363
     * @return $this
364
     */
365
    public function asMultipart(): self
366
    {
367
        return $this->bodyFormat('multipart');
368
    }
369
370
    /**
371
     * @return array<mixed>
372
     */
373
    public function getHeaders(): array
374
    {
375
        return $this->options['headers'] ?? [];
376
    }
377
378
    /**
379
     * @return null|string
380
     */
381
    public function getContentType()
382
    {
383
        return array_key_exists('Content-Type', $this->getHeaders())
384
            ? $this->getHeaders()['Content-Type']
385
            : null;
386
    }
387
388
    /**
389
     * @return string
390
     */
391
    public function getBodyFormat(): string
392
    {
393
        return $this->bodyFormat;
394
    }
395
396
    /**
397
     * Set any payload text, array, resource, callable ...
398
     *
399
     * @param mixed $payload
400
     *
401
     * @return $this
402
     */
403
    public function payload($payload): self
404
    {
405
        return $this->option('body', $payload);
406
    }
407
408
    /**
409
     * @param string $option
410
     *
411
     * @return mixed
412
     */
413
    protected function getOption(string $option)
414
    {
415
        return $this->options[$option] ?? '';
416
    }
417
418
    /**
419
     * @return $this
420
     */
421
    protected function resolveJsonPayload(): self
422
    {
423
        $body = $this->getOption('body');
424
425
        if (! empty($body) && is_array($body)) {
426
            $this->option('body', json_encode($body));
427
        }
428
429
        return $this;
430
    }
431
432
    /**
433
     * @return $this
434
     */
435
    public function resolveMultipartPayload(): self
436
    {
437
        $body = $this->getOption('body');
438
439
        if (! is_array($body) || ! is_iterable($body)) {
440
            throw InvalidArgument::payloadMustBeArray();
441
        }
442
443
        $formData = new FormDataPart($body);
444
        $headers = $formData->getPreparedHeaders()->toArray();
445
446
        $header = explode(':', $headers[0], 2);
447
448
        $this->header($header[0], $header[1]);
449
        $this->body($formData->bodyToIterable());
450
451
        return $this;
452
    }
453
454
    /**
455
     * @return $this
456
     */
457
    public function resolveFormParamsPayload(): self
458
    {
459
        $body = $this->getOption('body');
460
461
        if (!is_array($body) || !is_iterable($body)) {
462
            throw InvalidArgument::payloadMustBeArray();
463
        }
464
465
        return $this;
466
    }
467
468
    /**
469
     * resolve the payload
470
     * if body format is json then payload value must be json encoded
471
     *
472
     * @return $this
473
     */
474
    protected function resolvePayload(): self
475
    {
476
        $bodyFormat = $this->getBodyFormat();
477
478
479
        if ($bodyFormat == 'json') {
480
            $this->resolveJsonPayload();
481
        }
482
483
        if ($bodyFormat == 'multipart') {
484
            $this->resolveMultipartPayload();
485
        }
486
487
        if ($bodyFormat == 'form_params') {
488
            $this->resolveFormParamsPayload();
489
        }
490
491
        return $this;
492
    }
493
494
    /**
495
     * remove an option
496
     *
497
     * @param string $option
498
     *
499
     * @return $this
500
     */
501
    protected function removeOption(string $option): self
502
    {
503
        unset($this->options[$option]);
504
505
        return $this;
506
    }
507
508
    /**
509
     * @param array<String> $options
510
     *
511
     * @return $this
512
     */
513
    protected function removeOptions(array $options): self
514
    {
515
        foreach ($options as $option) {
516
            if (! is_string($option)) {
517
                continue;
518
            }
519
520
            $this->removeOption($option);
521
        }
522
523
        return $this;
524
    }
525
526
    /**
527
     * @param mixed $body
528
     *
529
     * @return $this
530
     */
531
    protected function body($body): self
532
    {
533
        return $this->option('body', $body);
534
    }
535
}
536