From 1a2c52079f751dd3fc04d5db4633076324e9169f Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Mon, 5 Jan 2026 10:34:16 +0100 Subject: [PATCH] Rename `Validator` to `ValidatorBuilder` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `Validator` class implements the Builder patterns, because it builds a complex validator within a chain. This is a major breaking change, as the `Validator` class is the foundation of the library. However, that’s something relatively easy to replace everywhere. --- aliases.php | 4 +-- bin/create-mixin | 4 +-- docs/02-feature-guide.md | 6 ++-- docs/03-handling-exceptions.md | 10 +++---- docs/06-concrete-api.md | 12 ++++---- library/ContainerRegistry.php | 4 +-- library/Mixins/Chain.php | 4 +-- library/Rules/KeySet.php | 4 +-- .../{Validator.php => ValidatorBuilder.php} | 2 +- ...lidationExceptionInterfaceForCheckTest.php | 4 +-- ...cludeAllValidationMessagesInAChainTest.php | 4 +-- tests/feature/Issues/Issue1289Test.php | 6 ++-- tests/feature/NotWithoutRecursionTest.php | 4 +-- ...torsShouldUseTemplateAsMainMessageTest.php | 4 +-- ...atorShouldUseTemplateAsMainMessageTest.php | 4 +-- tests/library/Stubs/MyValidator.php | 4 +-- tests/unit/ContainerRegistryTest.php | 2 +- tests/unit/ValidatorTest.php | 30 +++++++++---------- 18 files changed, 56 insertions(+), 56 deletions(-) rename library/{Validator.php => ValidatorBuilder.php} (98%) diff --git a/aliases.php b/aliases.php index 0cae8d89..cb3aba1f 100644 --- a/aliases.php +++ b/aliases.php @@ -7,8 +7,8 @@ declare(strict_types=1); -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; if (!class_exists('v')) { - class_alias(Validator::class, 'v'); + class_alias(ValidatorBuilder::class, 'v'); } diff --git a/bin/create-mixin b/bin/create-mixin index 77638764..2b689a4d 100755 --- a/bin/create-mixin +++ b/bin/create-mixin @@ -28,7 +28,7 @@ use Respect\Validation\Mixins\PropertyChain; use Respect\Validation\Mixins\UndefOrBuilder; use Respect\Validation\Mixins\UndefOrChain; use Respect\Validation\Rule; -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; function addMethodToInterface( string $originalName, @@ -219,7 +219,7 @@ function overwriteFile(string $content, string $basename): void $chainedInterface->addExtend(NullOrChain::class); $chainedInterface->addExtend(PropertyChain::class); $chainedInterface->addExtend(UndefOrChain::class); - $chainedInterface->addComment('@mixin \\' . Validator::class); + $chainedInterface->addComment('@mixin \\' . ValidatorBuilder::class); $staticInterface->addExtend(AllBuilder::class); $staticInterface->addExtend(KeyBuilder::class); diff --git a/docs/02-feature-guide.md b/docs/02-feature-guide.md index cbe799f8..958fbab3 100644 --- a/docs/02-feature-guide.md +++ b/docs/02-feature-guide.md @@ -1,8 +1,8 @@ # Feature Guide -The `Validator` class is the core of Respect\Validation, offering a fluent interface for building validation rules. +The `ValidatorBuilder` class is the core of Respect\Validation, offering a fluent interface for building validation rules. -For convenience, the `Validator` class is aliased as `v`. This means you can write `v::intType()` instead of `\Respect\Validation\Validator::intType()`. +For convenience, the `ValidatorBuilder` class is aliased as `v`. This means you can write `v::intType()` instead of `\Respect\Validation\ValidatorBuilder::intType()`. ## Validating using booleans @@ -76,7 +76,7 @@ v::alnum()->assert($input, new DomainException('Not a valid username')); Provide a callable that creates an exception object to be used when the validation fails: ```php -use Respect\Validation\Validator as v; +use Respect\Validation\ValidatorBuilder as v; use Respect\Validation\Exceptions\ValidationException; v::alnum()->lowercase()->assert( diff --git a/docs/03-handling-exceptions.md b/docs/03-handling-exceptions.md index 78dbd628..6c0f57af 100644 --- a/docs/03-handling-exceptions.md +++ b/docs/03-handling-exceptions.md @@ -1,6 +1,6 @@ # Handling exceptions -The `Validator::assert()` method simplifies exception handling by throwing `ValidationException` exceptions when validation fails. These exceptions provide detailed feedback on what went wrong. +The `ValidatorBuilder::assert()` method simplifies exception handling by throwing `ValidationException` exceptions when validation fails. These exceptions provide detailed feedback on what went wrong. ## Full exception message @@ -8,7 +8,7 @@ The `getFullMessage()` method will return a full comprehensive explanation of ru ```php use Respect\Validation\Exceptions\ValidationException; -use Respect\Validation\Validator as v; +use Respect\Validation\ValidatorBuilder as v; try { v::alnum()->lowercase()->assert('The Respect Panda'); @@ -31,7 +31,7 @@ Retrieve validation messages in array format using `getMessages()`. ```php use Respect\Validation\Exceptions\ValidationException; -use Respect\Validation\Validator as v; +use Respect\Validation\ValidatorBuilder as v; try { v::alnum()->lowercase()->assert('The Respect Panda'); @@ -63,7 +63,7 @@ Pass custom templates directly to the `assert()` method for one-off use cases. ```php use Respect\Validation\Exceptions\ValidationException; -use Respect\Validation\Validator as v; +use Respect\Validation\ValidatorBuilder as v; try { v::alnum() @@ -98,7 +98,7 @@ Define templates within a validator so you can reuse the same templates easily. ```php use Respect\Validation\Exceptions\ValidationException; -use Respect\Validation\Validator as v; +use Respect\Validation\ValidatorBuilder as v; $validator = v::alnum()->lowercase(); $validator->setTemplates([ diff --git a/docs/06-concrete-api.md b/docs/06-concrete-api.md index 0899a337..af947b4d 100644 --- a/docs/06-concrete-api.md +++ b/docs/06-concrete-api.md @@ -5,7 +5,7 @@ document we're gonna explore the Respect\Validation API without fluent interface or magic methods. We'll use a traditional dependency injection approach. ```php -use Respect\Validation\Validator as v; +use Respect\Validation\ValidatorBuilder as v; $usernameValidator = v::alnum()->notSpaced()->length(1, 15); $usernameValidator->isValid('alganet'); // true @@ -18,9 +18,9 @@ the chain only builds the structure. You can build it by yourself: ```php use Respect\Validation\Rules; -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; -$usernameValidator = Validator::init( +$usernameValidator = ValidatorBuilder::init( new Rules\Alnum(), new Rules\Not( new Rules\Spaced(), @@ -36,7 +36,7 @@ container or test it in the way you want. Nesting is still possible: ```php use Respect\Validation\Rules; -$usernameValidator = Validator::create( +$usernameValidator = ValidatorBuilder::init( new Rules\Key( 'name', new Rules\AllOf( @@ -62,7 +62,7 @@ live), and it's only job is to make rule construction terse and fluent. > Is `v` in `v::something` a class name? -No! The class is `Respect\Validation\Validator`, we suggest `v` as a very short alias. +No! The class is `Respect\Validation\ValidatorBuilder`, we suggest `v` as a very short alias. > Is `v::something()` a static call? @@ -72,7 +72,7 @@ something complex and returns for you. > I really don't like static calls, can I avoid it? -Yes. Just use `$validator = Validator::create();` each time you want a new validator, +Yes. Just use `$validator = ValidatorBuilder::create();` each time you want a new validator, and continue from there. > Do you have a static method for each rule? diff --git a/library/ContainerRegistry.php b/library/ContainerRegistry.php index 03fbd703..da629fe3 100644 --- a/library/ContainerRegistry.php +++ b/library/ContainerRegistry.php @@ -54,7 +54,7 @@ final class ContainerRegistry 'respect.validation.formatter.message' => autowire(FirstResultStringFormatter::class), 'respect.validation.formatter.full_message' => autowire(NestedListStringFormatter::class), 'respect.validation.formatter.messages' => autowire(NestedArrayFormatter::class), - 'respect.validation.ignored_backtrace_paths' => [__DIR__ . '/Validator.php'], + 'respect.validation.ignored_backtrace_paths' => [__DIR__ . '/ValidatorBuilder.php'], 'respect.validation.rule_factory.namespaces' => ['Respect\\Validation\\Rules'], RuleFactory::class => factory(static fn(Container $container) => new NamespacedRuleFactory( $container->get(Transformer::class), @@ -74,7 +74,7 @@ final class ContainerRegistry ), ), )), - Validator::class => factory(static fn(Container $container) => new Validator( + ValidatorBuilder::class => factory(static fn(Container $container) => new ValidatorBuilder( $container->get(RuleFactory::class), $container->get(Renderer::class), $container->get('respect.validation.formatter.message'), diff --git a/library/Mixins/Chain.php b/library/Mixins/Chain.php index fad1bee8..a301f6c5 100644 --- a/library/Mixins/Chain.php +++ b/library/Mixins/Chain.php @@ -12,9 +12,9 @@ namespace Respect\Validation\Mixins; use DateTimeImmutable; use Respect\Validation\Name; use Respect\Validation\Rule; -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; -/** @mixin Validator */ +/** @mixin ValidatorBuilder */ interface Chain extends Rule, AllChain, diff --git a/library/Rules/KeySet.php b/library/Rules/KeySet.php index 3847d558..673cc40a 100644 --- a/library/Rules/KeySet.php +++ b/library/Rules/KeySet.php @@ -16,7 +16,7 @@ use Respect\Validation\Result; use Respect\Validation\Rule; use Respect\Validation\Rules\Core\KeyRelated; use Respect\Validation\Rules\Core\Reducer; -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; use function array_diff; use function array_filter; @@ -105,7 +105,7 @@ final readonly class KeySet implements Rule continue; } - if (!$rule instanceof Validator) { + if (!$rule instanceof ValidatorBuilder) { throw new InvalidRuleConstructorException('You must provide only key-related rules'); } diff --git a/library/Validator.php b/library/ValidatorBuilder.php similarity index 98% rename from library/Validator.php rename to library/ValidatorBuilder.php index 9dff0210..20d62d47 100644 --- a/library/Validator.php +++ b/library/ValidatorBuilder.php @@ -26,7 +26,7 @@ use function is_callable; use function is_string; /** @mixin Builder */ -final readonly class Validator implements Rule, Nameable +final readonly class ValidatorBuilder implements Rule, Nameable { /** @var array */ private array $rules; diff --git a/tests/feature/DoNotRelyOnNestedValidationExceptionInterfaceForCheckTest.php b/tests/feature/DoNotRelyOnNestedValidationExceptionInterfaceForCheckTest.php index bb7089eb..8913c287 100644 --- a/tests/feature/DoNotRelyOnNestedValidationExceptionInterfaceForCheckTest.php +++ b/tests/feature/DoNotRelyOnNestedValidationExceptionInterfaceForCheckTest.php @@ -7,9 +7,9 @@ declare(strict_types=1); -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; test('Scenario #1', catchMessage( - fn() => Validator::alnum('__')->lengthBetween(1, 15)->notSpaced()->assert('really messed up screen#name'), + fn() => ValidatorBuilder::alnum('__')->lengthBetween(1, 15)->notSpaced()->assert('really messed up screen#name'), fn(string $message) => expect($message)->toBe('"really messed up screen#name" must contain only letters (a-z), digits (0-9), and "__"'), )); diff --git a/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php b/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php index fe162c38..223f0d74 100644 --- a/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php +++ b/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php @@ -7,10 +7,10 @@ declare(strict_types=1); -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; test('Scenario #1', catchFullMessage( - fn() => Validator::stringType()->lengthBetween(2, 15)->assert(0), + fn() => ValidatorBuilder::stringType()->lengthBetween(2, 15)->assert(0), fn(string $fullMessage) => expect($fullMessage)->toBe(<<<'FULL_MESSAGE' - 0 must pass all the rules - 0 must be a string diff --git a/tests/feature/Issues/Issue1289Test.php b/tests/feature/Issues/Issue1289Test.php index 2f804074..eac917a8 100644 --- a/tests/feature/Issues/Issue1289Test.php +++ b/tests/feature/Issues/Issue1289Test.php @@ -14,12 +14,12 @@ use Respect\Validation\Rules\KeyOptional; use Respect\Validation\Rules\OneOf; use Respect\Validation\Rules\StringType; use Respect\Validation\Rules\StringVal; -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; test('https://github.com/Respect/Validation/issues/1289', catchAll( - fn() => Validator::init( + fn() => ValidatorBuilder::init( new Each( - Validator::init( + ValidatorBuilder::init( new KeyOptional( 'default', new OneOf( diff --git a/tests/feature/NotWithoutRecursionTest.php b/tests/feature/NotWithoutRecursionTest.php index 261c9042..5e341dfb 100644 --- a/tests/feature/NotWithoutRecursionTest.php +++ b/tests/feature/NotWithoutRecursionTest.php @@ -7,10 +7,10 @@ declare(strict_types=1); -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; test('Scenario #1', catchMessage(function (): void { - $validator = Validator::not(Validator::intVal()->positive()); + $validator = ValidatorBuilder::not(ValidatorBuilder::intVal()->positive()); $validator->assert(2); }, fn(string $message) => expect($message)->toBe('2 must not be an integer value'))); diff --git a/tests/feature/SetTemplateWithMultipleValidatorsShouldUseTemplateAsMainMessageTest.php b/tests/feature/SetTemplateWithMultipleValidatorsShouldUseTemplateAsMainMessageTest.php index 840675b4..a2e74d1d 100644 --- a/tests/feature/SetTemplateWithMultipleValidatorsShouldUseTemplateAsMainMessageTest.php +++ b/tests/feature/SetTemplateWithMultipleValidatorsShouldUseTemplateAsMainMessageTest.php @@ -7,9 +7,9 @@ declare(strict_types=1); -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; test('Scenario #1', catchMessage(function (): void { - v::templated('{{subject}} is not tasty', Validator::callback('is_int')->between(1, 2))->assert('something'); + v::templated('{{subject}} is not tasty', ValidatorBuilder::callback('is_int')->between(1, 2))->assert('something'); }, fn(string $message) => expect($message)->toBe('"something" is not tasty'))); diff --git a/tests/feature/SetTemplateWithSingleValidatorShouldUseTemplateAsMainMessageTest.php b/tests/feature/SetTemplateWithSingleValidatorShouldUseTemplateAsMainMessageTest.php index eaed1d15..cd04fee3 100644 --- a/tests/feature/SetTemplateWithSingleValidatorShouldUseTemplateAsMainMessageTest.php +++ b/tests/feature/SetTemplateWithSingleValidatorShouldUseTemplateAsMainMessageTest.php @@ -7,9 +7,9 @@ declare(strict_types=1); -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; test('Scenario', catchMessage( - fn() => v::templated('{{subject}} is not tasty', Validator::callback('is_int'))->assert('something'), + fn() => v::templated('{{subject}} is not tasty', ValidatorBuilder::callback('is_int'))->assert('something'), fn(string $message) => expect($message)->toBe('"something" is not tasty'), )); diff --git a/tests/library/Stubs/MyValidator.php b/tests/library/Stubs/MyValidator.php index 04a874e7..603e9599 100644 --- a/tests/library/Stubs/MyValidator.php +++ b/tests/library/Stubs/MyValidator.php @@ -11,7 +11,7 @@ namespace Respect\Validation\Test\Stubs; use Respect\Validation\ContainerRegistry; use Respect\Validation\Exceptions\ValidationException; -use Respect\Validation\Validator; +use Respect\Validation\ValidatorBuilder; final class MyValidator { @@ -27,7 +27,7 @@ final class MyValidator ContainerRegistry::setContainer($container); try { - Validator::intType()->assert($input); + ValidatorBuilder::intType()->assert($input); } catch (ValidationException $exception) { // This is a workaround to avoid changing exceptions that are thrown in other places. ContainerRegistry::setContainer($defaultContainer); diff --git a/tests/unit/ContainerRegistryTest.php b/tests/unit/ContainerRegistryTest.php index 283c62fb..700f5d9c 100644 --- a/tests/unit/ContainerRegistryTest.php +++ b/tests/unit/ContainerRegistryTest.php @@ -24,7 +24,7 @@ final class ContainerRegistryTest extends TestCase public function itTheCreatedContainerShouldBeAbleToProvideAnInstanceOfValidator(): void { $container = ContainerRegistry::createContainer(); - $container->get(Validator::class); + $container->get(ValidatorBuilder::class); } #[Test] diff --git a/tests/unit/ValidatorTest.php b/tests/unit/ValidatorTest.php index 7218009f..035b6a71 100644 --- a/tests/unit/ValidatorTest.php +++ b/tests/unit/ValidatorTest.php @@ -19,7 +19,7 @@ use Respect\Validation\Test\TestCase; use function uniqid; -#[CoversClass(Validator::class)] +#[CoversClass(ValidatorBuilder::class)] final class ValidatorTest extends TestCase { #[Test] @@ -28,13 +28,13 @@ final class ValidatorTest extends TestCase $this->expectException(ComponentException::class); // @phpstan-ignore-next-line - Validator::iDoNotExistSoIShouldThrowException(); + ValidatorBuilder::iDoNotExistSoIShouldThrowException(); } #[Test] public function shouldReturnValidatorInstanceWhenTheNotRuleIsCalledWithArguments(): void { - $validator = Validator::init(); + $validator = ValidatorBuilder::init(); // @phpstan-ignore-next-line self::assertNotSame($validator, $validator->not($validator->falsy())); @@ -43,7 +43,7 @@ final class ValidatorTest extends TestCase #[Test] public function itShouldProxyResultWithTheIsValidMethod(): void { - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); self::assertFalse($validator->isValid('whatever')); } @@ -52,7 +52,7 @@ final class ValidatorTest extends TestCase #[DoesNotPerformAssertions] public function itShouldAssertAndNotThrowAnExceptionWhenValidatorPasses(): void { - $validator = Validator::init(Stub::pass(1)); + $validator = ValidatorBuilder::init(Stub::pass(1)); $validator->assert('whatever'); } @@ -61,7 +61,7 @@ final class ValidatorTest extends TestCase { $this->expectException(ValidationException::class); - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); $validator->assert('whatever'); } @@ -72,14 +72,14 @@ final class ValidatorTest extends TestCase $this->expectExceptionMessage($template); - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); $validator->assert('whatever', $template); } #[Test] public function itShouldValidateAndReturnValidResultQueryWhenValidationPasses(): void { - $validator = Validator::init(Stub::pass(1)); + $validator = ValidatorBuilder::init(Stub::pass(1)); $resultQuery = $validator->validate('whatever'); @@ -89,7 +89,7 @@ final class ValidatorTest extends TestCase #[Test] public function itShouldValidateAndReturnInvalidResultQueryWhenValidationFails(): void { - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); $resultQuery = $validator->validate('whatever'); @@ -101,7 +101,7 @@ final class ValidatorTest extends TestCase { $template = uniqid(); - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); $resultQuery = $validator->validate('whatever', $template); @@ -113,7 +113,7 @@ final class ValidatorTest extends TestCase { $template = uniqid(); - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); $resultQuery = $validator->validate('whatever', ['stub' => $template]); @@ -126,14 +126,14 @@ final class ValidatorTest extends TestCase $this->expectException(ComponentException::class); $this->expectExceptionMessage('No rules have been added to this validator.'); - $validator = Validator::init(); + $validator = ValidatorBuilder::init(); $validator->evaluate('whatever'); } #[Test] public function itShouldEvaluateAndReturnResultWhenOneRuleIsAdded(): void { - $validator = Validator::init(Stub::pass(1)); + $validator = ValidatorBuilder::init(Stub::pass(1)); $result = $validator->evaluate('whatever'); @@ -143,7 +143,7 @@ final class ValidatorTest extends TestCase #[Test] public function itShouldEvaluateAndReturnResultWhenMultipleRulesAreAdded(): void { - $validator = Validator::init(Stub::pass(1), Stub::fail(2)); + $validator = ValidatorBuilder::init(Stub::pass(1), Stub::fail(2)); $result = $validator->evaluate('whatever'); @@ -153,7 +153,7 @@ final class ValidatorTest extends TestCase #[Test] public function itShouldEvaluateAndReturnResultWhenSingleFailingRuleIsAdded(): void { - $validator = Validator::init(Stub::fail(1)); + $validator = ValidatorBuilder::init(Stub::fail(1)); $result = $validator->evaluate('whatever');