Passed
Push — main ( 902994...f9905b )
by Dimitri
03:03
created

index_page()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
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\Container\Services;
13
use BlitzPHP\Core\App;
14
use BlitzPHP\Exceptions\RouterException;
15
use BlitzPHP\Http\ServerRequest;
16
use BlitzPHP\Http\Uri;
17
use BlitzPHP\Http\UrlGenerator;
18
use BlitzPHP\Utilities\Helpers;
19
20
/**
21
 * FONCTIONS DE MANIPULATION D'URL
22
 *
23
 * @credit	<a href="https://codeigniter.com">CodeIgniter 4.2 - url_helper</a>
24
 */
25
26
// =================================  ================================= //
27
28
if (! function_exists('site_url')) {
29
    /**
30
     * Renvoie une URL de site telle que définie par la configuration de l'application.
31
     *
32
     * @param mixed $relativePath Chaîne d'URI ou tableau de segments d'URI
33
     */
34
    function site_url($relativePath = '', ?string $scheme = null): string
35
    {
36
        if (is_array($relativePath)) {
37 8
            $relativePath = implode('/', $relativePath);
38
        }
39
40 8
        $uri = App::getUri($relativePath);
41
42
        return Uri::createURIString(
43
            $scheme ?? $uri->getScheme(),
44
            $uri->getAuthority(),
45
            $uri->getPath(),
46
            $uri->getQuery(),
47
            $uri->getFragment()
48 8
        );
49
    }
50
}
51
52
if (! function_exists('base_url')) {
53
    /**
54
     * Renvoie l'URL de base telle que définie par la configuration de l'application.
55
     * Les URL de base sont des URL de site coupées sans la page d'index.
56
     *
57
     * @param mixed $relativePath Chaîne d'URI ou tableau de segments d'URI
58
     */
59
    function base_url($relativePath = '', ?string $scheme = null): string
60
    {
61 2
        $index_page = index_page();
62 2
        config()->set('app.index_page', '');
63
64 2
        $url = rtrim(site_url($relativePath, $scheme), '/');
65 2
        config()->set('app.index_page', $index_page);
66
67 2
        return $url;
68
    }
69
}
70
71
if (! function_exists('current_url')) {
72
    /**
73
     * Renvoie l'URL complète (y compris les segments) de la page où cette fonction est placée
74
     *
75
     * @param bool $returnObject True pour renvoyer un objet au lieu d'une chaîne
76
     *
77
     * @return \BlitzPHP\Http\Uri|string
78
     */
79
    function current_url(bool $returnObject = false, ?ServerRequest $request = null)
80
    {
81
        $request ??= Services::request();
82
        $path = $request->getPath();
83
84
        // Ajouter des chaine de requêtes et des fragments
85
        if ($query = $request->getUri()->getQuery()) {
86
            $path .= '?' . $query;
87
        }
88
        if ($fragment = $request->getUri()->getFragment()) {
89
            $path .= '#' . $fragment;
90
        }
91
92
        $uri = App::getUri($path);
93
94
        return $returnObject ? $uri : Uri::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath());
95
    }
