diff --git a/library/NamespacedValidatorFactory.php b/library/NamespacedValidatorFactory.php index fdbda3f75..68b5a823d 100644 --- a/library/NamespacedValidatorFactory.php +++ b/library/NamespacedValidatorFactory.php @@ -17,6 +17,7 @@ use Respect\Validation\Transformers\ValidatorSpec; use function array_merge; +use function Respect\Stringifier\stringify; use function sprintf; use function trim; use function ucfirst; @@ -57,6 +58,8 @@ private function createValidatorSpec(ValidatorSpec $validatorSpec): Validator /** @param array $arguments */ private function createRule(string $ruleName, array $arguments = []): Validator { + $reflection = null; + foreach ($this->rulesNamespaces as $namespace) { try { /** @var class-string $name */ @@ -72,12 +75,22 @@ private function createRule(string $ruleName, array $arguments = []): Validator throw new InvalidClassException(sprintf('"%s" must be instantiable', $name)); } - return $reflection->newInstanceArgs($arguments); + break; } catch (ReflectionException) { continue; } } - throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName)); + if (!$reflection) { + throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName)); + } + + try { + return $reflection->newInstanceArgs($arguments); + } catch (ReflectionException) { + throw new InvalidClassException( + sprintf('"%s" could not be instantiated with arguments %s', $ruleName, stringify($arguments)), + ); + } } } diff --git a/tests/library/Validators/NoConstructor.php b/tests/library/Validators/NoConstructor.php new file mode 100644 index 000000000..329f208be --- /dev/null +++ b/tests/library/Validators/NoConstructor.php @@ -0,0 +1,26 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Test\Validators; + +use Respect\Validation\Message\Template; +use Respect\Validation\Validators\Core\Simple; + +#[Template( + '{{subject}} must be a no-constructor validator', + '{{subject}} must not be a no-constructor validator', +)] +final class NoConstructor extends Simple +{ + public function isValid(mixed $input): bool + { + // Accept everything for test purposes + return true; + } +} diff --git a/tests/unit/NamespacedRuleFactoryTest.php b/tests/unit/NamespacedRuleFactoryTest.php index ab996495d..270c8e5b1 100644 --- a/tests/unit/NamespacedRuleFactoryTest.php +++ b/tests/unit/NamespacedRuleFactoryTest.php @@ -59,6 +59,19 @@ public function shouldDefineConstructorArgumentsWhenCreatingRule(): void self::assertSame($constructorArguments, $validator->validations); } + #[Test] + public function shouldThrowsAnExceptionOnConstructorReflectionFailure(): void + { + $constructorArguments = ['a', 'b']; + + $factory = new NamespacedValidatorFactory(new StubTransformer(), [self::TEST_RULES_NAMESPACE]); + + $this->expectException(InvalidClassException::class); + $this->expectExceptionMessage('"noConstructor" could not be instantiated with arguments `["a", "b"]`'); + + $factory->create('noConstructor', $constructorArguments); + } + #[Test] public function shouldThrowsAnExceptionWhenRuleIsInvalid(): void {