Passed
Push — main ( 89bfd0...bcc78b )
by Dimitri
04:50
created

Request::userAgent()   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\Contracts\Support\Arrayable;
16
use BlitzPHP\Exceptions\ValidationException;
17
use BlitzPHP\Session\Store;
18
use BlitzPHP\Utilities\Iterable\Arr;
19
use BlitzPHP\Utilities\String\Text;
20
use BlitzPHP\Validation\Validation;
21
use BlitzPHP\Validation\Validator;
22
use Dimtrovich\Validation\Exceptions\ValidationException as DimtrovichValidationException;
23
use Dimtrovich\Validation\ValidatedInput;
24
25
class Request extends ServerRequest implements Arrayable, ArrayAccess
26
{
27
    use Concerns\InteractsWithContentTypes;
28
    use Concerns\InteractsWithInput;
29
    use Concerns\InteractsWithFlashData;
30
31
    /**
32
     * Validation des donnees de la requete
33
     */
34
    public function validate(array $rules, array $messages = []): ValidatedInput
35
    {
36
        try {
37
            return $this->validation($rules, $messages)->safe();
38
        } catch (DimtrovichValidationException $e) {
39
            $th = new ValidationException($e->getMessage());
40
            $th->setErrors($e->getErrors());
41
42
            throw $th;
43
        }
44
    }
45
46
    /**
47
     * Cree un validateur avec les donnees de la requete actuelle
48
     */
49
    public function validation(array $rules, array $messages = []): Validation
50
    {
51
        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...
52
    }
53
54
    /**
55
     * Obtenez la méthode de requête.
56
     */
57
    public function method(): string
58
    {
59
        return $this->getMethod();
60
    }
61
62
    /**
63
     * Obtenez l'URL racine de l'application.
64
     */
65
    public function root(): string
66
    {
67
        return rtrim(site_url(), '/');
68
    }
69
70
    /**
71
     * Renvoie l'URL racine à partir de laquelle cette requête est exécutée.
72
     *
73
     * L'URL de base ne se termine jamais par un /.
74
     *
75
     * Ceci est similaire à getBasePath(), sauf qu'il inclut également le
76
     * nom de fichier du script (par exemple index.php) s'il existe.
77
     *
78
     * @return string L'URL brute (c'est-à-dire non décodée en url)
79
     */
80
    public function getBaseUrl(): string
81
    {
82
        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

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

206
    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...
207
    {
208
        return false;
209
        // return $this->route() && $this->route()->named(...$patterns);
210
    }
211
212
    /**
213
     * Verifier si la methode de la requete actuelle est l'une envoyee en parametre
214
     */
215
    public function isMethod(array|string $methods): bool
216
    {
217
		foreach ((array) $methods as $method) {
218
			if (strtolower($method) === strtolower($this->method())) {
219
				return true;
220
			}
221
		}
222
223
        return false;
224
    }
225
226
    /**
227
     * Déterminez si l'URL de requête et la chaîne de requête actuelles correspondent à un modèle.
228
     *
229
     * @param mixed ...$patterns
230
     */
231
    public function fullUrlIs(...$patterns): bool
232
    {
233
        $url = $this->fullUrl();
234
235
        return collect($patterns)->contains(static fn ($pattern) => Text::is($pattern, $url));
236
    }
237
238
    /**
239
     * Obtenez l'hôte HTTP demandé.
240
     */
241
    public function httpHost(): ?string
242
    {
243
        return $this->host();
244
    }
245
246
    /**
247
     * Déterminez si la demande est le résultat d'un appel AJAX.
248
     */
249
    public function ajax(): bool
250
    {
251
        return $this->is('ajax');
252
    }
253
254
    /**
255
     * Déterminez si la demande est le résultat d'un appel PJAX.
256
     */
257
    public function pjax(): bool
258
    {
259
        return $this->header('X-PJAX') === true;
260
    }
261
262
    /**
263
     * Déterminez si la demande est le résultat d'un appel de prélecture.
264
     */
265
    public function prefetch(): bool
266
    {
267
        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

267
        return strcasecmp(/** @scrutinizer ignore-type */ $this->server('HTTP_X_MOZ', ''), 'prefetch') === 0
Loading history...
268
               || strcasecmp($this->header('Purpose', ''), 'prefetch') === 0;
269
    }
270
271
    /**
272
     * Déterminez si la demande est via HTTPS.
273
     */
274
    public function secure(): bool
275
    {
276
        return $this->is('ssl');
277
    }
278
279
    /**
280
     * Obtenez l'adresse IP du client.
281
     */
282
    public function ip(): ?string
283
    {
284
        return $this->clientIp();
285
    }
286
287
    /**
288
     * Obtenez l'agent utilisateur client.
289
     */
290
    public function userAgent(): ?string
291
    {
292
        return $this->header('User-Agent');
293
    }
294
295
    /**
296
     * Fusionne la nouvelle entrée dans le tableau d'entrée de la requête actuelle.
297
     */
298
    public function merge(array $input): self
299
    {
300
        $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

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