96
}
97
98
if (! function_exists('previous_url')) {
99
    /**
100
     * Renvoie l'URL précédente sur laquelle se trouvait le visiteur actuel. Pour des raisons de sécurité
101
     * nous vérifions d'abord une variable de session enregistrée, si elle existe, et l'utilisons.
102
     * Si ce n'est pas disponible, cependant, nous utiliserons une URL épurée de $_SERVER['HTTP_REFERER']
103
     * qui peut être défini par l'utilisateur, il n'est donc pas fiable et n'est pas défini par certains navigateurs/serveurs.
104
     *
105
     * @return \BlitzPHP\Http\Uri|mixed|string
106
     */
107
    function previous_url(bool $returnObject = false)
108
    {
109
        /** @var UrlGenerator $generator */
110
        $generator = service(UrlGenerator::class);
111
112
        $referer = $generator->previous();
113
114
        return $returnObject ? Services::uri($referer) : $referer;
115
    }
116
}
117
118
if (! function_exists('uri_string')) {
119
    /**
120
     * Renvoie la partie chemin de l'URL actuelle
121
     *
122
     * @param bool $relative Si le chemin résultant doit être relatif à baseURL
123
     */
124
    function uri_string(bool $relative = false): string
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...
125
    {
126
        return $relative
127
            ? ltrim(Services::request()->getPath(), '/')
128
            : Services::request()->getUri()->getPath();
129
    }
130
}
131
132
if (! function_exists('index_page')) {
133
    /**
134
     * Renvoie la "index_page" de votre fichier de configuration
135
     */
136
    function index_page(): string
137
    {
138 2
        return config('app.index_page');
0 ignored issues
show
Bug Best Practice introduced by
The expression return config('app.index_page') returns the type BlitzPHP\Config\Config|null which is incompatible with the type-hinted return string.
Loading history...
139
    }
140
}
141
142
if (! function_exists('anchor')) {
143
    /**
144
     * Crée une ancre basée sur l'URL locale.
145
     *
146
     * @param string             $title      le titre du lien
147
     * @param array|false|string $attributes tous les attributs
148
     * @param mixed              $uri
149
     */
150
    function anchor($uri = '', string $title = '', $attributes = ''): string
151
    {
152
        $siteUrl = is_array($uri) ? site_url($uri, null) : (preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri, null));
153
        $siteUrl = rtrim($siteUrl, '/');
154
155
        if ($title === '') {
156
            $title = $siteUrl;
157
        }
158
159
        if ($attributes !== '') {
160
            $attributes = stringify_attributes($attributes);
0 ignored issues
show
Bug introduced by
It seems like $attributes can also be of type false; however, parameter $attributes of stringify_attributes() does only seem to accept array|object|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

160
            $attributes = stringify_attributes(/** @scrutinizer ignore-type */ $attributes);
Loading history...
161
        }
162
163
        return '<a href="' . $siteUrl . '"' . $attributes . '>' . $title . '</a>';
164
    }
165
}
166
167
if (! function_exists('anchor_popup')) {
168
    /**
169
     * Lien d'ancrage - Version contextuelle
170
     *
171
     * Crée une ancre basée sur l'URL locale. Le lien
172
     * ouvre une nouvelle fenêtre basée sur les attributs spécifiés.
173
     *
174
     * @param string             $title      le titre du lien
175
     * @param array|false|string $attributes tous les attributs
176
     */
177
    function anchor_popup(string $uri = '', string $title = '', $attributes = false): string
178
    {
179
        $siteUrl = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri, null);
180
        $siteUrl = rtrim($siteUrl, '/');
181
182
        if ($title === '') {
183
            $title = $siteUrl;
184
        }
185
186
        if ($attributes === false) {
187
            return '<a href="' . $siteUrl . '" onclick="window.open(\'' . $siteUrl . "', '_blank'); return false;\">" . $title . '</a>';
188
        }
189
190
        if (! is_array($attributes)) {
191
            $attributes = [$attributes];
192
193
            // Ref: http://www.w3schools.com/jsref/met_win_open.asp
194
            $windowName = '_blank';
195
        } elseif (! empty($attributes['window_name'])) {
196
            $windowName = $attributes['window_name'];
197
            unset($attributes['window_name']);
198
        } else {
199
            $windowName = '_blank';
200
        }
201
202
        foreach (['width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'menubar' => 'no', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0'] as $key => $val) {
203
            $atts[$key] = $attributes[$key] ?? $val;
204
            unset($attributes[$key]);
205
        }
206
207
        $attributes = stringify_attributes($attributes);
208
209
        return '<a href="' . $siteUrl
210
                . '" onclick="window.open(\'' . $siteUrl . "', '" . $windowName . "', '" . stringify_attributes($atts, true) . "'); return false;\""
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $atts seems to be defined by a foreach iteration on line 202. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
211
                . $attributes . '>' . $title . '</a>';
212
    }
