bug #11571 [Form] Fixed FormValidator compatibility with the non-BC 2.5 Validation API (webmozart)
This PR was merged into the 2.5 branch.
Discussion
----------
[Form] Fixed FormValidator compatibility with the non-BC 2.5 Validation API
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #11568
| License | MIT
| Doc PR | -
Commits
-------
6ac130e
[Form] Fixed FormValidator compatibility with the non-BC 2.5 Validation API
This commit is contained in:
commit
cd322c42a8
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
@ -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 <bschussek@gmail.com>
|
||||
*/
|
||||
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();
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
$context->expects($this->never())
|
||||
->method('addViolationAt');
|
||||
|
||||
$this->validator->initialize($context);
|
||||
$this->validator->validate($form, new Form());
|
||||
|
||||
$violations = array();
|
||||
|
||||
for ($i = 0; $i < $nbViolation; ++$i) {
|
||||
$violations[] = $this->createViolation($options['post_max_size_message'], $params, 'property.path', $contentLength);
|
||||
}
|
||||
|
||||
$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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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 <bschussek@gmail.com>
|
||||
*/
|
||||
class LegacyFormValidator2Dot4ApiTest extends FormValidatorTest
|
||||
{
|
||||
protected function getApiVersion()
|
||||
{
|
||||
return Validation::API_VERSION_2_4;
|
||||
}
|
||||
|
||||
protected function createValidator()
|
||||
{
|
||||
return new LegacyFormValidator($this->serverParams);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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 <bschussek@gmail.com>
|
||||
*/
|
||||
class LegacyFormValidatorLegacyApiTest extends FormValidatorTest
|
||||
{
|
||||
protected function getApiVersion()
|
||||
{
|
||||
return Validation::API_VERSION_2_5_BC;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user