Test Failed
Push — main ( 96fa17...2c2b65 )
by Dimitri
03:36
created

command()   B

Complexity

Conditions 8
Paths 17

Size

Total Lines 48
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 26
c 1
b 0
f 0
nc 17
nop 1
dl 0
loc 48
rs 8.4444
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\Exceptions\PageNotFoundException;
17
use BlitzPHP\Http\Redirection;
18
use BlitzPHP\Http\ServerRequest;
19
use BlitzPHP\Http\Uri;
20
use BlitzPHP\Loader\Load;
21
use BlitzPHP\Session\Store;
22
use BlitzPHP\Utilities\Helpers;
23
use BlitzPHP\Utilities\Iterable\Collection;
24
use BlitzPHP\Utilities\Support\Invader;
25
26
// ================================= FONCTIONS UTIILITAIRES ESSENTIELLES ================================= //
27
28
if (! function_exists('env')) {
29
    /**
30
     * Obtient une variable d'environnement à partir des sources disponibles et fournit une émulation
31
     * pour les variables d'environnement non prises en charge ou incohérentes
32
     *
33
     * @param string     $key     Nom de la variable d'environnement
34
     * @param mixed|null $default
35
     *
36
     * @return string Paramétrage des variables d'environnement.
37
     */
38
    function env(string $key, $default = null)
39
    {
40
        return Helpers::env($key, $default);
41
    }
42
}
43
44
if (! function_exists('helper')) {
45
    /**
46
     * Charge un fichier d'aide en mémoire. Prend en charge les assistants d'espace de noms,
47
     * à la fois dans et hors du répertoire 'helpers' d'un répertoire à espace de noms.
48
     *
49
     * Chargera TOUS les helpers du nom correspondant, dans l'ordre suivant :
50
     *   1. app/Helpers
51
     *   2. {namespace}/Helpers
52
     *   3. system/Helpers
53
     */
54
    function helper(array|string $filenames)
55
    {
56
        Load::helper($filenames);
57
    }
58
}
59
60
if (! function_exists('model')) {
61
    /**
62
     * Simple maniere d'obtenir un modele.
63
     *
64
     * @template T
65
     *
66
     * @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...
67
     *
68
     * @return T
69
     */
70
    function model(array|string $name, ?ConnectionInterface &$conn = null)
71
    {
72
        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...
73
    }
74
}
75
76
if (! function_exists('service')) {
77
    /**
78
     * Permet un accès plus propre au fichier de configuration des services.
79
     * Renvoie toujours une instance SHARED de la classe, donc
80
     * appeler la fonction plusieurs fois doit toujours
81
     * renvoie la même instance.
82
     *
83
     * Ceux-ci sont égaux :
84
     *  - $cache = service('cache')
85
     *  - $cache = \BlitzPHP\Container\Services::cache();
86
     *
87
     * @template T
88
     *
89
     * @param class-string<T>|string $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T>|string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>|string.
Loading history...
90
     *
91
     * @return T
92
     */
93
    function service(string $name, ...$params)
94
    {
95
        return Services::$name(...$params);
96
    }
97
}
98
99
if (! function_exists('single_service')) {
100
    /**
101
     * Autoriser l'accès propre à un service.
102
     * Renvoie toujours une nouvelle instance de la classe.
103
     */
104
    function single_service(string $name, ...$params)
105
    {
106
        // Assurez-vous qu'il ne s'agit PAS d'une instance partagée
107
        $params[] = false;
108
109
        return Services::$name(...$params);
110
    }
111
}
112
113
if (! function_exists('show404')) {
114
    /**
115
     * Afficher une page 404 introuvable dans le navigateur
116
     */
117
    function show404(string $message = 'The page you requested was not found.', string $heading = 'Page Not Found', array $params = [])
118
    {
119
        throw PageNotFoundException::pageNotFound($message);
120
    }
121
}
122
123
if (! function_exists('command')) {
124
    /**
125
     * Runs a single command.
126
     * Input expected in a single string as would be used on the command line itself:
127
     *
128
     *  > command('migrate:create SomeMigration');
129
     *
130
     * @return false|string
131
     */
132
    function command(string $command)
133
    {
134
        $regexString = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
135
        $regexQuoted = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
136
137
        $args   = [];
138
        $length = strlen($command);
139
        $cursor = 0;
140
141
        /**
142
         * Adopted from Symfony's `StringInput::tokenize()` with few changes.
143
         *
144
         * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Console/Input/StringInput.php
145
         */
146
        while ($cursor < $length) {
147
            if (preg_match('/\s+/A', $command, $match, 0, $cursor)) {
148
                // nothing to do
149
            } elseif (preg_match('/' . $regexQuoted . '/A', $command, $match, 0, $cursor)) {
150
                $args[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
151
            } elseif (preg_match('/' . $regexString . '/A', $command, $match, 0, $cursor)) {
152
                $args[] = stripcslashes($match[1]);
153
            } else {
154
                // @codeCoverageIgnoreStart
155
                throw new InvalidArgumentException(sprintf(
156
                    'Unable to parse input near "... %s ...".',
157
                    substr($command, $cursor, 10)
158
                ));
159
                // @codeCoverageIgnoreEnd
160
            }
161
162
            $cursor += strlen($match[0]);
163
        }
164
165
        $command = array_shift($args);
166
        $params  = [];
167
168
        foreach ($args as $key => $arg) {
169
            if (mb_strpos($arg, '--') !== false) {
170
                unset($args[$key]);
171
                [$arg, $v]          = explode('=', $arg) + [1 => true];
172
                $params[trim($arg)] = is_string($v) ? trim($v) : $v;
173
            }
174
        }
175
176
        ob_start();
177
        Console::call($command, $args, $params);
178
179
        return ob_get_clean();
180
    }
181
}
182
183
if (! function_exists('config')) {
184
    /**
185
     * GET/SET App config
186
     *
187
     * @param mixed|null $default
188
     *
189
     * @return Config|mixed|void
190
     */
191
    function config(null|array|string $key = null, $default = null)
192
    {
193
        $config = Services::config();
194
195
        if (null === $key) {
196
            return $config;
197
        }
198
199
        if (is_string($key)) {
0 ignored issues
show
introduced by
The condition is_string($key) is always false.
Loading history...
200
            return $config->get($key, $default);
201
        }
202
203
        foreach ($key as $k => $v) {
204
            if (is_string($k)) {
205
                $config->set($k, $v);
206
            }
207
        }
208
    }
209
}
210
211
if (! function_exists('logger')) {
212
    /**
213
     * Une méthode de commodité pour les événements de journalisation via le système Log.
214
     *
215
     * Les niveaux de journal autorisés sont :
216
     *  - emergency
217
     *  - alert
218
     *  - critical
219
     *  - error
220
     *  - warning
221
     *  - notice
222
     *  - info
223
     *  - debug
224
     *
225
     * @param int|string $level
226
     *
227
     * @return \BlitzPHP\Debug\Logger|void
228
     */
229
    function logger($level = null, ?string $message = null, array $context = [])
230
    {
231
        $logger = Services::logger();
232
233
        if (empty($level) || empty($message)) {
234
            return $logger;
235
        }
236
237
        $logger->log($level, $message, $context);
238
    }
239
}
240
241
if (! function_exists('cache')) {
242
    /**
243
     * Une méthode pratique qui donne accès au cache
244
     * objet. Si aucun paramètre n'est fourni, renverra l'objet,
245
     * sinon, tentera de renvoyer la valeur mise en cache.
246
     *
247
     * Exemples:
248
     *    cache()->set('foo', 'bar'); ou cache('foo', 'bar');
249
     *    $foo = cache('bar');
250
     *
251
     * @param mixed|null $value
252
     *
253
     * @return \BlitzPHP\Cache\Cache|bool|mixed
254
     */
255
    function cache(?string $key = null, $value = null)
256
    {
257
        $cache = Services::cache();
258
259
        if (empty($key)) {
260
            return $cache;
261
        }
262
263
        if (empty($value)) {
264
            return $cache->get($key);
265
        }
266
267
        return $cache->set($key, $value);
268
    }
269
}
270
271
if (! function_exists('session')) {
272
    /**
273
     * Une méthode pratique pour accéder à l'instance de session, ou un élément qui a été défini dans la session.
274
     *
275
     * Exemples:
276
     *    session()->set('foo', 'bar');
277
     *    $foo = session('bar');
278
     *
279
     * @return array|bool|float|int|object|Store|string|null
280
     */
281
    function session(?string $val = null)
282
    {
283
        $session = Services::session();
284
285
        // Vous retournez un seul element ?
286
        if (is_string($val)) {
287
            return $session->get($val);
288
        }
289
290
        return $session;
291
    }
292
}
293
294
// =========================== FONCTIONS DE PREVENTION D'ATTAQUE =========================== //
295
296
if (! function_exists('esc')) {
297
    /**
298
     * Effectue un simple échappement automatique des données pour des raisons de sécurité.
299
     * Pourrait envisager de rendre cela plus complexe à une date ultérieure.
300
     *
301
     * Si $data est une chaîne, il suffit alors de l'échapper et de la renvoyer.
302
     * Si $data est un tableau, alors il boucle dessus, s'échappant de chaque
303
     * 'valeur' des paires clé/valeur.
304
     *
305
     * Valeurs de contexte valides : html, js, css, url, attr, raw, null
306
     *
307
     * @param array|string $data
308
     *
309
     * @return array|string
310
     *
311
     * @throws InvalidArgumentException
312
     */
313
    function esc($data, ?string $context = 'html', ?string $encoding = null)
314
    {
315
        if (class_exists('\Laminas\Escaper\Escaper')) {
316
            return Helpers::esc($data, $context, $encoding);
317
        }
318
319
        return h($data, true, $encoding);
320
    }
321
}
322
323
if (! function_exists('h')) {
324
    /**
325
     * Méthode pratique pour htmlspecialchars.
326
     *
327
     * @param mixed       $text    Texte à envelopper dans htmlspecialchars. Fonctionne également avec des tableaux et des objets.
328
     *                             Les tableaux seront mappés et tous leurs éléments seront échappés. Les objets seront transtypés s'ils
329
     *                             implémenter une méthode `__toString`. Sinon, le nom de la classe sera utilisé.
330
     *                             Les autres types de scalaires seront renvoyés tels quels.
331
     * @param bool        $double  Encodez les entités html existantes.
332
     * @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'.
333
     *
334
     * @return mixed Texte enveloppé.
335
     */
336
    function h($text, bool $double = true, ?string $charset = null)
337
    {
338
        return Helpers::h($text, $double, $charset);
339
    }
340
}
341
342
if (! function_exists('purify')) {
343
    /**
344
     * Purifiez l'entrée à l'aide de la classe autonome HTMLPurifier.
345
     * Utilisez facilement plusieurs configurations de purificateur.
346
     *
347
     * @param string|string[] $dirty_html
348
     * @param false|string    $config
349
     *
350
     * @return string|string[]
351
     */
352
    function purify($dirty_html, $config = false)
353
    {
354
        return Helpers::purify($dirty_html, $config);
355
    }
356
}
357
358
if (! function_exists('remove_invisible_characters')) {
359
    /**
360
     * Supprimer les caractères invisibles
361
     *
362
     * Cela empêche de prendre en sandwich des caractères nuls
363
     * entre les caractères ascii, comme Java\0script.
364
     */
365
    function remove_invisible_characters(string $str, bool $url_encoded = true): string
366
    {
367
        return Helpers::removeInvisibleCharacters($str, $url_encoded);
368
    }
369
}
370
371
if (! function_exists('stringify_attributes')) {
372
    /**
373
     * Chaîner les attributs à utiliser dans les balises HTML.
374
     *
375
     * @param array|object|string $attributes
376
     */
377
    function stringify_attributes($attributes, bool $js = false): string
378
    {
379
        return Helpers::stringifyAttributes($attributes, $js);
380
    }
381
}
382
383
// ================================= FONCTIONS D'ENVIRONNEMENT D'EXECUTION ================================= //
384
385
if (! function_exists('environment')) {
386
    /**
387
     * Renvoi l'environnement d'execution actuel ou determine si on est dans un environnement specifie
388
     *
389
     * @return bool|string
390
     */
391
    function environment(null|array|string $env)
392
    {
393
        $current = env('ENVIRONMENT');
394
        if (empty($current) || $current === 'auto') {
395
            $current = config('app.environment');
396
        }
397
398
        if (empty($env)) {
399
            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...
400
        }
401
402
        $envMap = [
403
            'dev'     => 'development',
404
            'local'   => 'development',
405
            'prod'    => 'production',
406
            'test'    => 'testing',
407
            'stage'   => 'testing',
408
            'staging' => 'testing',
409
        ];
410
411
        $current = $envMap[$current] ?? $current;
412
413
        if (is_string($env)) {
0 ignored issues
show
introduced by
The condition is_string($env) is always false.
Loading history...
414
            $env = [$env];
415
        }
416
417
        $env = array_map(static fn ($k) => $envMap[$k] ?? $k, $env);
418
419
        return in_array($current, $env, true);
420
    }
421
}
422
423
if (! function_exists('on_dev')) {
424
    /**
425
     * Testez pour voir si nous sommes dans un environnement de développement.
426
     */
427
    function on_dev(bool $checkOnline = false): bool
428
    {
429
        if ($checkOnline && is_online()) {
430
            return false;
431
        }
432
433
        return environment(['dev', 'development', 'local']);
434
    }
435
}
436
437
if (! function_exists('on_prod')) {
438
    /**
439
     * Testez pour voir si nous sommes dans un environnement de production.
440
     */
441
    function on_prod(bool $checkOnline = false): bool
442
    {
443
        if ($checkOnline && is_online()) {
444
            return true;
445
        }
446
447
        return environment(['prod', 'production']);
448
    }
449
}
450
451
if (! function_exists('on_test')) {
452
    /**
453
     * Testez pour voir si nous sommes dans un environnement de test
454
     */
455
    function on_test(): bool
456
    {
457
        return environment(['test', 'testing', 'stage', 'staging']);
458
    }
459
}
460
461
if (! function_exists('is_cli')) {
462
    /**
463
     * Testez pour voir si une demande a été faite à partir de la ligne de commande.
464
     */
465
    function is_cli(): bool
466
    {
467
        return Helpers::isCli();
468
    }
469
}
470
471
if (! function_exists('is_php')) {
472
    /**
473
     * Détermine si la version actuelle de PHP est égale ou supérieure à la valeur fournie.
474
     */
475
    function is_php(string $version): bool
476
    {
477
        return Helpers::isPhp($version);
478
    }
479
}
480
481
if (! function_exists('is_windows')) {
482
    /**
483
     * Déterminez si l'environnement actuel est basé sur Windows.
484
     */
485
    function is_windows(): bool
486
    {
487
        return PHP_OS_FAMILY === 'Windows';
488
    }
489
}
490
491
if (! function_exists('is_https')) {
492
    /**
493
     * Determines if the application is accessed via an encrypted * (HTTPS) connection.
494
     */
495
    function is_https(): bool
496
    {
497
        return Services::request()->is('ssl');
498
    }
499
}
500
501
if (! function_exists('is_localfile')) {
502
    /**
503
     * Vérifiez si le fichier auquel vous souhaitez accéder est un fichier local de votre application ou non
504
     */
505
    function is_localfile(string $name): bool
506
    {
507
        if (preg_match('#^' . base_url() . '#i', $name)) {
508
            return true;
509
        }
510
511
        return ! preg_match('#^(https?://)#i', $name);
512
    }
513
}
514
515
if (! function_exists('is_online')) {
516
    /**
517
     * Tester si l'application s'exécute en local ou en ligne.
518
     */
519
    function is_online(): bool
520
    {
521
        return Helpers::isOnline();
522
    }
523
}
524
525
if (! function_exists('is_connected')) {
526
    /**
527
     * Verifie si l'utilisateur a une connexion internet active.
528
     */
529
    function is_connected(): bool
530
    {
531
        return Helpers::isConnected();
532
    }
533
}
534
535
if (! function_exists('is_ajax_request')) {
536
    /**
537
     * Testez pour voir si une requête contient l'en-tête HTTP_X_REQUESTED_WITH.
538
     */
539
    function is_ajax_request(): bool
540
    {
541
        return Services::request()->is('ajax');
542
    }
543
}
544
545
if (! function_exists('redirection')) {
546
    /**
547
     * Redirige l'utilisateur
548
     */
549
    function redirection(string $uri = '', string $method = 'location', ?int $code = 302)
550
    {
551
        $response = redirect()->to($uri, $code, [], null, $method);
552
553
        Services::emitter()->emitHeaders($response);
554
555
        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...
556
    }
557
}
558
559
if (! function_exists('redirect')) {
560
    /**
561
     * Méthode pratique qui fonctionne avec la $request globale actuelle et
562
     * l'instance $router à rediriger à l'aide de routes nommées et le routage inversé
563
     * pour déterminer l'URL à laquelle aller. Si rien n'est trouvé, traitera
564
     * comme une redirection traditionnelle et passez la chaîne, en laissant
565
     * $redirection->redirect() détermine la méthode et le code corrects.
566
     *
567
     * Si plus de contrôle est nécessaire, vous devez utiliser explicitement $response->redirect.
568
     */
569
    function redirect(?string $uri = null): Redirection
570
    {
571
        $redirection = Services::redirection();
572
573
        if (! empty($uri)) {
574
            return $redirection->route($uri);
575
        }
576
577
        return $redirection;
578
    }
579
}
580
581
if (! function_exists('back')) {
582
    /**
583
     * Retourne a la page precedente
584
     *
585
     * @param mixed $fallback
586
     */
587
    function back(int $code = 302, array $headers = [], $fallback = false): Redirection
588
    {
589
        return redirect()->back($code, $headers, $fallback);
590
    }
591
}
592
593
if (! function_exists('link_to')) {
594
    /**
595
     * Étant donné une chaîne de contrôleur/méthode et tous les paramètres,
596
     * tentera de créer l'URL relative à la route correspondante.
597
     *
598
     * REMARQUE : Cela nécessite que le contrôleur/la méthode
599
     * ait une route définie dans le fichier de configuration des routes.
600
     */
601
    function link_to(string $method, ...$params): string
602
    {
603
        $url = Services::routes()->reverseRoute($method, ...$params);
604
605
        if (empty($url)) {
606
            return '';
607
        }
608
609
        return site_url($url);
610
    }
611
}
612
613
if (! function_exists('clean_path')) {
614
    /**
615
     * Une méthode pratique pour nettoyer les chemins pour
616
     * une sortie plus belle. Utile pour les exceptions
617
     * gestion, journalisation des erreurs, etc.
618
     */
619
    function clean_path(string $path): string
620
    {
621
        $path = realpath($path) ?: $path;
622
623
        switch (true) {
624
            case str_starts_with($path, APP_PATH)  :
625
                return 'APP_PATH' . DS . substr($path, strlen(APP_PATH));
626
627
            case str_starts_with($path, SYST_PATH)  :
628
                return 'SYST_PATH' . DS . substr($path, strlen(SYST_PATH));
629
630
            case defined('VENDOR_PATH') && str_starts_with($path, VENDOR_PATH . 'blitz-php' . DS)  :
631
                return 'BLITZ_PATH' . DS . substr($path, strlen(VENDOR_PATH . 'blitz-php' . DS));
632
633
            case defined('VENDOR_PATH') && str_starts_with($path, VENDOR_PATH)  :
634
                return 'VENDOR_PATH' . DS . substr($path, strlen(VENDOR_PATH));
635
636
            case str_starts_with($path, ROOTPATH)  :
637
                return 'ROOTPATH' . DS . substr($path, strlen(ROOTPATH));
638
639
            default:
640
                return $path;
641
        }
642
    }
643
}
644
645
if (! function_exists('old')) {
646
    /**
647
     * Fournit l'accès à "entrée ancienne" qui a été définie dans la session lors d'un redirect()-withInput().
648
     *
649
     * @param false|string $escape
650
     * @param mixed|null   $default
651
     * @phpstan-param false|'attr'|'css'|'html'|'js'|'raw'|'url' $escape
652
     *
653
     * @return array|string|null
654
     */
655
    function old(string $key, $default = null, $escape = 'html')
656
    {
657
        // Assurez-vous de charger la session
658
        if (session_status() === PHP_SESSION_NONE && ! on_test()) {
659
            session(); // @codeCoverageIgnore
660
        }
661
662
        // Retourne la valeur par défaut si rien n'a été trouvé dans l'ancien input.
663
        if (null === $value = Services::request()->old($key)) {
664
            return $default;
665
        }
666
667
        return $escape === false ? $value : esc($value, $escape);
668
    }
669
}
670
671
// ================================= FONCTIONS DE DEBOGAGE ================================= //
672
673
if (! function_exists('deprecationWarning')) {
674
    /**
675
     * Méthode d'assistance pour générer des avertissements d'obsolescence
676
     *
677
     * @param string $message    Le message à afficher comme avertissement d'obsolescence.
678
     * @param int    $stackFrame Le cadre de pile à inclure dans l'erreur. Par défaut à 1
679
     *                           car cela devrait pointer vers le code de l'application/du plugin.
680
     *
681
     * @return void
682
     */
683
    function deprecation_warning(string $message, int $stackFrame = 1)
684
    {
685
        Helpers::deprecationWarning($message, $stackFrame);
686
    }
687
}
688
689
if (! function_exists('pr')) {
690
    /**
691
     * print_r() convenience function.
692
     *
693
     * In terminals this will act similar to using print_r() directly, when not run on cli
694
     * print_r() will also wrap <pre> tags around the output of given variable. Similar to debug().
695
     *
696
     * This function returns the same variable that was passed.
697
     *
698
     * @param mixed $var Variable to print out.
699
     *
700
     * @return mixed the same $var that was passed to this function
701
     */
702
    function pr($var)
703
    {
704
        $template = (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') ? '<pre class="pr">%s</pre>' : "\n%s\n\n";
705
        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

705
        printf($template, trim(/** @scrutinizer ignore-type */ print_r($var, true)));
Loading history...
706
707
        return $var;
708
    }
709
}
710
711
if (! function_exists('pj')) {
712
    /**
713
     * json pretty print convenience function.
714
     *
715
     * In terminals this will act similar to using json_encode() with JSON_PRETTY_PRINT directly, when not run on cli
716
     * will also wrap <pre> tags around the output of given variable. Similar to pr().
717
     *
718
     * This function returns the same variable that was passed.
719
     *
720
     * @param mixed $var Variable to print out.
721
     *
722
     * @return mixed the same $var that was passed to this function
723
     *
724
     * @see pr()
725
     */
726
    function pj($var)
727
    {
728
        return Helpers::pj($var);
729
    }
730
}
731
732
if (! function_exists('trigger_warning')) {
733
    /**
734
     * Déclenche un E_USER_WARNING.
735
     */
736
    function trigger_warning(string $message)
737
    {
738
        Helpers::triggerWarning($message);
739
    }
740
}
741
742
// ================================= FONCTIONS DIVERSES ================================= //
743
744
if (! function_exists('force_https')) {
745
    /**
746
     * Utilisé pour forcer l'accès à une page via HTTPS.
747
     * Utilise une redirection standard, plus définira l'en-tête HSTS
748
     * pour les navigateurs modernes qui prennent en charge, ce qui donne une meilleur
749
     * protection contre les attaques de l'homme du milieu.
750
     *
751
     * @see https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
752
     *
753
     * @param int $duration Combien de temps l'en-tête SSL doit-il être défini ? (en secondes)
754
     *                      Par défaut à 1 an.
755
     *
756
     * @credit CodeIgniter <a href="http://codeigniter.com/">helpers force_https() - /system/Common.php</a>
757
     *
758
     * Non testable, car il sortira !
759
     *
760
     * @codeCoverageIgnore
761
     */
762
    function force_https(int $duration = 31536000, ?ServerRequest $request = null, ?Redirection $response = null)
763
    {
764
        if (null === $request) {
765
            $request = Services::request();
766
        }
767
        if (null === $response) {
768
            $response = Services::redirection();
769
        }
770
771
        if (is_cli() || $request->is('ssl')) {
772
            return;
773
        }
774
775
        // Si la bibliothèque de session est chargée, nous devons régénérer
776
        // l'ID de session pour des raisons de sécurité.
777
        Services::session()->regenerate();
778
779
        $baseURL = base_url();
780
781
        if (str_starts_with($baseURL, 'http://')) {
782
            $baseURL = (string) substr($baseURL, strlen('http://'));
783
        }
784
785
        $uri = Uri::createURIString(
786
            'https',
787
            $baseURL,
788
            $request->getUri()->getPath(), // Les URI absolus doivent utiliser un "/" pour un chemin vide
789
            $request->getUri()->getQuery(),
790
            $request->getUri()->getFragment()
791
        );
792
793
        // Définir un en-tête HSTS
794
        $response = $response->to($uri)->withHeader('Strict-Transport-Security', 'max-age=' . $duration);
795
796
        Services::emitter()->emitHeaders($response);
797
798
        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...
799
    }
800
}
801
802
if (! function_exists('get_type_name')) {
803
    /**
804
     * Renvoie la classe d'objets ou le type var de ce n'est pas un objet
805
     *
806
     * @param mixed $var Variable à vérifier
807
     *
808
     * @return string Renvoie le nom de la classe ou le type de variable
809
     */
810
    function get_type_name($var): string
811
    {
812
        return Helpers::typeName($var);
813
    }
814
}
815
816
if (! function_exists('ip_address')) {
817
    /**
818
     * Renvoie l'adresse IP de l'utilisateur actuel
819
     */
820
    function ip_address(): string
821
    {
822
        return (string) Services::request()->clientIp();
823
    }
824
}
825
826
if (! function_exists('is_really_writable')) {
827
    /**
828
     * Tests d'inscriptibilité des fichiers
829
     */
830
    function is_really_writable(string $file): bool
831
    {
832
        return Helpers::isReallyWritable($file);
833
    }
834
}
835
836
if (! function_exists('lang')) {
837
    /**
838
     * Une méthode pratique pour traduire une chaîne ou un tableau d'entrées et formater
839
     * le résultat avec le MessageFormatter de l'extension intl.
840
     */
841
    function lang(string $line, array $args = [], ?string $locale = null): string
842
    {
843
        return Services::translator($locale)->getLine($line, $args);
844
    }
845
}
846
847
if (! function_exists('__')) {
848
    /**
849
     * Une méthode pratique pour traduire une chaîne ou un tableau d'entrées et formater
850
     * le résultat avec le MessageFormatter de l'extension intl.
851
     */
852
    function __(string $line, array $args = [], ?string $locale = null): string
853
    {
854
        $tranlation = lang('App.' . $line, $args, $locale);
855
856
        return preg_replace('/^(App\.)/i', '', $tranlation);
857
    }
858
}
859
860
if (! function_exists('namespace_split')) {
861
    /**
862
     * Séparez l'espace de noms du nom de classe.
863
     *
864
     * Couramment utilisé comme `list($namespace, $className) = namespaceSplit($class);`.
865
     *
866
     * @param string $class Le nom complet de la classe, ie `BlitzPHP\Http\Request`.
867
     *
868
     * @return array Tableau avec 2 index. 0 => namespace, 1 => classname.
869
     */
870
    function namespace_split(string $class): array
871
    {
872
        $pos = strrpos($class, '\\');
873
        if ($pos === false) {
874
            return ['', $class];
875
        }
876
877
        return [substr($class, 0, $pos), substr($class, $pos + 1)];
878
    }
879
}
880
881
if (! function_exists('view_exist')) {
882
    /**
883
     * Verifie si un fichier de vue existe. Utile pour limiter les failles include
884
     */
885
    function view_exist(string $name, string $ext = '.php'): bool
886
    {
887
        $ext  = str_replace('.', '', $ext);
888
        $name = str_replace(VIEW_PATH, '', $name);
889
        $name = preg_match('#\.' . $ext . '$#', $name) ? $name : $name . '.' . $ext;
890
891
        return is_file(VIEW_PATH . rtrim($name, DS));
892
    }
893
}
894
895
if (! function_exists('view')) {
896
    /**
897
     * Charge une vue
898
     *
899
     * @return \BlitzPHP\View\View
900
     */
901
    function view(string $view, ?array $data = [], ?array $options = [])
902
    {
903
        $object = Services::viewer(false);
904
905
        $object->addData($data)->setOptions($options);
906
907
        return $object->display($view);
908
    }
909
}
910
911
if (! function_exists('flash')) {
912
    /**
913
     * Fournisseur d'acces rapide a la classe PHP Flash
914
     *
915
     * @return FlashMessages|string
916
     */
917
    /*
918
    function flash()
919
    {
920
         @var FlashMessages $flash
921
        $flash = service(FlashMessages::class);
922
923
        $params = func_get_args();
924
        $type = array_shift($params);
925
926
        if (!empty($type)) {
927
            if (empty($params)) {
928
                if ($type === 'all') {
929
                    $type = null;
930
                }
931
                return $flash->display($type, false);
932
            }
933
934
            $message = array_shift($params);
935
936
            return $flash->add($message, $type, ...$params);
937
        }
938
939
        return $flash;
940
    }*/
941
}
942
943
if (! function_exists('geo_ip')) {
944
    /**
945
     * Recuperation des coordonnees (pays, ville, etc) d'un utilisateur en fonction de son ip
946
     */
947
    function geo_ip(?string $ip = null): ?array
948
    {
949
        return json_decode(file_get_contents('http://ip-api.com/json/' . $ip), true);
950
    }
951
}
952
953
if (! function_exists('to_stream')) {
954
    /**
955
     * Créez un nouveau flux basé sur le type d'entrée.
956
     *
957
     * Options est un tableau associatif pouvant contenir les clés suivantes :
958
     * - metadata : Tableau de métadonnées personnalisées.
959
     * - size : Taille du flux.
960
     *
961
     * @param bool|callable|float|int|\Iterator|\Psr\Http\Message\StreamInterface|resource|string|null $resource Données du corps de l'entité
962
     * @param array                                                                                    $options  Additional options
963
     *
964
     * @uses GuzzleHttp\Psr7\stream_for
965
     *
966
     * @throws \InvalidArgumentException si l'argument $resource n'est pas valide.
967
     */
968
    function to_stream($resource = '', array $options = []): Psr\Http\Message\StreamInterface
969
    {
970
        return \GuzzleHttp\Psr7\Utils::streamFor($resource, $options);
971
    }
972
}
973
974
if (! function_exists('value')) {
975
    /**
976
     * Renvoie la valeur par défaut de la valeur donnée.
977
     */
978
    function value(mixed $value, ...$args): mixed
979
    {
980
        return Helpers::value($value, ...$args);
981
    }
982
}
983
984
if (! function_exists('collect')) {
985
    /**
986
     * Créez une collection à partir de la valeur donnée.
987
     */
988
    function collect(mixed $value = null): Collection
989
    {
990
        return Helpers::collect($value);
991
    }
992
}
993
994
if (! function_exists('with')) {
995
    /**
996
     * Renvoie la valeur donnée, éventuellement transmise via le rappel donné.
997
     *
998
     * @param mixed $value
999
     */
1000
    function with($value, ?callable $callback = null): mixed
1001
    {
1002
        return Helpers::with($value, $callback);
1003
    }
1004
}
1005
1006
if (! function_exists('tap')) {
1007
    /**
1008
     * Appelez la Closure donnée avec cette instance puis renvoyez l'instance.
1009
     */
1010
    function tap(mixed $value, ?callable $callback = null): mixed
1011
    {
1012
        return Helpers::tap($value, $callback);
1013
    }
1014
}
1015
1016
if (! function_exists('last')) {
1017
    /**
1018
     * Recupere le dernier element d'un tableau
1019
     */
1020
    function last(array|object $array)
1021
    {
1022
        return end($array);
1023
    }
1024
}
1025
1026
if (! function_exists('invade')) {
1027
    /**
1028
     * Cette classe offre une fonction d'invasion qui vous permettra de lire / écrire des propriétés privées d'un objet.
1029
     * Il vous permettra également de définir, obtenir et appeler des méthodes privées.
1030
     *
1031
     * @return Invader
1032
     *
1033
     * @see https://github.com/spatie/invade/blob/main/src/Invader.php
1034
     */
1035
    function invade(object $object)
1036
    {
1037
        return Invader::make($object);
1038
    }
1039
}
1040