213
}
214
215
if (! function_exists('mailto')) {
216
    /**
217
     * Lien Mailto
218
     *
219
     * @param string       $title      le titre du lien
220
     * @param array|string $attributes tous les attributs
221
     */
222
    function mailto(string $email, string $title = '', $attributes = ''): string
223
    {
224
        if (trim($title) === '') {
225
            $title = $email;
226
        }
227
228
        return '<a href="mailto:' . $email . '"' . stringify_attributes($attributes) . '>' . $title . '</a>';
229
    }
230
}
231
232
if (! function_exists('safe_mailto')) {
233
    /**
234
     * Lien Mailto codé
235
     *
236
     * Créer un lien mailto protégé contre les spams écrit en Javascript
237
     *
238
     * @param string $title      le titre du lien
239
     * @param mixed  $attributes tous les attributs
240
     */
241
    function safe_mailto(string $email, string $title = '', $attributes = ''): string
242
    {
243
        if (trim($title) === '') {
244
            $title = $email;
245
        }
246
247
        $x = str_split('<a href="mailto:', 1);
248
249
        for ($i = 0, $l = strlen($email); $i < $l; $i++) {
250
            $x[] = '|' . ord($email[$i]);
251
        }
252
253
        $x[] = '"';
254
255
        if ($attributes !== '') {
256
            if (is_array($attributes)) {
257
                foreach ($attributes as $key => $val) {
258
                    $x[] = ' ' . $key . '="';
259
260
                    for ($i = 0, $l = strlen($val); $i < $l; $i++) {
261
                        $x[] = '|' . ord($val[$i]);
262
                    }
263
264
                    $x[] = '"';
265
                }
266
            } else {
267
                for ($i = 0, $l = mb_strlen($attributes); $i < $l; $i++) {
268
                    $x[] = mb_substr($attributes, $i, 1);
269
                }
270
            }
271
        }
272
273
        $x[] = '>';
274
275
        $temp = [];
276
277
        for ($i = 0, $l = strlen($title); $i < $l; $i++) {
278
            $ordinal = ord($title[$i]);
279
280
            if ($ordinal < 128) {
281
                $x[] = '|' . $ordinal;
282
            } else {
283
                if (empty($temp)) {
284
                    $count = ($ordinal < 224) ? 2 : 3;
285
                } else {
286
                    $count = 0;
287
                }
288
289
                $temp[] = $ordinal;
290
291
                if (count($temp) === $count) {
292
                    $number = ($count === 3) ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64) : (($temp[0] % 32) * 64) + ($temp[1] % 64);
293
                    $x[]    = '|' . $number;
294
                    $count  = 1;
295
                    $temp   = [];
296
                }
297
            }
298
        }
299
300
        $x[] = '<';
301
        $x[] = '/';
302
        $x[] = 'a';
303
        $x[] = '>';
304
305
        $x = array_reverse($x);
0 ignored issues
show
Bug introduced by
It seems like $x can also be of type true; however, parameter $array of array_reverse() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

305
        $x = array_reverse(/** @scrutinizer ignore-type */ $x);
Loading history...
306
307
        // améliore l'obscurcissement en éliminant les retours à la ligne et les espaces
308
        $output = '<script type="text/javascript">'
309
                . 'var l=new Array();';
310
311
        foreach ($x as $i => $value) {
312
            $output .= 'l[' . $i . "] = '" . $value . "';";
313
        }
314
315
        return $output . ('for (var i = l.length-1; i >= 0; i=i-1) {'
316
                . "if (l[i].substring(0, 1) === '|') document.write(\"&#\"+unescape(l[i].substring(1))+\";\");"
317
                . 'else document.write(unescape(l[i]));'
318
                . '}'
319
                . '</script>');
320
    }
