Skip to content

Commit 14322f1

Browse files
committed
[Form] Deprecated "cascade_validation"
1 parent 1d68cea commit 14322f1

File tree

5 files changed

+119
-23
lines changed

5 files changed

+119
-23
lines changed

CHANGELOG.md

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

77
* deprecated option "read_only" in favor of "attr['readonly']"
88
* added the html5 "range" FormType
9+
* deprecated the "cascade_validation" option in favor of setting "constraints"
10+
with the Valid constraint
911

1012
2.7.0
1113
-----

Extension/Validator/Constraints/FormValidator.php

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

1414
use Symfony\Component\Form\FormInterface;
1515
use Symfony\Component\Validator\Constraint;
16+
use Symfony\Component\Validator\Constraints\Valid;
1617
use Symfony\Component\Validator\ConstraintValidator;
1718
use Symfony\Component\Validator\Context\ExecutionContextInterface;
1819
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
@@ -63,6 +64,20 @@ public function validate($form, Constraint $constraint)
6364
// in the form
6465
$constraints = $config->getOption('constraints');
6566
foreach ($constraints as $constraint) {
67+
// For the "Valid" constraint, validate the data in all groups
68+
if ($constraint instanceof Valid) {
69+
if ($validator) {
70+
$validator->atPath('data')->validate($form->getData(), $constraint, $groups);
71+
} else {
72+
// 2.4 API
73+
$this->context->validateValue($form->getData(), $constraint, 'data', $groups);
74+
}
75+
76+
continue;
77+
}
78+
79+
// Otherwise validate a constraint only once for the first
80+
// matching group
6681
foreach ($groups as $group) {
6782
if (in_array($group, $constraint->groups)) {
6883
if ($validator) {

Extension/Validator/Type/FormTypeValidatorExtension.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,26 @@ public function configureOptions(OptionsResolver $resolver)
6767
return is_object($constraints) ? array($constraints) : (array) $constraints;
6868
};
6969

70+
$cascadeValidationNormalizer = function (Options $options, $cascadeValidation) {
71+
if (null !== $cascadeValidation) {
72+
@trigger_error('The "cascade_validation" option is deprecated since version 2.8 and will be removed in 3.0. Use "constraints" with a Valid constraint instead.', E_USER_DEPRECATED);
73+
}
74+
75+
return null === $cascadeValidation ? false : $cascadeValidation;
76+
};
77+
7078
$resolver->setDefaults(array(
7179
'error_mapping' => array(),
7280
'constraints' => array(),
73-
'cascade_validation' => false,
81+
'cascade_validation' => null,
7482
'invalid_message' => 'This value is not valid.',
7583
'invalid_message_parameters' => array(),
7684
'allow_extra_fields' => false,
7785
'extra_fields_message' => 'This form should not contain extra fields.',
7886
));
7987

8088
$resolver->setNormalizer('constraints', $constraintsNormalizer);
89+
$resolver->setNormalizer('cascade_validation', $cascadeValidationNormalizer);
8190
}
8291

8392
/**

Tests/Extension/Validator/Constraints/FormValidatorTest.php

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
1919
use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator;
2020
use Symfony\Component\Form\SubmitButtonBuilder;
21-
use Symfony\Component\Validator\Context\ExecutionContextInterface;
2221
use Symfony\Component\Validator\Constraints\NotNull;
2322
use Symfony\Component\Validator\Constraints\NotBlank;
23+
use Symfony\Component\Validator\Constraints\Valid;
2424
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
2525
use Symfony\Component\Validator\Validation;
2626

@@ -109,6 +109,52 @@ public function testValidateConstraints()
109109
$this->assertNoViolation();
110110
}
111111

112+
public function testValidateIfParentWithCascadeValidation()
113+
{
114+
$object = $this->getMock('\stdClass');
115+
116+
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
117+
->setCompound(true)
118+
->setDataMapper($this->getDataMapper())
119+
->getForm();
120+
$options = array('validation_groups' => array('group1', 'group2'));
121+
$form = $this->getBuilder('name', '\stdClass', $options)->getForm();
122+
$parent->add($form);
123+
124+
$form->setData($object);
125+
126+
$this->expectValidateAt(0, 'data', $object, 'group1');
127+
$this->expectValidateAt(1, 'data', $object, 'group2');
128+
129+
$this->validator->validate($form, new Form());
130+
131+
$this->assertNoViolation();
132+
}
133+
134+
public function testValidateIfChildWithValidConstraint()
135+
{
136+
$object = $this->getMock('\stdClass');
137+
138+
$parent = $this->getBuilder('parent')
139+
->setCompound(true)
140+
->setDataMapper($this->getDataMapper())
141+
->getForm();
142+
$options = array(
143+
'validation_groups' => array('group1', 'group2'),
144+
'constraints' => array(new Valid()),
145+
);
146+
$form = $this->getBuilder('name', '\stdClass', $options)->getForm();
147+
$parent->add($form);
148+
149+
$form->setData($object);
150+
151+
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
152+
153+
$this->validator->validate($form, new Form());
154+
155+
$this->assertNoViolation();
156+
}
157+
112158
public function testDontValidateIfParentWithoutCascadeValidation()
113159
{
114160
$object = $this->getMock('\stdClass');
@@ -387,12 +433,13 @@ public function testUseValidationGroupOfClickedButton()
387433
{
388434
$object = $this->getMock('\stdClass');
389435

390-
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
436+
$parent = $this->getBuilder('parent')
391437
->setCompound(true)
392438
->setDataMapper($this->getDataMapper())
393439
->getForm();
394440
$form = $this->getForm('name', '\stdClass', array(
395441
'validation_groups' => 'form_group',
442+
'constraints' => array(new Valid()),
396443
));
397444

398445
$parent->add($form);
@@ -402,7 +449,7 @@ public function testUseValidationGroupOfClickedButton()
402449

403450
$parent->submit(array('name' => $object, 'submit' => ''));
404451

405-
$this->expectValidateAt(0, 'data', $object, 'button_group');
452+
$this->expectValidateAt(0, 'data', $object, array('button_group'));
406453

407454
$this->validator->validate($form, new Form());
408455

@@ -413,12 +460,13 @@ public function testDontUseValidationGroupOfUnclickedButton()
413460
{
414461
$object = $this->getMock('\stdClass');
415462

416-
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
463+
$parent = $this->getBuilder('parent')
417464
->setCompound(true)
418465
->setDataMapper($this->getDataMapper())
419466
->getForm();
420467
$form = $this->getForm('name', '\stdClass', array(
421468
'validation_groups' => 'form_group',
469+
'constraints' => array(new Valid()),
422470
));
423471

424472
$parent->add($form);
@@ -428,7 +476,7 @@ public function testDontUseValidationGroupOfUnclickedButton()
428476

429477
$form->setData($object);
430478

431-
$this->expectValidateAt(0, 'data', $object, 'form_group');
479+
$this->expectValidateAt(0, 'data', $object, array('form_group'));
432480

433481
$this->validator->validate($form, new Form());
434482

@@ -439,20 +487,18 @@ public function testUseInheritedValidationGroup()
439487
{
440488
$object = $this->getMock('\stdClass');
441489

442-
$parentOptions = array(
443-
'validation_groups' => 'group',
444-
'cascade_validation' => true,
445-
);
490+
$parentOptions = array('validation_groups' => 'group');
446491
$parent = $this->getBuilder('parent', null, $parentOptions)
447492
->setCompound(true)
448493
->setDataMapper($this->getDataMapper())
449494
->getForm();
450-
$form = $this->getBuilder('name', '\stdClass')->getForm();
495+
$formOptions = array('constraints' => array(new Valid()));
496+
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
451497
$parent->add($form);
452498

453499
$form->setData($object);
454500

455-
$this->expectValidateAt(0, 'data', $object, 'group');
501+
$this->expectValidateAt(0, 'data', $object, array('group'));
456502

457503
$this->validator->validate($form, new Form());
458504

@@ -463,21 +509,18 @@ public function testUseInheritedCallbackValidationGroup()
463509
{
464510
$object = $this->getMock('\stdClass');
465511

466-
$parentOptions = array(
467-
'validation_groups' => array($this, 'getValidationGroups'),
468-
'cascade_validation' => true,
469-
);
512+
$parentOptions = array('validation_groups' => array($this, 'getValidationGroups'));
470513
$parent = $this->getBuilder('parent', null, $parentOptions)
471514
->setCompound(true)
472515
->setDataMapper($this->getDataMapper())
473516
->getForm();
474-
$form = $this->getBuilder('name', '\stdClass')->getForm();
517+
$formOptions = array('constraints' => array(new Valid()));
518+
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
475519
$parent->add($form);
476520

477521
$form->setData($object);
478522

479-
$this->expectValidateAt(0, 'data', $object, 'group1');
480-
$this->expectValidateAt(1, 'data', $object, 'group2');
523+
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
481524

482525
$this->validator->validate($form, new Form());
483526

@@ -492,19 +535,18 @@ public function testUseInheritedClosureValidationGroup()
492535
'validation_groups' => function (FormInterface $form) {
493536
return array('group1', 'group2');
494537
},
495-
'cascade_validation' => true,
496538
);
497539
$parent = $this->getBuilder('parent', null, $parentOptions)
498540
->setCompound(true)
499541
->setDataMapper($this->getDataMapper())
500542
->getForm();
501-
$form = $this->getBuilder('name', '\stdClass')->getForm();
543+
$formOptions = array('constraints' => array(new Valid()));
544+
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
502545
$parent->add($form);
503546

504547
$form->setData($object);
505548

506-
$this->expectValidateAt(0, 'data', $object, 'group1');
507-
$this->expectValidateAt(1, 'data', $object, 'group2');
549+
$this->expectValidateAt(0, 'data', $object, array('group1', 'group2'));
508550

509551
$this->validator->validate($form, new Form());
510552

Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
1313

1414
use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension;
15+
use Symfony\Component\Validator\Constraints\Valid;
1516
use Symfony\Component\Validator\ConstraintViolationList;
1617

1718
class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest
@@ -37,6 +38,33 @@ public function testSubmitValidatesData()
3738
$form->submit(array());
3839
}
3940

41+
public function testValidConstraint()
42+
{
43+
$form = $this->createForm(array('constraints' => $valid = new Valid()));
44+
45+
$this->assertSame(array($valid), $form->getConfig()->getOption('constraints'));
46+
}
47+
48+
/**
49+
* @group legacy
50+
*/
51+
public function testCascadeValidationCanBeSetToTrue()
52+
{
53+
$form = $this->createForm(array('cascade_validation' => true));
54+
55+
$this->assertTrue($form->getConfig()->getOption('cascade_validation'));
56+
}
57+
58+
/**
59+
* @group legacy
60+
*/
61+
public function testCascadeValidationCanBeSetToFalse()
62+
{
63+
$form = $this->createForm(array('cascade_validation' => false));
64+
65+
$this->assertFalse($form->getConfig()->getOption('cascade_validation'));
66+
}
67+
4068
public function testValidatorInterfaceSinceSymfony25()
4169
{
4270
// Mock of ValidatorInterface since apiVersion 2.5

0 commit comments

Comments
 (0)