Passed
Pull Request — main (#9)
by
unknown
07:12 queued 03:32
created

method_field()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 7
ccs 2
cts 2
cp 1
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
use BlitzPHP\Cli\Console\Console;
0 ignored issues
show
Bug introduced by
The type BlitzPHP\Cli\Console\Console was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use BlitzPHP\Config\Config;
14
use BlitzPHP\Container\Services;
15
use BlitzPHP\Contracts\Database\ConnectionInterface;
16
use BlitzPHP\Contracts\Http\StatusCode;
17
use BlitzPHP\Contracts\Session\CookieInterface;
18
use BlitzPHP\Contracts\Session\CookieManagerInterface;
19
use BlitzPHP\Exceptions\PageNotFoundException;
20
use BlitzPHP\Exceptions\RedirectException;
21
use BlitzPHP\Http\Redirection;
22
use BlitzPHP\Http\ServerRequest;
23
use BlitzPHP\Loader\Load;
24
use BlitzPHP\Session\Store;
25
use BlitzPHP\Utilities\Helpers;
26
use BlitzPHP\Utilities\Iterable\Collection;
27
use BlitzPHP\Utilities\Support\Invader;
28
29
// ================================= FONCTIONS UTIILITAIRES ESSENTIELLES ================================= //
30
31
if (! function_exists('env')) {
32
    /**
33
     * Obtient une variable d'environnement à partir des sources disponibles et fournit une émulation
34
     * pour les variables d'environnement non prises en charge ou incohérentes
35
     *
36
     * @param string     $key     Nom de la variable d'environnement
37
     * @param mixed|null $default
38
     *
39
     * @return string Paramétrage des variables d'environnement.
40
     */
41
    function env(string $key, $default = null)
42
    {
43 115
        return Helpers::env($key, $default);
44
    }
45
}
46
47
if (! function_exists('helper')) {
48
    /**
49
     * Charge un fichier d'aide en mémoire. Prend en charge les assistants d'espace de noms,
50
     * à la fois dans et hors du répertoire 'helpers' d'un répertoire à espace de noms.
51
     *
52
     * Chargera TOUS les helpers du nom correspondant, dans l'ordre suivant :
53
     *   1. app/Helpers
54
     *   2. {namespace}/Helpers
55
     *   3. system/Helpers
56
     */
57
    function helper(array|string $filenames)
58
    {
59 32
        Load::helper($filenames);
60
    }
61
}
62
63
if (! function_exists('model')) {
64
    /**
65
     * Simple maniere d'obtenir un modele.
66
     *
67
     * @template T
68
     *
69
     * @param array<class-string<T>>|class-string<T> $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<T>>|class-string<T> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<T>>|class-string<T>.
Loading history...
70
     *
71
     * @return T
72
     */
73
    function model(array|string $name, ?ConnectionInterface &$conn = null)
74
    {
75
        return Load::model($name, $conn);
0 ignored issues
show
Bug Best Practice introduced by
The expression return BlitzPHP\Loader\Load::model($name, $conn) also could return the type array<mixed,object> which is incompatible with the documented return type T.
Loading history...
76
    }
77
}
78
79
if (! function_exists('service')) {
80
    /**
81
     * Permet un accès plus propre au fichier de configuration des services.
82
     * Renvoie toujours une instance SHARED de la classe, donc l'appel de la fonction plusieurs fois renvera toujours la même instance.
83
     *
84
     * Ceux-ci sont égaux :
85
     *  - $cache = service('cache')
86
     *  - $cache = \BlitzPHP\Container\Services::cache();
87
     *
88
     * @template T
89
     *
90
     * @param class-string<T> $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
91
     *
92
     * @return object|T
93
     */
94
    function service(string $name, ...$params)
95
    {
96 12
        return Services::$name(...$params);
97
    }
98
}
99
100
if (! function_exists('single_service')) {
101
    /**
102
     * Autoriser l'accès propre à un service.
103
     * Renvoie toujours une nouvelle instance de la classe.
104
     *
105
     * @template T
106
     *
107
     * @param class-string<T> $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
108
     *
109
     * @return object|T
110
     */
111
    function single_service(string $name, ...$params)
112
    {
113
        // Assurez-vous qu'il ne s'agit PAS d'une instance partagée
114
        $params[] = false;
115
116
        return Services::$name(...$params);
117
    }
118
}
119
120
if (! function_exists('show404')) {
121
    /**
122
     * Afficher une page 404 introuvable dans le navigateur
123
     */
124
    function show404(string $message = 'The page you requested was not found.', string $heading = 'Page Not Found', array $params = [])
125
    {
126
        throw PageNotFoundException::pageNotFound($message);
127
    }
128
}
129
130
if (! function_exists('command')) {
131
    /**
132
     * Exécute une seule commande.
133
     * Entrée attendue dans une seule chaîne comme celle qui serait utilisée sur la ligne de commande elle-même :
134
     *
135
     *  > command('migrate:create SomeMigration');
136
     *
137
     * @see https://github.com/codeigniter4/CodeIgniter4/blob/b56c85c9d09fd3b34893220b2221ed27f8d508e6/system/Common.php#L133
138
     *
139
     * @return false|string
140
     */
141
    function command(string $command)
142
    {
143 2
        $regexString = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
144 2
        $regexQuoted = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
145
146 2
        $args   = [];
147 2
        $length = strlen($command);
148 2
        $cursor = 0;
149
150
        /**
151
         * Adopté de `StringInput::tokenize()` de Symfony avec quelques modifications.
152
         *
153
         * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Console/Input/StringInput.php
154
         */
155
        while ($cursor < $length) {
156
            if (preg_match('/\s+/A', $command, $match, 0, $cursor)) {
157
                // Rien a faire
158
            } elseif (preg_match('/' . $regexQuoted . '/A', $command, $match, 0, $cursor)) {
159 2
                $args[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
160
            } elseif (preg_match('/' . $regexString . '/A', $command, $match, 0, $cursor)) {
161 2
                $args[] = stripcslashes($match[1]);
162
            } else {
163
                // @codeCoverageIgnoreStart
164
                throw new InvalidArgumentException(sprintf(
165
                    'Impossible d\'analyser l\'entrée à proximité "... %s ...".',
166
                    substr($command, $cursor, 10)
167
                ));
168
                // @codeCoverageIgnoreEnd
169
            }
170
171 2
            $cursor += strlen($match[0]);
172
        }
173
174 2
        $command = array_shift($args);
175 2
        $params  = [];
176
177
        foreach ($args as $key => $arg) {
178
            if (mb_strpos($arg, '--') !== false) {
179 2
                unset($args[$key]);
180 2
                [$arg, $v]          = explode('=', $arg) + [1 => true];
181 2
                $params[trim($arg)] = is_string($v) ? trim($v) : $v;
182
            }
183
        }
184
185 2
        ob_start();
186
187 2
        service(Console::class)->call($command, $args, $params);
188
189 2
        return ob_get_clean();
190
    }
191
}
192
193
if (! function_exists('config')) {
194
    /**
195
     * GET/SET App config
196
     *
197
     * @param mixed|null $default
198
     *
199
     * @return Config|mixed|void
200
     */
201
    function config(null|array|string $key = null, $default = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
202
    {
203 163
        $config = Services::config();
204
205
        if (null === $key) {
206 10
            return $config;
207
        }
208
209
        if (is_string($key)) {
0 ignored issues
show
introduced by
The condition is_string($key) is always false.
Loading history...
210 163
            return $config->get($key, $default);
211
        }
212
213
        foreach ($key as $k => $v) {
214
            if (is_string($k)) {
215 8
                $config->set($k, $v);
216
            }
217
        }
218
    }
219
}
220
221
if (! function_exists('logger')) {
222
    /**
223
     * Une méthode de commodité pour les événements de journalisation via le système Log.
224
     *
225
     * Les niveaux de journal autorisés sont :
226
     *  - emergency
227
     *  - alert
228
     *  - critical
229
     *  - error
230
     *  - warning
231
     *  - notice
232
     *  - info
233
     *  - debug
234
     *
235
     * @param int|string $level
236
     *
237
     * @return BlitzPHP\Debug\Logger|void
238
     */
239
    function logger($level = null, ?string $message = null, array $context = [])
240
    {
241
        $logger = Services::logger();
242
243
        if (empty($level) || empty($message)) {
244
            return $logger;
245
        }
246
247
        $logger->log($level, $message, $context);
248
    }
249
}
250
251
if (! function_exists('cache')) {
252
    /**
253
     * Une méthode pratique qui donne accès au cache
254
     * objet. Si aucun paramètre n'est fourni, renverra l'objet,
255
     * sinon, tentera de renvoyer la valeur mise en cache.
256
     *
257
     * Exemples:
258
     *    cache()->set('foo', 'bar'); ou cache('foo', 'bar');
259
     *    $foo = cache('bar');
260
     *
261
     * @param mixed|null $value
262
     *
263
     * @return BlitzPHP\Cache\Cache|bool|mixed
264
     */
265
    function cache(?string $key = null, $value = null)
266
    {
267 4
        $cache = Services::cache();
268
269
        if (empty($key)) {
270 4
            return $cache;
271
        }
272
273
        if (empty($value)) {
274 4
            return $cache->get($key);
275
        }
276
277
        return $cache->set($key, $value);
278
    }
279
}
280
281
if (! function_exists('cookie')) {
282
    /**
283
     * Une méthode pratique qui donne accès à l'objet cookie.
284
     * Si aucun paramètre n'est fourni, renverra l'objet,
285
     * sinon, tentera de renvoyer la valeur du cookie.
286
     *
287
     * Exemples:
288
     *    cookie()->make('foo', 'bar'); ou cookie('foo', 'bar');
289
     *    $foo = cookie('bar')
290
     *
291
     * @return CookieInterface|CookieManagerInterface|null
292
     */
293
    function cookie(?string $name = null, null|array|string $value = null, int $minutes = 0, array $options = [])
294
    {
295 4
        $cookie = Services::cookie();
296
297
        if (null === $name) {
298
            return $cookie;
299
        }
300
301
        if (null === $value) {
302 4
            return $cookie->get($name);
303
        }
304
305 4
        return $cookie->make($name, $value, $minutes, $options);
306
    }
307
}
308
309
if (! function_exists('session')) {
310
    /**
311
     * Une méthode pratique pour accéder à l'instance de session, ou un élément qui a été défini dans la session.
312
     *
313
     * Exemples:
314
     *    session()->set('foo', 'bar');
315
     *    $foo = session('bar');
316
     *
317
     * @return array|bool|float|int|object|Store|string|null
318
     */
319
    function session(?string $val = null)
320
    {
321
        $session = Services::session();
322
323
        // Vous retournez un seul element ?
324
        if (is_string($val)) {
325
            return $session->get($val);
326
        }
327
328
        return $session;
329
    }
330
}
331
332
// =========================== FONCTIONS DE PREVENTION D'ATTAQUE =========================== //
333
334
if (! function_exists('esc')) {
335
    /**
336
     * Effectue un simple échappement automatique des données pour des raisons de sécurité.
337
     * Pourrait envisager de rendre cela plus complexe à une date ultérieure.
338
     *
339
     * Si $data est une chaîne, il suffit alors de l'échapper et de la renvoyer.
340
     * Si $data est un tableau, alors il boucle dessus, s'échappant de chaque
341
     * 'valeur' des paires clé/valeur.
342
     *
343
     * Valeurs de contexte valides : html, js, css, url, attr, raw, null
344
     *
345
     * @param array|string $data
346
     *
347
     * @return array|string
348
     *
349
     * @throws InvalidArgumentException
350
     */
351
    function esc($data, ?string $context = 'html', ?string $encoding = null)
352
    {
353
        if (class_exists('\Laminas\Escaper\Escaper')) {
354 72
            return Helpers::esc($data, $context, $encoding);
355
        }
356
357 72
        return h($data, true, $encoding);
358
    }
359
}
360
361
if (! function_exists('h')) {
362
    /**
363
     * Méthode pratique pour htmlspecialchars.
364
     *
365
     * @param mixed       $text    Texte à envelopper dans htmlspecialchars. Fonctionne également avec des tableaux et des objets.
366
     *                             Les tableaux seront mappés et tous leurs éléments seront échappés. Les objets seront transtypés s'ils
367
     *                             implémenter une méthode `__toString`. Sinon, le nom de la classe sera utilisé.
368
     *                             Les autres types de scalaires seront renvoyés tels quels.
369
     * @param bool        $double  Encodez les entités html existantes.
370
     * @param string|null $charset Jeu de caractères à utiliser lors de l'échappement. La valeur par défaut est la valeur de configuration dans `mb_internal_encoding()` ou 'UTF-8'.
371
     *
372
     * @return mixed Texte enveloppé.
373
     */
374
    function h($text, bool $double = true, ?string $charset = null)
375
    {
376 72
        return Helpers::h($text, $double, $charset);
377
    }
378
}
379
380
if (! function_exists('purify')) {
381
    /**
382
     * Purifiez l'entrée à l'aide de la classe autonome HTMLPurifier.
383
     * Utilisez facilement plusieurs configurations de purificateur.
384
     *
385
     * @param string|string[] $dirty_html
386
     * @param false|string    $config
387
     *
388
     * @return string|string[]
389
     */
390
    function purify($dirty_html, $config = false)
391
    {
392
        return Helpers::purify($dirty_html, $config);
393
    }
394
}
395
396
if (! function_exists('remove_invisible_characters')) {
397
    /**
398
     * Supprimer les caractères invisibles
399
     *
400
     * Cela empêche de prendre en sandwich des caractères nuls
401
     * entre les caractères ascii, comme Java\0script.
402
     */
403
    function remove_invisible_characters(string $str, bool $url_encoded = true): string
404
    {
405
        return Helpers::removeInvisibleCharacters($str, $url_encoded);
406
    }
407
}
408
409
if (! function_exists('stringify_attributes')) {
410
    /**
411
     * Chaîner les attributs à utiliser dans les balises HTML.
412
     *
413
     * @param array|object|string $attributes
414
     */
415
    function stringify_attributes($attributes, bool $js = false): string
416
    {
417
        return Helpers::stringifyAttributes($attributes, $js);
418
    }
419
}
420
421
// ================================= FONCTIONS DE FORMULAIRE ================================= //
422
423
if (! function_exists('csrf_token')) {
424
    /**
425
     * Renvoie la valeur de hachage actuelle pour la protection CSRF.
426
     * Peut être utilisé dans les vues lors de la construction manuelle d'input cachées, ou utilisé dans les variables javascript pour l'utilisation de l'API.
427
     */
428
    function csrf_token(): string
429
    {
430
        return Services::session()->token();
0 ignored issues
show
Bug Best Practice introduced by
The expression return BlitzPHP\Containe...ces::session()->token() could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
431
    }
432
}
433
434
if (! function_exists('csrf_field')) {
435
    /**
436
     * Génère un champ input caché à utiliser dans les formulaires générés manuellement.
437
     */
438
    function csrf_field(?string $id = null): string
439
    {
440
        $name = config('security.csrf_token_name', '_token');
441
442
        return '<input type="hidden"' . (! empty($id) ? ' id="' . esc($id, 'attr') . '"' : '') . ' name="' . $name . '" value="' . csrf_token() . '">';
0 ignored issues
show
Bug introduced by
Are you sure esc($id, 'attr') of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

442
        return '<input type="hidden"' . (! empty($id) ? ' id="' . /** @scrutinizer ignore-type */ esc($id, 'attr') . '"' : '') . ' name="' . $name . '" value="' . csrf_token() . '">';
Loading history...
Bug introduced by
Are you sure $name of type BlitzPHP\Config\Config|null can be used in concatenation? ( Ignorable by Annotation )

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

442
        return '<input type="hidden"' . (! empty($id) ? ' id="' . esc($id, 'attr') . '"' : '') . ' name="' . /** @scrutinizer ignore-type */ $name . '" value="' . csrf_token() . '">';
Loading history...
443
    }
444
}
445
446
if (! function_exists('csrf_meta')) {
447
    /**
448
     * Génère une balise méta à utiliser dans les appels javascript.
449
     */
450
    function csrf_meta(?string $id = null): string
451
    {
452
        $name = config('security.csrf_header_name', 'X-CSRF-TOKEN');
453
454
        return '<meta' . (! empty($id) ? ' id="' . esc($id, 'attr') . '"' : '') . ' name="' . $name . '" content="' . csrf_token() . '">';
0 ignored issues
show
Bug introduced by
Are you sure esc($id, 'attr') of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

454
        return '<meta' . (! empty($id) ? ' id="' . /** @scrutinizer ignore-type */ esc($id, 'attr') . '"' : '') . ' name="' . $name . '" content="' . csrf_token() . '">';
Loading history...
Bug introduced by
Are you sure $name of type BlitzPHP\Config\Config|null can be used in concatenation? ( Ignorable by Annotation )

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

454
        return '<meta' . (! empty($id) ? ' id="' . esc($id, 'attr') . '"' : '') . ' name="' . /** @scrutinizer ignore-type */ $name . '" content="' . csrf_token() . '">';
Loading history...
455
    }
456
}
457
458
if (! function_exists('method_field')) {
459
    /**
460
     * Générer un champ de formulaire pour usurper le verbe HTTP utilisé par les formulaires.
461
     */
462
    function method_field(string $method): string
463
    {
464
        if (! in_array($method = strtoupper($method), ['PUT', 'POST', 'DELETE', 'PATCH'], true)) {
465 2
            throw new InvalidArgumentException(sprintf('Methode %s invalide', $method));
466
        }
467
468 2
        return '<input type="hidden" name="_method" value="' . $method . '">';
469
    }
470
}
471
472
// ================================= FONCTIONS D'ENVIRONNEMENT D'EXECUTION ================================= //
473
474
if (! function_exists('environment')) {
475
    /**
476
     * Renvoi l'environnement d'execution actuel ou determine si on est dans un environnement specifie
477
     *
478
     * @return bool|string
479
     */
480
    function environment(null|array|string $env = null)
481
    {
482 33
        $current = env('ENVIRONMENT');
483
        if (empty($current) || $current === 'auto') {
484 33
            $current = config('app.environment');
485
        }
486
487
        if (empty($env)) {
488
            return $current;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $current also could return the type BlitzPHP\Config\Config which is incompatible with the documented return type boolean|string.
Loading history...
489
        }
490
491
        $envMap = [
492
            'dev'     => 'development',
493
            'local'   => 'development',
494
            'prod'    => 'production',
495
            'test'    => 'testing',
496
            'stage'   => 'testing',
497
            'staging' => 'testing',
498 33
        ];
499
500 33
        $current = $envMap[$current] ?? $current;
501
502
        if (is_string($env)) {
0 ignored issues
show
introduced by
The condition is_string($env) is always false.
Loading history...
503 2
            $env = [$env];
504
        }
505
506 33
        $env = array_map(static fn ($k) => $envMap[$k] ?? $k, $env);
507
508 33
        return in_array($current, $env, true);
509
    }
510
}
511
512
if (! function_exists('on_dev')) {
513
    /**
514
     * Testez pour voir si nous sommes dans un environnement de développement.
515
     */
516
    function on_dev(bool $checkOnline = false): bool
517
    {
518
        if ($checkOnline && is_online()) {
519
            return false;
520
        }
521
522 8
        return environment(['dev', 'development', 'local']);
523
    }
524
}
525
526
if (! function_exists('on_prod')) {
527
    /**
528
     * Testez pour voir si nous sommes dans un environnement de production.
529
     */
530
    function on_prod(bool $checkOnline = false): bool
531
    {
532
        if ($checkOnline && is_online()) {
533
            return true;
534
        }
535
536
        return environment(['prod', 'production']);
537
    }
538
}
539
540
if (! function_exists('on_test')) {
541
    /**
542
     * Testez pour voir si nous sommes dans un environnement de test
543
     */
544
    function on_test(): bool
545
    {
546 27
        return environment(['test', 'testing', 'stage', 'staging']);
547
    }
548
}
549
550
if (! function_exists('is_cli')) {
551
    /**
552
     * Testez pour voir si une demande a été faite à partir de la ligne de commande.
553
     */
554
    function is_cli(): bool
555
    {
556
        return Helpers::isCli();
557
    }
558
}
559
560
if (! function_exists('is_php')) {
561
    /**
562
     * Détermine si la version actuelle de PHP est égale ou supérieure à la valeur fournie.
563
     */
564
    function is_php(string $version): bool
565
    {
566
        return Helpers::isPhp($version);
567
    }
568
}
569
570
if (! function_exists('is_windows')) {
571
    /**
572
     * Déterminez si l'environnement actuel est basé sur Windows.
573
     */
574
    function is_windows(): bool
575
    {
576
        return PHP_OS_FAMILY === 'Windows';
577
    }
578
}
579
580
if (! function_exists('is_https')) {
581
    /**
582
     * Determines if the application is accessed via an encrypted * (HTTPS) connection.
583
     */
584
    function is_https(): bool
585
    {
586
        return Services::request()->is('ssl');
587
    }
588
}
589
590
if (! function_exists('is_localfile')) {
591
    /**
592
     * Vérifiez si le fichier auquel vous souhaitez accéder est un fichier local de votre application ou non
593
     */
594
    function is_localfile(string $name): bool
595
    {
596
        if (preg_match('#^' . base_url() . '#i', $name)) {
597
            return true;
598
        }
599
600 2
        return ! preg_match('#^(https?://)#i', $name);
601
    }
602
}
603
604
if (! function_exists('is_online')) {
605
    /**
606
     * Tester si l'application s'exécute en local ou en ligne.
607
     */
608
    function is_online(): bool
609
    {
610 12
        return Helpers::isOnline();
611
    }
612
}
613
614
if (! function_exists('is_connected')) {
615
    /**
616
     * Verifie si l'utilisateur a une connexion internet active.
617
     */
618
    function is_connected(): bool
619
    {
620
        return Helpers::isConnected();
621
    }
622
}
623
624
if (! function_exists('is_ajax_request')) {
625
    /**
626
     * Testez pour voir si une requête contient l'en-tête HTTP_X_REQUESTED_WITH.
627
     */
628
    function is_ajax_request(): bool
629
    {
630
        return Services::request()->is('ajax');
631
    }
632
}
633
634
if (! function_exists('redirection')) {
635
    /**
636
     * Redirige l'utilisateur
637
     */
638
    function redirection(string $uri = '', string $method = 'location', ?int $code = 302)
639
    {
640
        $response = redirect()->to($uri, $code, [], null, $method);
641
642
        Services::emitter()->emitHeaders($response);
643
644
        exit(EXIT_SUCCESS);
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...
645
    }
646
}
647
648
if (! function_exists('redirect')) {
649
    /**
650
     * Méthode pratique qui fonctionne avec la $request globale actuelle et
651
     * l'instance $router à rediriger à l'aide de routes nommées et le routage inversé
652
     * pour déterminer l'URL à laquelle aller. Si rien n'est trouvé, traitera
653
     * comme une redirection traditionnelle et passez la chaîne, en laissant
654
     * $redirection->redirect() détermine la méthode et le code corrects.
655
     *
656
     * Si plus de contrôle est nécessaire, vous devez utiliser explicitement $response->redirect.
657
     */
658
    function redirect(?string $uri = null): Redirection
659
    {
660
        $redirection = Services::redirection();
661
662
        if (! empty($uri)) {
663
            return $redirection->route($uri);
664
        }
665
666
        return $redirection;
667
    }
668
}
669
670
if (! function_exists('back')) {
671
    /**
672
     * Retourne a la page precedente
673
     *
674
     * @param mixed $fallback
675
     */
676
    function back(int $code = 302, array $headers = [], $fallback = false): Redirection
677
    {
678
        return redirect()->back($code, $headers, $fallback);
679
    }
680
}
681
682
if (! function_exists('link_to')) {
683
    /**
684
     * Étant donné une chaîne de contrôleur/méthode et tous les paramètres,
685
     * tentera de créer l'URL relative à la route correspondante.
686
     *
687
     * REMARQUE : Cela nécessite que le contrôleur/la méthode
688
     * ait une route définie dans le fichier de configuration des routes.
689
     */
690
    function link_to(string $method, ...$params): string
691
    {
692
        $url = Services::routes()->reverseRoute($method, ...$params);
693
694
        if (empty($url)) {
695
            return '';
696
        }
697
698
        return site_url($url);
699
    }
700
}
701
702
if (! function_exists('clean_path')) {
703
    /**
704
     * Une méthode pratique pour nettoyer les chemins pour
705
     * une sortie plus belle. Utile pour les exceptions
706
     * gestion, journalisation des erreurs, etc.
707
     */
708
    function clean_path(string $path): string
709
    {
710 2
        $path = realpath($path) ?: $path;
711
712
        switch (true) {
713
            case str_starts_with($path, APP_PATH)  :
714 2
                return 'APP_PATH' . DS . substr($path, strlen(APP_PATH));
715
716
            case str_starts_with($path, SYST_PATH)  :
717 2
                return 'SYST_PATH' . DS . substr($path, strlen(SYST_PATH));
718
719
            case defined('VENDOR_PATH') && str_starts_with($path, VENDOR_PATH . 'blitz-php' . DS)  :
720 2
                return 'BLITZ_PATH' . DS . substr($path, strlen(VENDOR_PATH . 'blitz-php' . DS));
721
722
            case defined('VENDOR_PATH') && str_starts_with($path, VENDOR_PATH)  :
723 2
                return 'VENDOR_PATH' . DS . substr($path, strlen(VENDOR_PATH));
724
725
            case str_starts_with($path, ROOTPATH)  :
726 2
                return 'ROOTPATH' . DS . substr($path, strlen(ROOTPATH));
727
728
            default:
729
                return $path;
730
        }
731
    }
732
}
733
734
if (! function_exists('old')) {
735
    /**
736
     * Fournit l'accès à "entrée ancienne" qui a été définie dans la session lors d'un redirect()-withInput().
737
     *
738
     * @param false|string $escape
739
     * @param mixed|null   $default
740
     * @phpstan-param false|'attr'|'css'|'html'|'js'|'raw'|'url' $escape
741
     *
742
     * @return array|string|null
743
     */
744
    function old(string $key, $default = null, $escape = 'html')
745
    {
746
        // Assurez-vous de charger la session
747
        if (session_status() === PHP_SESSION_NONE && ! on_test()) {
748
            session(); // @codeCoverageIgnore
749
        }
750
751
        // Retourne la valeur par défaut si rien n'a été trouvé dans l'ancien input.
752
        if (null === $value = Services::request()->old($key)) {
753
            return $default;
754
        }
755
756
        return $escape === false ? $value : esc($value, $escape);
757
    }
758
}
759
760
// ================================= FONCTIONS DE DEBOGAGE ================================= //
761
762
if (! function_exists('deprecationWarning')) {
763
    /**
764
     * Méthode d'assistance pour générer des avertissements d'obsolescence
765
     *
766
     * @param string $message    Le message à afficher comme avertissement d'obsolescence.
767
     * @param int    $stackFrame Le cadre de pile à inclure dans l'erreur. Par défaut à 1
768
     *                           car cela devrait pointer vers le code de l'application/du plugin.
769
     *
770
     * @return void
771
     */
772
    function deprecation_warning(string $message, int $stackFrame = 1)
773
    {
774
        Helpers::deprecationWarning($message, $stackFrame);
775
    }
776
}
777
778
if (! function_exists('pr')) {
779
    /**
780
     * print_r() convenience function.
781
     *
782
     * In terminals this will act similar to using print_r() directly, when not run on cli
783
     * print_r() will also wrap <pre> tags around the output of given variable. Similar to debug().
784
     *
785
     * This function returns the same variable that was passed.
786
     *
787
     * @param mixed $var Variable to print out.
788
     *
789
     * @return mixed the same $var that was passed to this function
790
     */
791
    function pr($var)
792
    {
793
        $template = (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') ? '<pre class="pr">%s</pre>' : "\n%s\n\n";
794
        printf($template, trim(print_r($var, true)));
0 ignored issues
show
Bug introduced by
It seems like print_r($var, true) can also be of type true; 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

794
        printf($template, trim(/** @scrutinizer ignore-type */ print_r($var, true)));
Loading history...
795
796
        return $var;
797
    }
798
}
799
800
if (! function_exists('pj')) {
801
    /**
802
     * json pretty print convenience function.
803
     *
804
     * In terminals this will act similar to using json_encode() with JSON_PRETTY_PRINT directly, when not run on cli
805
     * will also wrap <pre> tags around the output of given variable. Similar to pr().
806
     *
807
     * This function returns the same variable that was passed.
808
     *
809
     * @param mixed $var Variable to print out.
810
     *
811
     * @return mixed the same $var that was passed to this function
812
     *
813
     * @see pr()
814
     */
815
    function pj($var)
816
    {
817
        return Helpers::pj($var);
818
    }
819
}
820
821
if (! function_exists('trigger_warning')) {
822
    /**
823
     * Déclenche un E_USER_WARNING.
824
     */
825
    function trigger_warning(string $message)
826
    {
827
        Helpers::triggerWarning($message);
828
    }
829
}
830
831
// ================================= FONCTIONS DIVERSES ================================= //
832
833
if (! function_exists('force_https')) {
834
    /**
835
     * Utilisé pour forcer l'accès à une page via HTTPS.
836
     * Utilise une redirection standard, plus définira l'en-tête HSTS
837
     * pour les navigateurs modernes qui prennent en charge, ce qui donne une meilleur
838
     * protection contre les attaques de l'homme du milieu.
839
     *
840
     * @see https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
841
     *
842
     * @param int $duration Combien de temps l'en-tête SSL doit-il être défini ? (en secondes)
843
     *                      Par défaut à 1 an.
844
     *
845
     * @credit CodeIgniter <a href="http://codeigniter.com/">helpers force_https() - /system/Common.php</a>
846
     *
847
     * @throws RedirectException
848
     */
849
    function force_https(int $duration = 31536000, ?ServerRequest $request = null, ?Redirection $response = null)
850
    {
851
        $request ??= Services::request();
852
        $response ??= Services::redirection();
853
854
        if (is_cli() || $request->is('ssl')) {
855
            return;
856
        }
857
858
        // Si la session est active, nous devons régénérer
859
        // l'ID de session pour des raisons de sécurité.
860
        if (! on_test() && session_status() === PHP_SESSION_ACTIVE) {
861
            Services::session()->regenerate(); // @codeCoverageIgnore
862
        }
863
864
        $uri = (string) $request->getUri()->withScheme('https');
865
866
        // Définir un en-tête HSTS
867
        $response = $response->to($uri)
868
            ->withStatus(StatusCode::TEMPORARY_REDIRECT)
869
            ->withHeader('Strict-Transport-Security', 'max-age=' . $duration)
870
            ->withStringBody('');
871
872
        throw new RedirectException($response);
873
    }
874
}
875
876
if (! function_exists('get_type_name')) {
877
    /**
878
     * Renvoie la classe d'objets ou le type var de ce n'est pas un objet
879
     *
880
     * @param mixed $var Variable à vérifier
881
     *
882
     * @return string Renvoie le nom de la classe ou le type de variable
883
     */
884
    function get_type_name($var): string
885
    {
886
        return Helpers::typeName($var);
887
    }
888
}
889
890
if (! function_exists('ip_address')) {
891
    /**
892
     * Renvoie l'adresse IP de l'utilisateur actuel
893
     */
894
    function ip_address(): string
895
    {
896
        return (string) Services::request()->clientIp();
897
    }
898
}
899
900
if (! function_exists('is_really_writable')) {
901
    /**
902
     * Tests d'inscriptibilité des fichiers
903
     */
904
    function is_really_writable(string $file): bool
905
    {
906
        return Helpers::isReallyWritable($file);
907
    }
908
}
909
910
if (! function_exists('lang')) {
911
    /**
912
     * Une méthode pratique pour traduire une chaîne ou un tableau d'entrées et formater
913
     * le résultat avec le MessageFormatter de l'extension intl.
914
     */
915
    function lang(string $line, array $args = [], ?string $locale = null): string
916
    {
917 36
        return Services::translator($locale)->getLine($line, $args);
918
    }
919
}
920
921
if (! function_exists('__')) {
922
    /**
923
     * Une méthode pratique pour traduire une chaîne ou un tableau d'entrées et formater
924
     * le résultat avec le MessageFormatter de l'extension intl.
925
     */
926
    function __(string $line, array $args = [], ?string $locale = null): string
927
    {
928
        $tranlation = lang('App.' . $line, $args, $locale);
929
930
        return preg_replace('/^(App\.)/i', '', $tranlation);
931
    }
932
}
933
934
if (! function_exists('namespace_split')) {
935
    /**
936
     * Séparez l'espace de noms du nom de classe.
937
     *
938
     * Couramment utilisé comme `list($namespace, $className) = namespaceSplit($class);`.
939
     *
940
     * @param string $class Le nom complet de la classe, ie `BlitzPHP\Http\Request`.
941
     *
942
     * @return array Tableau avec 2 index. 0 => namespace, 1 => classname.
943
     */
944
    function namespace_split(string $class): array
945
    {
946
        $pos = strrpos($class, '\\');
947
        if ($pos === false) {
948
            return ['', $class];
949
        }
950
951
        return [substr($class, 0, $pos), substr($class, $pos + 1)];
952
    }
953
}
954
955
if (! function_exists('view_exist')) {
956
    /**
957
     * Verifie si un fichier de vue existe. Utile pour limiter les failles include
958
     */
959
    function view_exist(string $name, ?string $ext = null, array $options = []): bool
960
    {
961
        return Services::viewer()->exists($name, $ext, $options);
962
    }
963
}
964
965
if (! function_exists('view')) {
966
    /**
967
     * Saisit la classe compatible avec le RendererInterface et lui demande d'effectuer le rendu de la vue spécifiée.
968
     * Fournit simplement une méthode de commodité qui peut être utilisée dans les contrôleurs, les bibliothèques et les routes sous forme de closure.
969
     *
970
     * NOTE : Ne fournit pas d'échappement des données, ce qui doit être géré manuellement par le développeur.
971
     *
972
     * @return BlitzPHP\View\View
973
     */
974
    function view(string $view, array $data = [], array $options = [])
975
    {
976
        return Services::viewer()->make($view, $data, $options);
977
    }
978
}
979
980
if (! function_exists('component')) {
981
    /**
982
     * Les composants de vue sont utilisées dans les vues pour insérer des morceaux de HTML qui sont gérés par d'autres classes.
983
     *
984
     * @throws ReflectionException
985
     */
986
    function component(array|string $library, null|array|string $params = null, int $ttl = 0, ?string $cacheName = null): string
987
    {
988
        if (is_array($library)) {
0 ignored issues
show
introduced by
The condition is_array($library) is always true.
Loading history...
989
            $library = implode('::', $library);
990
        }
991
992
        return Services::componentLoader()->render($library, $params, $ttl, $cacheName);
993
    }
994
}
995
996
if (! function_exists('flash')) {
997
    /**
998
     * Fournisseur d'acces rapide a la classe PHP Flash
999
     *
1000
     * @return FlashMessages|string
1001
     */
1002
    /*
1003
    function flash()
1004
    {
1005
         @var FlashMessages $flash
1006
        $flash = service(FlashMessages::class);
1007
1008
        $params = func_get_args();
1009
        $type = array_shift($params);
1010
1011
        if (!empty($type)) {
1012
            if (empty($params)) {
1013
                if ($type === 'all') {
1014
                    $type = null;
1015
                }
1016
                return $flash->display($type, false);
1017
            }
1018
1019
            $message = array_shift($params);
1020
1021
            return $flash->add($message, $type, ...$params);
1022
        }
1023
1024
        return $flash;
1025
    }*/
1026
}
1027
1028
if (! function_exists('geo_ip')) {
1029
    /**
1030
     * Recuperation des coordonnees (pays, ville, etc) d'un utilisateur en fonction de son ip
1031
     */
1032
    function geo_ip(?string $ip = null): ?array
1033
    {
1034
        return json_decode(file_get_contents('http://ip-api.com/json/' . $ip), true);
1035
    }
1036
}
1037
1038
if (! function_exists('to_stream')) {
1039
    /**
1040
     * Créez un nouveau flux basé sur le type d'entrée.
1041
     *
1042
     * Options est un tableau associatif pouvant contenir les clés suivantes :
1043
     * - metadata : Tableau de métadonnées personnalisées.
1044
     * - size : Taille du flux.
1045
     *
1046
     * @param bool|callable|float|int|Iterator|Psr\Http\Message\StreamInterface|resource|string|null $resource Données du corps de l'entité
1047
     * @param array                                                                                  $options  Additional options
1048
     *
1049
     * @uses GuzzleHttp\Psr7\stream_for
1050
     *
1051
     * @throws InvalidArgumentException si l'argument $resource n'est pas valide.
1052
     */
1053
    function to_stream($resource = '', array $options = []): Psr\Http\Message\StreamInterface
1054
    {
1055 2
        return GuzzleHttp\Psr7\Utils::streamFor($resource, $options);
1056
    }
1057
}
1058
1059
if (! function_exists('value')) {
1060
    /**
1061
     * Renvoie la valeur par défaut de la valeur donnée.
1062
     */
1063
    function value(mixed $value, ...$args): mixed
1064
    {
1065 2
        return Helpers::value($value, ...$args);
1066
    }
1067
}
1068
1069
if (! function_exists('collect')) {
1070
    /**
1071
     * Créez une collection à partir de la valeur donnée.
1072
     */
1073
    function collect(mixed $value = null): Collection
1074
    {
1075 2
        return Helpers::collect($value);
1076
    }
1077
}
1078
1079
if (! function_exists('with')) {
1080
    /**
1081
     * Renvoie la valeur donnée, éventuellement transmise via le rappel donné.
1082
     *
1083
     * @param mixed $value
1084
     */
1085
    function with($value, ?callable $callback = null): mixed
1086
    {
1087
        return Helpers::with($value, $callback);
1088
    }
1089
}
1090
1091
if (! function_exists('tap')) {
1092
    /**
1093
     * Appelez la Closure donnée avec cette instance puis renvoyez l'instance.
1094
     */
1095
    function tap(mixed $value, ?callable $callback = null): mixed
1096
    {
1097
        return Helpers::tap($value, $callback);
1098
    }
1099
}
1100
1101
if (! function_exists('last')) {
1102
    /**
1103
     * Recupere le dernier element d'un tableau
1104
     *
1105
     * @template T
1106
     *
1107
     * @param array<T> $array
1108
     *
1109
     * @return false|T
1110
     */
1111
    function last(array $array)
1112
    {
1113
        return end($array);
1114
    }
1115
}
1116
1117
if (! function_exists('invade')) {
1118
    /**
1119
     * Cette classe offre une fonction d'invasion qui vous permettra de lire / écrire des propriétés privées d'un objet.
1120
     * Il vous permettra également de définir, obtenir et appeler des méthodes privées.
1121
     *
1122
     * @return Invader
1123
     *
1124
     * @see https://github.com/spatie/invade/blob/main/src/Invader.php
1125
     */
1126
    function invade(object $object)
1127
    {
1128
        return Invader::make($object);
1129
    }
1130
}
1131