321
}
322
323
if (! function_exists('auto_link')) {
324
    /**
325
     * Lien automatique
326
     *
327
     * Liens automatiquement URL et adresses e-mail.
328
     * Remarque : il y a un peu de code supplémentaire ici à gérer
329
     * URL ou e-mails se terminant par un point. Nous allons les dépouiller
330
     * off et ajoutez-les après le lien.
331
     *
332
     * @param string $type  le type : email, url, ou les deux
333
     * @param bool   $popup s'il faut créer des liens contextuels
334
     */
335
    function auto_link(string $str, string $type = 'both', bool $popup = false): string
336
    {
337
        // Recherche et remplace tous les URLs.
338
        if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
339
            // Définissez notre HTML cible si vous utilisez des liens contextuels.
340
            $target = ($popup) ? ' target="_blank"' : '';
341
342
            // Nous traitons les liens dans l'ordre inverse (dernier -> premier) de sorte que
343
            // les décalages de chaîne renvoyés par preg_match_all() ne sont pas
344
            // déplacées au fur et à mesure que nous ajoutons plus de HTML.
345
            foreach (array_reverse($matches) as $match) {
346
                // $match[0] est la chaîne/le lien correspondant
347
                // $match[1] est soit un préfixe de protocole soit 'www.'
348
                //
349
                // Avec PREG_OFFSET_CAPTURE, les deux éléments ci-dessus sont un tableau,
350
                // où la valeur réelle est contenue dans [0] et son décalage à l'index [1].
351
                $a   = '<a href="' . (strpos($match[1][0], '/') ? '' : 'http://') . $match[0][0] . '"' . $target . '>' . $match[0][0] . '</a>';
352
                $str = substr_replace($str, $a, $match[0][1], strlen($match[0][0]));
353
            }
354
        }
355
356
        // Recherche et remplace tous les e-mails.
357
        if ($type !== 'url' && preg_match_all('#([\w\.\-\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+[^[:punct:]\s])#i', $str, $matches, PREG_OFFSET_CAPTURE)) {
0 ignored issues
show
Unused Code introduced by
The call to preg_match_all() has too many arguments starting with PREG_OFFSET_CAPTURE. ( Ignorable by Annotation )

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

357
        if ($type !== 'url' && /** @scrutinizer ignore-call */ preg_match_all('#([\w\.\-\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+[^[:punct:]\s])#i', $str, $matches, PREG_OFFSET_CAPTURE)) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
358
            foreach (array_reverse($matches[0]) as $match) {
359
                if (filter_var($match[0], FILTER_VALIDATE_EMAIL) !== false) {
360
                    $str = substr_replace($str, safe_mailto($match[0]), $match[1], strlen($match[0]));
361
                }
362
            }
363
        }
364
365
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $str could return the type array which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
366
    }
