Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b768608

Browse files
committed
fixup mixing groups in class and fields
1 parent 98743fc commit b768608

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,27 +53,31 @@ public function validate($form, Constraint $formConstraint)
5353
}
5454

5555
$data = $form->getData();
56-
5756
// Validate the data against its own constraints
58-
if ($form->isRoot() && (\is_object($data) || \is_array($data))) {
59-
if (($groups && \is_array($groups)) || ($groups instanceof GroupSequence && $groups->groups)) {
60-
$validator->atPath('data')->validate($data, null, $groups);
61-
}
62-
}
57+
$validateDataGraph = $form->isRoot()
58+
&& (\is_object($data) || \is_array($data))
59+
&& (($groups && \is_array($groups)) || ($groups instanceof GroupSequence && $groups->groups))
60+
;
6361

6462
// Validate the data against the constraints defined in the form
6563
/** @var Constraint[] $constraints */
6664
$constraints = $config->getOption('constraints', []);
6765

6866
if ($groups instanceof GroupSequence) {
69-
// Validate the form AND nested fields in sequence
70-
$violationsCount = \count($this->context->getViolations());
67+
// Validate the data, the form AND nested fields in sequence
68+
$violationsCount = $this->context->getViolations()->count();
7169
$fieldPropertyPath = \is_object($data) ? 'data.%s' : '%s';
72-
$hasChildren = \count($form) > 0;
70+
$hasChildren = $form->count() > 0;
7371
$this->resolvedGroups = $hasChildren ? new \SplObjectStorage() : null;
7472

7573
foreach ($groups->groups as $group) {
76-
$validator->atPath('data')->validate($data, $constraints, $group);
74+
if ($validateDataGraph) {
75+
$validator->atPath('data')->validate($data, null, $group);
76+
}
77+
78+
if ($groupedConstraints = self::getConstraintsInGroups($constraints, $group)) {
79+
$validator->atPath('data')->validate($data, $groupedConstraints, $group);
80+
}
7781

7882
foreach ($form->all() as $field) {
7983
if ($field->isSubmitted()) {
@@ -86,7 +90,7 @@ public function validate($form, Constraint $formConstraint)
8690
}
8791
}
8892

89-
if ($violationsCount < \count($this->context->getViolations())) {
93+
if ($violationsCount < $this->context->getViolations()->count()) {
9094
break;
9195
}
9296
}
@@ -96,6 +100,10 @@ public function validate($form, Constraint $formConstraint)
96100
$this->resolvedGroups = null;
97101
}
98102
} else {
103+
if ($validateDataGraph) {
104+
$validator->atPath('data')->validate($data, null, $groups);
105+
}
106+
99107
foreach ($constraints as $constraint) {
100108
// For the "Valid" constraint, validate the data in all groups
101109
if ($constraint instanceof Valid) {
@@ -221,4 +229,11 @@ private static function resolveValidationGroups($groups, FormInterface $form)
221229

222230
return (array) $groups;
223231
}
232+
233+
private static function getConstraintsInGroups($constraints, $group)
234+
{
235+
return array_filter($constraints, static function (Constraint $constraint) use ($group) {
236+
return \in_array($group, $constraint->groups, true);
237+
});
238+
}
224239
}

src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,8 @@ public function testHandleGroupSequenceValidationGroups()
401401
$form = $this->getCompoundForm($object, $options);
402402
$form->submit([]);
403403

404-
$this->expectValidateAt(0, 'data', $object, new GroupSequence(['group1', 'group2']));
405-
$this->expectValidateAt(1, 'data', $object, 'group1');
406-
$this->expectValidateAt(2, 'data', $object, 'group2');
404+
$this->expectValidateAt(0, 'data', $object, 'group1');
405+
$this->expectValidateAt(1, 'data', $object, 'group2');
407406

408407
$this->validator->validate($form, new Form());
409408

src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,20 @@
1212
namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
1313

1414
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
15+
use Symfony\Component\Form\Form;
1516
use Symfony\Component\Form\Forms;
1617
use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait;
1718
use Symfony\Component\Form\Tests\Extension\Core\Type\FormTypeTest;
1819
use Symfony\Component\Form\Tests\Extension\Core\Type\TextTypeTest;
20+
use Symfony\Component\Form\Tests\Fixtures\Author;
1921
use Symfony\Component\Validator\Constraints\GroupSequence;
2022
use Symfony\Component\Validator\Constraints\Length;
2123
use Symfony\Component\Validator\Constraints\NotBlank;
24+
use Symfony\Component\Validator\Constraints\NotNull;
2225
use Symfony\Component\Validator\Constraints\Valid;
2326
use Symfony\Component\Validator\ConstraintViolationList;
27+
use Symfony\Component\Validator\Mapping\ClassMetadata;
28+
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
2429
use Symfony\Component\Validator\Validation;
2530

2631
class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest
@@ -79,23 +84,48 @@ public function testGroupSequenceWithConstraintsOption()
7984

8085
public function testManyFieldsGroupSequenceWithConstraintsOption()
8186
{
87+
$formMetadata = new ClassMetadata(Form::class);
88+
$authorMetadata = (new ClassMetadata(Author::class))
89+
->addPropertyConstraint('firstName', new NotNull(['groups' => 'Second']))
90+
;
91+
$metadataFactory = $this->createMock(MetadataFactoryInterface::class);
92+
$metadataFactory->expects($this->any())
93+
->method('getMetadataFor')
94+
->willReturnCallback(static function ($classOrObject) use ($formMetadata, $authorMetadata) {
95+
if (Author::class === $classOrObject || $classOrObject instanceof Author) {
96+
return $authorMetadata;
97+
}
98+
99+
if (Form::class === $classOrObject || $classOrObject instanceof Form) {
100+
return $formMetadata;
101+
}
102+
103+
return new ClassMetadata(\is_string($classOrObject) ? $classOrObject : \get_class($classOrObject));
104+
})
105+
;
106+
107+
$validator = Validation::createValidatorBuilder()
108+
->setMetadataFactory($metadataFactory)
109+
->getValidator()
110+
;
82111
$form = Forms::createFormFactoryBuilder()
83-
->addExtension(new ValidatorExtension(Validation::createValidator()))
112+
->addExtension(new ValidatorExtension($validator))
84113
->getFormFactory()
85-
->create(FormTypeTest::TESTED_TYPE, null, (['validation_groups' => new GroupSequence(['First', 'Second'])]))
86-
->add('field1', TextTypeTest::TESTED_TYPE, [
114+
->create(FormTypeTest::TESTED_TYPE, new Author(), (['validation_groups' => new GroupSequence(['First', 'Second'])]))
115+
->add('firstName', TextTypeTest::TESTED_TYPE)
116+
->add('lastName', TextTypeTest::TESTED_TYPE, [
87117
'constraints' => [
88118
new Length(['min' => 10, 'groups' => ['First']]),
89119
],
90120
])
91-
->add('field2', TextTypeTest::TESTED_TYPE, [
121+
->add('australian', TextTypeTest::TESTED_TYPE, [
92122
'constraints' => [
93123
new NotBlank(['groups' => ['Second']]),
94124
],
95125
])
96126
;
97127

98-
$form->submit(['field1' => 'wrong_1', 'field2' => '']);
128+
$form->submit(['firstName' => '', 'lastName' => 'wrong_1', 'australian' => '']);
99129

100130
$errors = $form->getErrors(true);
101131

0 commit comments

Comments
 (0)