8000 [Form] Made validation of form children configurable. Set the option … · symfony/symfony@0c70a41 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0c70a41

Browse files
committed
[Form] Made validation of form children configurable. Set the option "cascade_validation" to true if you need it.
1 parent efada56 commit 0c70a41

File tree

4 files changed

+104
-3
lines changed

4 files changed

+104
-3
lines changed

src/Symfony/Component/Form/Extension/Validator/Type/FieldTypeValidatorExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function buildForm(FormBuilder $builder, array $options)
3838
$builder
3939
->setAttribute('validation_groups', $options['validation_groups'])
4040
->setAttribute('validation_constraint', $options['validation_constraint'])
41+
->setAttribute('cascade_validation', $options['cascade_validation'])
4142
->addValidator(new DelegatingValidator($this->validator));
4243
}
4344

@@ -46,6 +47,7 @@ public function getDefaultOptions(array $options)
4647
return array(
4748
'validation_groups' => null,
4849
'validation_constraint' => null,
50+
'cascade_validation' => false,
4951
);
5052
}
5153

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,29 @@ static public function validateFormData(FormInterface $form, ExecutionContext $c
127127
}
128128
}
129129

130+
static public function validateFormChildren(FormInterface $form, ExecutionContext $context)
131+
{
132+
if ($form->getAttribute('cascade_validation')) {
133+
$propertyPath = $context->getPropertyPath();
134+
$graphWalker = $context->getGraphWalker();
135+
136+
// The Execute constraint is called on class level, so we need to
137+
// set the property manually
138+
$context->setCurrentProperty('children');
139+
140+
// Adjust the property path accordingly
141+
if (!empty($propertyPath)) {
142+
$propertyPath .= '.';
143+
}
144+
145+
$propertyPath .= 'children';
146+
147+
foreach (self::getFormValidationGroups($form) as $group) {
148+
$graphWalker->walkReference($form->getChildren(), $group, $propertyPath, true);
8000 149+
}
150+
}
151+
}
152+
130153
static protected function getFormValidationGroups(FormInterface $form)
131154
{
132155
$groups = null;

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
<value>Symfony\Component\Form\Extension\Validator\Validator\DelegatingValidator</value>
1111
<value>validateFormData</value>
1212
</value>
13+
<value>
14+
<value>Symfony\Component\Form\Extension\Validator\Validator\DelegatingValidator</value>
15+
<value>validateFormChildren</value>
16+
</value>
1317
</constraint>
14-
<property name="children">
15-
<constraint name="Valid" />
16-
</property>
1718
</class>
1819
</constraint-mapping>

tests/Symfony/Tests/Component/Form/Extension/Validator/Validator/DelegatingValidatorTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,81 @@ public function testValidateFormDataDoesNotWalkScalars()
798798
DelegatingValidator::validateFormData($form, $context);
799799
}
800800

801+
public function testValidateFormChildren()
802+
{
803+
$graphWalker = $this->getMockGraphWalker();
804+
$metadataFactory = $this->getMockMetadataFactory();
805+
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
806+
$form = $this->getBuilder()
807+
->setAttribute('cascade_validation', true)
808+
->setAttribute('validation_groups', array('group1', 'group2'))
809+
->getForm();
810+
$form->add($this->getForm('firstName'));
811+
812+
$graphWalker->expects($this->at(0))
813+
->method('walkReference')
814+
->with($form->getChildren(), 'group1', 'children', true);
815+
$graphWalker->expects($this->at(1))
816+
->method('walkReference')
817+
->with($form->getChildren(), 'group2', 'children', true);
818+
819+
DelegatingValidator::validateFormChildren($form, $context);
820+
}
821+
822+
public function testValidateFormChildrenAppendsPropertyPath()
823+
{
824+
$graphWalker = $this->getMockGraphWalker();
825+
$metadataFactory = $this->getMockMetadataFactory();
826+
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
827+
$context->setPropertyPath('path');
828+
$form = $this->getBuilder()
829+
->setAttribute('cascade_validation', true)
830+
->getForm();
831+
$form->add($this->getForm('firstName'));
832+
833+
$graphWalker->expects($this->once())
834+
->method('walkReference')
835+
->with($form->getChildren(), 'Default', 'path.children', true);
836+
837+
DelegatingValidator::validateFormChildren($form, $context);
838+
}
839+
840+
public function testValidateFormChildrenSetsCurrentPropertyToData()
841+
{
842+
$graphWalker = $this->getMockGraphWalker();
843+
$metadataFactory = $this->getMockMetadataFactory();
844+
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
845+
$form = $this->getBuilder()
846+
->setAttribute('cascade_validation', true)
847+
->getForm();
848+
$form->add($this->getForm('firstName'));
849+
$test = $this;
850+
851+
$graphWalker->expects($this->once())
852+
->method('walkReference')
853+
->will($this->returnCallback(function () use ($context, $test) {
854+
$test->assertEquals('children', $context->getCurrentProperty());
855+
}));
856+
857+
DelegatingValidator::validateFormChildren($form, $context);
858+
}
859+
860+
public function testValidateFormChildrenDoesNothingIfDisabled()
861+
{
862+
$graphWalker = $this->getMockGraphWalker();
863+
$metadataFactory = $this->getMockMetadataFactory();
864+
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
865+
$form = $this->getBuilder()
866+
->setAttribute('cascade_validation', false)
867+
->getForm();
868+
$form->add($this->getForm('firstName'));
869+
870+
$graphWalker->expects($this->never())
871+
->method('walkReference');
872+
873+
DelegatingValidator::validateFormChildren($form, $context);
874+
}
875+
801876
public function testValidateIgnoresNonRoot()
802877
{
803878
$form = $this->getMockForm();

0 commit comments

Comments
 (0)
0