Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the possibility to add a context to a validation #28

Merged
merged 3 commits into from
Apr 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Assertion/Asserter.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function assert(mixed $subject, ValidationInterface $validation): Validat
$message = $validation->getMessage();
if (null !== $message) {
$failures->add(
$this->validationFailureFactory->create($message, $subject, $validation->getProperty())
$this->validationFailureFactory->create($validation, $message, $subject)
);

return $failures;
Expand All @@ -60,7 +60,7 @@ public function assert(mixed $subject, ValidationInterface $validation): Validat
$exceptionMessages = $this->extractMessagesFromException($exception, $validation);
foreach ($exceptionMessages as $ruleName => $message) {
$failures->add(
$this->validationFailureFactory->create($message, $subject, $validation->getProperty(), $ruleName)
$this->validationFailureFactory->create($validation, $message, $subject, $ruleName)
);
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/Failure/ValidationFailure.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Awurth\Validator\Failure;

use Awurth\Validator\ValidationInterface;

/**
* Represents a validation failure.
*
Expand All @@ -21,13 +23,18 @@
final class ValidationFailure implements ValidationFailureInterface
{
public function __construct(
private readonly ValidationInterface $validation,
private readonly string $message,
private readonly mixed $invalidValue,
private readonly ?string $property = null,
private readonly ?string $ruleName = null,
) {
}

public function getValidation(): ValidationInterface
{
return $this->validation;
}

public function getInvalidValue(): mixed
{
return $this->invalidValue;
Expand All @@ -38,11 +45,6 @@ public function getMessage(): string
return $this->message;
}

public function getProperty(): ?string
{
return $this->property;
}

public function getRuleName(): ?string
{
return $this->ruleName;
Expand Down
6 changes: 4 additions & 2 deletions src/Failure/ValidationFailureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Awurth\Validator\Failure;

use Awurth\Validator\ValidationInterface;

/**
* Handles the creation of a validation failure.
*
Expand All @@ -21,11 +23,11 @@
final class ValidationFailureFactory implements ValidationFailureFactoryInterface
{
public function create(
ValidationInterface $validation,
string $message,
mixed $invalidValue,
?string $property = null,
?string $ruleName = null,
): ValidationFailureInterface {
return new ValidationFailure($message, $invalidValue, $property, $ruleName);
return new ValidationFailure($validation, $message, $invalidValue, $ruleName);
}
}
5 changes: 3 additions & 2 deletions src/Failure/ValidationFailureFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Awurth\Validator\Failure;

use Awurth\Validator\ValidationInterface;

/**
* Handles the creation of a validation failure.
*
Expand All @@ -25,8 +27,7 @@ interface ValidationFailureFactoryInterface
*
* @param string $message The error message
* @param mixed $invalidValue The invalid value
* @param string|null $property The object property, array key or request parameter
* @param string|null $ruleName The Respect/Validation rule name
*/
public function create(string $message, mixed $invalidValue, ?string $property = null, ?string $ruleName = null): ValidationFailureInterface;
public function create(ValidationInterface $validation, string $message, mixed $invalidValue, ?string $ruleName = null): ValidationFailureInterface;
}
9 changes: 4 additions & 5 deletions src/Failure/ValidationFailureInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@

namespace Awurth\Validator\Failure;

use Awurth\Validator\ValidationInterface;

/**
* Represents a validation failure.
*
* @author Alexis Wurth <awurth.dev@gmail.com>
*/
interface ValidationFailureInterface
{
public function getValidation(): ValidationInterface;

/**
* Gets the validated data.
*/
Expand All @@ -30,11 +34,6 @@ public function getInvalidValue(): mixed;
*/
public function getMessage(): string;

/**
* Gets the object property, array key or request parameter.
*/
public function getProperty(): ?string;

/**
* Gets the Respect/Validation rule name.
*/
Expand Down
6 changes: 4 additions & 2 deletions src/StatefulValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ public static function create(?AsserterInterface $asserter = null): self
);
}

