From 163411410d03d2962f1d7bab3edb8fecf6cc3b38 Mon Sep 17 00:00:00 2001 From: Raffaele Carelle Date: Fri, 11 Oct 2024 17:14:32 +0200 Subject: [PATCH 1/5] [String] Add `AbstractString::pascal()` method --- AbstractString.php | 5 +++++ CHANGELOG.md | 5 +++++ Tests/AbstractAsciiTestCase.php | 27 +++++++++++++++++++++++++++ Tests/AbstractUnicodeTestCase.php | 11 +++++++++++ 4 files changed, 48 insertions(+) diff --git a/AbstractString.php b/AbstractString.php index 500d7c3..fc60f8f 100644 --- a/AbstractString.php +++ b/AbstractString.php @@ -438,6 +438,11 @@ public function kebab(): static return $this->snake()->replace('_', '-'); } + public function pascal(): static + { + return $this->camel()->title(); + } + abstract public function splice(string $replacement, int $start = 0, ?int $length = null): static; /** diff --git a/CHANGELOG.md b/CHANGELOG.md index ff505b1..ac4b8fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.3 +--- + +* Add the `AbstractString::pascal()` method + 7.2 --- diff --git a/Tests/AbstractAsciiTestCase.php b/Tests/AbstractAsciiTestCase.php index ee4890f..e673f27 100644 --- a/Tests/AbstractAsciiTestCase.php +++ b/Tests/AbstractAsciiTestCase.php @@ -1118,6 +1118,33 @@ public static function provideKebab(): array ]; } + /** + * @dataProvider providePascal + */ + public function testPascal(string $expectedString, string $origin) + { + $instance = static::createFromString($origin)->pascal(); + + $this->assertEquals(static::createFromString($expectedString), $instance); + $this->assertNotSame($origin, $instance, 'Strings should be immutable'); + } + + public static function providePascal(): array + { + return [ + ['', ''], + ['XY', 'x_y'], + ['XuYo', 'xu_yo'], + ['SymfonyIsGreat', 'symfony_is_great'], + ['Symfony5IsGreat', 'symfony_5_is_great'], + ['SymfonyIsGreat', 'Symfony is great'], + ['SYMFONYISGREAT', 'SYMFONY_IS_GREAT'], + ['SymfonyIsAGreatFramework', 'Symfony is a great framework'], + ['SymfonyIsGREAT', '*Symfony* is GREAT!!'], + ['SYMFONY', 'SYMFONY'], + ]; + } + /** * @dataProvider provideStartsWith */ diff --git a/Tests/AbstractUnicodeTestCase.php b/Tests/AbstractUnicodeTestCase.php index bde19d7..2433f89 100644 --- a/Tests/AbstractUnicodeTestCase.php +++ b/Tests/AbstractUnicodeTestCase.php @@ -655,6 +655,17 @@ public static function provideCamel() ); } + public static function providePascal(): array + { + return array_merge( + parent::providePascal(), + [ + ['SymfonyIstÄußerstCool', 'symfonyIstÄußerstCool'], + ['SymfonyWithEmojis', 'Symfony with 😃 emojis'], + ] + ); + } + public static function provideSnake() { return array_merge( From 373a11f2d03e71934a0023888edf3328a583e4ec Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Jan 2025 17:34:30 +0100 Subject: [PATCH 2/5] Fix typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac4b8fb..0782ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 7.3 --- -* Add the `AbstractString::pascal()` method + * Add the `AbstractString::pascal()` method 7.2 --- From a75110076ac661a4a52792b5a1d286d113653a70 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Fri, 21 Feb 2025 02:28:48 +0100 Subject: [PATCH 3/5] chore: PHP CS Fixer - allow header validator --- Resources/WcswidthDataGenerator.php | 7 +++++++ Resources/data/wcswidth_table_wide.php | 7 +++++++ Resources/data/wcswidth_table_zero.php | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/Resources/WcswidthDataGenerator.php b/Resources/WcswidthDataGenerator.php index 19e6e89..005b148 100644 --- a/Resources/WcswidthDataGenerator.php +++ b/Resources/WcswidthDataGenerator.php @@ -83,10 +83,17 @@ private function getHeader(string $version): string + * * This file has been auto-generated by the Symfony String Component for internal use. * * Unicode version: $version * Date: $date + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ diff --git a/Resources/data/wcswidth_table_wide.php b/Resources/data/wcswidth_table_wide.php index 6a75094..b2c94c3 100644 --- a/Resources/data/wcswidth_table_wide.php +++ b/Resources/data/wcswidth_table_wide.php @@ -1,10 +1,17 @@ + * * This file has been auto-generated by the Symfony String Component for internal use. * * Unicode version: 16.0.0 * Date: 2024-09-11T08:21:22+00:00 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ return [ diff --git a/Resources/data/wcswidth_table_zero.php b/Resources/data/wcswidth_table_zero.php index fdd7f3c..287c36c 100644 --- a/Resources/data/wcswidth_table_zero.php +++ b/Resources/data/wcswidth_table_zero.php @@ -1,10 +1,17 @@ + * * This file has been auto-generated by the Symfony String Component for internal use. * * Unicode version: 16.0.0 * Date: 2024-09-11T08:21:22+00:00 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ return [ From 71c369598bfa44bb9815fc26b26e592d1d989be1 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 17 Apr 2025 13:34:07 +0200 Subject: [PATCH 4/5] ignore the current locale before transliterating ASCII codes with iconv() --- AbstractUnicodeString.php | 22 ++++++++++++++-------- Tests/Slugger/AsciiSluggerTest.php | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/AbstractUnicodeString.php b/AbstractUnicodeString.php index 70598e4..bd84b25 100644 --- a/AbstractUnicodeString.php +++ b/AbstractUnicodeString.php @@ -135,15 +135,21 @@ public function ascii(array $rules = []): self } elseif (!\function_exists('iconv')) { $s = preg_replace('/[^\x00-\x7F]/u', '?', $s); } else { - $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) { - $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); - - if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { - throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); - } + $previousLocale = setlocale(\LC_CTYPE, 0); + try { + setlocale(\LC_CTYPE, 'C'); + $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) { + $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); + + if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { + throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); + } - return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); - }, $s); + return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); + }, $s); + } finally { + setlocale(\LC_CTYPE, $previousLocale); + } } } diff --git a/Tests/Slugger/AsciiSluggerTest.php b/Tests/Slugger/AsciiSluggerTest.php index 703212f..7a6c06a 100644 --- a/Tests/Slugger/AsciiSluggerTest.php +++ b/Tests/Slugger/AsciiSluggerTest.php @@ -106,4 +106,19 @@ public static function provideSlugEmojiTests(): iterable 'undefined_locale', // Behaves the same as if emoji support is disabled ]; } + + /** + * @requires extension intl + */ + public function testSlugEmojiWithSetLocale() + { + if (!setlocale(LC_ALL, 'C.UTF-8')) { + $this->markTestSkipped('Unable to switch to the "C.UTF-8" locale.'); + } + + $slugger = new AsciiSlugger(); + $slugger = $slugger->withEmoji(true); + + $this->assertSame('a-and-a-go-to', (string) $slugger->slug('a 😺, 🐈‍⬛, and a 🦁 go to 🏞️... 😍 🎉 💛', '-')); + } } From 73e2c6966a5aef1d4892873ed5322245295370c6 Mon Sep 17 00:00:00 2001 From: Korvin Szanto Date: Thu, 17 Apr 2025 09:33:24 -0700 Subject: [PATCH 5/5] Support nexus -> nexuses pluralization --- Inflector/EnglishInflector.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Inflector/EnglishInflector.php b/Inflector/EnglishInflector.php index a5be28d..73db80c 100644 --- a/Inflector/EnglishInflector.php +++ b/Inflector/EnglishInflector.php @@ -333,6 +333,9 @@ final class EnglishInflector implements InflectorInterface // conspectuses (conspectus), prospectuses (prospectus) ['sutcep', 6, true, true, 'pectuses'], + // nexuses (nexus) + ['suxen', 5, false, false, 'nexuses'], + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['su', 2, true, true, 'i'],