diff --git a/src/Symfony/Component/Validator/Constraints/Composite.php b/src/Symfony/Component/Validator/Constraints/Composite.php index bd7030ee27a4..b14276c3bbf1 100644 --- a/src/Symfony/Component/Validator/Constraints/Composite.php +++ b/src/Symfony/Component/Validator/Constraints/Composite.php @@ -88,7 +88,8 @@ public function __construct($options = null) } } - $this->groups = array_keys($mergedGroups); + // prevent empty composite constraint to have empty groups + $this->groups = array_keys($mergedGroups) ?: [self::DEFAULT_GROUP]; $this->$compositeOption = $nestedConstraints; return; diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php index fef129cfa749..254154dae724 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php @@ -100,4 +100,16 @@ public function testAcceptRequiredConstraintAsOneElementArray() $this->assertEquals($collection1, $collection2); } + + public function testConstraintHasDefaultGroupWithOptionalValues() + { + $constraint = new Collection([ + 'foo' => new Required(), + 'bar' => new Optional(), + ]); + + $this->assertEquals(['Default'], $constraint->groups); + $this->assertEquals(['Default'], $constraint->fields['foo']->groups); + $this->assertEquals(['Default'], $constraint->fields['bar']->groups); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php index e0ccdba754b0..11913eb2307a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php @@ -143,6 +143,29 @@ public function testExtraFieldsDisallowed() ->assertRaised(); } + public function testExtraFieldsDisallowedWithOptionalValues() + { + $constraint = new Optional(); + + $data = $this->prepareTestData([ + 'baz' => 6, + ]); + + $this->validator->validate($data, new Collection([ + 'fields' => [ + 'foo' => $constraint, + ], + 'extraFieldsMessage' => 'myMessage', + ])); + + $this->buildViolation('myMessage') + ->setParameter('{{ field }}', '"baz"') + ->atPath('property.path[baz]') + ->setInvalidValue(6) + ->setCode(Collection::NO_SUCH_FIELD_ERROR) + ->assertRaised(); + } + // bug fix public function testNullNotConsideredExtraField() { diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php index 2d42807821bb..287fd6d6681c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php @@ -19,7 +19,7 @@ class ConcreteComposite extends Composite { - public $constraints; + public $constraints = []; protected function getCompositeOption() { @@ -37,6 +37,30 @@ public function getDefaultOption() */ class CompositeTest extends TestCase { + public function testConstraintHasDefaultGroup() + { + $constraint = new ConcreteComposite([ + new NotNull(), + new NotBlank(), + ]); + + $this->assertEquals(['Default'], $constraint->groups); + $this->assertEquals(['Default'], $constraint->constraints[0]->groups); + $this->assertEquals(['Default'], $constraint->constraints[1]->groups); + } + + public function testNestedCompositeConstraintHasDefaultGroup() + { + $constraint = new ConcreteComposite([ + new ConcreteComposite(), + new ConcreteComposite(), + ]); + + $this->assertEquals(['Default'], $constraint->groups); + $this->assertEquals(['Default'], $constraint->constraints[0]->groups); + $this->assertEquals(['Default'], $constraint->constraints[1]->groups); + } + public function testMergeNestedGroupsIfNoExplicitParentGroup() { $constraint = new ConcreteComposite([