diff --git a/src/StringHelper.php b/src/StringHelper.php index afebcb2..3dde95f 100644 --- a/src/StringHelper.php +++ b/src/StringHelper.php @@ -619,6 +619,35 @@ public static function rtrim(string|array $string, string $pattern = self::DEFAU return preg_replace("#[$pattern]+$#uD", '', $string); } + /** + * 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|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 $string, string $start, string $end): ?string + { + $startPos = mb_strpos($string, $start); + + if ($startPos === false) { + return null; + } + + // Cut the string from the start position + $subString = mb_substr($string, $startPos + mb_strlen($start)); + $endPos = mb_strrpos($subString, $end); + + if ($endPos === false) { + return null; + } + + return mb_substr($subString, 0, $endPos); + } + /** * Ensure the input string is a valid UTF-8 string. * diff --git a/tests/StringHelperTest.php b/tests/StringHelperTest.php index 506fdb0..ea61e8d 100644 --- a/tests/StringHelperTest.php +++ b/tests/StringHelperTest.php @@ -763,4 +763,30 @@ public function testInvalidTrimPattern(): void StringHelper::trim('string', "\xC3\x28"); } + + /** + * @dataProvider dataProviderFindBetween + */ + public function testFindBetween(string $string, string $start, string $end, string $expectedResult): void + { + $this->assertSame($expectedResult, StringHelper::findBetween($string, $start, $end)); + } + + public function dataProviderFindBetween(): array + { + return [ + ['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', 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 + ]; + } }