8000 validate subforms in all validation groups · symfony/symfony@b819d94 · GitHub
[go: up one dir, main page]

Skip to content

Commit b819d94

Browse files
committed
validate subforms in all validation groups
1 parent 5ec5bfb commit b819d94

File tree

5 files changed

+61
-18
lines changed
  • src/Symfony/Component/Form
  • 5 files changed

    +61
    -18
    lines changed

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

    Lines changed: 23 additions & 8 deletions
    Original file line numberDiff line numberDiff line change
    @@ -63,12 +63,16 @@ public function validate($form, Constraint $formConstraint)
    6363
    /** @var Constraint[] $constraints */
    6464
    $constraints = $config->getOption('constraints', []);
    6565

    66+
    $hasChildren = $form->count() > 0;
    67+
    68+
    if ($hasChildren && $form->isRoot()) {
    69+
    $this->resolvedGroups = new \SplObjectStorage();
    70+
    }
    71+
    6672
    if ($groups instanceof GroupSequence) {
    6773
    // Validate the data, the form AND nested fields in sequence
    6874
    $violationsCount = $this->context->getViolations()->count();
    6975
    $fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s';
    70-
    $hasChildren = $form->count() > 0;
    71-
    $this->resolvedGroups = $hasChildren ? new \SplObjectStorage() : null;
    7276

    7377
    foreach ($groups->groups as $group) {
    7478
    if ($validateDataGraph) {
    @@ -86,20 +90,18 @@ public function validate($form, Constraint $formConstraint)
    8690
    // sequence recursively, thus some fields could fail
    8791
    // in different steps without breaking early enough
    8892
    $this->resolvedGroups[$field] = (array) $group;
    89-
    $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $formConstraint);
    93+
    $fieldFormConstraint = new Form();
    94+
    $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $fieldFormConstraint);
    9095
    }
    9196
    }
    9297

    9398
    if ($violationsCount < $this->context->getViolations()->count()) {
    9499
    break;
    95100
    }
    96101
    }
    97-
    98-
    if ($hasChildren) {
    99-
    // destroy storage at the end of the sequence to avoid memory leaks
    100-
    $this->resolvedGroups = null;
    101-
    }
    102102
    } else {
    103+
    $fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s';
    104+
    103105
    if ($validateDataGraph) {
    104106
    $validator->atPath('data')->validate($data, null, $groups);
    105107
    }
    @@ -125,6 +127,19 @@ public function validate($form, Constraint $formConstraint)
    125127
    }
    126128
    }
    127129
    }
    130+
    131+
    foreach ($form->all() as $field) {
    132+
    if ($field->isSubmitted()) {
    133+
    $this->resolvedGroups[$field] = $groups;
    134+
    $fieldFormConstraint = new Form();
    135+
    $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $fieldFormConstraint);
    136+
    }
    137+
    }
    138+
    }
    139+
    140+
    if ($hasChildren && $form->isRoot()) {
    141+
    // destroy storage to avoid memory leaks
    142+
    $this->resolvedGroups = new \SplObjectStorage();
    128143
    }
    129144
    } elseif (!$form->isSynchronized()) {
    130145
    $childrenSynchronized = true;

    src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -13,7 +13,7 @@
    1313

    1414
    use Symfony\Component\Form\AbstractExtension;
    1515
    use Symfony\Component\Form\Extension\Validator\Constraints\Form;
    16-
    use Symfony\Component\Validator\Constraints\Valid;
    16+
    use Symfony\Component\Validator\Constraints\Traverse;
    1717
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    1818
    use Symfony\Component\Validator\Validator\ValidatorInterface;
    1919

    @@ -37,7 +37,7 @@ public function __construct(ValidatorInterface $validator)
    3737

    3838
    /* @var $metadata ClassMetadata */
    3939
    $metadata->addConstraint(new Form());
    40-
    $metadata->addPropertyConstraint('children', new Valid());
    40+
    $metadata->addConstraint(new Traverse(false));
    4141

    4242
    $this->validator = $validator;
    4343
    }

    src/Symfony/Component/Form/Resources/config/validation.xml

    Lines changed: 3 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -6,8 +6,8 @@
    66

    77
    <class name="Symfony\Component\Form\Form">
    88
    <constraint name="Symfony\Component\Form\Extension\Validator\Constraints\Form" />
    9-
    <property name="children">
    10-
    <constraint name="Valid" />
    11-
    </property>
    9+
    <constraint name="Symfony\Component\Validator\Constraints\Traverse">
    10+
    <option name="traverse">false</option>
    11+
    </constraint>
    1212
    </class>
    1313
    </constraint-mapping>

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

    Lines changed: 4 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -615,7 +615,8 @@ public function testViolationIfExtraData()
    615615

    616616
    $this->assertTrue($form->isSubmitted());
    617617
    $this->assertTrue($form->isSynchronized());
    618-
    $this->expectNoValidate();
    618+
    619+
    $this->expectValidateValueAt(0, 'children[child]', $form->get('child'), new Form());
    619620

    620621
    $this->validator->validate($form, new Form());
    621622

    @@ -638,7 +639,8 @@ public function testViolationFormatIfMultipleExtraFields()
    638639

    639640
    $this->assertTrue($form->isSubmitted());
    640641
    $this->assertTrue($form->isSynchronized());
    641-
    $this->expectNoValidate();
    642+
    643+
    $this->expectValidateValueAt(0, 'children[child]', $form->get('child'), new Form());
    642644

    643645
    $this->validator->validate($form, new Form());
    644646

    src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php

    Lines changed: 29 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -54,9 +54,8 @@ public function test2Dot5ValidationApi()
    5454
    $this->assertInstanceOf(FormConstraint::class, $metadata->getConstraints()[0]);
    5555

    5656
    $this->assertSame(CascadingStrategy::NONE, $metadata->cascadingStrategy);
    57-
    $this->assertSame(TraversalStrategy::IMPLICIT, $metadata->traversalStrategy);
    58-
    $this->assertSame(CascadingStrategy::CASCADE, $metadata->getPropertyMetadata('children')[0]->cascadingStrategy);
    59-
    $this->assertSame(TraversalStrategy::IMPLICIT, $metadata->getPropertyMetadata('children')[0]->traversalStrategy);
    57+
    $this->assertSame(TraversalStrategy::NONE, $metadata->traversalStrategy);
    58+
    $this->assertCount(0, $metadata->getPropertyMetadata('children'));
    6059
    }
    6160

    6261
    public function testDataConstraintsInvalidateFormEvenIfFieldIsNotSubmitted()
    @@ -138,6 +137,33 @@ public function testFieldsValidateInSequenceWithNestedGroupsArray()
    138137
    $this->assertInstanceOf(Length::class, $errors[1]->getCause()->getConstraint());
    139138
    }
    140139

    140+
    public function testConstraintsInDifferentGroupsOnSingleField()
    141+
    {
    142+
    $form = $this->createForm(FormType::class, null, [
    143+
    'validation_groups' => new GroupSequence(['group1', 'group2']),
    144+
    ])
    145+
    ->add('foo', TextType::class, [
    146+
    'constraints' => [
    147+
    new NotBlank([
    148+
    'groups' => ['group1'],
    149+
    ]),
    150+
    new Length([
    151+
    'groups' => ['group2'],
    152+
    'max' => 3,
    153+
    ]),
    154+
    ],
    155+
    ]);
    156+
    $form->submit([
    157+
    'foo' => 'test@example.com',
    158+
    ]);
    159+
    160+
    $errors = $form->getErrors(true);
    161+
    162+
    $this->assertFalse($form->isValid());
    163+
    $this->assertCount(1, $errors);
    164+
    $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint());
    165+
    }
    166+
    141167
    private function createForm($type, $data = null, array $options = [])
    142168
    {
    143169
    $validator = Validation::createValidatorBuilder()

    0 commit comments

    Comments
     (0)
    0