Skip to content

Commit 0f62d32

Browse files
committed
[Form] Deprecated "cascade_validation"
1 parent 09fabfe commit 0f62d32

File tree

7 files changed

+173
-29
lines changed

7 files changed

+173
-29
lines changed

UPGRADE-2.6.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,45 @@ Form
5555
...
5656
{% endif %}
5757
```
58+
59+
* The "cascade_validation" option was deprecated. Use the "constraints"
60+
option together with the `Valid` constraint instead. Contrary to
61+
"cascade_validation", "constraints" must be set on the respective child forms,
62+
not the parent form.
63+
64+
Before:
65+
66+
```php
67+
$form = $this->createForm('form', $article, array('cascade_validation' => true))
68+
->add('author', new AuthorType())
69+
->getForm();
70+
```
71+
72+
After:
73+
74+
```php
75+
use Symfony\Component\Validator\Constraints\Valid;
76+
77+
$form = $this->createForm('form', $article)
78+
->add('author', new AuthorType(), array(
79+
'constraints' => new Valid(),
80+
))
81+
->getForm();
82+
```
83+
84+
Alternatively, you can set the `Valid` constraint in the model itself:
85+
86+
```php
87+
use Symfony\Component\Validator\Constraints as Assert;
88+
89+
class Article
90+
{
91+
/**
92+
* @Assert\Valid
93+
*/
94+
private $author;
95+
}
96+
```
5897

5998
Validator
6099
---------

src/Symfony/Component/Form/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
-----

src/Symfony/Component/Form/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) {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
5656
}
5757

5858
/**
59+
*
5960
* {@inheritdoc}
6061
*/
6162
public function configureOptions(OptionsResolver $resolver)
@@ -67,6 +68,14 @@ public function configureOptions(OptionsResolver $resolver)
6768
return is_object($constraints) ? array($constraints) : (array) $constraints;
6869
};
6970

71+
$cascadeValidationNormalizer = function (Options $options, $cascadeValidation) {
72+
if ($cascadeValidation) {
73+
@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);
74+
}
75+
76+
return $cascadeValidation;
77+
};
78+
7079
$resolver->setDefaults(array(
7180
'error_mapping' => array(),
7281
'constraints' => array(),
@@ -78,6 +87,7 @@ public function configureOptions(OptionsResolver $resolver)
7887
));
7988

8089
$resolver->setNormalizer('constraints', $constraintsNormalizer);
90+
$resolver->setNormalizer('cascade_validation', $cascadeValidationNormalizer);
8191
}
8292

8393
/**

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

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Validator\Context\ExecutionContextInterface;
2222
use Symfony\Component\Validator\Constraints\NotNull;
2323
use Symfony\Component\Validator\Constraints\NotBlank;
24+
use Symfony\Component\Validator\Constraints\Valid;
2425
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
2526
use Symfony\Component\Validator\Validation;
2627

@@ -109,6 +110,52 @@ public function testValidateConstraints()
109110
$this->assertNoViolation();
110111
}
111112

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

390-
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
437+
$parent = $this->getBuilder('parent')
391438
->setCompound(true)
392439
->setDataMapper($this->getDataMapper())
393440
->getForm();
394441
$form = $this->getForm('name', '\stdClass', array(
395442
'validation_groups' => 'form_group',
443+
'constraints' => array(new Valid()),
396444
));
397445

398446
$parent->add($form);
@@ -402,7 +450,7 @@ public function testUseValidationGroupOfClickedButton()
402450

403451
$parent->submit(array('name' => $object, 'submit' => ''));
404452

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

407455
$this->validator->validate($form, new Form());
408456

@@ -413,12 +461,13 @@ public function testDontUseValidationGroupOfUnclickedButton()
413461
{
414462
$object = $this->getMock('\stdClass');
415463

416-
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
464+
$parent = $this->getBuilder('parent')
417465
->setCompound(true)
418466
->setDataMapper($this->getDataMapper())
419467
->getForm();
420468
$form = $this->getForm('name', '\stdClass', array(
421469
'validation_groups' => 'form_group',
470+
'constraints' => array(new Valid()),
422471
));
423472

424473
$parent->add($form);
@@ -428,7 +477,7 @@ public function testDontUseValidationGroupOfUnclickedButton()
428477

429478
$form->setData($object);
430479

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

433482
$this->validator->validate($form, new Form());
434483

@@ -439,20 +488,18 @@ public function testUseInheritedValidationGroup()
439488
{
440489
$object = $this->getMock('\stdClass');
441490

442-
$parentOptions = array(
443-
'validation_groups' => 'group',
444-
'cascade_validation' => true,
445-
);
491+
$parentOptions = array('validation_groups' => 'group');
446492
$parent = $this->getBuilder('parent', null, $parentOptions)
447493
->setCompound(true)
448494
->setDataMapper($this->getDataMapper())
449495
->getForm();
450-
$form = $this->getBuilder('name', '\stdClass')->getForm();
496+
$formOptions = array('constraints' => array(new Valid()));
497+
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
451498
$parent->add($form);
452499

453500
$form->setData($object);
454501

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

457504
$this->validator->validate($form, new Form());
458505

@@ -463,21 +510,18 @@ public function testUseInheritedCallbackValidationGroup()
463510
{
464511
$object = $this->getMock('\stdClass');
465512

466-
$parentOptions = array(
467-
'validation_groups' => array($this, 'getValidationGroups'),
468-
'cascade_validation' => true,
469-
);
513+
$parentOptions = array('validation_groups' => array($this, 'getValidationGroups'));
470514
$parent = $this->getBuilder('parent', null, $parentOptions)
471515
->setCompound(true)
472516
->setDataMapper($this->getDataMapper())
473517
->getForm();
474-
$form = $this->getBuilder('name', '\stdClass')->getForm();
518+
$formOptions = array('constraints' => array(new Valid()));
519+
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
475520
$parent->add($form);
476521

477522
$form->setData($object);
478523

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

482526
$this->validator->validate($form, new Form());
483527

@@ -492,19 +536,18 @@ public function testUseInheritedClosureValidationGroup()
492536
'validation_groups' => function (FormInterface $form) {
493537
return array('group1', 'group2');
494538
},
495-
'cascade_validation' => true,
496539
);
497540
$parent = $this->getBuilder('parent', null, $parentOptions)
498541
->setCompound(true)
499542
->setDataMapper($this->getDataMapper())
500543
->getForm();
501-
$form = $this->getBuilder('name', '\stdClass')->getForm();
544+
$formOptions = array('constraints' => array(new Valid()));
545+
$form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm();
502546
$parent->add($form);
503547

504548
$form->setData($object);
505549

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

509552
$this->validator->validate($form, new Form());
510553

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

Lines changed: 25 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,30 @@ 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+
public function testCascadeValidationCanBeSetToFalse()
59+
{
60+
$form = $this->createForm(array('cascade_validation' => false));
61+
62+
$this->assertFalse($form->getConfig()->getOption('cascade_validation'));
63+
}
64+
4065
public function testValidatorInterfaceSinceSymfony25()
4166
{
4267
// Mock of ValidatorInterface since apiVersion 2.5

src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,24 @@ protected function expectNoValidate()
220220

221221
protected function expectValidateAt($i, $propertyPath, $value, $group)
222222
{
223-
$validator = $this->context->getValidator()->inContext($this->context);
224-
$validator->expects($this->at(2 * $i))
225-
->method('atPath')
226-
->with($propertyPath)
227-
->will($this->returnValue($validator));
228-
$validator->expects($this->at(2 * $i + 1))
229-
->method('validate')
230-
->with($value, $this->logicalOr(null, array()), $group);
223+
switch ($this->getApiVersion()) {
224+
case Validation::API_VERSION_2_4:
225+
$this->context->expects($this->at($i))
226+
->method('validate')
227+
->with($value, $propertyPath, $group);
228+
break;
229+
case Validation::API_VERSION_2_5:
230+
case Validation::API_VERSION_2_5_BC:
231+
$validator = $this->context->getValidator()->inContext($this->context);
232+
$validator->expects($this->at(2 * $i))
233+
->method('atPath')
234+
->with($propertyPath)
235+
->will($this->returnValue($validator));
236+
$validator->expects($this->at(2 * $i + 1))
237+
->method('validate')
238+
->with($value, $this->logicalOr(null, array(), $this->isInstanceOf('\Symfony\Component\Validator\Constraints\Valid')), $group);
239+
break;
240+
}
231241
}
232242

233243
protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy