From 59e9413b2012464129c8ab3cb52fd46effbf3b9b Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 3 Sep 2024 21:42:07 +0100 Subject: [PATCH] Refactor `Digits` Filter - Remove inheritance and implement `FilterInterface` directly - Remove checks for Unicode support in PCRE - Refactor test case with additional tests Signed-off-by: George Steel --- psalm-baseline.xml | 2 +- src/Digits.php | 27 ++++------ test/DigitsTest.php | 121 ++++++++++++++++++-------------------------- 3 files changed, 59 insertions(+), 91 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 346531e3..b25ab331 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -763,7 +763,7 @@ - + diff --git a/src/Digits.php b/src/Digits.php index 9671efa9..e7ea7daa 100644 --- a/src/Digits.php +++ b/src/Digits.php @@ -4,45 +4,36 @@ namespace Laminas\Filter; -use Laminas\Stdlib\StringUtils; - use function is_float; use function is_int; use function is_string; use function preg_replace; -/** - * @psalm-type Options = array{} - * @extends AbstractFilter - */ -final class Digits extends AbstractFilter +/** @implements FilterInterface */ +final class Digits implements FilterInterface { /** - * Defined by Laminas\Filter\FilterInterface - * * Returns the string $value, removing all but digit characters * * If the value provided is not integer, float or string, the value will remain unfiltered * - * @psalm-return ($value is int|float|string ? numeric-string : mixed) + * @inheritDoc */ public function filter(mixed $value): mixed { if (is_int($value)) { return (string) $value; } + if (! is_float($value) && ! is_string($value)) { return $value; } - $value = (string) $value; - if (! StringUtils::hasPcreUnicodeSupport()) { - // POSIX named classes are not supported, use alternative 0-9 match - $pattern = '/[^0-9]/'; - } else { - $pattern = '/[^[:digit:]]/'; - } + return preg_replace('/[^[:digit:]]/', '', (string) $value); + } - return preg_replace($pattern, '', $value); + public function __invoke(mixed $value): mixed + { + return $this->filter($value); } } diff --git a/test/DigitsTest.php b/test/DigitsTest.php index 5ef791a0..11863a5b 100644 --- a/test/DigitsTest.php +++ b/test/DigitsTest.php @@ -7,92 +7,69 @@ use Laminas\Filter\Digits as DigitsFilter; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use stdClass; -use function preg_match; +use function get_debug_type; +use function sprintf; -class DigitsTest extends TestCase -{ - /** - * Is PCRE is compiled with UTF-8 and Unicode support - **/ - private bool $unicodeEnabled; +use const PHP_INT_MAX; - /** - * Creates a new Laminas_Filter_Digits object for each test method - */ - public function setUp(): void +final class DigitsTest extends TestCase +{ + /** @return array */ + public static function basicDataProvider(): array { - $this->unicodeEnabled = (bool) @preg_match('/\pL/u', 'a'); + $object = (object) ['foo']; + + return [ + 'Mixed Unicode Numerics' => ['192八3四8', '123'], + 'Unicode String with Numbers' => ['C 4.5B 6', '456'], + 'Unicode String with Numbers 2' => ['9壱8@7.6,5#4', '987654'], + 'Numeric String' => ['789', '789'], + 'ASCII Alnum 1' => ['abc123', '123'], + 'ASCII Alnum 2' => ['abc 123', '123'], + 'ASCII Alnum 3' => ['AZ@#4.3', '43'], + 'No Numbers' => ['abcxyz', ''], + 'Float String' => ['1.23', '123'], + 'Hex String' => ['0x9f', '09'], + 'Hex Int' => [0xff, '255'], + 'Boolean' => [true, true], + 'Null' => [null, null], + 'Array' => [['foo'], ['foo']], + 'Object' => [$object, $object], + 'Small Integer' => [123, '123'], + 'Big Integer' => [PHP_INT_MAX, (string) PHP_INT_MAX], + 'Float' => [3.141592653, '3141592653'], + ]; } - /** - * Ensures that the filter follows expected behavior - */ - public function testBasic(): void + #[DataProvider('basicDataProvider')] + public function testBasic(mixed $input, mixed $expect): void { $filter = new DigitsFilter(); - if ($this->unicodeEnabled) { - // Filter for the value with mbstring - /** - * The first element of $valuesExpected contains multibyte digit characters. - * But , Laminas_Filter_Digits is expected to return only singlebyte digits. - * - * The second contains multibyte or singebyte space, and also alphabet. - * The third contains various multibyte characters. - * The last contains only singlebyte digits. - */ - $valuesExpected = [ - '192八3四8' => '123', - 'C 4.5B 6' => '456', - '9壱8@7.6,5#4' => '987654', - '789' => '789', - ]; - } else { - // POSIX named classes are not supported, use alternative 0-9 match - // Or filter for the value without mbstring - $valuesExpected = [ - 'abc123' => '123', - 'abc 123' => '123', - 'abcxyz' => '', - 'AZ@#4.3' => '43', - '1.23' => '123', - '0x9f' => '09', - ]; - } + /** @psalm-var mixed $result */ + $result = $filter->filter($input); - foreach ($valuesExpected as $input => $output) { - self::assertSame( - $output, - $result = $filter($input), - "Expected '$input' to filter to '$output', but received '$result' instead" - ); - } - } - - /** @return list */ - public static function returnUnfilteredDataProvider(): array - { - return [ - [null], - [new stdClass()], - [ - [ - 'abc123', - 'abc 123', - ], - ], - [true], - [false], - ]; + self::assertSame( + $expect, + $result, + sprintf( + 'Expected "%s" to filter to "%s", but received "%s" instead', + get_debug_type($input), + get_debug_type($expect), + get_debug_type($result), + ), + ); } - #[DataProvider('returnUnfilteredDataProvider')] - public function testReturnUnfiltered(mixed $input): void + #[DataProvider('basicDataProvider')] + public function testInvokeProxiesToFilter(mixed $input): void { $filter = new DigitsFilter(); - self::assertSame($input, $filter($input)); + self::assertSame( + $filter->filter($input), + $filter->__invoke($input), + ); } }