From e0ecd175264a74f3c982a55b23548c41af31be62 Mon Sep 17 00:00:00 2001 From: Benjamin Lazarecki Date: Mon, 22 Jan 2018 16:34:27 +0100 Subject: [PATCH] [Validator] Propagate embedded groups for collection validator --- .../Validator/Constraints/AllValidator.php | 4 +- .../Constraints/CollectionValidator.php | 4 +- .../Component/Validator/ExecutionContext.php | 8 +++ .../AbstractConstraintValidatorTest.php | 2 +- .../Constraints/CollectionValidatorTest.php | 60 +++++++++++++++++++ .../Validator/Tests/LegacyValidatorTest.php | 47 +++++++++++++++ 6 files changed, 120 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/AllValidator.php b/src/Symfony/Component/Validator/Constraints/AllValidator.php index 94ff8190e47c..b89730e0ba25 100644 --- a/src/Symfony/Component/Validator/Constraints/AllValidator.php +++ b/src/Symfony/Component/Validator/Constraints/AllValidator.php @@ -44,12 +44,12 @@ public function validate($value, Constraint $constraint) $validator = $context->getValidator()->inContext($context); foreach ($value as $key => $element) { - $validator->atPath('['.$key.']')->validate($element, $constraint->constraints); + $validator->atPath('['.$key.']')->validate($element, $constraint->constraints, array($context->getGroup())); } } else { // 2.4 API foreach ($value as $key => $element) { - $context->validateValue($element, $constraint->constraints, '['.$key.']'); + $context->validateValue($element, $constraint->constraints, '['.$key.']', $context->getGroup()); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CollectionValidator.php b/src/Symfony/Component/Validator/Constraints/CollectionValidator.php index 737e880968aa..a94e7f4ec4e3 100644 --- a/src/Symfony/Component/Validator/Constraints/CollectionValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CollectionValidator.php @@ -60,10 +60,10 @@ public function validate($value, Constraint $constraint) $context->getValidator() ->inContext($context) ->atPath('['.$field.']') - ->validate($value[$field], $fieldConstraint->constraints); + ->validate($value[$field], $fieldConstraint->constraints, array($context->getGroup())); } else { // 2.4 API - $context->validateValue($value[$field], $fieldConstraint->constraints, '['.$field.']'); + $context->validateValue($value[$field], $fieldConstraint->constraints, '['.$field.']', $context->getGroup()); } } } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) { diff --git a/src/Symfony/Component/Validator/ExecutionContext.php b/src/Symfony/Component/Validator/ExecutionContext.php index a33fb6ae6c16..f6b1f8ba3e9f 100644 --- a/src/Symfony/Component/Validator/ExecutionContext.php +++ b/src/Symfony/Component/Validator/ExecutionContext.php @@ -244,7 +244,15 @@ public function getMetadataFactory() */ private function executeConstraintValidators($value, array $constraints) { + // Filter constraints with the context group. + $filteredConstraints = array(); foreach ($constraints as $constraint) { + if (in_array($this->getGroup(), $constraint->groups)) { + $filteredConstraints[] = $constraint; + } + } + + foreach ($filteredConstraints as $constraint) { $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint); $validator->initialize($this); $validator->validate($value, $constraint); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php index cfe8b8e7e473..43d172b6f062 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php @@ -226,7 +226,7 @@ protected function expectValidateAt($i, $propertyPath, $value, $group) ->with($value, $this->logicalOr(null, array()), $group); } - protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null) + protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = array('MyGroup')) { $contextualValidator = $this->context->getValidator()->inContext($this->context); $contextualValidator->expects($this->at(2 * $i)) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php index 0376814341fb..32516e15f507 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php @@ -386,4 +386,64 @@ public function testObjectShouldBeLeftUnchanged() 'foo' => 3, ), (array) $value); } + + /** + * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + */ + public function testGroupShouldBePassedToTheContainingConstraint() + { + $value = array('baz' => 2); + + $constraint = new Collection( + array( + 'fields' => array( + 'baz' => array( + new Range(array('min' => 1, 'groups' => 'bar')), + ), + ), + 'groups' => 'foo', + ) + ); + + $data = $this->prepareTestData($value); + $this->validator->validate($data, $constraint); + } + + /** + * @dataProvider multipleGroupsForCollectionProvider + */ + public function testValidateMultipleGroupsForCollectionConstraint($fooGroups, $barGroups, $collectionGroups) + { + $value = array('baz' => 2); + + $constraint = new Collection( + array( + 'fields' => array( + 'baz' => array( + $fooConstraint = new Range(array('min' => 3, 'minMessage' => 'Group foo', 'groups' => $fooGroups)), + $barConstraint = new Range(array('min' => 5, 'minMessage' => 'Group bar', 'groups' => $barGroups)), + ), + ), + 'groups' => $collectionGroups, + ) + ); + + $data = $this->prepareTestData($value); + + $this->expectValidateValueAt(0, '[baz]', $value['baz'], array($fooConstraint, $barConstraint), array('MyGroup')); + + $this->validator->validate($data, $constraint); + } + + public static function multipleGroupsForCollectionProvider() + { + return array( + array(array('foo', 'bar'), array('foo', 'bar'), array('foo', 'bar')), + array(array('foo', 'bar'), array('bar'), array('foo', 'bar')), + array(array('foo'), array('foo', 'bar'), array('foo', 'bar')), + array(array('foo'), array('bar'), array('foo', 'bar')), + array(array('foo'), array('foo'), array('foo', 'bar')), + array(array('foo'), array('foo'), array('foo')), + ); + } } diff --git a/src/Symfony/Component/Validator/Tests/LegacyValidatorTest.php b/src/Symfony/Component/Validator/Tests/LegacyValidatorTest.php index a38f1abb9bbc..d117d2a12724 100644 --- a/src/Symfony/Component/Validator/Tests/LegacyValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/LegacyValidatorTest.php @@ -12,6 +12,9 @@ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Translation\IdentityTranslator; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\MetadataFactoryInterface; @@ -39,4 +42,48 @@ public function testValidateValueRejectsValid() { $this->validator->validateValue(new Entity(), new Valid()); } + + public function testValidateMultipleGroupsForCollectionConstraint() + { + $entity = new Entity(); + $entity->firstName = array('baz' => 2); + + $this->metadata->addPropertyConstraint('firstName', new Collection( + array( + 'fields' => array( + 'baz' => array( + new Range(array('min' => 3, 'minMessage' => 'Group foo', 'groups' => 'foo')), + new Range(array('min' => 5, 'minMessage' => 'Group bar', 'groups' => 'bar')), + ), + ), + ) + )); + + $violations = $this->validate($entity, null, array('foo', 'bar')); + + $this->assertCount(2, $violations); + $this->assertSame('Group foo', $violations[0]->getMessage()); + $this->assertSame('Group bar', $violations[1]->getMessage()); + } + + public function testValidateMultipleGroupsForAllConstraint() + { + $entity = new Entity(); + $entity->firstName = array(1); + + $this->metadata->addPropertyConstraint('firstName', new All( + array( + 'constraints' => array( + new Range(array('min' => 3, 'minMessage' => 'Group foo', 'groups' => 'foo')), + new Range(array('min' => 5, 'minMessage' => 'Group bar', 'groups' => 'bar')), + ), + ) + )); + + $violations = $this->validate($entity, null, array('foo', 'bar')); + + $this->assertCount(2, $violations); + $this->assertSame('Group foo', $violations[0]->getMessage()); + $this->assertSame('Group bar', $violations[1]->getMessage()); + } }