367
}
368
369
if (! function_exists('prep_url')) {
370
    /**
371
     * Ajoute simplement la partie http:// ou https:// si aucun schéma n'est inclus.
372
     *
373
     * @param bool $secure définissez true si vous voulez forcer https://
374
     */
375
    function prep_url(string $str = '', bool $secure = false): string
376
    {
377
        if (in_array($str, ['http://', 'https://', '//', ''], true)) {
378
            return '';
379
        }
380
381
        if (parse_url($str, PHP_URL_SCHEME) === null) {
382
            $str = 'http://' . ltrim($str, '/');
383
        }
384
385
        // force le remplacement de http:// par https://
386
        if ($secure) {
387
            $str = preg_replace('/^(?:http):/i', 'https:', $str);
388
        }
389
390
        return $str;
391
    }
392
}
393
394
if (! function_exists('url_title')) {
395
    /**
396
     * Créer un titre d'URL
397
     *
398
     * Prend une chaîne de "titre" en entrée et crée un
399
     * Chaîne d'URL conviviale avec une chaîne de "séparateur"
400
     * comme séparateur de mots.
401
     *
402
     * @param string $separator Séparateur de mots (généralement '-' ou '_')
403
     * @param bool   $lowercase Indique s'il faut transformer la chaîne de sortie en minuscules
404
     */
405
    function url_title(string $str, string $separator = '-', bool $lowercase = false): string
406
    {
407
        $qSeparator = preg_quote($separator, '#');
408
409
        $trans = [
410
            '&.+?;'                  => '',
411
            '[^\w\d\pL\pM _-]'       => '',
412
            '\s+'                    => $separator,
413
            '(' . $qSeparator . ')+' => $separator,
414
        ];
415
416
        $str = strip_tags($str);
417
418
        foreach ($trans as $key => $val) {
419
            $str = preg_replace('#' . $key . '#iu', $val, $str);
420
        }
421
422
        if ($lowercase === true) {
423
            $str = mb_strtolower($str);
424
        }
425
426
        return trim(trim($str, $separator));
427
    }
428
}
429
430
if (! function_exists('mb_url_title')) {
431
    /**
432
     * Créer un titre d'URL qui prend en compte les caractères accentués
433
     *
434
     * Prend une chaîne de "titre" en entrée et crée un
435
     * Chaîne d'URL conviviale avec une chaîne de "séparateur"
436
     * comme séparateur de mots.
437
     *
438
     * @param string $separator Séparateur de mots (généralement '-' ou '_')
439
     * @param bool   $lowercase Indique s'il faut transformer la chaîne de sortie en minuscules
440
     */
441
    function mb_url_title(string $str, string $separator = '-', bool $lowercase = false): string
442
    {
443
        helper('scl');
444
445
        return url_title(scl_moveSpecialChar($str), $separator, $lowercase);
446
    }
447
}
448
449
if (! function_exists('url_to')) {
450
    /**
451
     * Obtenir l'URL complète et absolue d'une méthode de contrôleur
452
     * (avec arguments supplémentaires)
453
     *
454
     * REMARQUE : Cela nécessite que le contrôleur/la méthode ait une route définie dans le fichier de configuration des routes.
455
     *
456
     * @param mixed ...$args
457
     *
458
     * @throws RouterException
459
     */
460
    function url_to(string $controller, ...$args): string
461
    {
462
        if (! $route = route($controller, ...$args)) {
463
            $explode = explode('::', $controller);
464
465
            if (isset($explode[1])) {
466
                throw RouterException::controllerNotFound($explode[0], $explode[1]);
467
            }
468
469
            throw RouterException::invalidRoute($controller);
470
        }
471
472
        return site_url($route);
473
    }
474
}
475
476
if (! function_exists('route')) {
477
    /**
478
     * Tente de rechercher une route en fonction de sa destination.
479
     *
480
     * @return false|string
481
     */
482
    function route(string $method, ...$params)
483
    {
484
        return Services::routes()->reverseRoute($method, ...$params);
485
    }
486
}
487
488
if (! function_exists('url_is')) {
489
    /**
490
     * Détermine si le chemin d'URL actuel contient le chemin donné.
491
     * Il peut contenir un caractère générique (*) qui autorisera tout caractère valide.
492
     *
493
     * Exemple:
494
     *   if (url_is('admin*)) ...
495
     */
496
    function url_is(string $path): bool
497
    {
498
        // Configurez notre regex pour autoriser les caractères génériques
499
        $path        = '/' . trim(str_replace('*', '(\S)*', $path), '/ ');
500
        $currentPath = '/' . trim(uri_string(true), '/ ');
501
502
        return (bool) preg_match("|^{$path}$|", $currentPath, $matches);
503
    }
504
}
505
506
if (! function_exists('link_active')) {
507
    /**
508
     * Lien actif dans la navbar
509
     * Un peut comme le router-active-link de vuejs
510
     */
511
    function link_active(array|string $path, string $active_class = 'active', bool $exact = false): string
512
    {
513
        if (is_array($path)) {
0 ignored issues
show
introduced by
The condition is_array($path) is always true.
Loading history...
514
            foreach ($path as $p) {
515
                if ($active_class === link_active($p, $active_class, $exact)) {
516
                    return $active_class;
517
                }
518
            }
519
520
            return '';
521
        }
522
523
        $current_url     = trim(current_url(false), '/');
524
        $current_section = trim(str_replace(trim(site_url(), '/'), '', $current_url), '/');
525
526
        if ($current_section === $path || $current_url === $path) {
527
            return $active_class;
528
        }
529
530
        if (! $exact && preg_match('#^' . $path . '/?#i', $current_section)) {
531
            return $active_class;
532
        }
533
534
        if (trim(link_to($path), '/') === $current_url) {
535
            return $active_class;
536
        }
537
538
        return '';
539
    }
540
}
541
542
if (! function_exists('clean_url')) {
543
    function clean_url(string $url): string
544
    {
545
        return Helpers::cleanUrl($url);
546
    }
547
}
548
549
if (! function_exists('is_absolute_link')) {
550
    /**
551
     * Verifies si un chemin donnée est une url absolue ou relative
552
     */
553
    function is_absolute_link(string $url): bool
554
    {
555
        return Helpers::isAbsoluteUrl($url);
556
    }
557
}
558