Skip to content

[10.x] Adds start and end string replacement helpers #48025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/Illuminate/Support/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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;
}
Expand All @@ -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.
*
Expand Down
24 changes: 24 additions & 0 deletions src/Illuminate/Support/Stringable.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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.
*
Expand Down
27 changes: 27 additions & 0 deletions tests/Support/SupportStrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand All @@ -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'));
Expand Down
27 changes: 27 additions & 0 deletions tests/Support/SupportStringableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand All @@ -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'));
Expand Down