PluginProbe
Depicter — Popup & Slider Builder / 1.3.2
Depicter — Popup & Slider Builder v1.3.2
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / vendor / symfony / string / Slugger / AsciiSlugger.php

AsciiSlugger.php in Depicter — Popup & Slider Builder 1.3.2, at vendor/symfony/string/Slugger/AsciiSlugger.php

184 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\String\Slugger;
13
14 use Symfony\Component\String\AbstractUnicodeString;
15 use Symfony\Component\String\UnicodeString;
16 use Symfony\Contracts\Translation\LocaleAwareInterface;
17
18 if (!interface_exists(LocaleAwareInterface::class)) {
19 throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".');
20 }
21
22 /**
23 * @author Titouan Galopin <galopintitouan@gmail.com>
24 */
25 class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
26 {
27 private const LOCALE_TO_TRANSLITERATOR_ID = [
28 'am' => 'Amharic-Latin',
29 'ar' => 'Arabic-Latin',
30 'az' => 'Azerbaijani-Latin',
31 'be' => 'Belarusian-Latin',
32 'bg' => 'Bulgarian-Latin',
33 'bn' => 'Bengali-Latin',
34 'de' => 'de-ASCII',
35 'el' => 'Greek-Latin',
36 'fa' => 'Persian-Latin',
37 'he' => 'Hebrew-Latin',
38 'hy' => 'Armenian-Latin',
39 'ka' => 'Georgian-Latin',
40 'kk' => 'Kazakh-Latin',
41 'ky' => 'Kirghiz-Latin',
42 'ko' => 'Korean-Latin',
43 'mk' => 'Macedonian-Latin',
44 'mn' => 'Mongolian-Latin',
45 'or' => 'Oriya-Latin',
46 'ps' => 'Pashto-Latin',
47 'ru' => 'Russian-Latin',
48 'sr' => 'Serbian-Latin',
49 'sr_Cyrl' => 'Serbian-Latin',
50 'th' => 'Thai-Latin',
51 'tk' => 'Turkmen-Latin',
52 'uk' => 'Ukrainian-Latin',
53 'uz' => 'Uzbek-Latin',
54 'zh' => 'Han-Latin',
55 ];
56
57 private $defaultLocale;
58 private $symbolsMap = [
59 'en' => ['@' => 'at', '&' => 'and'],
60 ];
61
62 /**
63 * Cache of transliterators per locale.
64 *
65 * @var \Transliterator[]
66 */
67 private $transliterators = [];
68
69 /**
70 * @param array|\Closure|null $symbolsMap
71 */
72 public function __construct(string $defaultLocale = null, $symbolsMap = null)
73 {
74 if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) {
75 throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap)));
76 }
77
78 $this->defaultLocale = $defaultLocale;
79 $this->symbolsMap = $symbolsMap ?? $this->symbolsMap;
80 }
81
82 /**
83 * {@inheritdoc}
84 */
85 public function setLocale($locale)
86 {
87 $this->defaultLocale = $locale;
88 }
89
90 /**
91 * {@inheritdoc}
92 */
93 public function getLocale()
94 {
95 return $this->defaultLocale;
96 }
97
98 /**
99 * {@inheritdoc}
100 */
101 public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString
102 {
103 $locale = $locale ?? $this->defaultLocale;
104
105 $transliterator = [];
106 if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) {
107 // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl)
108 $transliterator = ['de-ASCII'];
109 } elseif (\function_exists('transliterator_transliterate') && $locale) {
110 $transliterator = (array) $this->createTransliterator($locale);
111 }
112
113 if ($this->symbolsMap instanceof \Closure) {
114 // If the symbols map is passed as a closure, there is no need to fallback to the parent locale
115 // as the closure can just provide substitutions for all locales of interest.
116 $symbolsMap = $this->symbolsMap;
117 array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) {
118 return $symbolsMap($s, $locale);
119 });
120 }
121
122 $unicodeString = (new UnicodeString($string))->ascii($transliterator);
123
124 if (\is_array($this->symbolsMap)) {
125 $map = null;
126 if (isset($this->symbolsMap[$locale])) {
127 $map = $this->symbolsMap[$locale];
128 } else {
129 $parent = self::getParentLocale($locale);
130 if ($parent && isset($this->symbolsMap[$parent])) {
131 $map = $this->symbolsMap[$parent];
132 }
133 }
134 if ($map) {
135 foreach ($map as $char => $replace) {
136 $unicodeString = $unicodeString->replace($char, ' '.$replace.' ');
137 }
138 }
139 }
140
141 return $unicodeString
142 ->replaceMatches('/[^A-Za-z0-9]++/', $separator)
143 ->trim($separator)
144 ;
145 }
146
147 private function createTransliterator(string $locale): ?\Transliterator
148 {
149 if (\array_key_exists($locale, $this->transliterators)) {
150 return $this->transliterators[$locale];
151 }
152
153 // Exact locale supported, cache and return
154 if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) {
155 return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
156 }
157
158 // Locale not supported and no parent, fallback to any-latin
159 if (!$parent = self::getParentLocale($locale)) {
160 return $this->transliterators[$locale] = null;
161 }
162
163 // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
164 if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
165 $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
166 }
167
168 return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
169 }
170
171 private static function getParentLocale(?string $locale): ?string
172 {
173 if (!$locale) {
174 return null;
175 }
176 if (false === $str = strrchr($locale, '_')) {
177 // no parent locale
178 return null;
179 }
180
181 return substr($locale, 0, -\strlen($str));
182 }
183 }
184