Skip to content

Commit 4be56f6

Browse files
bug symfony#38380 [Form] propagate validation groups to subforms (johanderuijter, xabbuh)
This PR was merged into the 3.4 branch. Discussion ---------- [Form] propagate validation groups to subforms | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix symfony#38300 | License | MIT | Doc PR | Commits ------- 04f5698 propagate validation groups to subforms e2c7c33 [Form] [Validator] Add failing testcase to demonstrate group sequence issue
2 parents 60bfdaa + 04f5698 commit 4be56f6

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
class FormValidator extends ConstraintValidator
2626
{
2727
private $resolvedGroups;
28+
private $fieldFormConstraints;
2829

2930
/**
3031
* {@inheritdoc}
@@ -67,6 +68,7 @@ public function validate($form, Constraint $formConstraint)
6768

6869
if ($hasChildren && $form->isRoot()) {
6970
$this->resolvedGroups = new \SplObjectStorage();
71+
$this->fieldFormConstraints = [];
7072
}
7173

7274
if ($groups instanceof GroupSequence) {
@@ -84,14 +86,16 @@ public function validate($form, Constraint $formConstraint)
8486

8587
foreach ($form->all() as $field) {
8688
if ($field->isSubmitted()) {
87-
// remember to validate this field is one group only
89+
// remember to validate this field in one group only
8890
// otherwise resolving the groups would reuse the same
8991
// sequence recursively, thus some fields could fail
9092
// in different steps without breaking early enough
9193
$this->resolvedGroups[$field] = (array) $group;
9294
$fieldFormConstraint = new Form();
95+
$fieldFormConstraint->groups = $group;
96+
$this->fieldFormConstraints[] = $fieldFormConstraint;
9397
$this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath());
94-
$validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint);
98+
$validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint, $group);
9599
}
96100
}
97101

@@ -130,6 +134,7 @@ public function validate($form, Constraint $formConstraint)
130134
if ($field->isSubmitted()) {
131135
$this->resolvedGroups[$field] = $groups;
132136
$fieldFormConstraint = new Form();
137+
$this->fieldFormConstraints[] = $fieldFormConstraint;
133138
$this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath());
134139
$validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint);
135140
}
@@ -139,6 +144,7 @@ public function validate($form, Constraint $formConstraint)
139144
if ($hasChildren && $form->isRoot()) {
140145
// destroy storage to avoid memory leaks
141146
$this->resolvedGroups = new \SplObjectStorage();
147+
$this->fieldFormConstraints = [];
142148
}
143149
} elseif (!$form->isSynchronized()) {
144150
$childrenSynchronized = true;
@@ -149,6 +155,7 @@ public function validate($form, Constraint $formConstraint)
149155
$childrenSynchronized = false;
150156

151157
$fieldFormConstraint = new Form();
158+
$this->fieldFormConstraints[] = $fieldFormConstraint;
152159
$this->context->setNode($this->context->getValue(), $child, $this->context->getMetadata(), $this->context->getPropertyPath());
153160
$validator->atPath(sprintf('children[%s]', $child->getName()))->validate($child, $fieldFormConstraint);
154161
}

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,34 @@ public function testConstraintsInDifferentGroupsOnSingleField()
232232
$this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint());
233233
}
234234

235+
public function testConstraintsInDifferentGroupsOnSingleFieldWithAdditionalFieldThatHasNoConstraintsAddedBeforeTheFieldWithConstraints()
236+
{
237+
$form = $this->formFactory->create(FormType::class, null, [
238+
'validation_groups' => new GroupSequence(['group1', 'group2']),
239+
])
240+
->add('bar')
241+
->add('foo', TextType::class, [
242+
'constraints' => [
243+
new NotBlank([
244+
'groups' => ['group1'],
245+
]),
246+
new Length([
247+
'groups' => ['group2'],
248+
'max' => 3,
249+
]),
250+
],
251+
]);
252+
$form->submit([
253+
'foo' => '[email protected]',
254+
]);
255+
256+
$errors = $form->getErrors(true);
257+
258+
$this->assertFalse($form->isValid());
259+
$this->assertCount(1, $errors);
260+
$this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint());
261+
}
262+
235263
public function testCascadeValidationToChildFormsUsingPropertyPaths()
236264
{
237265
$form = $this->formFactory->create(FormType::class, null, [

0 commit comments

Comments
 (0)