Passed
Push — main ( 23dfd3...d0ed98 )
by Dimitri
05:06 queued 25s
created

csrf_field()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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

441
        return '<input type="hidden"' . (! empty($id) ? ' id="' . esc($id, 'attr') . '"' : '') . ' name="' . /** @scrutinizer ignore-type */ $name . '" value="' . csrf_token() . '">';
Loading history...
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

441
        return '<input type="hidden"' . (! empty($id) ? ' id="' . /** @scrutinizer ignore-type */ esc($id, 'attr') . '"' : '') . ' name="' . $name . '" value="' . csrf_token() . '">';
Loading history...
442
    }
443
}
444
445
if (! function_exists('csrf_meta')) {
446
    /**
447
     * Génère une balise méta à utiliser dans les appels javascript.
448
     */
449
    function csrf_meta(?string $id = null): string
450
    {
451
        $name = config('security.csrf_header_name', 'X-CSRF-TOKEN');
452
453
        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

453
        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

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

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