Passed
Push — main ( 57b38b...aec17e )
by Dimitri
04:13
created

Request::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 1
cp 0
crap 2
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;
13
14
use ArrayAccess;
15
use BlitzPHP\Container\Services;
16
use BlitzPHP\Contracts\Support\Arrayable;
17
use BlitzPHP\Exceptions\ValidationException;
18
use BlitzPHP\Session\Store;
19
use BlitzPHP\Utilities\Iterable\Arr;
20
use BlitzPHP\Utilities\String\Text;
21
use BlitzPHP\Validation\DataValidation;
22
use BlitzPHP\Validation\Validation;
23
use BlitzPHP\Validation\Validator;
24
use Dimtrovich\Validation\Exceptions\ValidationException as DimtrovichValidationException;
25
use Dimtrovich\Validation\ValidatedInput;
26
use InvalidArgumentException;
27
28
class Request extends ServerRequest implements Arrayable, ArrayAccess
29
{
30
    use Concerns\InteractsWithContentTypes;
31
    use Concerns\InteractsWithInput;
32
    use Concerns\InteractsWithFlashData;
33
34
    /**
35
     * Validation des donnees de la requete
36
     *
37
     * @param array|class-string<DataValidation> $rules
0 ignored issues
show
Documentation Bug introduced by
The doc comment array|class-string<DataValidation> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array|class-string<DataValidation>.
Loading history...
38
     */
39
    public function validate(array|string $rules, array $messages = []): ValidatedInput
40
    {
41
        try {
42
            return $this->validation($rules, $messages)->safe();
43
        } catch (DimtrovichValidationException $e) {
44
            $th = new ValidationException($e->getMessage());
45
            $th->setErrors($e->getErrors());
46
47
            throw $th;
48
        }
49
    }
50
51
    /**
52
     * Cree un validateur avec les donnees de la requete actuelle
53
     *
54
     * @param array|class-string<DataValidation> $rules
0 ignored issues
show
Documentation Bug introduced by
The doc comment array|class-string<DataValidation> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array|class-string<DataValidation>.
Loading history...
55
     */
56
    public function validation(array|string $rules, array $messages = []): Validation
57
    {
58
        if (is_string($rules)) {
0 ignored issues
show
introduced by
The condition is_string($rules) is always false.
Loading history...
59
            if (! class_exists($rules) || ! is_subclass_of($rules, DataValidation::class)) {
60
                throw new InvalidArgumentException();
61
            }
62
63
            /** @var DataValidation $validation */
64
            $validation = Services::container()->make($rules);
65
66
            return $validation->process($this);
67
        }
68
69
        return Validator::make($this->all(), $rules, $messages);
0 ignored issues
show
Bug Best Practice introduced by
The expression return BlitzPHP\Validati...l(), $rules, $messages) returns the type Dimtrovich\Validation\Validation which includes types incompatible with the type-hinted return BlitzPHP\Validation\Validation.
Loading history...
70
    }
71
72
    /**
73
     * Obtenez la méthode de requête.
74
     */
75
    public function method(): string
76
    {
77
        return $this->getMethod();
78
    }
79
80
    /**
81
     * Obtenez l'URL racine de l'application.
82
     */
83
    public function root(): string
84
    {
85
        return rtrim(site_url(), '/');
86
    }
87
88
    /**
89
     * Renvoie l'URL racine à partir de laquelle cette requête est exécutée.
90
     *
91
     * L'URL de base ne se termine jamais par un /.
92
     *
93
     * Ceci est similaire à getBasePath(), sauf qu'il inclut également le
94
     * nom de fichier du script (par exemple index.php) s'il existe.
95
     *
96
     * @return string L'URL brute (c'est-à-dire non décodée en url)
97
     */
98
    public function getBaseUrl(): string
99
    {
100
        return trim(config()->get('app.base_url'), '/');
0 ignored issues
show
Bug introduced by
It seems like config()->get('app.base_url') can also be of type null; however, parameter $string of trim() 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

100
        return trim(/** @scrutinizer ignore-type */ config()->get('app.base_url'), '/');
Loading history...
101
    }
102
103
    /**
104
     * Obtient le schéma et l'hôte HTTP.
105
     *
106
     * Si l'URL a été appelée avec une authentification de base, l'utilisateur et
107
     * le mot de passe ne sont pas ajoutés à la chaîne générée.
108
     */
109
    public function getSchemeAndHttpHost(): string
110
    {
111
        return $this->getScheme() . '://' . $this->getHttpHost();
112
    }
113
114
    /**
115
     * Renvoie l'hôte HTTP demandé.
116
     *
117
     * Le nom du port sera ajouté à l'hôte s'il n'est pas standard.
118
     */
