From 8dc471f98d9e813564da92de886f45cadf04de20 Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 26 Mar 2024 10:27:37 +0000 Subject: [PATCH 1/2] Add an IsArray Validator In order to provide a fix for https://github.com/laminas/laminas-inputfilter/issues/104 a standard validator is required for injection into the validator chain when validating array inputs. Signed-off-by: George Steel --- docs/book/set.md | 1 + docs/book/validators/is-array.md | 14 ++++++++ mkdocs.yml | 1 + src/IsArray.php | 37 +++++++++++++++++++++ src/ValidatorPluginManager.php | 2 ++ test/IsArrayTest.php | 55 ++++++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+) create mode 100644 docs/book/validators/is-array.md create mode 100644 src/IsArray.php create mode 100644 test/IsArrayTest.php diff --git a/docs/book/set.md b/docs/book/set.md index e46ddadb2..7a11046ac 100644 --- a/docs/book/set.md +++ b/docs/book/set.md @@ -20,6 +20,7 @@ The following validators come with the laminas-validator distribution. - [Identical](validators/identical.md) - [InArray](validators/in-array.md) - [Ip](validators/ip.md) +- [IsArray](validators/is-array.md) - [Isbn](validators/isbn.md) - [IsCountable](validators/is-countable.md) - [IsInstanceOf](validators/isinstanceof.md) diff --git a/docs/book/validators/is-array.md b/docs/book/validators/is-array.md new file mode 100644 index 000000000..165060be8 --- /dev/null +++ b/docs/book/validators/is-array.md @@ -0,0 +1,14 @@ +# IsArray Validator + +- **Since 2.52.0** + +`Laminas\Validator\IsArray` checks that a given value is an array. There are no options. + +## Example Usage + +```php +$validator = new Laminas\Validator\IsArray(); + +$validator->isValid('Not an Array'); // false +$validator->isValid(['Any Array']); // true +``` diff --git a/mkdocs.yml b/mkdocs.yml index cbdcb4587..d1806a1b1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,6 +28,7 @@ nav: - Identical: validators/identical.md - InArray: validators/in-array.md - Ip: validators/ip.md + - IsArray: validators/is-array.md - Isbn: validators/isbn.md - IsCountable: validators/is-countable.md - IsInstanceOf: validators/isinstanceof.md diff --git a/src/IsArray.php b/src/IsArray.php new file mode 100644 index 000000000..d47bf1a09 --- /dev/null +++ b/src/IsArray.php @@ -0,0 +1,37 @@ + */ + protected $messageTemplates = [ + self::NOT_ARRAY => 'Expected an array value but %type% provided', + ]; + + /** @var array */ + protected $messageVariables = [ + 'type' => 'type', + ]; + + protected ?string $type = null; + + public function isValid(mixed $value): bool + { + if (is_array($value)) { + return true; + } + + $this->type = get_debug_type($value); + $this->error(self::NOT_ARRAY); + + return false; + } +} diff --git a/src/ValidatorPluginManager.php b/src/ValidatorPluginManager.php index 23ad705e5..f4db1d800 100644 --- a/src/ValidatorPluginManager.php +++ b/src/ValidatorPluginManager.php @@ -147,6 +147,7 @@ class ValidatorPluginManager extends AbstractPluginManager 'Int' => I18nValidator\IsInt::class, 'ip' => Ip::class, 'Ip' => Ip::class, + 'IsArray' => IsArray::class, 'isbn' => Isbn::class, 'Isbn' => Isbn::class, 'isCountable' => IsCountable::class, @@ -378,6 +379,7 @@ class ValidatorPluginManager extends AbstractPluginManager InArray::class => InvokableFactory::class, I18nValidator\IsInt::class => InvokableFactory::class, Ip::class => InvokableFactory::class, + IsArray::class => InvokableFactory::class, Isbn::class => InvokableFactory::class, IsCountable::class => InvokableFactory::class, IsInstanceOf::class => InvokableFactory::class, diff --git a/test/IsArrayTest.php b/test/IsArrayTest.php new file mode 100644 index 000000000..194cc7416 --- /dev/null +++ b/test/IsArrayTest.php @@ -0,0 +1,55 @@ + */ + public static function invalidValueProvider(): array + { + return [ + 'String' => ['foo'], + 'Integer' => [123], + 'Float' => [4.2], + 'Object' => [(object) ['foo' => 'bar']], + 'Boolean' => [true], + 'Null' => [null], + ]; + } + + #[DataProvider('invalidValueProvider')] + public function testInvalidValuesAreDeemedInvalid(mixed $input): void + { + $validator = new IsArray(); + self::assertFalse($validator->isValid($input)); + } + + public function testThatAnArrayIsConsideredValid(): void + { + self::assertTrue( + (new IsArray())->isValid(['whatever']), + ); + } + + public function testThatTheInvalidTypeIsPresentInTheErrorMessage(): void + { + $validator = new IsArray(); + self::assertFalse($validator->isValid('Foo')); + $messages = $validator->getMessages(); + + self::assertArrayHasKey(IsArray::NOT_ARRAY, $messages); + + self::assertEquals( + 'Expected an array value but string provided', + $messages[IsArray::NOT_ARRAY] + ); + } +} From ed51b4d227d6bd1bfc373fbb1e0dbd05a1eb3852 Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 26 Mar 2024 10:52:56 +0000 Subject: [PATCH 2/2] Minor SA fixes Signed-off-by: George Steel --- psalm-baseline.xml | 7 ++++++- src/IsArray.php | 3 +++ test/Db/TestAsset/ConcreteDbValidator.php | 9 ++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index ee152bd0e..3c177b470 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -22,6 +22,7 @@ + @@ -81,7 +82,6 @@ options]]> options]]> options]]> - options]]> @@ -2654,6 +2654,11 @@ + + + + + diff --git a/src/IsArray.php b/src/IsArray.php index d47bf1a09..cba75f2fd 100644 --- a/src/IsArray.php +++ b/src/IsArray.php @@ -23,6 +23,9 @@ final class IsArray extends AbstractValidator protected ?string $type = null; + /** @var array */ + protected $options = []; + public function isValid(mixed $value): bool { if (is_array($value)) { diff --git a/test/Db/TestAsset/ConcreteDbValidator.php b/test/Db/TestAsset/ConcreteDbValidator.php index f4ee203af..a449ed9a5 100644 --- a/test/Db/TestAsset/ConcreteDbValidator.php +++ b/test/Db/TestAsset/ConcreteDbValidator.php @@ -17,11 +17,10 @@ final class ConcreteDbValidator extends AbstractDb 'barMessage' => '%value% was wrong', ]; - /** - * @param mixed $value - * @return bool - */ - public function isValid($value) + /** @var array */ + protected $options = []; + + public function isValid(mixed $value): bool { $this->setValue($value); $this->error(self::FOO_MESSAGE);