diff --git a/src/Symfony/Component/String/AbstractUnicodeString.php b/src/Symfony/Component/String/AbstractUnicodeString.php index 258407959c846..0cba861b7c5ba 100644 --- a/src/Symfony/Component/String/AbstractUnicodeString.php +++ b/src/Symfony/Component/String/AbstractUnicodeString.php @@ -77,7 +77,7 @@ public static function fromCodePoints(int ...$codes): self * * Install the intl extension for best results. * - * @param string[]|\Transliterator[] $rules See "*-Latin" rules from Transliterator::listIDs() + * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs() */ public function ascii(array $rules = []): self { @@ -107,6 +107,8 @@ public function ascii(array $rules = []): self if ($rule instanceof \Transliterator) { $s = $rule->transliterate($s); + } elseif ($rule instanceof \Closure) { + $s = $rule($s); } elseif ($rule) { if ('nfd' === $rule = strtolower($rule)) { normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD); diff --git a/src/Symfony/Component/String/Slugger/AsciiSlugger.php b/src/Symfony/Component/String/Slugger/AsciiSlugger.php index 3352b04995f9f..c6ddbdfcc6915 100644 --- a/src/Symfony/Component/String/Slugger/AsciiSlugger.php +++ b/src/Symfony/Component/String/Slugger/AsciiSlugger.php @@ -66,8 +66,15 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface */ private $transliterators = []; - public function __construct(string $defaultLocale = null, array $symbolsMap = null) + /** + * @param array|\Closure|null $symbolsMap + */ + public function __construct(string $defaultLocale = null, $symbolsMap = null) { + if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) { + throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolMap))); + } + $this->defaultLocale = $defaultLocale; $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } @@ -103,9 +110,16 @@ public function slug(string $string, string $separator = '-', string $locale = n $transliterator = (array) $this->createTransliterator($locale); } + if ($this->symbolsMap instanceof \Closure) { + $symbolsMap = $this->symbolsMap; + array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) { + return $symbolsMap($s, $locale); + }); + } + $unicodeString = (new UnicodeString($string))->ascii($transliterator); - if (isset($this->symbolsMap[$locale])) { + if (\is_array($this->symbolsMap) && isset($this->symbolsMap[$locale])) { foreach ($this->symbolsMap[$locale] as $char => $replace) { $unicodeString = $unicodeString->replace($char, ' '.$replace.' '); } diff --git a/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php b/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php index 84e64b02e9f6a..e4bf99853779d 100644 --- a/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php +++ b/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php @@ -20,6 +20,16 @@ public function testAscii() $this->assertSame('Dieser Wert sollte groesser oder gleich', (string) $s->ascii(['de-ASCII'])); } + public function testAsciiClosureRule() + { + $rule = function ($c) { + return str_replace('ö', 'OE', $c); + }; + + $s = static::createFromString('Dieser Wert sollte größer oder gleich'); + $this->assertSame('Dieser Wert sollte grOEsser oder gleich', (string) $s->ascii([$rule])); + } + public function provideCreateFromCodePoint(): array { return [ diff --git a/src/Symfony/Component/String/Tests/SluggerTest.php b/src/Symfony/Component/String/Tests/SluggerTest.php index 1290759b68515..e838da6afb53d 100644 --- a/src/Symfony/Component/String/Tests/SluggerTest.php +++ b/src/Symfony/Component/String/Tests/SluggerTest.php @@ -64,4 +64,15 @@ public function testSlugCharReplacementLocaleMethod() $slug = (string) $slugger->slug('yo & tu a esta dirección slug@test.es', '_', 'es'); $this->assertSame('yo_y_tu_a_esta_direccion_slug_en_senal_test_es', $slug); } + + public function testSlugClosure() + { + $slugger = new AsciiSlugger(null, function ($s, $locale) { + $this->assertSame('foo', $locale); + + return str_replace('❤️', 'love', $s); + }); + + $this->assertSame('love', (string) $slugger->slug('❤️', '-', 'foo')); + } }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: