diff --git a/src/Symfony/Bundle/FrameworkBundle/Validator/LegacyConstraintValidatorFactory.php b/src/Symfony/Bundle/FrameworkBundle/Validator/LegacyConstraintValidatorFactory.php index ac85eb4fb5..3af644bb18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Validator/LegacyConstraintValidatorFactory.php +++ b/src/Symfony/Bundle/FrameworkBundle/Validator/LegacyConstraintValidatorFactory.php @@ -29,6 +29,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException; class LegacyConstraintValidatorFactory implements ConstraintValidatorFactoryInterface { const BASE_NAMESPACE = 'Symfony\\Component\\Validator\\Constraints'; + const FORM_BASE_NAMESPACE = 'Symfony\\Component\\Form\\Extension\\Validator\\Constraints'; protected $container; protected $validators; @@ -75,6 +76,9 @@ class LegacyConstraintValidatorFactory implements ConstraintValidatorFactoryInte case self::BASE_NAMESPACE.'\\Length': $name = self::BASE_NAMESPACE.'\\LegacyLengthValidator'; break; + case self::FORM_BASE_NAMESPACE.'\\Form': + $name = self::FORM_BASE_NAMESPACE.'\\LegacyFormValidator'; + break; } $this->validators[$name] = new $name(); diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index ab049bf66d..3e96bc75ac 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -53,6 +53,7 @@ class FormValidator extends ConstraintValidator /* @var FormInterface $form */ $config = $form->getConfig(); + $validator = $this->context->getValidator()->inContext($this->context); if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded @@ -61,7 +62,7 @@ class FormValidator extends ConstraintValidator // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { - $this->context->validate($form->getData(), 'data', $group, true); + $validator->atPath('data')->validate($form->getData(), null, $group); } } @@ -71,7 +72,7 @@ class FormValidator extends ConstraintValidator foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { - $this->context->validateValue($form->getData(), $constraint, 'data', $group); + $validator->atPath('data')->validate($form->getData(), $constraint, $group); // Prevent duplicate validation continue 2; @@ -100,23 +101,20 @@ class FormValidator extends ConstraintValidator ? (string) $form->getViewData() : gettype($form->getViewData()); - $this->context->addViolation( - $config->getOption('invalid_message'), - array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), - $form->getViewData(), - null, - Form::ERR_INVALID - ); + $this->context->buildViolation($config->getOption('invalid_message')) + ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) + ->setInvalidValue($form->getViewData()) + ->setCode(Form::ERR_INVALID) + ->addViolation(); } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { - $this->context->addViolation( - $config->getOption('extra_fields_message'), - array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), - $form->getExtraData() - ); + $this->context->buildViolation($config->getOption('extra_fields_message')) + ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) + ->setInvalidValue($form->getExtraData()) + ->addViolation(); } // Mark the form with an error if the uploaded size was too large @@ -126,11 +124,10 @@ class FormValidator extends ConstraintValidator $max = $this->serverParams->getPostMaxSize(); if (!empty($max) && $length > $max) { - $this->context->addViolation( - $config->getOption('post_max_size_message'), - array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), - $length - ); + $this->context->buildViolation($config->getOption('post_max_size_message')) + ->setParameter('{{ max }}', $this->serverParams->getNormalizedIniPostMaxSize()) + ->setInvalidValue($length) + ->addViolation(); } } } diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/LegacyFormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/LegacyFormValidator.php new file mode 100644 index 0000000000..2ed206b59d --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/LegacyFormValidator.php @@ -0,0 +1,223 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Validator\Constraints; + +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\Extension\Validator\Util\ServerParams; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; + +/** + * @author Bernhard Schussek + */ +class LegacyFormValidator extends ConstraintValidator +{ + /** + * @var ServerParams + */ + private $serverParams; + + /** + * Creates a validator with the given server parameters. + * + * @param ServerParams $params The server parameters. Default + * parameters are created if null. + */ + public function __construct(ServerParams $params = null) + { + $this->serverParams = $params ?: new ServerParams(); + } + + /** + * {@inheritdoc} + */ + public function validate($form, Constraint $constraint) + { + if (!$constraint instanceof Form) { + throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Form'); + } + + if (!$form instanceof FormInterface) { + return; + } + + /* @var FormInterface $form */ + $config = $form->getConfig(); + + if ($form->isSynchronized()) { + // Validate the form data only if transformation succeeded + $groups = self::getValidationGroups($form); + + // Validate the data against its own constraints + if (self::allowDataWalking($form)) { + foreach ($groups as $group) { + $this->context->validate($form->getData(), 'data', $group, true); + } + } + + // Validate the data against the constraints defined + // in the form + $constraints = $config->getOption('constraints'); + foreach ($constraints as $constraint) { + foreach ($groups as $group) { + if (in_array($group, $constraint->groups)) { + $this->context->validateValue($form->getData(), $constraint, 'data', $group); + + // Prevent duplicate validation + continue 2; + } + } + } + } else { + $childrenSynchronized = true; + + foreach ($form as $child) { + if (!$child->isSynchronized()) { + $childrenSynchronized = false; + break; + } + } + + // Mark the form with an error if it is not synchronized BUT all + // of its children are synchronized. If any child is not + // synchronized, an error is displayed there already and showing + // a second error in its parent form is pointless, or worse, may + // lead to duplicate errors if error bubbling is enabled on the + // child. + // See also https://github.com/symfony/symfony/issues/4359 + if ($childrenSynchronized) { + $clientDataAsString = is_scalar($form->getViewData()) + ? (string) $form->getViewData() + : gettype($form->getViewData()); + + $this->context->addViolation( + $config->getOption('invalid_message'), + array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), + $form->getViewData(), + null, + Form::ERR_INVALID + ); + } + } + + // Mark the form with an error if it contains extra fields + if (count($form->getExtraData()) > 0) { + $this->context->addViolation( + $config->getOption('extra_fields_message'), + array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), + $form->getExtraData() + ); + } + + // Mark the form with an error if the uploaded size was too large + $length = $this->serverParams->getContentLength(); + + if ($form->isRoot() && null !== $length) { + $max = $this->serverParams->getPostMaxSize(); + + if (!empty($max) && $length > $max) { + $this->context->addViolation( + $config->getOption('post_max_size_message'), + array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), + $length + ); + } + } + } + + /** + * Returns whether the data of a form may be walked. + * + * @param FormInterface $form The form to test. + * + * @return bool Whether the graph walker may walk the data. + */ + private static function allowDataWalking(FormInterface $form) + { + $data = $form->getData(); + + // Scalar values cannot have mapped constraints + if (!is_object($data) && !is_array($data)) { + return false; + } + + // Root forms are always validated + if ($form->isRoot()) { + return true; + } + + // Non-root forms are validated if validation cascading + // is enabled in all ancestor forms + while (null !== ($form = $form->getParent())) { + if (!$form->getConfig()->getOption('cascade_validation')) { + return false; + } + } + + return true; + } + + /** + * Returns the validation groups of the given form. + * + * @param FormInterface $form The form. + * + * @return array The validation groups. + */ + private static function getValidationGroups(FormInterface $form) + { + // Determine the clicked button of the complete form tree + $clickedButton = null; + + if (method_exists($form, 'getClickedButton')) { + $clickedButton = $form->getClickedButton(); + } + + if (null !== $clickedButton) { + $groups = $clickedButton->getConfig()->getOption('validation_groups'); + + if (null !== $groups) { + return self::resolveValidationGroups($groups, $form); + } + } + + do { + $groups = $form->getConfig()->getOption('validation_groups'); + + if (null !== $groups) { + return self::resolveValidationGroups($groups, $form); + } + + $form = $form->getParent(); + } while (null !== $form); + + return array(Constraint::DEFAULT_GROUP); + } + + /** + * Post-processes the validation groups option for a given form. + * + * @param array|callable $groups The validation groups. + * @param FormInterface $form The validated form. + * + * @return array The validation groups. + */ + private static function resolveValidationGroups($groups, FormInterface $form) + { + if (!is_string($groups) && is_callable($groups)) { + $groups = call_user_func($groups, $form); + } + + return (array) $groups; + } +} 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 4d9c26b81c..f8bf154d6e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -21,11 +21,13 @@ use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; +use Symfony\Component\Validator\Validation; /** * @author Bernhard Schussek */ -class FormValidatorTest extends \PHPUnit_Framework_TestCase +class FormValidatorTest extends AbstractConstraintValidatorTest { /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -40,12 +42,7 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $serverParams; - - /** - * @var FormValidator - */ - private $validator; + protected $serverParams; protected function setUp() { @@ -55,32 +52,38 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase 'Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize', 'getContentLength') ); - $this->validator = new FormValidator($this->serverParams); + + parent::setUp(); + } + + protected function getApiVersion() + { + return Validation::API_VERSION_2_5; + } + + protected function createValidator() + { + return new FormValidator($this->serverParams); } public function testValidate() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testValidateConstraints() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -94,28 +97,20 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase ->getForm(); // First default constraints - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); // Then custom constraints - $context->expects($this->at(2)) - ->method('validateValue') - ->with($object, $constraint1, 'data', 'group1'); - $context->expects($this->at(3)) - ->method('validateValue') - ->with($object, $constraint2, 'data', 'group2'); + $this->expectValidateValueAt(2, 'data', $object, $constraint1, 'group1'); + $this->expectValidateValueAt(3, 'data', $object, $constraint2, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfParentWithoutCascadeValidation() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) @@ -128,16 +123,15 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->setData($object); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testValidateConstraintsEvenIfNoCascadeValidation() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -155,20 +149,16 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase ->getForm(); $parent->add($form); - $context->expects($this->at(0)) - ->method('validateValue') - ->with($object, $constraint1, 'data', 'group1'); - $context->expects($this->at(1)) - ->method('validateValue') - ->with($object, $constraint2, 'data', 'group2'); + $this->expectValidateValueAt(0, 'data', $object, $constraint1, 'group1'); + $this->expectValidateValueAt(1, 'data', $object, $constraint2, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -179,16 +169,15 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->setData($object); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateConstraintsIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); @@ -204,16 +193,15 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase // Launch transformer $form->submit(array()); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -233,26 +221,18 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase // Launch transformer $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'foo' - ); - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + '{{ foo }}' => 'bar' + ), 'property.path', 'foo', null, Form::ERR_INVALID); } public function testAddInvalidErrorEvenIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -273,31 +253,24 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase // Launch transformer $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'foo' - ); - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + '{{ foo }}' => 'bar' + ), 'property.path', 'foo', null, Form::ERR_INVALID); } public function testDontValidateConstraintsIfNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( + 'invalid_message' => 'invalid_message_key', 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); @@ -310,19 +283,20 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase ->getForm(); // Launch transformer - $form->submit(array()); + $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + ), 'property.path','foo', null, Form::ERR_INVALID); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $failingTransformer = new CallbackTransformer( @@ -344,55 +318,46 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase // Launch transformer $form->submit(array('child' => 'foo')); - $context->expects($this->never()) - ->method('addViolation'); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testHandleCallbackValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array($this, 'getValidationGroups')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontExecuteFunctionNames() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => 'header'); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'header', true); + $this->expectValidateAt(0, 'data', $object, 'header'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testHandleClosureValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); @@ -401,20 +366,16 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseValidationGroupOfClickedButton() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) @@ -432,17 +393,15 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $parent->submit(array('name' => $object, 'submit' => '')); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'button_group', true); + $this->expectValidateAt(0, 'data', $object, 'button_group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontUseValidationGroupOfUnclickedButton() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) @@ -460,17 +419,15 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->setData($object); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'form_group', true); + $this->expectValidateAt(0, 'data', $object, 'form_group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -486,17 +443,15 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->setData($object); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'group', true); + $this->expectValidateAt(0, 'data', $object, 'group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedCallbackValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -512,20 +467,16 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->setData($object); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedClosureValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -543,52 +494,43 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->setData($object); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testAppendPropertyPath() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->getForm(); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'Default', true); + $this->expectValidateAt(0, 'data', $object, 'Default'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontWalkScalars() { - $context = $this->getMockExecutionContext(); - $form = $this->getBuilder() ->setData('scalar') ->getForm(); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testViolationIfExtraData() { - $context = $this->getMockExecutionContext(); - $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -597,18 +539,13 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form->submit(array('foo' => 'bar')); - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'Extra!', - array('{{ extra_fields }}' => 'foo'), - array('foo' => 'bar') - ); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('Extra!', array( + '{{ extra_fields }}' => 'foo' + ), 'property.path', array('foo' => 'bar')); } /** @@ -623,26 +560,18 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue($iniMax)); - $context = $this->getMockExecutionContext(); $options = array('post_max_size_message' => 'Max {{ max }}!'); $form = $this->getBuilder('name', null, $options)->getForm(); + $this->validator->validate($form, new Form()); + + $violations = array(); + for ($i = 0; $i < $nbViolation; ++$i) { - if (0 === $i && count($params) > 0) { - $context->expects($this->at($i)) - ->method('addViolation') - ->with($options['post_max_size_message'], $params); - } else { - $context->expects($this->at($i)) - ->method('addViolation'); - } + $violations[] = $this->createViolation($options['post_max_size_message'], $params, 'property.path', $contentLength); } - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); + $this->assertViolations($violations); } public function getPostMaxSizeFixtures() @@ -668,7 +597,6 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $this->serverParams->expects($this->never()) ->method('getNormalizedIniPostMaxSize'); - $context = $this->getMockExecutionContext(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -676,13 +604,11 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase $form = $this->getForm(); $parent->add($form); - $context->expects($this->never()) - ->method('addViolation'); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } /** diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php new file mode 100644 index 0000000000..a54e10676f --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use Symfony\Component\Form\Extension\Validator\Constraints\LegacyFormValidator; +use Symfony\Component\Validator\Validation; + +/** + * @since 2.5.3 + * @author Bernhard Schussek + */ +class LegacyFormValidator2Dot4ApiTest extends FormValidatorTest +{ + protected function getApiVersion() + { + return Validation::API_VERSION_2_4; + } + + protected function createValidator() + { + return new LegacyFormValidator($this->serverParams); + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php new file mode 100644 index 0000000000..faa68b2518 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use Symfony\Component\Validator\Validation; + +/** + * @since 2.5.3 + * @author Bernhard Schussek + */ +class LegacyFormValidatorLegacyApiTest extends FormValidatorTest +{ + protected function getApiVersion() + { + return Validation::API_VERSION_2_5_BC; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php index cbb3025233..678c20ff1f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php @@ -224,6 +224,26 @@ abstract class AbstractConstraintValidatorTest extends \PHPUnit_Framework_TestCa } } + protected function expectNoValidate() + { + switch ($this->getApiVersion()) { + case Validation::API_VERSION_2_4: + $this->context->expects($this->never()) + ->method('validate'); + $this->context->expects($this->never()) + ->method('validateValue'); + break; + case Validation::API_VERSION_2_5: + case Validation::API_VERSION_2_5_BC: + $validator = $this->context->getValidator()->inContext($this->context); + $validator->expects($this->never()) + ->method('atPath'); + $validator->expects($this->never()) + ->method('validate'); + break; + } + } + protected function expectValidateAt($i, $propertyPath, $value, $group) { switch ($this->getApiVersion()) { @@ -241,7 +261,7 @@ abstract class AbstractConstraintValidatorTest extends \PHPUnit_Framework_TestCa ->will($this->returnValue($validator)); $validator->expects($this->at(2 * $i + 1)) ->method('validate') - ->with($value, array(), $group); + ->with($value, $this->logicalOr(null, array()), $group); break; } }