-
Notifications
You must be signed in to change notification settings - Fork 772
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This rule resembles a proper replacement for the old "KeyValue" rule rather than the "LazyConsecutive" rule[1]. I will soon delete the "LazyConsecutive" rule and replace it with something else. [1]: 41245f6 Signed-off-by: Henrique Moody <[email protected]>
- Loading branch information
1 parent
df16dda
commit 78715fb
Showing
9 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Lazy | ||
|
||
- `Lazy(callable(mixed $input): Validatable $ruleCreator)` | ||
|
||
Validates the input using a rule that is created from a callback. | ||
|
||
This rule is particularly useful when creating rules that rely on the input. A good example is validating whether a | ||
`confirmation` field matches the `password` field when processing data from a form. | ||
|
||
```php | ||
v::key('confirmation', v::equals($_POST['password'] ?? null))->validate($_POST); | ||
``` | ||
|
||
The issue with the code is that it’s hard to reuse because you’re relying upon the input itself (`$_POST`). That means | ||
you can create a chain of rules and use it everywhere. | ||
|
||
The `lazy()` rule makes this job much simpler and more elegantly: | ||
|
||
```php | ||
v::lazy(static fn($input) => v::key('confirmation', v::equals($input['password'] ?? null)))->validate($_POST); | ||
``` | ||
|
||
The code above is similar to the first example, but the biggest difference is that the creation of the rule doesn't rely | ||
on the input itself (`$_POST`), but it will use any input that’s given to the rule | ||
|
||
## Categorization | ||
|
||
- Callables | ||
- Nesting | ||
|
||
## Changelog | ||
|
||
| Version | Description | | ||
|--------:|-------------------------| | ||
| 3.0.0 | Created from `KeyValue` | | ||
|
||
*** | ||
See also: | ||
|
||
- [Call](Call.md) | ||
- [CallableType](CallableType.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright (c) Alexandre Gomes Gaigalas <[email protected]> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Respect\Validation\Rules; | ||
|
||
use Respect\Validation\Exceptions\ComponentException; | ||
use Respect\Validation\Helpers\CanBindEvaluateRule; | ||
use Respect\Validation\Result; | ||
use Respect\Validation\Rules\Core\Standard; | ||
use Respect\Validation\Validatable; | ||
|
||
use function call_user_func; | ||
|
||
final class Lazy extends Standard | ||
{ | ||
use CanBindEvaluateRule; | ||
|
||
/** @var callable(mixed): Validatable */ | ||
private $ruleCreator; | ||
|
||
/** | ||
* @param callable(mixed): Validatable $ruleCreator | ||
*/ | ||
public function __construct(callable $ruleCreator) | ||
{ | ||
$this->ruleCreator = $ruleCreator; | ||
} | ||
|
||
public function evaluate(mixed $input): Result | ||
{ | ||
$rule = call_user_func($this->ruleCreator, $input); | ||
if (!$rule instanceof Validatable) { | ||
throw new ComponentException('Lazy failed because it could not create the rule'); | ||
} | ||
|
||
return $this->bindEvaluate($rule, $this, $input); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
--FILE-- | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
require 'vendor/autoload.php'; | ||
|
||
use Respect\Validation\Validator as v; | ||
|
||
run([ | ||
'Default' => [v::lazy(static fn() => v::intType()), true], | ||
'Negative' => [v::not(v::lazy(static fn() => v::intType())), 2], | ||
'With created name, default' => [ | ||
v::lazy(static fn() => v::intType()->setName('Created'))->setName('Wrapper'), | ||
true, | ||
], | ||
'With wrapper name, default' => [ | ||
v::lazy(static fn() => v::intType())->setName('Wrapper'), | ||
true, | ||
], | ||
'With created name, negative' => [ | ||
v::not(v::lazy(static fn() => v::intType()->setName('Created'))->setName('Wrapped'))->setName('Not'), | ||
2, | ||
], | ||
'With wrapper name, negative' => [ | ||
v::not(v::lazy(static fn() => v::intType())->setName('Wrapped'))->setName('Not'), | ||
2, | ||
], | ||
'With not name, negative' => [ | ||
v::not(v::lazy(static fn() => v::intType()))->setName('Not'), | ||
2, | ||
], | ||
'With template, default' => [ | ||
v::lazy(static fn() => v::intType()), | ||
true, | ||
'Lazy lizards lounging like lords in the local lagoon', | ||
], | ||
]); | ||
?> | ||
--EXPECT-- | ||
Default | ||
⎺⎺⎺⎺⎺⎺⎺ | ||
`true` must be of type integer | ||
- `true` must be of type integer | ||
[ | ||
'intType' => '`true` must be of type integer', | ||
] | ||
|
||
Negative | ||
⎺⎺⎺⎺⎺⎺⎺⎺ | ||
2 must not be of type integer | ||
- 2 must not be of type integer | ||
[ | ||
'intType' => '2 must not be of type integer', | ||
] | ||
|
||
With created name, default | ||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ | ||
Created must be of type integer | ||
- Created must be of type integer | ||
[ | ||
'Created' => 'Created must be of type integer', | ||
] | ||
|
||
With wrapper name, default | ||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ | ||
Wrapper must be of type integer | ||
- Wrapper must be of type integer | ||
[ | ||
'Wrapper' => 'Wrapper must be of type integer', | ||
] | ||
|
||
With created name, negative | ||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ | ||
Created must not be of type integer | ||
- Created must not be of type integer | ||
[ | ||
'Created' => 'Created must not be of type integer', | ||
] | ||
|
||
With wrapper name, negative | ||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ | ||
Wrapped must not be of type integer | ||
- Wrapped must not be of type integer | ||
[ | ||
'Wrapped' => 'Wrapped must not be of type integer', | ||
] | ||
|
||
With not name, negative | ||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ | ||
Not must not be of type integer | ||
- Not must not be of type integer | ||
[ | ||
'Not' => 'Not must not be of type integer', | ||
] | ||
|
||
With template, default | ||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ | ||
Lazy lizards lounging like lords in the local lagoon | ||
- Lazy lizards lounging like lords in the local lagoon | ||
[ | ||
'intType' => 'Lazy lizards lounging like lords in the local lagoon', | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright (c) Alexandre Gomes Gaigalas <[email protected]> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Respect\Validation\Rules; | ||
|
||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use PHPUnit\Framework\Attributes\Group; | ||
use PHPUnit\Framework\Attributes\Test; | ||
use Respect\Validation\Exceptions\ComponentException; | ||
use Respect\Validation\Test\Rules\Stub; | ||
use Respect\Validation\Test\TestCase; | ||
|
||
#[Group('rule')] | ||
#[CoversClass(Lazy::class)] | ||
final class LazyTest extends TestCase | ||
{ | ||
#[Test] | ||
public function itShouldThrowAnExceptionWhenRuleCreatorDoesNotReturnValidatable(): void | ||
{ | ||
// @phpstan-ignore-next-line | ||
$rule = new Lazy(static fn () => null); | ||
|
||
$this->expectException(ComponentException::class); | ||
$this->expectExceptionMessage('Lazy failed because it could not create the rule'); | ||
|
||
$rule->evaluate('something'); | ||
} | ||
|
||
#[Test] | ||
#[DataProvider('providerForAnyValues')] | ||
public function itShouldInvalidInputWhenCreatedRuleFails(mixed $input): void | ||
{ | ||
self::assertInvalidInput(new Lazy(static fn ($creatorInput) => Stub::fail(1)), $input); | ||
} | ||
|
||
#[Test] | ||
#[DataProvider('providerForAnyValues')] | ||
public function itShouldValidInputWhenCreatedRulePasses(mixed $input): void | ||
{ | ||
self::assertValidInput(new Lazy(static fn ($creatorInput) => Stub::pass(1)), $input); | ||
} | ||
|
||
#[Test] | ||
#[DataProvider('providerForAnyValues')] | ||
public function itShouldReturnTheResultFromTheCreatedRule(mixed $input): void | ||
{ | ||
$expected = Stub::fail(1)->evaluate($input); | ||
|
||
$rule = new Lazy(static fn ($creatorInput) => Stub::fail(1)); | ||
$actual = $rule->evaluate($input); | ||
|
||
self::assertEquals($expected, $actual); | ||
} | ||
} |