From caa2029ec70604747fe36cfd4fd7d01ff31680d6 Mon Sep 17 00:00:00 2001 From: salehhashemi1992 <81674631+salehhashemi1992@users.noreply.github.com> Date: Mon, 23 Oct 2023 22:48:14 +0330 Subject: [PATCH 1/3] implement findBetween method to StringHelper --- framework/helpers/BaseStringHelper.php | 28 ++++++++++++++++++++ tests/framework/helpers/StringHelperTest.php | 26 ++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/framework/helpers/BaseStringHelper.php b/framework/helpers/BaseStringHelper.php index e9c5327b031..1dda22be7c8 100644 --- a/framework/helpers/BaseStringHelper.php +++ b/framework/helpers/BaseStringHelper.php @@ -527,4 +527,32 @@ public static function mask($string, $start, $length, $mask = '*') { return $masked; } + + /** + * Returns the portion of the string that lies between the first occurrence of the start string + * and the last occurrence of the end string after that. + * + * @param string $string The input string. + * @param string $start The string marking the start of the portion to extract. + * @param string $end The string marking the end of the portion to extract. + * @return string The portion of the string between the first occurrence of start and the last occurrence of end. + */ + public static function findBetween($string, $start, $end) + { + $startPos = mb_strpos($string, $start); + + if ($startPos === false) { + return ''; + } + + // Cut the string from the start position + $subString = mb_substr($string, $startPos + mb_strlen($start)); + $endPos = mb_strrpos($subString, $end); + + if ($endPos === false) { + return ''; + } + + return mb_substr($subString, 0, $endPos); + } } diff --git a/tests/framework/helpers/StringHelperTest.php b/tests/framework/helpers/StringHelperTest.php index a640e5cdda2..ff6298eacf8 100644 --- a/tests/framework/helpers/StringHelperTest.php +++ b/tests/framework/helpers/StringHelperTest.php @@ -506,4 +506,30 @@ public function testMask() $this->assertSame('em**l@email.com', StringHelper::mask('email@email.com', 2, 2)); $this->assertSame('******email.com', StringHelper::mask('email@email.com', 0, 6)); } + + /** + * @param string $string + * @param string $start + * @param string $end + * @param string $expectedResult + * @dataProvider dataProviderFindBetween + */ + public function testFindBetween($string, $start, $end, $expectedResult) + { + $this->assertSame($expectedResult, StringHelper::findBetween($string, $start, $end)); + } + + public function dataProviderFindBetween() + { + return [ + ['hello world hello', 'hello ', ' world', ''], // end before start + ['This is a sample string', 'is ', ' string', 'is a sample'], // normal case + ['startendstart', 'start', 'end', ''], // end before start + ['startmiddleend', 'start', 'end', 'middle'], // normal case + ['startend', 'start', 'end', ''], // end immediately follows start + ['multiple start start end end', 'start ', ' end', 'start end'], // multiple starts and ends + ['', 'start', 'end', ''], // empty string + ['no delimiters here', 'start', 'end', ''], // no start and end + ]; + } } From 26032ad686f140b019cb7abfe25ca3c88d1648a2 Mon Sep 17 00:00:00 2001 From: salehhashemi1992 <81674631+salehhashemi1992@users.noreply.github.com> Date: Sat, 28 Oct 2023 22:19:51 +0330 Subject: [PATCH 2/3] refactor findBetween method and add other tests --- framework/CHANGELOG.md | 1 + framework/helpers/BaseStringHelper.php | 7 ++++--- tests/framework/helpers/StringHelperTest.php | 12 ++++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index a80668a4524..206da6ab1ae 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -14,6 +14,7 @@ Yii Framework 2 Change Log - Enh #20030: Improve performance of handling `ErrorHandler::$memoryReserveSize` (antonshevelev, rob006) - Enh #20042: Add empty array check to `ActiveQueryTrait::findWith()` (renkas) - Enh #20032: Added `mask` method for string masking with multibyte support (salehhashemi1992) +- Enh #20034: Added `findBetween` to retrieve a substring that lies between two strings (salehhashemi1992) 2.0.49.2 October 12, 2023 diff --git a/framework/helpers/BaseStringHelper.php b/framework/helpers/BaseStringHelper.php index 1dda22be7c8..21a1f9e6432 100644 --- a/framework/helpers/BaseStringHelper.php +++ b/framework/helpers/BaseStringHelper.php @@ -535,14 +535,15 @@ public static function mask($string, $start, $length, $mask = '*') { * @param string $string The input string. * @param string $start The string marking the start of the portion to extract. * @param string $end The string marking the end of the portion to extract. - * @return string The portion of the string between the first occurrence of start and the last occurrence of end. + * @return string|null The portion of the string between the first occurrence of + * start and the last occurrence of end, or null if either start or end cannot be found. */ public static function findBetween($string, $start, $end) { $startPos = mb_strpos($string, $start); if ($startPos === false) { - return ''; + return null; } // Cut the string from the start position @@ -550,7 +551,7 @@ public static function findBetween($string, $start, $end) $endPos = mb_strrpos($subString, $end); if ($endPos === false) { - return ''; + return null; } return mb_substr($subString, 0, $endPos); diff --git a/tests/framework/helpers/StringHelperTest.php b/tests/framework/helpers/StringHelperTest.php index ff6298eacf8..94efbf67137 100644 --- a/tests/framework/helpers/StringHelperTest.php +++ b/tests/framework/helpers/StringHelperTest.php @@ -522,14 +522,18 @@ public function testFindBetween($string, $start, $end, $expectedResult) public function dataProviderFindBetween() { return [ - ['hello world hello', 'hello ', ' world', ''], // end before start - ['This is a sample string', 'is ', ' string', 'is a sample'], // normal case + ['hello world hello', ' hello', ' world', null], // end before start + ['This is a sample string', ' is ', ' string', 'a sample'], // normal case ['startendstart', 'start', 'end', ''], // end before start ['startmiddleend', 'start', 'end', 'middle'], // normal case ['startend', 'start', 'end', ''], // end immediately follows start ['multiple start start end end', 'start ', ' end', 'start end'], // multiple starts and ends - ['', 'start', 'end', ''], // empty string - ['no delimiters here', 'start', 'end', ''], // no start and end + ['', 'start', 'end', null], // empty string + ['no delimiters here', 'start', 'end', null], // no start and end + ['start only', 'start', 'end', null], // start found but no end + ['end only', 'start', 'end', null], // end found but no start + ['spécial !@#$%^&*()', 'spé', '&*()', 'cial !@#$%^'], // Special characters + ['من صالح هاشمی هستم', 'من ', ' هستم', 'صالح هاشمی'], // other languages ]; } } From 3d4e108a3e0ac6393f34159e9255748545238ec3 Mon Sep 17 00:00:00 2001 From: Bizley Date: Mon, 30 Oct 2023 12:18:25 +0100 Subject: [PATCH 3/3] Update CHANGELOG.md --- framework/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 206da6ab1ae..e2c67473595 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -13,8 +13,8 @@ Yii Framework 2 Change Log - Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) - Enh #20030: Improve performance of handling `ErrorHandler::$memoryReserveSize` (antonshevelev, rob006) - Enh #20042: Add empty array check to `ActiveQueryTrait::findWith()` (renkas) -- Enh #20032: Added `mask` method for string masking with multibyte support (salehhashemi1992) -- Enh #20034: Added `findBetween` to retrieve a substring that lies between two strings (salehhashemi1992) +- Enh #20032: Added `yii\helpers\BaseStringHelper::mask()` method for string masking with multibyte support (salehhashemi1992) +- Enh #20034: Added `yii\helpers\BaseStringHelper::findBetween()` to retrieve a substring that lies between two strings (salehhashemi1992) 2.0.49.2 October 12, 2023