Skip to content

Commit

Permalink
feature #35783 [Validator] Add the divisibleBy option to the Count co…
Browse files Browse the repository at this point in the history
…nstraint (fancyweb)

This PR was merged into the 5.1-dev branch.

Discussion
----------

[Validator] Add the divisibleBy option to the Count constraint

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | TODO

From my experience, it is sometimes useful to assert that the number of elements in a collection is a multiple of X.

Commits
-------

8dfb7b2 [Validator] Add the divisibleBy option to the Count constraint
  • Loading branch information
fabpot committed Feb 21, 2020
2 parents d33a483 + 8dfb7b2 commit f01bbc7
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Component/Validator/CHANGELOG.md
Expand Up @@ -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
-----
Expand Down
8 changes: 6 additions & 2 deletions src/Symfony/Component/Validator/Constraints/Count.php
Expand Up @@ -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)
{
Expand All @@ -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']);
}
}
}
14 changes: 14 additions & 0 deletions src/Symfony/Component/Validator/Constraints/CountValidator.php
Expand Up @@ -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());
}
}
}
Expand Up @@ -370,6 +370,10 @@
<source>This value is not a valid hostname.</source>
<target>This value is not a valid hostname.</target>
</trans-unit>
<trans-unit id="96">
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>The number of elements in this collection should be a multiple of {{ compared_value }}.</target>
</trans-unit>
</body>
</file>
</xliff>
Expand Up @@ -370,6 +370,10 @@
<source>This value is not a valid hostname.</source>
<target>Cette valeur n'est pas un nom d'hôte valide.</target>
</trans-unit>
<trans-unit id="96">
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>Le nombre d'éléments de cette collection doit être un multiple de {{ compared_value }}.</target>
</trans-unit>
</body>
</file>
</xliff>
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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();
}
}

0 comments on commit f01bbc7

Please sign in to comment.