diff --git a/src/Symfony/Component/String/AbstractString.php b/src/Symfony/Component/String/AbstractString.php index 81636c45925ac..500d7c3111e0b 100644 --- a/src/Symfony/Component/String/AbstractString.php +++ b/src/Symfony/Component/String/AbstractString.php @@ -433,6 +433,11 @@ abstract public function slice(int $start = 0, ?int $length = null): static; abstract public function snake(): static; + public function kebab(): static + { + return $this->snake()->replace('_', '-'); + } + abstract public function splice(string $replacement, int $start = 0, ?int $length = null): static; /** diff --git a/src/Symfony/Component/String/CHANGELOG.md b/src/Symfony/Component/String/CHANGELOG.md index f1f7204784f7d..ff505b14924a4 100644 --- a/src/Symfony/Component/String/CHANGELOG.md +++ b/src/Symfony/Component/String/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add `TruncateMode` enum to handle more truncate methods + * Add the `AbstractString::kebab()` method 7.1 --- diff --git a/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php b/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php index e046255eef289..ee4890f6bea6e 100644 --- a/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php +++ b/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php @@ -1089,6 +1089,35 @@ public static function provideSnake() ]; } + /** + * @dataProvider provideKebab + */ + public function testKebab(string $expectedString, string $origin) + { + $instance = static::createFromString($origin)->kebab(); + + $this->assertEquals(static::createFromString($expectedString), $instance); + $this->assertNotSame($origin, $instance, 'Strings should be immutable'); + } + + public static function provideKebab(): array + { + return [ + ['', ''], + ['x-y', 'x_y'], + ['x-y', 'X_Y'], + ['xu-yo', 'xu_yo'], + ['symfony-is-great', 'symfonyIsGreat'], + ['symfony123-is-great', 'symfony123IsGreat'], + ['symfony123is-great', 'symfony123isGreat'], + ['symfony-is-great', 'Symfony is great'], + ['symfony-is-a-great-framework', 'symfonyIsAGreatFramework'], + ['symfony-is-great', 'symfonyIsGREAT'], + ['symfony-is-really-great', 'symfonyIsREALLYGreat'], + ['symfony', 'SYMFONY'], + ]; + } + /** * @dataProvider provideStartsWith */ diff --git a/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php b/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php index e838c44419016..bde19d771937c 100644 --- a/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php +++ b/src/Symfony/Component/String/Tests/AbstractUnicodeTestCase.php @@ -665,6 +665,15 @@ public static function provideSnake() ); } + public static function provideKebab(): array + { + return [ + ...parent::provideKebab(), + ['symfony-ist-äußerst-cool', 'symfonyIstÄußerstCool'], + ['symfony-with-emojis', 'Symfony with 😃 emojis'], + ]; + } + public static function provideEqualsTo() { return array_merge(