@@ -15,14 +15,12 @@ class SlugTransformer extends AbstractTransformerProcessor implements Configurab
15
15
private string $ separator = '- ' ;
16
16
private bool $ lowercase = true ;
17
17
private array $ replacements = [];
18
- private string $ transliterationLocale = 'en ' ;
19
18
20
19
public function configure (array $ options ): void
21
20
{
22
21
$ this ->separator = $ options ['separator ' ] ?? $ this ->separator ;
23
22
$ this ->lowercase = $ options ['lowercase ' ] ?? $ this ->lowercase ;
24
- $ this ->replacements = array_merge ($ this ->replacements , $ options ['replacements ' ] ?? []);
25
- $ this ->transliterationLocale = $ options ['transliterationLocale ' ] ?? $ this ->transliterationLocale ;
23
+ $ this ->replacements = array_merge ($ this ->getDefaultReplacements (), $ options ['replacements ' ] ?? []);
26
24
}
27
25
28
26
public function process (mixed $ input ): string
@@ -35,46 +33,76 @@ public function process(mixed $input): string
35
33
36
34
$ slug = $ this ->createSlug ($ input );
37
35
38
- return $ this ->finalizeSlug ($ slug );
36
+ if (empty ($ slug )) {
37
+ $ this ->setInvalid ('emptySlug ' );
38
+
39
+ return '' ;
40
+ }
41
+
42
+ return $ slug ;
39
43
}
40
44
41
45
private function createSlug (string $ input ): string
42
46
{
43
- // Apply custom replacements
47
+ // Apply custom replacements first
44
48
$ text = str_replace (
45
49
array_keys ($ this ->replacements ),
46
50
array_values ($ this ->replacements ),
47
51
$ input
48
52
);
49
53
50
- // Transliterate
51
- $ text = transliterator_transliterate (
52
- "Any- {$ this ->transliterationLocale }; Latin-ASCII; NFD; [:Nonspacing Mark:] Remove; NFC " ,
53
- $ text
54
- );
54
+ // Convert accented characters to ASCII
55
+ $ text = $ this ->convertAccentsToAscii ($ text );
55
56
56
57
// Convert to lowercase if needed
57
58
if ($ this ->lowercase ) {
58
- $ text = strtolower ($ text );
59
+ $ text = mb_strtolower ($ text );
59
60
}
60
61
61
62
// Replace non-alphanumeric characters with separator
62
- $ text = preg_replace ('/[^\p{L}\p{N}]+/u ' , $ this ->separator , $ text );
63
+ $ text = preg_replace ('/[^a-zA-Z0-9\-_]/ ' , $ this ->separator , $ text );
63
64
64
- // Remove duplicate separators
65
+ // Replace multiple separators with a single one
65
66
$ text = preg_replace ('/ ' . preg_quote ($ this ->separator , '/ ' ) . '+/ ' , $ this ->separator , $ text );
66
67
67
68
return trim ($ text , $ this ->separator );
68
69
}
69
70
70
- private function finalizeSlug ( string $ slug ): string
71
+ private function getDefaultReplacements ( ): array
71
72
{
72
- if (empty ($ slug )) {
73
- $ this ->setInvalid ('emptySlug ' );
74
-
75
- return '' ;
76
- }
73
+ return [
74
+ ' ' => $ this ->separator ,
75
+ '& ' => 'and ' ,
76
+ '@ ' => 'at ' ,
77
+ ];
78
+ }
77
79
78
- return $ slug ;
80
+ private function convertAccentsToAscii (string $ string ): string
81
+ {
82
+ $ chars = [
83
+ // Latin
84
+ 'À ' => 'A ' , 'Á ' => 'A ' , 'Â ' => 'A ' , 'Ã ' => 'A ' , 'Ä ' => 'A ' , 'Å ' => 'A ' , 'Æ ' => 'AE ' ,
85
+ 'Ç ' => 'C ' , 'È ' => 'E ' , 'É ' => 'E ' , 'Ê ' => 'E ' , 'Ë ' => 'E ' , 'Ì ' => 'I ' , 'Í ' => 'I ' ,
86
+ 'Î ' => 'I ' , 'Ï ' => 'I ' , 'Ð ' => 'D ' , 'Ñ ' => 'N ' , 'Ò ' => 'O ' , 'Ó ' => 'O ' , 'Ô ' => 'O ' ,
87
+ 'Õ ' => 'O ' , 'Ö ' => 'O ' , 'Ő ' => 'O ' , 'Ø ' => 'O ' , 'Ù ' => 'U ' , 'Ú ' => 'U ' , 'Û ' => 'U ' ,
88
+ 'Ü ' => 'U ' , 'Ű ' => 'U ' , 'Ý ' => 'Y ' , 'Þ ' => 'TH ' , 'ß ' => 'ss ' , 'à ' => 'a ' , 'á ' => 'a ' ,
89
+ 'â ' => 'a ' , 'ã ' => 'a ' , 'ä ' => 'a ' , 'å ' => 'a ' , 'æ ' => 'ae ' , 'ç ' => 'c ' , 'è ' => 'e ' ,
90
+ 'é ' => 'e ' , 'ê ' => 'e ' , 'ë ' => 'e ' , 'ì ' => 'i ' , 'í ' => 'i ' , 'î ' => 'i ' , 'ï ' => 'i ' ,
91
+ 'ð ' => 'd ' , 'ñ ' => 'n ' , 'ò ' => 'o ' , 'ó ' => 'o ' , 'ô ' => 'o ' , 'õ ' => 'o ' , 'ö ' => 'o ' ,
92
+ 'ő ' => 'o ' , 'ø ' => 'o ' , 'ù ' => 'u ' , 'ú ' => 'u ' , 'û ' => 'u ' , 'ü ' => 'u ' , 'ű ' => 'u ' ,
93
+ 'ý ' => 'y ' , 'þ ' => 'th ' , 'ÿ ' => 'y ' ,
94
+ // Latin symbols
95
+ '© ' => '(c) ' ,
96
+ // Greek
97
+ 'Α ' => 'A ' , 'Β ' => 'B ' , 'Γ ' => 'G ' , 'Δ ' => 'D ' , 'Ε ' => 'E ' , 'Ζ ' => 'Z ' , 'Η ' => 'H ' ,
98
+ 'Θ ' => '8 ' , 'Ι ' => 'I ' , 'Κ ' => 'K ' , 'Λ ' => 'L ' , 'Μ ' => 'M ' , 'Ν ' => 'N ' , 'Ξ ' => '3 ' ,
99
+ 'Ο ' => 'O ' , 'Π ' => 'P ' , 'Ρ ' => 'R ' , 'Σ ' => 'S ' , 'Τ ' => 'T ' , 'Υ ' => 'Y ' , 'Φ ' => 'F ' ,
100
+ 'Χ ' => 'X ' , 'Ψ ' => 'PS ' , 'Ω ' => 'W ' , 'α ' => 'a ' , 'β ' => 'b ' , 'γ ' => 'g ' , 'δ ' => 'd ' ,
101
+ 'ε ' => 'e ' , 'ζ ' => 'z ' , 'η ' => 'h ' , 'θ ' => '8 ' , 'ι ' => 'i ' , 'κ ' => 'k ' , 'λ ' => 'l ' ,
102
+ 'μ ' => 'm ' , 'ν ' => 'n ' , 'ξ ' => '3 ' , 'ο ' => 'o ' , 'π ' => 'p ' , 'ρ ' => 'r ' , 'σ ' => 's ' ,
103
+ 'τ ' => 't ' , 'υ ' => 'y ' , 'φ ' => 'f ' , 'χ ' => 'x ' , 'ψ ' => 'ps ' , 'ω ' => 'w ' ,
104
+ ];
105
+
106
+ return strtr ($ string , $ chars );
79
107
}
80
108
}
0 commit comments