From 8dfb7b2ad1e2fff915376aafdc24ec8600538788 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 19 Feb 2020 08:53:51 +0100 Subject: [PATCH] [Validator] Add the divisibleBy option to the Count constraint --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Component/Validator/Constraints/Count.php | 8 ++++++-- .../Validator/Constraints/CountValidator.php | 14 +++++++++++++ .../Resources/translations/validators.en.xlf | 4 ++++ .../Resources/translations/validators.fr.xlf | 4 ++++ .../Tests/Constraints/CountValidatorTest.php | 20 +++++++++++++++++++ 6 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index d3bebec61e0c1..1dea1e7fa1a48 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * added option `alpha3` to `Country` constraint * allow to define a reusable set of constraints by extending the `Compound` constraint * added `Sequentially` constraint, to sequentially validate a set of constraints (any violation raised will prevent further validation of the nested constraints) + * added the `divisibleBy` option to the `Count` constraint 5.0.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Count.php b/src/Symfony/Component/Validator/Constraints/Count.php index b11f994f58b65..6d1e7afcd8de5 100644 --- a/src/Symfony/Component/Validator/Constraints/Count.php +++ b/src/Symfony/Component/Validator/Constraints/Count.php @@ -24,17 +24,21 @@ class Count extends Constraint { const TOO_FEW_ERROR = 'bef8e338-6ae5-4caf-b8e2-50e7b0579e69'; const TOO_MANY_ERROR = '756b1212-697c-468d-a9ad-50dd783bb169'; + const NOT_DIVISIBLE_BY_ERROR = DivisibleBy::NOT_DIVISIBLE_BY; protected static $errorNames = [ self::TOO_FEW_ERROR => 'TOO_FEW_ERROR', self::TOO_MANY_ERROR => 'TOO_MANY_ERROR', + self::NOT_DIVISIBLE_BY_ERROR => 'NOT_DIVISIBLE_BY_ERROR', ]; public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.'; public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.'; public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.'; + public $divisibleByMessage = 'The number of elements in this collection should be a multiple of {{ compared_value }}.'; public $min; public $max; + public $divisibleBy; public function __construct($options = null) { @@ -50,8 +54,8 @@ public function __construct($options = null) parent::__construct($options); - if (null === $this->min && null === $this->max) { - throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), ['min', 'max']); + if (null === $this->min && null === $this->max && null === $this->divisibleBy) { + throw new MissingOptionsException(sprintf('Either option "min", "max" or "divisibleBy" must be given for constraint %s', __CLASS__), ['min', 'max', 'divisibleBy']); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CountValidator.php b/src/Symfony/Component/Validator/Constraints/CountValidator.php index 5c40e47b211de..9f9ac4d4057bb 100644 --- a/src/Symfony/Component/Validator/Constraints/CountValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CountValidator.php @@ -60,6 +60,20 @@ public function validate($value, Constraint $constraint) ->setPlural((int) $constraint->min) ->setCode(Count::TOO_FEW_ERROR) ->addViolation(); + + return; + } + + if (null !== $constraint->divisibleBy) { + $this->context + ->getValidator() + ->inContext($this->context) + ->validate($count, [ + new DivisibleBy([ + 'value' => $constraint->divisibleBy, + 'message' => $constraint->divisibleByMessage, + ]), + ], $this->context->getGroup()); } } } diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index 635e6736f6941..8f8d2d0a0fe98 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -370,6 +370,10 @@ This value is not a valid hostname. This value is not a valid hostname. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + The number of elements in this collection should be a multiple of {{ compared_value }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index 4a7ab3538c41a..e54be35c15cca 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -370,6 +370,10 @@ This value is not a valid hostname. Cette valeur n'est pas un nom d'hôte valide. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Le nombre d'éléments de cette collection doit être un multiple de {{ compared_value }}. + diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php index 664b96b2d2576..a6337a534ee1a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Constraints\Count; use Symfony\Component\Validator\Constraints\CountValidator; +use Symfony\Component\Validator\Constraints\DivisibleBy; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** @@ -202,4 +203,23 @@ public function testConstraintAnnotationDefaultOption() $this->assertEquals(5, $constraint->max); $this->assertEquals('message', $constraint->exactMessage); } + + // Since the contextual validator is mocked, this test only asserts that it + // is called with the right DivisibleBy constraint. + public function testDivisibleBy() + { + $constraint = new Count([ + 'divisibleBy' => 123, + 'divisibleByMessage' => 'foo {{ compared_value }}', + ]); + + $this->expectValidateValue(0, 3, [new DivisibleBy([ + 'value' => 123, + 'message' => 'foo {{ compared_value }}', + ])], $this->group); + + $this->validator->validate(['foo', 'bar', 'ccc'], $constraint); + + $this->assertNoViolation(); + } }