From 90e3545c3d9a2738ab4d895c7ae08e83b778a4ed Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Wed, 26 Jun 2024 11:24:26 +1000 Subject: [PATCH] Introduces Str::chop* --- src/Illuminate/Support/Str.php | 36 ++++++++++++++++++++++++ src/Illuminate/Support/Stringable.php | 22 +++++++++++++++ tests/Support/SupportStrTest.php | 40 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index c9082a8de161..76dd8e1b033a 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -242,6 +242,42 @@ public static function charAt($subject, $index) return mb_substr($subject, $index, 1); } + /** + * Remove the given string(s) if it exists at the end of the haystack. + * + * @param string $subject + * @param string|array $needle + * @return string + */ + public static function chopEnd($subject, $needle) + { + foreach ((array) $needle as $n) { + if (str_ends_with($subject, $n)) { + return substr($subject, 0, -strlen($n)); + } + } + + return $subject; + } + + /** + * Remove the given string(s) if it exists at the start of the haystack. + * + * @param string $subject + * @param string|array $needle + * @return string + */ + public static function chopStart($subject, $needle) + { + foreach ((array) $needle as $n) { + if (str_starts_with($subject, $n)) { + return substr($subject, strlen($n)); + } + } + + return $subject; + } + /** * Determine if a given string contains a given substring. * diff --git a/src/Illuminate/Support/Stringable.php b/src/Illuminate/Support/Stringable.php index f9b31839c1b5..e72f2d57b620 100644 --- a/src/Illuminate/Support/Stringable.php +++ b/src/Illuminate/Support/Stringable.php @@ -111,6 +111,28 @@ public function charAt($index) return Str::charAt($this->value, $index); } + /** + * Remove the given string if it exists at the end of the current string. + * + * @param string|array $needle + * @return static + */ + public function chopEnd($needle) + { + return new static(Str::chopEnd($this->value, $needle)); + } + + /** + * Remove the given string if it exists at the start of the current string. + * + * @param string|array $needle + * @return static + */ + public function chopStart($needle) + { + return new static(Str::chopStart($this->value, $needle)); + } + /** * Get the basename of the class path. * diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php index d1e7977b2cdd..725326e7e8aa 100755 --- a/tests/Support/SupportStrTest.php +++ b/tests/Support/SupportStrTest.php @@ -1526,6 +1526,46 @@ public function testFromBase64() $this->assertSame('foo', Str::fromBase64(base64_encode('foo'))); $this->assertSame('foobar', Str::fromBase64(base64_encode('foobar'), true)); } + + public function testChopStart() + { + foreach ([ + 'http://laravel.com' => ['http://', 'laravel.com'], + 'http://-http://' => ['http://', '-http://'], + 'http://laravel.com' => ['htp:/', 'http://laravel.com'], + 'http://laravel.com' => ['http://www.', 'http://laravel.com'], + 'http://laravel.com' => ['-http://', 'http://laravel.com'], + 'http://laravel.com' => [['https://', 'http://'], 'laravel.com'], + 'http://www.laravel.com' => [['http://', 'www.'], 'www.laravel.com'], + 'http://http-is-fun.test' => ['http://', 'http-is-fun.test'], + '🌊✋' => ['🌊', '✋'], + '🌊✋' => ['✋', '🌊✋'], + ] as $subject => $value) { + [$needle, $expected] = $value; + + $this->assertSame($expected, Str::chopStart($subject, $needle)); + } + } + + public function testChopEnd() + { + foreach ([ + 'path/to/file.php' => ['.php', 'path/to/file'], + '.php-.php' => ['.php', '.php-'], + 'path/to/file.php' => ['.ph', 'path/to/file.php'], + 'path/to/file.php' => ['foo.php', 'path/to/file.php'], + 'path/to/file.php' => ['.php-', 'path/to/file.php'], + 'path/to/file.php' => [['.html', '.php'], 'path/to/file'], + 'path/to/file.php' => [['.php', 'file'], 'path/to/file'], + 'path/to/php.php' => ['.php', 'path/to/php'], + '✋🌊' => ['🌊', '✋'], + '✋🌊' => ['✋', '✋🌊'], + ] as $subject => $value) { + [$needle, $expected] = $value; + + $this->assertSame($expected, Str::chopEnd($subject, $needle)); + } + } } class StringableObjectStub