Passed
Push — main ( d0ed98...da6fcc )
by Dimitri
13:43
created

InteractsWithInput::anyFilled()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 11
ccs 0
cts 3
cp 0
crap 20
rs 10
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\Http\Concerns;
13
14
use BlitzPHP\Filesystem\Files\UploadedFile;
15
use BlitzPHP\Utilities\Date;
16
use BlitzPHP\Utilities\Iterable\Arr;
17
use BlitzPHP\Utilities\Iterable\Collection;
18
use BlitzPHP\Utilities\String\Stringable;
19
use BlitzPHP\Utilities\String\Text;
20
use Kint\Kint;
21
use Psr\Http\Message\UploadedFileInterface;
22
use SplFileInfo;
23
use stdClass;
24
25
/**
26
 * @credit <a href="http://laravel.com/">Laravel - Illuminate\Http\Concerns\InteractsWithInput</a>
27
 */
28
trait InteractsWithInput
29
{
30
    /**
31
     * Récupérez une variable de serveur à partir de la requête.
32
     *
33
     * @return array|string|null
34
     */
35
    public function server(?string $key = null, null|array|string $default = null)
36
    {
37
        return Arr::get($this->_environment, $key, $default);
38
    }
39
40
    /**
41
     * Récupérer un en-tête de la requête.
42
     *
43
     * @return array|string|null
44
     */
45
    public function header(?string $key = null, null|array|string $default = null)
46
    {
47
        if (null === $key) {
48
            return $this->getHeaders();
0 ignored issues
show
Bug introduced by
It seems like getHeaders() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

48
            return $this->/** @scrutinizer ignore-call */ getHeaders();
Loading history...
49
        }
50
51
        return empty($header = $this->getHeaderLine($key)) ? $default : $header;
0 ignored issues
show
Bug introduced by
It seems like getHeaderLine() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
        return empty($header = $this->/** @scrutinizer ignore-call */ getHeaderLine($key)) ? $default : $header;
Loading history...
52
    }
53
54
    /**
55
     * Obtenez le jeton du porteur à partir des en-têtes de requête.
56
     */
57
    public function bearerToken(): ?string
58
    {
59
        $header = $this->header('Authorization', '');
60
61
        $position = strrpos($header, 'Bearer ');
0 ignored issues
show
Bug introduced by
It seems like $header can also be of type array and null; however, parameter $haystack of strrpos() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
        $position = strrpos(/** @scrutinizer ignore-type */ $header, 'Bearer ');
Loading history...
62
63
        if ($position !== false) {
64
            $header = substr($header, $position + 7);
0 ignored issues
show
Bug introduced by
It seems like $header can also be of type array and null; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
            $header = substr(/** @scrutinizer ignore-type */ $header, $position + 7);
Loading history...
65
66
            return str_contains($header, ',') ? strstr($header, ',', true) : $header;
67
        }
68
69
        return null;
70
    }
71
72
    /**
73
     * Déterminez si la demande contient une clé d'élément d'entrée donnée.
74
     */
75
    public function exists(array|string $key): bool
76
    {
77
        return $this->has($key);
78
    }
79
80
    /**
81
     *Déterminez si la demande contient une clé d'élément d'entrée donnée.
82
     */
83
    public function has(array|string $key): bool
84
    {
85
        $keys = is_array($key) ? $key : func_get_args();
0 ignored issues
show
introduced by
The condition is_array($key) is always true.
Loading history...
86
87
        $input = $this->all();
88
89
        foreach ($keys as $value) {
90
            if (! Arr::has($input, $value)) {
91
                return false;
92
            }
93
        }
94
95
        return true;
96
    }
97
98
    /**
99
     * Déterminez si la demande contient l'une des entrées données.
100
     */
101
    public function hasAny(array|string $keys): bool
102
    {
103
        $keys = is_array($keys) ? $keys : func_get_args();
0 ignored issues
show
introduced by
The condition is_array($keys) is always true.
Loading history...
104
105
        $input = $this->all();
106
107
        return Arr::hasAny($input, $keys);
108
    }
109
110
    /**
111
     * Appliquez le rappel si la demande contient la clé d'élément d'entrée donnée.
112
     *
113
     * @return mixed|self
114
     */
115
    public function whenHas(string $key, callable $callback, ?callable $default = null)
116
    {
117
        if ($this->has($key)) {
118
            return $callback(Arr::dataGet($this->all(), $key)) ?: $this;
119
        }
120
121
        if ($default) {
122
            return $default();
123
        }
124
125
        return $this;
126
    }
127
128
    /**
129
     * Déterminez si la requête contient une valeur non vide pour un élément d'entrée.
130
     */
131
    public function filled(array|string $key): bool
132
    {
133
        $keys = is_array($key) ? $key : func_get_args();
0 ignored issues
show
introduced by
The condition is_array($key) is always true.
Loading history...
134
135
        foreach ($keys as $value) {
136
            if ($this->isEmptyString($value)) {
137
                return false;
138
            }
139
        }
140
141
        return true;
142
    }
143
144
    /**
145
     * Déterminez si la requête contient une valeur vide pour un élément d'entrée.
146
     */
147
    public function isNotFilled(array|string $key): bool
148
    {
149
        $keys = is_array($key) ? $key : func_get_args();
0 ignored issues
show
introduced by
The condition is_array($key) is always true.
Loading history...
150
151
        foreach ($keys as $value) {
152
            if (! $this->isEmptyString($value)) {
153
                return false;
154
            }
155
        }
156
157
        return true;
158
    }
159
160
    /**
161
     * Determine if the request contains a non-empty value for any of the given inputs.
162
     */
163
    public function anyFilled(array|string $keys): bool
164
    {
165
        $keys = is_array($keys) ? $keys : func_get_args();
0 ignored issues
show
introduced by
The condition is_array($keys) is always true.
Loading history...
166
167
        foreach ($keys as $key) {
168
            if ($this->filled($key)) {
169
                return true;
170
            }
171
        }
172
173
        return false;
174
    }
175
176
    /**
177
     * Appliquez le rappel si la requête contient une valeur non vide pour la clé d'élément d'entrée donnée.
178
     *
179
     * @return mixed|self
180
     */
181
    public function whenFilled(string $key, callable $callback, ?callable $default = null)
182
    {
183
        if ($this->filled($key)) {
184
            return $callback(Arr::dataGet($this->all(), $key)) ?: $this;
185
        }
186
187
        if ($default) {
188
            return $default();
189
        }
190
191
        return $this;
192
    }
193
194
    /**
195
     * Déterminez s'il manque une clé d'élément d'entrée donnée dans la requête.
196
     */
197
    public function missing(array|string $key): bool
198
    {
199
        $keys = is_array($key) ? $key : func_get_args();
0 ignored issues
show
introduced by
The condition is_array($key) is always true.
Loading history...
200
201
        return ! $this->has($keys);
202
    }
203
204
    /**
205
     * Appliquez le rappel s'il manque à la demande la clé d'élément d'entrée donnée.
206
     *
207
     * @return mixed|self
208
     */
209
    public function whenMissing(string $key, callable $callback, ?callable $default = null)
210
    {
211
        if ($this->missing($key)) {
212
            return $callback(Arr::dataGet($this->all(), $key)) ?: $this;
213
        }
214
215
        if ($default) {
216
            return $default();
217
        }
218
219
        return $this;
220
    }
221
222
    /**
223
     * Déterminez si la clé d'entrée donnée est une chaîne vide pour "remplie".
224
     */
225
    protected function isEmptyString(string $key): bool
226
    {
227
        $value = $this->input($key);
228
229
        return ! is_bool($value) && ! is_array($value) && trim((string) $value) === '';
230
    }
231
232
    /**
233
     * Obtenez les clés pour toutes les entrées et tous les fichiers.
234
     */
235
    public function keys(): array
236
    {
237
        return array_keys($this->input());
238
    }
239
240
    /**
241
     * Obtenez toutes les entrées et tous les fichiers de la requête.
242
     *
243
     * @param array|mixed|null $keys
244
     */
245
    public function all($keys = null): array
246
    {
247
        $input = array_replace_recursive($this->input(), $this->allFiles());
248
249
        if (! $keys) {
250
            return $input;
251
        }
252
253
        $results = [];
254
255
        foreach (is_array($keys) ? $keys : func_get_args() as $key) {
256
            Arr::set($results, $key, Arr::get($input, $key));
257
        }
258
259
        return $results;
260
    }
261
262
    /**
263
     * Récupérer un élément d'entrée de la requête.
264
     */
265
    public function input(?string $key = null, mixed $default = null): mixed
266
    {
267
        return Arr::dataGet(
268
            $this->data + $this->query,
269
            $key,
270
            $default
271
        );
272
    }
273
274
    /**
275
     * Récupérez l'entrée de la requête en tant qu'instance Stringable.
276
     */
277
    public function str(string $key, mixed $default = null): Stringable
278
    {
279
        return $this->string($key, $default);
280
    }
281
282
    /**
283
     * Récupérez l'entrée de la requête en tant qu'instance Stringable.
284
     */
285
    public function string(string $key, mixed $default = null): Stringable
286
    {
287
        return Text::of($this->input($key, $default));
288
    }
289
290
    /**
291
     * Récupérer l'entrée sous forme de valeur booléenne.
292
     *
293
     * Renvoie true lorsque la valeur est "1", "true", "on" et "yes". Sinon, renvoie faux.
294
     */
295
    public function boolean(?string $key = null, bool $default = false): bool
296
    {
297
        return filter_var($this->input($key, $default), FILTER_VALIDATE_BOOLEAN);
298
    }
299
300
    /**
301
     * Récupérer l'entrée sous forme de valeur entière.
302
     */
303
    public function integer(string $key, int $default = 0): int
304
    {
305
        return (int) ($this->input($key, $default));
306
    }
307
308
    /**
309
     * Récupérer l'entrée sous forme de valeur flottante.
310
     */
311
    public function float(string $key, float $default = 0.0): float
312
    {
313
        return (float) ($this->input($key, $default));
314
    }
315
316
    /**
317
     * Récupérez l'entrée de la demande en tant qu'instance Date.
318
     */
319
    public function date(string $key, ?string $format = null, ?string $tz = null): ?Date
320
    {
321
        if ($this->isNotFilled($key)) {
322
            return null;
323
        }
324
325
        if (null === $format) {
326
            return Date::parse($this->input($key), $tz);
327
        }
328
329
        return Date::createFromFormat($format, $this->input($key), $tz);
330
    }
331
332
    /**
333
     * Retrieve input from the request as an enum.
334
     *
335
     * @template TEnum
336
     *
337
     * @param class-string<TEnum> $enumClass
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<TEnum> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<TEnum>.
Loading history...
338
     *
339
     * @return TEnum|null
340
     */
341
    public function enum(string $key, $enumClass)
342
    {
343
        if ($this->isNotFilled($key)
344
            || ! function_exists('enum_exists')
345
            || ! enum_exists($enumClass)
346
            || ! method_exists($enumClass, 'tryFrom')) {
347
            return null;
348
        }
349
350
        return $enumClass::tryFrom($this->input($key));
351
    }
352
353
    /**
354
     * Récupérer l'entrée de la requête sous forme de collection.
355
     */
356
    public function collect(null|array|string $key = null): Collection
357
    {
358
        return collect(is_array($key) ? $this->only($key) : $this->input($key));
359
    }
360
361
    /**
362
     * Obtenez un sous-ensemble contenant les clés fournies avec les valeurs des données d'entrée.
363
     *
364
     * @param array|mixed $keys
365
     */
366
    public function only($keys): array
367
    {
368
        $results = [];
369
370
        $input = $this->all();
371
372
        $placeholder = new stdClass();
373
374
        foreach (is_array($keys) ? $keys : func_get_args() as $key) {
375
            $value = Arr::dataGet($input, $key, $placeholder);
376
377
            if ($value !== $placeholder) {
378
                Arr::set($results, $key, $value);
379
            }
380
        }
381
382
        return $results;
383
    }
384
385
    /**
386
     * Récupère toutes les entrées à l'exception d'un tableau d'éléments spécifié.
387
     *
388
     * @param array|mixed $keys
389
     */
390
    public function except($keys): array
391
    {
392
        $keys = is_array($keys) ? $keys : func_get_args();
393
394
        $results = $this->all();
395
396
        Arr::forget($results, $keys);
397
398
        return $results;
399
    }
400
401
    /**
402
     * Récupérez un élément de chaîne de requête à partir de la demande.
403
     *
404
     * @return array|string|null
405
     */
406
    public function query(?string $key = null, null|array|string $default = null)
407
    {
408
        return $this->getQuery($key, $default);
0 ignored issues
show
Bug introduced by
It seems like getQuery() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

408
        return $this->/** @scrutinizer ignore-call */ getQuery($key, $default);
Loading history...
409
    }
410
411
    /**
412
     * Récupérer un élément de charge utile de requête à partir de la requête.
413
     *
414
     * @return array|string|null
415
     */
416
    public function post(?string $key = null, null|array|string $default = null)
417
    {
418
        if ($key === null) {
419
            return $this->data;
420
        }
421
422
        return Arr::get($this->data, $key, $default);
423
    }
424
425
    /**
426
     * Déterminez si un cookie est défini sur la demande.
427
     */
428
    public function hasCookie(string $key): bool
429
    {
430
        return null !== $this->cookie($key);
431
    }
432
433
    /**
434
     * Récupérer un cookie de la requête.
435
     *
436
     * @return array|string|null
437
     */
438
    public function cookie(?string $key = null, null|array|string $default = null)
439
    {
440
        if (null === $key) {
441
            return $this->getCookieParams();
0 ignored issues
show
Bug introduced by
It seems like getCookieParams() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

441
            return $this->/** @scrutinizer ignore-call */ getCookieParams();
Loading history...
442
        }
443
444
        return $this->getCookie($key, $default);
0 ignored issues
show
Bug introduced by
It seems like getCookie() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

444
        return $this->/** @scrutinizer ignore-call */ getCookie($key, $default);
Loading history...
445
    }
446
447
    /**
448
     * Obtenez un tableau de tous les fichiers de la requête.
449
     */
450
    public function allFiles(): array
451
    {
452
        return $this->getUploadedFiles();
0 ignored issues
show
Bug introduced by
It seems like getUploadedFiles() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

452
        return $this->/** @scrutinizer ignore-call */ getUploadedFiles();
Loading history...
453
    }
454
455
    /**
456
     * Déterminez si les données téléchargées contiennent un fichier.
457
     */
458
    public function hasFile(string $key): bool
459
    {
460
        if (! is_array($files = $this->file($key))) {
461
            $files = [$files];
462
        }
463
464
        foreach ($files as $file) {
465
            if ($this->isValidFile($file)) {
466
                return true;
467
            }
468
        }
469
470
        return false;
471
    }
472
473
    /**
474
     * Vérifiez que le fichier donné est une instance de fichier valide.
475
     */
476
    protected function isValidFile(mixed $file): bool
477
    {
478
        return ($file instanceof SplFileInfo && $file->getPath() !== '') || $file instanceof UploadedFileInterface;
479
    }
480
481
    /**
482
     * Récupérer un fichier à partir de la requête.
483
     *
484
     * @return array|UploadedFile|UploadedFile[]|null
485
     */
486
    public function file(?string $key = null, mixed $default = null)
487
    {
488
        return Arr::dataGet($this->allFiles(), $key, $default);
489
    }
490
491
    /**
492
     * Videz les éléments de la requête et terminez le script.
493
     *
494
     * @return never
495
     */
496
    public function dd(...$keys)
497
    {
498
        $this->dump(...$keys);
499
500
        exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
501
    }
502
503
    /**
504
     * Videz les elements.
505
     *
506
     * @param mixed $keys
507
     */
508
    public function dump($keys = []): self
509
    {
510
        $keys = is_array($keys) ? $keys : func_get_args();
511
512
        Kint::dump(count($keys) > 0 ? $this->only($keys) : $this->all());
513
514
        return $this;
515
    }
516
}
517