diff --git a/README.md b/README.md index f1bb5d7..dd7410b 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,11 @@ with the value first in order to work with the `Filterer`. It also defaults to $value = \TraderInteractive\Filter\Strings::explode('abc,def,ghi'); assert($value === ['abc', 'def', 'ghi']); ``` - +This filter can also be given padding settings to ensure the result has a specific number of elements. For example: +```php +$value = Strings::explode('a-b-c', '-', 5, null, Strings::EXPLODE_PAD_FRONT); +assert($value === [null, null, 'a', 'b', 'c']); +``` #### Strings::compress This filter trims and remove superfluous whitespace from a given string. ```php diff --git a/src/Filter/Strings.php b/src/Filter/Strings.php index 3f3c345..f2f8d53 100644 --- a/src/Filter/Strings.php +++ b/src/Filter/Strings.php @@ -2,6 +2,7 @@ namespace TraderInteractive\Filter; +use InvalidArgumentException; use TraderInteractive\Exceptions\FilterException; use TypeError; @@ -10,6 +11,16 @@ */ final class Strings { + /** + * @var string + */ + const EXPLODE_PAD_FRONT = 'front'; + + /** + * @var string + */ + const EXPLODE_PAD_END = 'end'; + /** * Filter a string. * @@ -52,14 +63,23 @@ public static function filter( * * For example, given the string 'foo,bar,baz', this would return the array ['foo', 'bar', 'baz']. * - * @param string $value The string to explode. - * @param string $delimiter The non-empty delimiter to explode on. + * @param string $value The string to explode. + * @param string $delimiter The non-empty delimiter to explode on. + * @param int|null $padLength The number of elements to be returned in the result. + * @param mixed $padValue The value to use when padding the resulting array. + * @param string $padType Argument to specify if the resulting array should be padded on the left or right. + * * @return array The exploded values. * * @throws \InvalidArgumentException if the delimiter does not pass validation. */ - public static function explode($value, string $delimiter = ',') - { + public static function explode( + $value, + string $delimiter = ',', + int $padLength = null, + $padValue = null, + string $padType = self::EXPLODE_PAD_END + ) : array { self::validateIfObjectIsAString($value); if (empty($delimiter)) { @@ -68,7 +88,25 @@ public static function explode($value, string $delimiter = ',') ); } - return explode($delimiter, $value); + if ($padType !== self::EXPLODE_PAD_FRONT && $padType !== self::EXPLODE_PAD_END) { + throw new InvalidArgumentException('Invalid $padType value provided'); + } + + $values = explode($delimiter, $value); + $valueCount = count($values); + $padLength = $padLength ?? $valueCount; + if ($padLength <= $valueCount) { + return $values; + } + + $padding = array_fill(0, $padLength - $valueCount, $padValue); + if ($padType === self::EXPLODE_PAD_END) { + array_push($values, ...$padding); + return $values; + } + + array_unshift($values, ...$padding); + return $values; } /** diff --git a/tests/Filter/StringsTest.php b/tests/Filter/StringsTest.php index 871298c..276c4e9 100644 --- a/tests/Filter/StringsTest.php +++ b/tests/Filter/StringsTest.php @@ -224,25 +224,72 @@ public function translateValueNotFoundInMap() } /** - * Verifies basic explode functionality. + * @param string $value The value to be filtered. + * @param array $expectedResult The expected filter result. + * @param string $delimiter The delimiter to use. + * @param int|null $padLength The array length of the result. + * @param mixed $padValue The value to use when padding. + * @param string $padType The direction to pad the resulting array. * * @test * @covers ::explode + * @dataProvider provideExplodeData */ - public function explode() + public function explode( + string $value, + array $expectedResult, + string $delimiter = ',', + int $padLength = null, + $padValue = null, + string $padType = Strings::EXPLODE_PAD_END + ) { + $actualResult = Strings::explode($value, $delimiter, $padLength, $padValue, $padType); + $this->assertSame($expectedResult, $actualResult); + } + + /** + * @return array + */ + public function provideExplodeData() : array { - $this->assertSame(['a', 'bcd', 'e'], Strings::explode('a,bcd,e')); + return [ + [ + 'value' => 'a,bcd,e', + 'result' => ['a', 'bcd', 'e'], + ], + [ + 'value' => 'a b c d,e', + 'result' => ['a', 'b', 'c', 'd,e'], + 'delimiter' => ' ', + ], + [ + 'value' => 'a-b-c', + 'result' => ['a', 'b', 'c', null, null], + 'delimiter' => '-', + 'padLength' => 5, + 'padValue' => null, + 'padType' => Strings::EXPLODE_PAD_END, + ], + [ + 'value' => 'a-b-c', + 'result' => [null, null, 'a', 'b', 'c'], + 'delimiter' => '-', + 'padLength' => 5, + 'padValue' => null, + 'padType' => Strings::EXPLODE_PAD_FRONT, + ], + ]; } /** - * Verifies explode with a custom delimiter. - * * @test * @covers ::explode */ - public function explodeCustomDelimiter() + public function explodeWithInvalidPadType() { - $this->assertSame(['a', 'b', 'c', 'd,e'], Strings::explode('a b c d,e', ' ')); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid $padType value provided'); + Strings::explode('a,b,c', ',', 4, null, 'invalid'); } /**