public function validate(mixed $subject, Validatable|array $rules, array $messages = []): ValidationFailureCollectionInterface
public function validate(mixed $subject, Validatable|array $rules, array $messages = [], mixed $context = null): ValidationFailureCollectionInterface
{
$this->failures->addAll($this->validator->validate($subject, $rules, $messages));
$failures = $this->validator->validate($subject, $rules, $messages, $context);

$this->failures->addAll($failures);

return $this->failures;
}
Expand Down
6 changes: 3 additions & 3 deletions src/Twig/LegacyValidatorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function getFunctions(): array

public function getError(string $key, int $index = 0): ?string
{
$failures = $this->validator->getFailures()->filter(static fn (ValidationFailureInterface $failure): bool => $failure->getProperty() === $key);
$failures = $this->validator->getFailures()->filter(static fn (ValidationFailureInterface $failure): bool => $failure->getValidation()->getProperty() === $key);
$failure = $failures->has($index) ? $failures->get($index) : null;

return $failure?->getMessage();
Expand All @@ -84,7 +84,7 @@ public function getErrors(?string $key = null): array
{
$failures = null === $key
? $this->validator->getFailures()
: $this->validator->getFailures()->filter(static fn (ValidationFailureInterface $failure) => $failure->getProperty() === $key)
: $this->validator->getFailures()->filter(static fn (ValidationFailureInterface $failure) => $failure->getValidation()->getProperty() === $key)
;

return \array_map(
Expand All @@ -106,7 +106,7 @@ public function getValue(string $key): mixed

public function hasError(string $key): bool
{
return null !== $this->validator->getFailures()->find(static fn (ValidationFailureInterface $failure) => $failure->getProperty() === $key);
return null !== $this->validator->getFailures()->find(static fn (ValidationFailureInterface $failure) => $failure->getValidation()->getProperty() === $key);
}

public function hasErrors(): bool
Expand Down
6 changes: 6 additions & 0 deletions src/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function __construct(
private readonly ?string $message = null,
private readonly array $messages = [],
private readonly array $globalMessages = [],
private readonly mixed $context = null,
) {
}

Expand Down Expand Up @@ -61,4 +62,9 @@ public function getGlobalMessages(): array
{
return $this->globalMessages;
}

public function getContext(): mixed
{
return $this->context;
}
}
2 changes: 2 additions & 0 deletions src/ValidationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function create(array $options, ?string $property = null, mixed $default
$options['message'],
$options['messages'],
$options['globalMessages'],
$options['context'],
);
}

Expand All @@ -48,6 +49,7 @@ private static function getOptionsResolver(): OptionsResolver
'message' => null,
'messages' => [],
'globalMessages' => [],
'context' => null,
])
->setRequired('rules')
->setAllowedTypes('rules', Validatable::class)
Expand Down
5 changes: 5 additions & 0 deletions src/ValidationInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ interface ValidationInterface
{
public function getRules(): Validatable;

/**
* Gets the object property, array key or request parameter.
*/
public function getProperty(): ?string;

public function getDefault(): mixed;
Expand All @@ -33,4 +36,6 @@ public function getMessage(): ?string;
public function getMessages(): array;

public function getGlobalMessages(): array;

public function getContext(): mixed;
}
5 changes: 4 additions & 1 deletion src/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@ public static function create(
);
}

