Skip to content

Commit 4618996

Browse files
committed
Fix factory when validator has no constructor
This change introduces a less misleading exception when trying to construct an instance and failing due to mismatched arguments coming from ReflectionExceptions.
1 parent d2198df commit 4618996

3 files changed

Lines changed: 54 additions & 2 deletions

File tree

library/NamespacedValidatorFactory.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Respect\Validation\Transformers\ValidatorSpec;
1818

1919
use function array_merge;
20+
use function Respect\Stringifier\stringify;
2021
use function sprintf;
2122
use function trim;
2223
use function ucfirst;
@@ -57,6 +58,8 @@ private function createValidatorSpec(ValidatorSpec $validatorSpec): Validator
5758
/** @param array<int, mixed> $arguments */
5859
private function createRule(string $ruleName, array $arguments = []): Validator
5960
{
61+
$reflection = null;
62+
6063
foreach ($this->rulesNamespaces as $namespace) {
6164
try {
6265
/** @var class-string<Validator> $name */
@@ -72,12 +75,22 @@ private function createRule(string $ruleName, array $arguments = []): Validator
7275
throw new InvalidClassException(sprintf('"%s" must be instantiable', $name));
7376
}
7477

75-
return $reflection->newInstanceArgs($arguments);
78+
break;
7679
} catch (ReflectionException) {
7780
continue;
7881
}
7982
}
8083

81-
throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
84+
if (!$reflection) {
85+
throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
86+
}
87+
88+
try {
89+
return $reflection->newInstanceArgs($arguments);
90+
} catch (ReflectionException) {
91+
throw new InvalidClassException(
92+
sprintf('"%s" could not be instantiated with arguments %s', $ruleName, stringify($arguments)),
93+
);
94+
}
8295
}
8396
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
5+
* SPDX-License-Identifier: MIT
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Respect\Validation\Test\Validators;
11+
12+
use Respect\Validation\Message\Template;
13+
use Respect\Validation\Validators\Core\Simple;
14+
15+
#[Template(
16+
'{{subject}} must be a no-constructor validator',
17+
'{{subject}} must not be a no-constructor validator',
18+
)]
19+
final class NoConstructor extends Simple
20+
{
21+
public function isValid(mixed $input): bool
22+
{
23+
// Accept everything for test purposes
24+
return true;
25+
}
26+
}

tests/unit/NamespacedRuleFactoryTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ public function shouldDefineConstructorArgumentsWhenCreatingRule(): void
5959
self::assertSame($constructorArguments, $validator->validations);
6060
}
6161

62+
#[Test]
63+
public function shouldThrowsAnExceptionOnConstructorReflectionFailure(): void
64+
{
65+
$constructorArguments = ['a', 'b'];
66+
67+
$factory = new NamespacedValidatorFactory(new StubTransformer(), [self::TEST_RULES_NAMESPACE]);
68+
69+
$this->expectException(InvalidClassException::class);
70+
$this->expectExceptionMessage('"noConstructor" could not be instantiated with arguments `["a", "b"]`');
71+
72+
$factory->create('noConstructor', $constructorArguments);
73+
}
74+
6275
#[Test]
6376
public function shouldThrowsAnExceptionWhenRuleIsInvalid(): void
6477
{

0 commit comments

Comments
 (0)