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..0782ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.3 +--- + + * Add the `AbstractString::pascal()` method + 7.2 --- diff --git a/Inflector/EnglishInflector.php b/Inflector/EnglishInflector.php index 73db80c..5583669 100644 --- a/Inflector/EnglishInflector.php +++ b/Inflector/EnglishInflector.php @@ -25,9 +25,22 @@ final class EnglishInflector implements InflectorInterface // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: singular suffix, normal + // insignias (insigne), insignia (insigne) + ['saingisni', 9, true, true, 'insigne'], + ['aingisni', 8, true, true, 'insigne'], + + // passersby (passerby) + ['ybsressap', 9, true, true, 'passerby'], + + // nodes (node) + ['sedon', 5, true, true, 'node'], + // bacteria (bacterium) ['airetcab', 8, true, true, 'bacterium'], + // issues (issue) + ['seussi', 6, true, true, 'issue'], + // corpora (corpus) ['aroproc', 7, true, true, 'corpus'], @@ -166,6 +179,9 @@ final class EnglishInflector implements InflectorInterface // edges (edge) ['segd', 4, true, true, 'dge'], + // outages (outage) - specific fix to avoid 'outag' + ['segatuo', 7, true, true, 'outage'], + // roses (rose), garages (garage), cassettes (cassette), // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), // shoes (shoe) @@ -196,6 +212,15 @@ final class EnglishInflector implements InflectorInterface // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: plural suffix, normal + // passerby (passersby) + ['ybressap', 8, true, true, 'passersby'], + + // insigne (insignia, insignias) + ['engisni', 7, true, true, ['insignia', 'insignias']], + + // nodes (node) + ['edon', 4, true, true, 'nodes'], + // axes (axis) ['sixa', 4, false, false, 'axes'], 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 [ diff --git a/Slugger/AsciiSlugger.php b/Slugger/AsciiSlugger.php index 9d4edf1..f5967e4 100644 --- a/Slugger/AsciiSlugger.php +++ b/Slugger/AsciiSlugger.php @@ -128,8 +128,8 @@ public function slug(string $string, string $separator = '-', ?string $locale = if (\is_array($this->symbolsMap)) { $map = null; - if (isset($this->symbolsMap[$locale])) { - $map = $this->symbolsMap[$locale]; + if (isset($this->symbolsMap[$locale ?? ''])) { + $map = $this->symbolsMap[$locale ?? '']; } else { $parent = self::getParentLocale($locale); if ($parent && isset($this->symbolsMap[$parent])) { 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( diff --git a/Tests/Inflector/EnglishInflectorTest.php b/Tests/Inflector/EnglishInflectorTest.php index 16287f4..aeff309 100644 --- a/Tests/Inflector/EnglishInflectorTest.php +++ b/Tests/Inflector/EnglishInflectorTest.php @@ -103,6 +103,7 @@ public static function singularizeProvider() ['indices', ['index', 'indix', 'indice']], ['ions', 'ion'], ['irises', ['iris', 'irise', 'irisis']], + ['issues', 'issue'], ['kisses', 'kiss'], ['knives', 'knife'], ['lamps', 'lamp'], @@ -122,8 +123,10 @@ public static function singularizeProvider() ['nebulae', 'nebula'], ['neuroses', ['neuros', 'neurose', 'neurosis']], ['news', 'news'], + ['nodes', 'node'], ['oases', ['oas', 'oase', 'oasis']], ['objectives', 'objective'], + ['outages', 'outage'], ['oxen', 'ox'], ['parties', 'party'], ['people', 'person'], @@ -168,16 +171,15 @@ public static function singularizeProvider() ['waltzes', ['waltz', 'waltze']], ['wives', 'wife'], ['zombies', 'zombie'], + ['passersby', 'passerby'], + ['rattles', 'rattle'], + ['insignia', 'insigne'], + ['insignias', 'insigne'], // test casing: if the first letter was uppercase, it should remain so ['Men', 'Man'], ['GrandChildren', 'GrandChild'], ['SubTrees', 'SubTree'], - - // Known issues - // ['insignia', 'insigne'], - // ['insignias', 'insigne'], - // ['rattles', 'rattle'], ]; } @@ -259,8 +261,10 @@ public static function pluralizeProvider() ['house', 'houses'], ['icon', 'icons'], ['index', ['indicies', 'indexes']], + ['insigne', ['insignia', 'insignias']], ['ion', 'ions'], ['iris', 'irises'], + ['issue', 'issues'], ['kiss', 'kisses'], ['knife', 'knives'], ['lamp', 'lamps'], @@ -278,10 +282,12 @@ public static function pluralizeProvider() ['nebula', 'nebulae'], ['neurosis', 'neuroses'], ['news', 'news'], + ['node', 'nodes'], ['oasis', 'oases'], ['objective', 'objectives'], ['ox', 'oxen'], ['party', 'parties'], + ['passerby', 'passersby'], ['person', ['persons', 'people']], ['phenomenon', 'phenomena'], ['photo', 'photos'], @@ -293,6 +299,7 @@ public static function pluralizeProvider() ['quiz', 'quizzes'], ['quorum', ['quora', 'quorums']], ['radius', 'radii'], + ['rattle', 'rattles'], ['roof', ['roofs', 'rooves']], ['rose', 'roses'], ['sandwich', 'sandwiches'], diff --git a/Tests/LazyStringTest.php b/Tests/LazyStringTest.php index b5405bb..cb52644 100644 --- a/Tests/LazyStringTest.php +++ b/Tests/LazyStringTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\String\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\ErrorHandler\ErrorHandler; use Symfony\Component\String\LazyString; class LazyStringTest extends TestCase @@ -34,8 +33,6 @@ public function testLazyString() */ public function testReturnTypeError() { - ErrorHandler::register(); - $s = LazyString::fromCallable(fn () => []); $this->expectException(\TypeError::class); diff --git a/composer.json b/composer.json index 10d0ee6..bb71530 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/error-handler": "^6.4|^7.0", "symfony/emoji": "^7.1", "symfony/http-client": "^6.4|^7.0", "symfony/intl": "^6.4|^7.0",