119
    public function getHttpHost(): string
120
    {
121
        $scheme = $this->getScheme();
122
        $port   = $this->getPort();
123
124
        if (('http' === $scheme && 80 === $port) || ('https' === $scheme && 443 === $port)) {
125
            return $this->getHost();
126
        }
127
128
        return $this->getHost() . ':' . $port;
129
    }
130
131
    /**
132
     * Obtenez l'URL (pas de chaîne de requête) pour la demande.
133
     */
134
    public function url(): string
135
    {
136
        return rtrim(preg_replace('/\?.*/', '', (string) $this->getUri()), '/');
137
    }
138
139
    /**
140
     * Obtenez l'URL complète de la demande.
141
     */
142
    public function fullUrl(): string
143
    {
144
        if (! empty($query = $this->getEnv('QUERY_STRING'))) {
145
            return $this->url() . '?' . $query;
146
        }
147
148
        return $this->url();
149
    }
150
151
    /**
152
     * Obtenez l'URL complète de la demande avec les paramètres de chaîne de requête ajoutés.
153
     */
154
    public function fullUrlWithQuery(array $query): string
155
    {
156
        $question = '?';
157
158
        return count($this->query()) > 0
159
            ? $this->url() . $question . Arr::query(array_merge($this->query(), $query))
160
            : $this->fullUrl() . $question . Arr::query($query);
161
    }
162
163
    /**
164
     * Obtenez l'URL complète de la requête sans les paramètres de chaîne de requête donnés.
165
     */
166
    public function fullUrlWithoutQuery(array|string $keys): string
167
    {
168
        $query = Arr::except($this->query(), $keys);
169
170
        return count($query) > 0
171
            ? $this->url() . '?' . Arr::query($query)
172
            : $this->url();
173
    }
174
175
    /**
176
     * Obtenez les informations de chemin actuelles pour la demande.
177
     */
178
    public function path(): string
179
    {
180
        return $this->getPath();
181
    }
182
183
    /**
184
     * Obtenez les informations de chemin décodées actuelles pour la demande.
185
     */
186
    public function decodedPath(): string
187
    {
188
        return rawurldecode($this->path());
189
    }
190
191
    /**
192
     * Obtenir un segment de l'URI (index basé sur 1).
193
     */
194
    public function segment(int $index, ?string $default = null): ?string
195
    {
196
        return Arr::get($this->segments(), $index - 1, $default);
197
    }
198
199
    /**
200
     * Obtenez tous les segments pour le chemin de la demande.
201
     */
202
    public function segments(): array
203
    {
204
        $segments = explode('/', $this->decodedPath());
205
206
        return array_values(array_filter($segments, static fn ($value) => $value !== ''));
207
    }
208
209
    /**
210
     * Déterminez si l’URI de la demande actuelle correspond à un modèle.
211
     */
212
    public function pathIs(...$patterns): bool
213
    {
214
        $path = $this->decodedPath();
215
216
        return collect($patterns)->contains(static fn ($pattern) => Text::is($pattern, $path));
217
    }
218
219
    /**
220
     * Déterminez si le nom de la route correspond à un modèle donné.
221
     *
222
     * @param mixed ...$patterns
223
     */
224
    public function routeIs(...$patterns): bool
0 ignored issues
show
Unused Code introduced by
The parameter $patterns is not used and could be removed. ( Ignorable by Annotation )

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

224
    public function routeIs(/** @scrutinizer ignore-unused */ ...$patterns): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
225
    {
226
        return false;
227
        // return $this->route() && $this->route()->named(...$patterns);
228
    }
229
230
    /**
231
     * Verifier si la methode de la requete actuelle est l'une envoyee en parametre
232
     */
233
    public function isMethod(array|string $methods): bool
234
    {
235
        foreach ((array) $methods as $method) {
236
            if (strtolower($method) === strtolower($this->method())) {
237
                return true;
238
            }
239
        }
240
241
        return false;
242
    }
243
244
    /**
245
     * Déterminez si l'URL de requête et la chaîne de requête actuelles correspondent à un modèle.
246
     *
247
     * @param mixed ...$patterns
248
     */
249
    public function fullUrlIs(...$patterns): bool
250
    {
251
        $url = $this->fullUrl();
252
253
        return collect($patterns)->contains(static fn ($pattern) => Text::is($pattern, $url));
254
    }
255
256
    /**
257
     * Obtenez l'hôte HTTP demandé.
258
     */
259
    public function httpHost(): ?string
260
    {
261
        return $this->host();
262
    }
263
264
    /**
265
     * Déterminez si la demande est le résultat d'un appel AJAX.
266
     */
267
    public function ajax(): bool
268
    {
269
        return $this->is('ajax');
270
    }
