diff --git a/docs/02-feature-guide.md b/docs/02-feature-guide.md index 4c6184d3..646fbcee 100644 --- a/docs/02-feature-guide.md +++ b/docs/02-feature-guide.md @@ -199,15 +199,13 @@ method as well by passing the templates as an argument: ```php try { - $usernameValidator->assert('really messed up screen#name'); + $usernameValidator->assert('really messed up screen#name', [ + 'alnum' => '{{name}} must contain only letters and digits', + 'noWhitespace' => '{{name}} cannot contain spaces', + 'length' => '{{name}} must not have more than 15 chars', + ]); } catch(NestedValidationException $exception) { - print_r( - $exception->getMessages([ - 'alnum' => '{{name}} must contain only letters and digits', - 'noWhitespace' => '{{name}} cannot contain spaces', - 'length' => '{{name}} must not have more than 15 chars', - ]) - ); + print_r($exception->getMessages()); } ``` diff --git a/library/Validator.php b/library/Validator.php index f96fb8ae..9b33bfb8 100644 --- a/library/Validator.php +++ b/library/Validator.php @@ -16,15 +16,17 @@ use Respect\Validation\Message\StandardFormatter; use Respect\Validation\Message\StandardRenderer; use Respect\Validation\Mixins\StaticValidator; use Respect\Validation\Rules\AllOf; -use Respect\Validation\Rules\Core\Standard; +use Throwable; use function count; use function current; +use function is_array; +use function is_string; /** * @mixin StaticValidator */ -final class Validator extends Standard +final class Validator implements Validatable { use CanBindEvaluateRule; @@ -34,6 +36,10 @@ final class Validator extends Standard /** @var array */ private array $templates = []; + private ?string $name = null; + + private ?string $template = null; + public function __construct( private readonly Factory $factory, private readonly Formatter $formatter, @@ -66,15 +72,24 @@ final class Validator extends Standard return $this->evaluate($input)->isValid; } - public function assert(mixed $input): void + /** @param array|string|Throwable|null $template */ + public function assert(mixed $input, array|string|Throwable|null $template = null): void { $result = $this->evaluate($input); if ($result->isValid) { return; } + if ($template instanceof Throwable) { + throw $template; + } + $templates = $this->templates; - if (count($templates) === 0 && $this->getTemplate() != null) { + if (is_array($template)) { + $templates = $template; + } elseif (is_string($template)) { + $templates = ['__root__' => $template]; + } elseif ($this->getTemplate() != null) { $templates = ['__root__' => $this->getTemplate()]; } @@ -115,6 +130,30 @@ final class Validator extends Standard $this->assert($input); } + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } + + public function getTemplate(): ?string + { + return $this->template; + } + + public function setTemplate(string $template): static + { + $this->template = $template; + + return $this; + } + private function rule(): Validatable { if (count($this->rules) === 1) { diff --git a/tests/integration/get_messages_with_replacements.phpt b/tests/integration/get_messages_with_replacements.phpt index 8352c6e9..cfd19849 100644 --- a/tests/integration/get_messages_with_replacements.phpt +++ b/tests/integration/get_messages_with_replacements.phpt @@ -26,25 +26,27 @@ exceptionMessages( ->key('password', v::stringType()) ->key('schema', v::stringType()) ) - ->setTemplates([ - 'mysql' => [ - 'user' => 'Value should be a MySQL username', - 'host' => '`{{name}}` should be a MySQL host', + ->assert( + [ + 'mysql' => [ + 'host' => 42, + 'schema' => 42, + ], + 'postgresql' => [ + 'user' => 42, + 'password' => 42, + ], ], - 'postgresql' => [ - 'schema' => 'You must provide a valid PostgreSQL schema', - ], - ]) - ->assert([ - 'mysql' => [ - 'host' => 42, - 'schema' => 42, - ], - 'postgresql' => [ - 'user' => 42, - 'password' => 42, - ], - ]); + [ + 'mysql' => [ + 'user' => 'Value should be a MySQL username', + 'host' => '`{{name}}` should be a MySQL host', + ], + 'postgresql' => [ + 'schema' => 'You must provide a valid PostgreSQL schema', + ], + ] + ); } ); ?> diff --git a/tests/integration/lib/helpers.php b/tests/integration/lib/helpers.php index 624ca57e..2b993b44 100644 --- a/tests/integration/lib/helpers.php +++ b/tests/integration/lib/helpers.php @@ -51,19 +51,11 @@ function run(array $scenarios): void echo $description . PHP_EOL; echo str_repeat('⎺', strlen($description)) . PHP_EOL; - if (is_string($template)) { - $rule->setTemplate($template); - } - - if (is_array($template)) { - $rule->setTemplates($template); - } - $fallbackMessage = 'No exception was thrown with: ' . stringify($input); - exceptionMessage(static fn() => $rule->check($input), $fallbackMessage); - exceptionFullMessage(static fn() => $rule->assert($input), $fallbackMessage); - exceptionMessages(static fn() => $rule->assert($input), $fallbackMessage); + exceptionMessage(static fn() => $rule->assert($input, $template), $fallbackMessage); + exceptionFullMessage(static fn() => $rule->assert($input, $template), $fallbackMessage); + exceptionMessages(static fn() => $rule->assert($input, $template), $fallbackMessage); echo PHP_EOL; } } diff --git a/tests/integration/readme/custom_messages.phpt b/tests/integration/readme/custom_messages.phpt index 3b6f77f9..32f77b06 100644 --- a/tests/integration/readme/custom_messages.phpt +++ b/tests/integration/readme/custom_messages.phpt @@ -11,12 +11,11 @@ exceptionMessages( static fn() => v::alnum() ->noWhitespace() ->length(v::between(1, 15)) - ->setTemplates([ + ->assert('really messed up screen#name', [ 'alnum' => '{{name}} must contain only letters and digits', 'noWhitespace' => '{{name}} cannot contain spaces', 'length' => '{{name}} must not have more than 15 chars', ]) - ->assert('really messed up screen#name') ); ?> --EXPECT-- @@ -25,4 +24,4 @@ exceptionMessages( 'alnum' => '"really messed up screen#name" must contain only letters and digits', 'noWhitespace' => '"really messed up screen#name" cannot contain spaces', 'lengthBetween' => 'The length of "really messed up screen#name" must be between 1 and 15', -] \ No newline at end of file +] diff --git a/tests/unit/ValidatorTest.php b/tests/unit/ValidatorTest.php index fdab91d1..7ba76f56 100644 --- a/tests/unit/ValidatorTest.php +++ b/tests/unit/ValidatorTest.php @@ -9,7 +9,9 @@ declare(strict_types=1); namespace Respect\Validation; +use Exception; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Respect\Validation\Exceptions\ComponentException; use Respect\Validation\Test\Rules\Stub; @@ -49,4 +51,77 @@ final class ValidatorTest extends TestCase self::assertFalse($validator->isValid('whatever')); } + + #[Test] + public function itShouldAssertUsingTheGivingExceptionEvenWhenRuleAlreadyHasTemplate(): void + { + $template = new Exception('This is a test'); + + $this->expectExceptionObject($template); + + $validator = Validator::create(Stub::fail(1)); + $validator->setTemplate('This wont be used'); + $validator->assert('whatever', $template); + } + + #[Test] + public function itShouldAssertUsingTheGivingStringTemplate(): void + { + $template = 'This is my new template'; + + $this->expectExceptionMessage($template); + + $validator = Validator::create(Stub::fail(1)); + $validator->assert('whatever', $template); + } + + #[Test] + public function itShouldAssertUsingTheGivingArrayTemplateWithTheRuleNameAsKey(): void + { + $template = ['stub' => 'This is my new template']; + + $this->expectExceptionMessage($template['stub']); + + $validator = Validator::create(Stub::fail(1)); + $validator->setTemplates(['stub' => 'This is my pre-defined template']); + $validator->assert('whatever', $template); + } + + #[Test] + public function itShouldAssertUsingTheGivingArrayTemplateWithRootKey(): void + { + $template = ['__root__' => 'This is my new template']; + + $this->expectExceptionMessage($template['__root__']); + + $validator = Validator::create(Stub::fail(1)); + $validator->setTemplates(['__root__' => 'This is my pre-defined template']); + $validator->assert('whatever', $template); + } + + /** @param string|array $template */ + #[Test] + #[DataProvider('providerForTemplates')] + public function itShouldAssertNotOverwritingThePreDefinedTemplate(array|string $template): void + { + $preDefinedTemplate = 'This is my pre-defined template'; + + $this->expectExceptionMessage($preDefinedTemplate); + + $validator = Validator::create(Stub::fail(1)); + $validator->setTemplate($preDefinedTemplate); + $validator->assert('whatever', $template); + } + + /** + * @return array}> + */ + public static function providerForTemplates(): array + { + return [ + 'string' => ['This is my new template'], + 'array key named key' => [['stub' => 'This is my new template']], + 'array key __root__ key' => [['__root__' => 'This is my new template']], + ]; + } }