From 38434a778d48b9f64dae67f7ca4cf116878fedfb Mon Sep 17 00:00:00 2001 From: Joe Dixon Date: Wed, 23 Aug 2023 21:45:10 +0200 Subject: [PATCH] [10.x] Adds start and end string replacement helpers (#48025) * add start and end replacement helpers * formatting --------- Co-authored-by: Taylor Otwell --- src/Illuminate/Support/Str.php | 48 +++++++++++++++++++++++++ src/Illuminate/Support/Stringable.php | 24 +++++++++++++ tests/Support/SupportStrTest.php | 27 ++++++++++++++ tests/Support/SupportStringableTest.php | 27 ++++++++++++++ 4 files changed, 126 insertions(+) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 90f1b0f25f4e..0d706d1920ca 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -1007,6 +1007,29 @@ public static function replaceFirst($search, $replace, $subject) return $subject; } + /** + * Replace the first occurrence of the given value if it appears at the start of the string. + * + * @param string $search + * @param string $replace + * @param string $subject + * @return string + */ + public static function replaceStart($search, $replace, $subject) + { + $search = (string) $search; + + if ($search === '') { + return $subject; + } + + if (static::startsWith($subject, $search)) { + return static::replaceFirst($search, $replace, $subject); + } + + return $subject; + } + /** * Replace the last occurrence of a given value in the string. * @@ -1017,6 +1040,8 @@ public static function replaceFirst($search, $replace, $subject) */ public static function replaceLast($search, $replace, $subject) { + $search = (string) $search; + if ($search === '') { return $subject; } @@ -1030,6 +1055,29 @@ public static function replaceLast($search, $replace, $subject) return $subject; } + /** + * Replace the last occurrence of a given value if it appears at the end of the string. + * + * @param string $search + * @param string $replace + * @param string $subject + * @return string + */ + public static function replaceEnd($search, $replace, $subject) + { + $search = (string) $search; + + if ($search === '') { + return $subject; + } + + if (static::endsWith($subject, $search)) { + return static::replaceLast($search, $replace, $subject); + } + + return $subject; + } + /** * Remove any occurrence of the given string in the subject. * diff --git a/src/Illuminate/Support/Stringable.php b/src/Illuminate/Support/Stringable.php index d4a7726ef3b2..645b3949da36 100644 --- a/src/Illuminate/Support/Stringable.php +++ b/src/Illuminate/Support/Stringable.php @@ -656,6 +656,18 @@ public function replaceFirst($search, $replace) return new static(Str::replaceFirst($search, $replace, $this->value)); } + /** + * Replace the first occurrence of the given value if it appears at the start of the string. + * + * @param string $search + * @param string $replace + * @return static + */ + public function replaceStart($search, $replace) + { + return new static(Str::replaceStart($search, $replace, $this->value)); + } + /** * Replace the last occurrence of a given value in the string. * @@ -668,6 +680,18 @@ public function replaceLast($search, $replace) return new static(Str::replaceLast($search, $replace, $this->value)); } + /** + * Replace the last occurrence of a given value if it appears at the end of the string. + * + * @param string $search + * @param string $replace + * @return static + */ + public function replaceEnd($search, $replace) + { + return new static(Str::replaceEnd($search, $replace, $this->value)); + } + /** * Replace the patterns matching the given regular expression. * diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php index 8b9532823468..0377762dc1ed 100755 --- a/tests/Support/SupportStrTest.php +++ b/tests/Support/SupportStrTest.php @@ -609,6 +609,19 @@ public function testReplaceFirst() $this->assertSame('Jönköping Malmö', Str::replaceFirst('', 'yyy', 'Jönköping Malmö')); } + public function testReplaceStart() + { + $this->assertSame('foobar foobar', Str::replaceStart('bar', 'qux', 'foobar foobar')); + $this->assertSame('foo/bar? foo/bar?', Str::replaceStart('bar?', 'qux?', 'foo/bar? foo/bar?')); + $this->assertSame('quxbar foobar', Str::replaceStart('foo', 'qux', 'foobar foobar')); + $this->assertSame('qux? foo/bar?', Str::replaceStart('foo/bar?', 'qux?', 'foo/bar? foo/bar?')); + $this->assertSame('bar foobar', Str::replaceStart('foo', '', 'foobar foobar')); + $this->assertSame('1', Str::replaceStart(0, '1', '0')); + // Test for multibyte string support + $this->assertSame('xxxnköping Malmö', Str::replaceStart('Jö', 'xxx', 'Jönköping Malmö')); + $this->assertSame('Jönköping Malmö', Str::replaceStart('', 'yyy', 'Jönköping Malmö')); + } + public function testReplaceLast() { $this->assertSame('foobar fooqux', Str::replaceLast('bar', 'qux', 'foobar foobar')); @@ -621,6 +634,20 @@ public function testReplaceLast() $this->assertSame('Malmö Jönköping', Str::replaceLast('', 'yyy', 'Malmö Jönköping')); } + public function testReplaceEnd() + { + $this->assertSame('foobar fooqux', Str::replaceEnd('bar', 'qux', 'foobar foobar')); + $this->assertSame('foo/bar? foo/qux?', Str::replaceEnd('bar?', 'qux?', 'foo/bar? foo/bar?')); + $this->assertSame('foobar foo', Str::replaceEnd('bar', '', 'foobar foobar')); + $this->assertSame('foobar foobar', Str::replaceEnd('xxx', 'yyy', 'foobar foobar')); + $this->assertSame('foobar foobar', Str::replaceEnd('', 'yyy', 'foobar foobar')); + $this->assertSame('fooxxx foobar', Str::replaceEnd('xxx', 'yyy', 'fooxxx foobar')); + + // // Test for multibyte string support + $this->assertSame('Malmö Jönköping', Str::replaceEnd('ö', 'xxx', 'Malmö Jönköping')); + $this->assertSame('Malmö Jönkyyy', Str::replaceEnd('öping', 'yyy', 'Malmö Jönköping')); + } + public function testRemove() { $this->assertSame('Fbar', Str::remove('o', 'Foobar')); diff --git a/tests/Support/SupportStringableTest.php b/tests/Support/SupportStringableTest.php index a0c5f233c537..a16eb12bd982 100644 --- a/tests/Support/SupportStringableTest.php +++ b/tests/Support/SupportStringableTest.php @@ -863,6 +863,19 @@ public function testReplaceFirst() $this->assertSame('Jönköping Malmö', (string) $this->stringable('Jönköping Malmö')->replaceFirst('', 'yyy')); } + public function testReplaceStart() + { + $this->assertSame('foobar foobar', (string) $this->stringable('foobar foobar')->replaceStart('bar', 'qux')); + $this->assertSame('foo/bar? foo/bar?', (string) $this->stringable('foo/bar? foo/bar?')->replaceStart('bar?', 'qux?')); + $this->assertSame('quxbar foobar', (string) $this->stringable('foobar foobar')->replaceStart('foo', 'qux')); + $this->assertSame('qux? foo/bar?', (string) $this->stringable('foo/bar? foo/bar?')->replaceStart('foo/bar?', 'qux?')); + $this->assertSame('bar foobar', (string) $this->stringable('foobar foobar')->replaceStart('foo', '')); + $this->assertSame('1', (string) $this->stringable('0')->replaceStart(0, '1')); + // Test for multibyte string support + $this->assertSame('xxxnköping Malmö', (string) $this->stringable('Jönköping Malmö')->replaceStart('Jö', 'xxx')); + $this->assertSame('Jönköping Malmö', (string) $this->stringable('Jönköping Malmö')->replaceStart('', 'yyy')); + } + public function testReplaceLast() { $this->assertSame('foobar fooqux', (string) $this->stringable('foobar foobar')->replaceLast('bar', 'qux')); @@ -875,6 +888,20 @@ public function testReplaceLast() $this->assertSame('Malmö Jönköping', (string) $this->stringable('Malmö Jönköping')->replaceLast('', 'yyy')); } + public function testReplaceEnd() + { + $this->assertSame('foobar fooqux', (string) $this->stringable('foobar foobar')->replaceEnd('bar', 'qux')); + $this->assertSame('foo/bar? foo/qux?', (string) $this->stringable('foo/bar? foo/bar?')->replaceEnd('bar?', 'qux?')); + $this->assertSame('foobar foo', (string) $this->stringable('foobar foobar')->replaceEnd('bar', '')); + $this->assertSame('foobar foobar', (string) $this->stringable('foobar foobar')->replaceLast('xxx', 'yyy')); + $this->assertSame('foobar foobar', (string) $this->stringable('foobar foobar')->replaceEnd('', 'yyy')); + $this->assertSame('fooxxx foobar', (string) $this->stringable('fooxxx foobar')->replaceEnd('xxx', 'yyy')); + + // // Test for multibyte string support + $this->assertSame('Malmö Jönköping', (string) $this->stringable('Malmö Jönköping')->replaceEnd('ö', 'xxx')); + $this->assertSame('Malmö Jönkyyy', (string) $this->stringable('Malmö Jönköping')->replaceEnd('öping', 'yyy')); + } + public function testRemove() { $this->assertSame('Fbar', (string) $this->stringable('Foobar')->remove('o'));