public function validate(mixed $subject, Validatable|array $rules, array $messages = []): ValidationFailureCollectionInterface
public function validate(mixed $subject, Validatable|array $rules, array $messages = [], mixed $context = null): ValidationFailureCollectionInterface
{
if ($rules instanceof Validatable) {
return $this->asserter->assert($subject, $this->validationFactory->create([
'rules' => $rules,
'globalMessages' => $messages,
'context' => $context,
]), $messages);
}

if (!$subject instanceof Request && !\is_object($subject) && !\is_array($subject)) {
$rules['globalMessages'] = $messages;
$rules['context'] = $context;

return $this->asserter->assert($subject, $this->validationFactory->create($rules), $messages);
}
Expand All @@ -76,6 +78,7 @@ public function validate(mixed $subject, Validatable|array $rules, array $messag
}

$options['globalMessages'] = $messages;
$options['context'] = $context;

$validation = $this->validationFactory->create($options, $property);
$value = $this->getValue($subject, $property, $validation->getDefault());
Expand Down
2 changes: 1 addition & 1 deletion src/ValidatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ interface ValidatorInterface
/**
* @param array<string, string> $messages
*/
public function validate(mixed $subject, Validatable|array $rules, array $messages = []): ValidationFailureCollectionInterface;
public function validate(mixed $subject, Validatable|array $rules, array $messages = [], mixed $context = null): ValidationFailureCollectionInterface;
}
30 changes: 15 additions & 15 deletions tests/Twig/LegacyValidatorExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@
use Awurth\Validator\ValidatedValueCollectionInterface;
use Awurth\Validator\Validation;
use PHPUnit\Framework\TestCase;
use Respect\Validation\Validator;
use Respect\Validation\Validator as V;

class LegacyValidatorExtensionTest extends TestCase
final class LegacyValidatorExtensionTest extends TestCase
{
public function testGetError(): void
{
$extension = self::createExtension(new ValidationFailureCollection([
new ValidationFailure('first message', null, 'first'),
new ValidationFailure('second message', null, 'second'),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'first'), 'first message', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'second'), 'second message', null),
]));

self::assertSame('first message', $extension->getError('first'));
self::assertSame('second message', $extension->getError('second'));

$extension = self::createExtension(new ValidationFailureCollection([
new ValidationFailure('first message of first property', null, 'first'),
new ValidationFailure('first message of second property', null, 'second'),
new ValidationFailure('second message of second property', null, 'second'),
new ValidationFailure('second message of first property', null, 'first'),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'first'), 'first message of first property', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'second'), 'first message of second property', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'second'), 'second message of second property', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'first'), 'second message of first property', null),
]));

self::assertSame('first message of first property', $extension->getError('first'));
Expand All @@ -56,10 +56,10 @@ public function testGetError(): void
public function testGetErrors(): void
{
$extension = self::createExtension(new ValidationFailureCollection([
new ValidationFailure('first', null, 'first'),
new ValidationFailure('second', null, 'second'),
new ValidationFailure('third', null, 'third'),
new ValidationFailure('fourth', null, 'third'),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'first'), 'first', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'second'), 'second', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'third'), 'third', null),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'third'), 'fourth', null),
]));

self::assertSame(['first', 'second', 'third', 'fourth'], $extension->getErrors());
Expand All @@ -69,7 +69,7 @@ public function testGetErrors(): void
public function testGetValue(): void
{
$extension = self::createExtension(data: new ValidatedValueCollection([
new ValidatedValue(new Validation(Validator::alwaysInvalid(), 'property'), 'invalid string'),
new ValidatedValue(new Validation(V::alwaysInvalid(), 'property'), 'invalid string'),
]));

self::assertSame('invalid string', $extension->getValue('property'));
Expand All @@ -79,7 +79,7 @@ public function testGetValue(): void
public function testHasError(): void
{
$extension = self::createExtension(new ValidationFailureCollection([
new ValidationFailure('message', null, 'property'),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'property'), 'message', null),
]));

self::assertTrue($extension->hasError('property'));
Expand All @@ -93,7 +93,7 @@ public function testHasErrors(): void
self::assertFalse($extension->hasErrors());

$extension = self::createExtension(new ValidationFailureCollection([
new ValidationFailure('message', null, 'property'),
new ValidationFailure(new Validation(V::alwaysInvalid(), 'property'), 'message', null),
]));

self::assertTrue($extension->hasErrors());
Expand Down