1: <?php
2: namespace TIC\CoreBundle\Util;
3:
4: /**
5: * Méthodes statiques utilitaires pour convertir des chaines de caractères.
6: */
7: class StringHelper
8: {
9:
10: /**
11: * This class should not be instantiated.
12: */
13: private function __construct()
14: {
15: }
16:
17: /**
18: * Retourne une chaine ASCII en convertissant les caractères étendus.
19: *
20: * @param string $text Texte en UTF-8 à transformer
21: * @return string Chaine équivalente avec les caractères 7 bits
22: */
23: public static function asciify(string $text): string
24: {
25: return \preg_replace_callback('/([\xA0-\xFF])/', function($m){
26: // remplacement des caractères du second bloc par leurs équivalents
27: $mapA0FF = ' !cL*Y|$_ca<--R_o+23\'mp.,10>423?AAAAAAACEEEEIIIIDNOOOOOx0UUUUYPBaaaaaaaceeeeiiiidnooooo:0uuuuypy';
28: return \substr($mapA0FF, \ord($m[0]) - 160, 1);
29: },
30: // conversion du texte d'origine supposé en UTF-8 en latin
31: \mb_convert_encoding($text, 'iso-8859-15', 'UTF-8')
32: );
33: }
34:
35: /**
36: * Retourne une chaine canonisée à partir d'une chaine donnée.
37: *
38: * @param string $text Texte en UTF-8 à slugifier
39: * @param string $re_ok Ensemble des caractères autorisés (pour regexp)
40: * @param string $subst Caractère de substitution pour les caractères non autorisés
41: * @return string Slug en minuscules et underscores pour les espaces
42: */
43: public static function slugify(string $text, string $subst = '-', string $re_ok = 'a-z0-9_\-\.'): string
44: {
45: // remplacement des caractères du second bloc ASCII par leurs équivalents en ISO latin
46: $slug = self::asciify($text);
47:
48: // substitution des espaces en underscores et des autres caractères en tirets
49: $slug = \preg_replace('/[^'.$re_ok.']/', '-', \strtolower(\strtr($slug, ' ', '_')));
50:
51: // retrait des caractères de séparation/substitution consécutifs et terminaux
52: return \trim(\preg_replace('/([_\-\.])[_\-\.]+/', '$1', $slug), '_-.');
53: }
54:
55: /**
56: * Retourne une chaine avec les échappements pour du code JavaScript.
57: * cf. Twig\Extension\EscaperExtension : twig_escape_filter()
58: *
59: * @param string $text Valeur à échapper pour utilisation dans du code JS
60: * @return string Valeur échappée prête pour insertion dans du code JS
61: */
62: public static function jsescape(string $text): string
63: {
64: return \preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', function ($matches) {
65: $char = $matches[0];
66:
67: // A few characters have short escape sequences in JSON and JavaScript.
68: // Escape sequences supported only by JavaScript, not JSON, are omitted.
69: // \" is also supported but omitted, because the resulting string is not HTML safe.
70: $shortMap = [
71: "\\" => "\\\\",
72: '/' => '\\/',
73: "\x08" => '\b',
74: "\x0C" => '\f',
75: "\x0A" => '\n',
76: "\x0D" => '\r',
77: "\x09" => '\t',
78: ];
79: if (isset($shortMap[$char])) return $shortMap[$char];
80:
81: $codepoint = \mb_ord($char);
82: if (0x10000 > $codepoint) return \sprintf('\u%04X', $codepoint);
83:
84: // Split characters outside the BMP into surrogate pairs
85: // https://tools.ietf.org/html/rfc2781.html#section-2.1
86: $u = $codepoint - 0x10000;
87: return \sprintf('\u%04X\u%04X', 0xD800 | ($u >> 10), 0xDC00 | ($u & 0x3FF));
88: }, $text);
89: }
90:
91: /**
92: * Génération d'une chaine aléatoire.
93: *
94: * @param integer $length Nombre de caractères à générer (longueur de la chaine)
95: * @param mixed $sigils Alphabet à utiliser (caractères autorisés dans la chaine)
96: * si Null : ensemble alpha-numérique [a-zA-Z0-9]
97: * si True : ASCII de base imprimable, sauf & < > $ ^ " ' ` \ |
98: * si False : alpha-numérique non ambigus [A-Z0-9], sauf 0 O 1 I
99: * @return string Chaine constituée de $length caractères aléatoires parmis $sigils
100: */
101: public static function genrandom(int $length = 8, mixed $sigils = null): string
102: {
103: if (null === $sigils) $sigils = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
104: elseif (true === $sigils) $sigils = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-+/*=.,;:!?@#%~(){}[]';
105: elseif (false === $sigils) $sigils = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
106:
107: \srand((double)\microtime()*1000000);
108: $str = '';
109: while ($length-- > 0) $str.= $sigils[ \rand() % \strlen($sigils) ];
110: return $str;
111: }
112:
113: }
114: