From 8d7d783698cb1c41dc9a35c919413c586f14b745 Mon Sep 17 00:00:00 2001 From: Alan Taylor Date: Fri, 17 Feb 2023 23:58:23 +0900 Subject: [PATCH] Check if property is initialized before getting its value This commit also removed the use of "setAccessible", since it's not neccessary after PHP 8.1. Co-authored-by: Henrique Moody --- CHANGELOG.md | 1 + library/Rules/Attribute.php | 6 ++++-- tests/library/Stubs/WithUninitialized.php | 17 +++++++++++++++++ tests/unit/Rules/AttributeTest.php | 9 +++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/library/Stubs/WithUninitialized.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 607de5399..2401151f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Fixes: - `KeySet` now reports which extra keys are causing the rule to fail. - Ensure empty strings are never a valid currency code - Do not hide messages on EachException + - Dot not throw exception when validating an uninitialized property Changes: diff --git a/library/Rules/Attribute.php b/library/Rules/Attribute.php index e1873f13a..05518277b 100644 --- a/library/Rules/Attribute.php +++ b/library/Rules/Attribute.php @@ -17,7 +17,7 @@ use function property_exists; /** - * Validates an object attribute, event private ones. + * Validates an object attribute, even private ones. * * @author Alexandre Gomes Gaigalas * @author Emmerson Siqueira @@ -38,7 +38,9 @@ public function __construct(string $reference, ?Validatable $rule = null, bool $ public function getReferenceValue($input) { $propertyMirror = new ReflectionProperty($input, (string) $this->getReference()); - $propertyMirror->setAccessible(true); + if ($propertyMirror->isInitialized($input) === false) { + return null; + } return $propertyMirror->getValue($input); } diff --git a/tests/library/Stubs/WithUninitialized.php b/tests/library/Stubs/WithUninitialized.php new file mode 100644 index 000000000..15ab30c1d --- /dev/null +++ b/tests/library/Stubs/WithUninitialized.php @@ -0,0 +1,17 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Test\Stubs; + +final class WithUninitialized +{ + public string $initialized = 'foo'; + + public string $uninitialized; +} diff --git a/tests/unit/Rules/AttributeTest.php b/tests/unit/Rules/AttributeTest.php index 8d4dd74ef..678d138df 100644 --- a/tests/unit/Rules/AttributeTest.php +++ b/tests/unit/Rules/AttributeTest.php @@ -11,6 +11,7 @@ use Respect\Validation\Test\RuleTestCase; use Respect\Validation\Test\Stubs\WithProperties; +use Respect\Validation\Test\Stubs\WithUninitialized; /** * @group rule @@ -47,6 +48,10 @@ public static function providerForValidInput(): array new Attribute('public', new AlwaysValid()), new WithProperties(), ], + 'attribute is present but uninitialized' => [ + new Attribute('uninitialized'), + new WithUninitialized(), + ], 'non mandatory attribute is not present' => [ new Attribute('nonexistent', null, false), new WithProperties(), @@ -55,6 +60,10 @@ public static function providerForValidInput(): array new Attribute('nonexistent', new AlwaysValid(), false), new WithProperties(), ], + 'attribute is present but uninitialized with extra validator' => [ + new Attribute('uninitialized', new AlwaysValid()), + new WithUninitialized(), + ], ]; }