[Form] Made submit buttons able to convey validation groups
This commit is contained in:
parent
cc2118dd5c
commit
7b438a816b
@ -163,5 +163,8 @@
|
||||
<service id="form.type_extension.repeated.validator" class="Symfony\Component\Form\Extension\Validator\Type\RepeatedTypeValidatorExtension">
|
||||
<tag name="form.type_extension" alias="repeated" />
|
||||
</service>
|
||||
<service id="form.type_extension.submit.validator" class="Symfony\Component\Form\Extension\Validator\Type\SubmitTypeValidatorExtension">
|
||||
<tag name="form.type_extension" alias="submit" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@ -40,8 +40,6 @@ abstract class BaseType extends AbstractType
|
||||
*/
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
/* @var \Symfony\Component\Form\ClickableInterface $form */
|
||||
|
||||
$name = $form->getName();
|
||||
$blockName = $options['block_name'] ?: $form->getName();
|
||||
$translationDomain = $options['translation_domain'];
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Form\ClickableInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\Extension\Validator\Util\ServerParams;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
@ -171,15 +172,21 @@ class FormValidator extends ConstraintValidator
|
||||
*/
|
||||
private static function getValidationGroups(FormInterface $form)
|
||||
{
|
||||
$button = self::findClickedButton($form->getRoot());
|
||||
|
||||
if (null !== $button) {
|
||||
$groups = $button->getConfig()->getOption('validation_groups');
|
||||
|
||||
if (null !== $groups) {
|
||||
return self::resolveValidationGroups($groups, $form);
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
$groups = $form->getConfig()->getOption('validation_groups');
|
||||
|
||||
if (null !== $groups) {
|
||||
if (is_callable($groups)) {
|
||||
$groups = call_user_func($groups, $form);
|
||||
}
|
||||
|
||||
return (array) $groups;
|
||||
return self::resolveValidationGroups($groups, $form);
|
||||
}
|
||||
|
||||
$form = $form->getParent();
|
||||
@ -187,4 +194,43 @@ class FormValidator extends ConstraintValidator
|
||||
|
||||
return array(Constraint::DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a clicked button from a form tree, if one exists.
|
||||
*
|
||||
* @param FormInterface $form The root form.
|
||||
*
|
||||
* @return ClickableInterface|null The clicked button or null.
|
||||
*/
|
||||
private static function findClickedButton(FormInterface $form)
|
||||
{
|
||||
if ($form instanceof ClickableInterface && $form->isClicked()) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
foreach ($form as $child) {
|
||||
if (null !== ($button = self::findClickedButton($child))) {
|
||||
return $button;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_callable($groups)) {
|
||||
$groups = call_user_func($groups, $form);
|
||||
}
|
||||
|
||||
return (array) $groups;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
<?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\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
|
||||
/**
|
||||
* Encapsulates common logic of {@link FormTypeValidatorExtension} and
|
||||
* {@link SubmitTypeValidatorExtension}.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
abstract class BaseValidatorExtension extends AbstractTypeExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDefaultOptions(OptionsResolverInterface $resolver)
|
||||
{
|
||||
// Make sure that validation groups end up as null, closure or array
|
||||
$validationGroupsNormalizer = function (Options $options, $groups) {
|
||||
if (empty($groups)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_callable($groups)) {
|
||||
return $groups;
|
||||
}
|
||||
|
||||
return (array) $groups;
|
||||
};
|
||||
|
||||
$resolver->setDefaults(array(
|
||||
'validation_groups' => null,
|
||||
));
|
||||
|
||||
$resolver->setNormalizers(array(
|
||||
'validation_groups' => $validationGroupsNormalizer,
|
||||
));
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class FormTypeValidatorExtension extends AbstractTypeExtension
|
||||
class FormTypeValidatorExtension extends BaseValidatorExtension
|
||||
{
|
||||
/**
|
||||
* @var ValidatorInterface
|
||||
@ -53,6 +53,8 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
|
||||
*/
|
||||
public function setDefaultOptions(OptionsResolverInterface $resolver)
|
||||
{
|
||||
parent::setDefaultOptions($resolver);
|
||||
|
||||
// BC clause
|
||||
$constraints = function (Options $options) {
|
||||
return $options['validation_constraint'];
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?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\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class SubmitTypeValidatorExtension extends AbstractTypeExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getExtendedType()
|
||||
{
|
||||
return 'submit';
|
||||
}
|
||||
}
|
@ -51,6 +51,7 @@ class ValidatorExtension extends AbstractExtension
|
||||
return array(
|
||||
new Type\FormTypeValidatorExtension($this->validator),
|
||||
new Type\RepeatedTypeValidatorExtension(),
|
||||
new Type\SubmitTypeValidatorExtension(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ use Symfony\Component\Form\CallbackTransformer;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
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\Constraint;
|
||||
use Symfony\Component\Validator\Constraints\NotNull;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
@ -313,6 +314,62 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->validator->validate($form, new Form());
|
||||
}
|
||||
|
||||
public function testUseValidationGroupOfClickedButton()
|
||||
{
|
||||
$context = $this->getMockExecutionContext();
|
||||
$object = $this->getMock('\stdClass');
|
||||
|
||||
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
|
||||
->setCompound(true)
|
||||
->setDataMapper($this->getDataMapper())
|
||||
->getForm();
|
||||
$form = $this->getForm('name', '\stdClass', array(
|
||||
'validation_groups' => 'form_group',
|
||||
));
|
||||
|
||||
$parent->add($form);
|
||||
$parent->add($this->getClickedSubmitButton('submit', array(
|
||||
'validation_groups' => 'button_group',
|
||||
)));
|
||||
|
||||
$form->setData($object);
|
||||
|
||||
$context->expects($this->once())
|
||||
->method('validate')
|
||||
->with($object, 'data', 'button_group', true);
|
||||
|
||||
$this->validator->initialize($context);
|
||||
$this->validator->validate($form, new Form());
|
||||
}
|
||||
|
||||
public function testDontUseValidationGroupOfUnclickedButton()
|
||||
{
|
||||
$context = $this->getMockExecutionContext();
|
||||
$object = $this->getMock('\stdClass');
|
||||
|
||||
$parent = $this->getBuilder('parent', null, array('cascade_validation' => true))
|
||||
->setCompound(true)
|
||||
->setDataMapper($this->getDataMapper())
|
||||
->getForm();
|
||||
$form = $this->getForm('name', '\stdClass', array(
|
||||
'validation_groups' => 'form_group',
|
||||
));
|
||||
|
||||
$parent->add($form);
|
||||
$parent->add($this->getSubmitButton('submit', array(
|
||||
'validation_groups' => 'button_group',
|
||||
)));
|
||||
|
||||
$form->setData($object);
|
||||
|
||||
$context->expects($this->once())
|
||||
->method('validate')
|
||||
->with($object, 'data', 'form_group', true);
|
||||
|
||||
$this->validator->initialize($context);
|
||||
$this->validator->validate($form, new Form());
|
||||
}
|
||||
|
||||
public function testUseInheritedValidationGroup()
|
||||
{
|
||||
$context = $this->getMockExecutionContext();
|
||||
@ -561,9 +618,21 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options);
|
||||
}
|
||||
|
||||
private function getForm($name = 'name', $dataClass = null)
|
||||
private function getForm($name = 'name', $dataClass = null, array $options = array())
|
||||
{
|
||||
return $this->getBuilder($name, $dataClass)->getForm();
|
||||
return $this->getBuilder($name, $dataClass, $options)->getForm();
|
||||
}
|
||||
|
||||
private function getSubmitButton($name = 'name', array $options = array())
|
||||
{
|
||||
$builder = new SubmitButtonBuilder($name, $options);
|
||||
|
||||
return $builder->getForm();
|
||||
}
|
||||
|
||||
private function getClickedSubmitButton($name = 'name', array $options = array())
|
||||
{
|
||||
return $this->getSubmitButton($name, $options)->bind('');
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user