Improve composite-based rules

Because the rules' property is read-only, there aren't many reasons not
to expose that, especially since we already expose the rules anyways.

I also changed the implementation of "OneOf" because we don't see "xor"
enough these days.

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
Henrique Moody 2024-03-06 17:57:12 +01:00
parent 24885e4a5f
commit df16ddaf48
No known key found for this signature in database
GPG key ID: 221E9281655813A6
6 changed files with 10 additions and 8 deletions

View file

@ -36,7 +36,7 @@ final class AllOf extends Composite
public function evaluate(mixed $input): Result
{
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->getRules());
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->rules);
$valid = array_reduce($children, static fn (bool $carry, Result $result) => $carry && $result->isValid, true);
$failed = array_filter($children, static fn (Result $result): bool => !$result->isValid);
$template = self::TEMPLATE_SOME;

View file

@ -25,7 +25,7 @@ final class AnyOf extends Composite
{
public function evaluate(mixed $input): Result
{
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->getRules());
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->rules);
$valid = array_reduce($children, static fn (bool $carry, Result $result) => $carry || $result->isValid, false);
return (new Result($valid, $input, $this))->withChildren(...$children);

View file

@ -19,7 +19,7 @@ abstract class Composite implements Validatable
use DeprecatedValidatableMethods;
/** @var non-empty-array<Validatable> */
private readonly array $rules;
protected readonly array $rules;
private ?string $name = null;
@ -38,7 +38,7 @@ abstract class Composite implements Validatable
public function setName(string $name): static
{
foreach ($this->getRules() as $rule) {
foreach ($this->rules as $rule) {
if ($rule->getName() && $this->name !== $rule->getName()) {
continue;
}

View file

@ -25,7 +25,7 @@ final class NoneOf extends Composite
{
public function evaluate(mixed $input): Result
{
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input)->withInvertedMode(), $this->getRules());
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input)->withInvertedMode(), $this->rules);
$valid = array_reduce($children, static fn (bool $carry, Result $result) => $carry && $result->isValid, true);
return (new Result($valid, $input, $this))->withChildren(...$children);

View file

@ -25,9 +25,9 @@ final class OneOf extends Composite
{
public function evaluate(mixed $input): Result
{
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->getRules());
$count = array_reduce($children, static fn (int $carry, Result $result) => $carry + (int) $result->isValid, 0);
$children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->rules);
$valid = array_reduce($children, static fn (bool $carry, Result $result) => $carry xor $result->isValid, false);
return (new Result($count === 1, $input, $this))->withChildren(...$children);
return (new Result($valid, $input, $this))->withChildren(...$children);
}
}

View file

@ -22,8 +22,10 @@ final class AnyOfTest extends RuleTestCase
public static function providerForValidInput(): iterable
{
yield 'fail, pass' => [new AnyOf(Stub::fail(1), Stub::pass(1)), []];
yield 'pass, fail' => [new AnyOf(Stub::pass(1), Stub::fail(1)), []];
yield 'fail, fail, pass' => [new AnyOf(Stub::fail(1), Stub::fail(1), Stub::pass(1)), []];
yield 'fail, pass, fail' => [new AnyOf(Stub::fail(1), Stub::pass(1), Stub::fail(1)), []];
yield 'pass, fail, fail' => [new AnyOf(Stub::pass(1), Stub::fail(1), Stub::fail(1)), []];
}
/** @return iterable<string, array{AnyOf, mixed}> */