271
272
    /**
273
     * Déterminez si la demande est le résultat d'un appel PJAX.
274
     */
275
    public function pjax(): bool
276
    {
277
        return $this->header('X-PJAX') === true;
278
    }
279
280
    /**
281
     * Déterminez si la demande est le résultat d'un appel de prélecture.
282
     */
283
    public function prefetch(): bool
284
    {
285
        return strcasecmp($this->server('HTTP_X_MOZ', ''), 'prefetch') === 0
0 ignored issues
show
Bug introduced by
It seems like $this->server('HTTP_X_MOZ', '') can also be of type array and null; however, parameter $string1 of strcasecmp() 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

285
        return strcasecmp(/** @scrutinizer ignore-type */ $this->server('HTTP_X_MOZ', ''), 'prefetch') === 0
Loading history...
286
               || strcasecmp($this->header('Purpose', ''), 'prefetch') === 0;
287
    }
288
289
    /**
290
     * Déterminez si la demande est via HTTPS.
291
     */
292
    public function secure(): bool
293
    {
294
        return $this->is('ssl');
295
    }
296
297
    /**
298
     * Obtenez l'adresse IP du client.
299
     */
300
    public function ip(): ?string
301
    {
302
        return $this->clientIp();
303
    }
304
305
    /**
306
     * Obtenez l'agent utilisateur client.
307
     */
308
    public function userAgent(): ?string
309
    {
310
        return $this->header('User-Agent');
311
    }
312
313
    /**
314
     * Fusionne la nouvelle entrée dans le tableau d'entrée de la requête actuelle.
315
     */
316
    public function merge(array $input): self
317
    {
318
        $this->data = array_merge($this->data, $input);
0 ignored issues
show
Bug introduced by
It seems like $this->data can also be of type null and object; however, parameter $arrays of array_merge() does only seem to accept array, 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

318
        $this->data = array_merge(/** @scrutinizer ignore-type */ $this->data, $input);
Loading history...
319
320
        return $this;
321
    }
322
323
    /**
324
     * Fusionne la nouvelle entrée dans l'entrée de la requête, mais uniquement lorsque cette clé est absente de la requête.
325
     */
326
    public function mergeIfMissing(array $input): self
327
    {
328
        return $this->merge(collect($input)->filter(fn ($value, $key) => $this->missing($key))->toArray());
329
    }
330
331
    /**
332
     * Remplacez l'entrée de la requête en cours.
333
     */
334
    public function replace(array $input): self
335
    {
336
        $this->data = $input;
337
338
        return $this;
339
    }
340
341
    /**
342
     * {@inheritDoc}
343
     */
344
    public function hasSession(): bool
345
    {
346
        return null !== $this->session;
347
    }
348
349
    /**
350
     * Définissez l'instance de session sur la demande.
351
     */
352
    public function setSession(Store $session): void
353
    {
354
        $this->session = $session;
355
    }
356
357
    /**
358
     * Obtenez toutes les entrées et tous les fichiers de la requête.
359
     */
360
    public function toArray(): array
361
    {
362
        return $this->all();
363
    }
364
365
    public function getScheme(): string
366
    {
367
        return $this->getUri()->getScheme();
368
    }
369
370
    public function getHost(): string
371
    {
372
        return $this->getUri()->getHost();
373
    }
374
375
    public function getPort(): int
376
    {
377
        return $this->getUri()->getPort() ?? 80;
378
    }
379
380
    /**
381
     * {@inheritDoc}
382
     *
383
     * @param string $offset
384
     */
385
    public function offsetExists($offset): bool
386
    {
387
        return Arr::has($this->all(), $offset);
388
    }
389
390
    /**
391
     * {@inheritDoc}
392
     *
393
     * @param string $offset
394
     */
395
    public function offsetGet($offset): mixed
396
    {
397
        return $this->__get($offset);
398
    }
399
400
    /**
401
     * {@inheritDoc}
402
     *
403
     * @param string $offset
404
     */
405
    public function offsetSet($offset, $value): void
406
    {
407
        $this->data[$offset] = $value;
408
    }
409
410
    /**
411
     * {@inheritDoc}
412
     *
413
     * @param string $offset
414
     */
415
    public function offsetUnset($offset): void
416
    {
417
        unset($this->data[$offset]);
418
    }
419
420
    /**
421
     * Vérifiez si un élément d'entrée est défini sur la demande.
422
     */
423
    public function __isset(string $key): bool
424
    {
425
        return null !== $this->__get($key);
426
    }
427
428
    /**
429
     * Obtenez un élément d'entrée à partir de la requête.
430
     */
431
    public function __get(string $key): mixed
432
    {
433
        return Arr::get($this->all(), $key, null);
434
    }
435
}
436