From 6c554c6c1af6ca6a454c4aaed2b88135667c1153 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 16 Oct 2014 15:46:22 +0200 Subject: [PATCH] [Form] Deprecated "cascade_validation" --- UPGRADE-2.8.md | 43 ++++++++++ src/Symfony/Component/Form/CHANGELOG.md | 2 + .../Validator/Constraints/FormValidator.php | 15 ++++ .../Type/FormTypeValidatorExtension.php | 11 ++- .../Constraints/FormValidatorTest.php | 86 ++++++++++++++----- .../Type/FormTypeValidatorExtensionTest.php | 28 ++++++ .../AbstractConstraintValidatorTest.php | 26 ++++-- 7 files changed, 180 insertions(+), 31 deletions(-) diff --git a/UPGRADE-2.8.md b/UPGRADE-2.8.md index 07c336c7c2ba0..a58bb1834fe3e 100644 --- a/UPGRADE-2.8.md +++ b/UPGRADE-2.8.md @@ -1,8 +1,51 @@ UPGRADE FROM 2.7 to 2.8 ======================= +Form +---- + + * The "cascade_validation" option was deprecated. Use the "constraints" + option together with the `Valid` constraint instead. Contrary to + "cascade_validation", "constraints" must be set on the respective child forms, + not the parent form. + + Before: + + ```php + $form = $this->createForm('form', $article, array('cascade_validation' => true)) + ->add('author', new AuthorType()) + ->getForm(); + ``` + + After: + + ```php + use Symfony\Component\Validator\Constraints\Valid; + + $form = $this->createForm('form', $article) + ->add('author', new AuthorType(), array( + 'constraints' => new Valid(), + )) + ->getForm(); + ``` + + Alternatively, you can set the `Valid` constraint in the model itself: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + class Article + { + /** + * @Assert\Valid + */ + private $author; + } + ``` + Translator ---------- + * The `getMessages()` method of the `Symfony\Component\Translation\Translator` was deprecated and will be removed in Symfony 3.0. You should use the `getCatalogue()` method of the `Symfony\Component\Translation\TranslatorBagInterface`. diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 014bdbe26e156..330f0b1417e25 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * deprecated option "read_only" in favor of "attr['readonly']" * added the html5 "range" FormType + * deprecated the "cascade_validation" option in favor of setting "constraints" + with the Valid constraint 2.7.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 19e9dd5d7033e..25a8f3a3edace 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\UnexpectedTypeException; @@ -63,6 +64,20 @@ public function validate($form, Constraint $constraint) // in the form $constraints = $config->getOption('constraints'); foreach ($constraints as $constraint) { + // For the "Valid" constraint, validate the data in all groups + if ($constraint instanceof Valid) { + if ($validator) { + $validator->atPath('data')->validate($form->getData(), $constraint, $groups); + } else { + // 2.4 API + $this->context->validateValue($form->getData(), $constraint, 'data', $groups); + } + + continue; + } + + // Otherwise validate a constraint only once for the first + // matching group foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { if ($validator) { diff --git a/src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php index 16030ae03ffb9..97c0d67997ece 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -67,10 +67,18 @@ public function configureOptions(OptionsResolver $resolver) return is_object($constraints) ? array($constraints) : (array) $constraints; }; + $cascadeValidationNormalizer = function (Options $options, $cascadeValidation) { + if (null !== $cascadeValidation) { + @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); + } + + return null === $cascadeValidation ? false : $cascadeValidation; + }; + $resolver->setDefaults(array( 'error_mapping' => array(), 'constraints' => array(), - 'cascade_validation' => false, + 'cascade_validation' => null, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'allow_extra_fields' => false, @@ -78,6 +86,7 @@ public function configureOptions(OptionsResolver $resolver) )); $resolver->setNormalizer('constraints', $constraintsNormalizer); + $resolver->setNormalizer('cascade_validation', $cascadeValidationNormalizer); } /** diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index ba40307c3a458..74d6095d17d59 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -18,9 +18,9 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; use Symfony\Component\Form\SubmitButtonBuilder; -use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; use Symfony\Component\Validator\Validation; @@ -109,6 +109,52 @@ public function testValidateConstraints() $this->assertNoViolation(); } + public function testValidateIfParentWithCascadeValidation() + { + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $options = array('validation_groups' => array('group1', 'group2')); + $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); + $parent->add($form); + + $form->setData($object); + + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); + + $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); + } + + public function testValidateIfChildWithValidConstraint() + { + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $options = array( + 'validation_groups' => array('group1', 'group2'), + 'constraints' => array(new Valid()), + ); + $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); + $parent->add($form); + + $form->setData($object); + + $this->expectValidateAt(0, 'data', $object, array('group1', 'group2')); + + $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); + } + public function testDontValidateIfParentWithoutCascadeValidation() { $object = $this->getMock('\stdClass'); @@ -387,12 +433,13 @@ public function testUseValidationGroupOfClickedButton() { $object = $this->getMock('\stdClass'); - $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + $parent = $this->getBuilder('parent') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', array( 'validation_groups' => 'form_group', + 'constraints' => array(new Valid()), )); $parent->add($form); @@ -402,7 +449,7 @@ public function testUseValidationGroupOfClickedButton() $parent->submit(array('name' => $object, 'submit' => '')); - $this->expectValidateAt(0, 'data', $object, 'button_group'); + $this->expectValidateAt(0, 'data', $object, array('button_group')); $this->validator->validate($form, new Form()); @@ -413,12 +460,13 @@ public function testDontUseValidationGroupOfUnclickedButton() { $object = $this->getMock('\stdClass'); - $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + $parent = $this->getBuilder('parent') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', array( 'validation_groups' => 'form_group', + 'constraints' => array(new Valid()), )); $parent->add($form); @@ -428,7 +476,7 @@ public function testDontUseValidationGroupOfUnclickedButton() $form->setData($object); - $this->expectValidateAt(0, 'data', $object, 'form_group'); + $this->expectValidateAt(0, 'data', $object, array('form_group')); $this->validator->validate($form, new Form()); @@ -439,20 +487,18 @@ public function testUseInheritedValidationGroup() { $object = $this->getMock('\stdClass'); - $parentOptions = array( - 'validation_groups' => 'group', - 'cascade_validation' => true, - ); + $parentOptions = array('validation_groups' => 'group'); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); - $form = $this->getBuilder('name', '\stdClass')->getForm(); + $formOptions = array('constraints' => array(new Valid())); + $form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm(); $parent->add($form); $form->setData($object); - $this->expectValidateAt(0, 'data', $object, 'group'); + $this->expectValidateAt(0, 'data', $object, array('group')); $this->validator->validate($form, new Form()); @@ -463,21 +509,18 @@ public function testUseInheritedCallbackValidationGroup() { $object = $this->getMock('\stdClass'); - $parentOptions = array( - 'validation_groups' => array($this, 'getValidationGroups'), - 'cascade_validation' => true, - ); + $parentOptions = array('validation_groups' => array($this, 'getValidationGroups')); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); - $form = $this->getBuilder('name', '\stdClass')->getForm(); + $formOptions = array('constraints' => array(new Valid())); + $form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm(); $parent->add($form); $form->setData($object); - $this->expectValidateAt(0, 'data', $object, 'group1'); - $this->expectValidateAt(1, 'data', $object, 'group2'); + $this->expectValidateAt(0, 'data', $object, array('group1', 'group2')); $this->validator->validate($form, new Form()); @@ -492,19 +535,18 @@ public function testUseInheritedClosureValidationGroup() 'validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }, - 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); - $form = $this->getBuilder('name', '\stdClass')->getForm(); + $formOptions = array('constraints' => array(new Valid())); + $form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm(); $parent->add($form); $form->setData($object); - $this->expectValidateAt(0, 'data', $object, 'group1'); - $this->expectValidateAt(1, 'data', $object, 'group2'); + $this->expectValidateAt(0, 'data', $object, array('group1', 'group2')); $this->validator->validate($form, new Form()); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 4ca10da50e88d..f24f8404418c2 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; +use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest @@ -37,6 +38,33 @@ public function testSubmitValidatesData() $form->submit(array()); } + public function testValidConstraint() + { + $form = $this->createForm(array('constraints' => $valid = new Valid())); + + $this->assertSame(array($valid), $form->getConfig()->getOption('constraints')); + } + + /** + * @group legacy + */ + public function testCascadeValidationCanBeSetToTrue() + { + $form = $this->createForm(array('cascade_validation' => true)); + + $this->assertTrue($form->getConfig()->getOption('cascade_validation')); + } + + /** + * @group legacy + */ + public function testCascadeValidationCanBeSetToFalse() + { + $form = $this->createForm(array('cascade_validation' => false)); + + $this->assertFalse($form->getConfig()->getOption('cascade_validation')); + } + public function testValidatorInterfaceSinceSymfony25() { // Mock of ValidatorInterface since apiVersion 2.5 diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php index e23709f3fcfe6..20de505b58f4c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php @@ -220,14 +220,24 @@ protected function expectNoValidate() protected function expectValidateAt($i, $propertyPath, $value, $group) { - $validator = $this->context->getValidator()->inContext($this->context); - $validator->expects($this->at(2 * $i)) - ->method('atPath') - ->with($propertyPath) - ->will($this->returnValue($validator)); - $validator->expects($this->at(2 * $i + 1)) - ->method('validate') - ->with($value, $this->logicalOr(null, array()), $group); + switch ($this->getApiVersion()) { + case Validation::API_VERSION_2_4: + $this->context->expects($this->at($i)) + ->method('validate') + ->with($value, $propertyPath, $group); + break; + case Validation::API_VERSION_2_5: + case Validation::API_VERSION_2_5_BC: + $validator = $this->context->getValidator()->inContext($this->context); + $validator->expects($this->at(2 * $i)) + ->method('atPath') + ->with($propertyPath) + ->will($this->returnValue($validator)); + $validator->expects($this->at(2 * $i + 1)) + ->method('validate') + ->with($value, $this->logicalOr(null, array(), $this->isInstanceOf('\Symfony\Component\Validator\Constraints\Valid')), $group); + break; + } } protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null) 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