Skip to content

Commit

Permalink
[Form] Deprecated FormValidatorInterface and moved implementations to…
Browse files Browse the repository at this point in the history
… event listeners
  • Loading branch information
webmozart committed Apr 13, 2012
1 parent 989b418 commit 0f9606a
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 139 deletions.
15 changes: 13 additions & 2 deletions CallbackValidator.php
Expand Up @@ -11,17 +11,28 @@

namespace Symfony\Component\Form;

/**
* Deprecated. You should use FormEvents::POST_BIND event listeners instead.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
class CallbackValidator implements FormValidatorInterface
{
private $callback;

/**
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function __construct($callback)
{
// TODO validate callback

$this->callback = $callback;
}

/**
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function validate(FormInterface $form)
{
return call_user_func($this->callback, $form);
Expand Down
Expand Up @@ -9,16 +9,30 @@
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Extension\Core\Validator;
namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormValidatorInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class DefaultValidator implements FormValidatorInterface
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ValidationListener implements EventSubscriberInterface
{
public function validate(FormInterface $form)
/**
* {@inheritdoc}
*/
static public function getSubscribedEvents()
{
return array(FormEvents::POST_BIND => 'validateForm');
}

public function validateForm(DataEvent $event)
{
$form = $event->getForm();

if (!$form->isSynchronized()) {
$form->addError(new FormError(
$form->getAttribute('invalid_message'),
Expand Down
4 changes: 2 additions & 2 deletions Extension/Core/Type/FieldType.php
Expand Up @@ -19,7 +19,7 @@
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
use Symfony\Component\Form\Extension\Core\Validator\DefaultValidator;
use Symfony\Component\Form\Extension\Core\EventListener\ValidationListener;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Form\Exception\FormException;

Expand Down Expand Up @@ -60,7 +60,7 @@ public function buildForm(FormBuilder $builder, array $options)
->setAttribute('invalid_message_parameters', $options['invalid_message_parameters'])
->setAttribute('translation_domain', $options['translation_domain'])
->setData($options['data'])
->addValidator(new DefaultValidator())
->addEventSubscriber(new ValidationListener())
;

if ($options['trim']) {
Expand Down
Expand Up @@ -9,94 +9,33 @@
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Extension\Validator\Validator;
namespace Symfony\Component\Form\Extension\Validator\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormValidatorInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\Validator\ExecutionContext;

class DelegatingValidator implements FormValidatorInterface
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class DelegatingValidationListener implements EventSubscriberInterface
{
private $validator;

public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}

/**
* Validates the form and its domain object.
*
* @param FormInterface $form A FormInterface instance
* {@inheritdoc}
*/
public function validate(FormInterface $form)
static public function getSubscribedEvents()
{
if ($form->isRoot()) {
$mapping = array();
$forms = array();

$this->buildFormPathMapping($form, $mapping);
$this->buildDataPathMapping($form, $mapping);
$this->buildNamePathMapping($form, $forms);
$this->resolveMappingPlaceholders($mapping, $forms);

// Validate the form in group "Default"
// Validation of the data in the custom group is done by validateData(),
// which is constrained by the Execute constraint
if ($form->hasAttribute('validation_constraint')) {
$violations = $this->validator->validateValue(
$form->getData(),
$form->getAttribute('validation_constraint'),
self::getFormValidationGroups($form)
);

if ($violations) {
foreach ($violations as $violation) {
$propertyPath = new PropertyPath($violation->getPropertyPath());
$template = $violation->getMessageTemplate();
$parameters = $violation->getMessageParameters();
$pluralization = $violation->getMessagePluralization();
$error = new FormError($template, $parameters, $pluralization);

$child = $form;
foreach ($propertyPath->getElements() as $element) {
$children = $child->getChildren();
if (!isset($children[$element])) {
$form->addError($error);
break;
}

$child = $children[$element];
}

$child->addError($error);
}
}
} elseif (count($violations = $this->validator->validate($form))) {
foreach ($violations as $violation) {
$propertyPath = $violation->getPropertyPath();
$template = $violation->getMessageTemplate();
$parameters = $violation->getMessageParameters();
$pluralization = $violation->getMessagePluralization();
$error = new FormError($template, $parameters, $pluralization);

foreach ($mapping as $mappedPath => $child) {
if (preg_match($mappedPath, $propertyPath)) {
$child->addError($error);
continue 2;
}
}

$form->addError($error);
}
}
}
return array(FormEvents::POST_BIND => 'validateForm');
}

/**
Expand Down Expand Up @@ -175,6 +114,82 @@ static protected function getFormValidationGroups(FormInterface $form)
return (array) $groups;
}

public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}

/**
* Validates the form and its domain object.
*
* @param DataEvent $event The event object
*/
public function validateForm(DataEvent $event)
{
$form = $event->getForm();

if ($form->isRoot()) {
$mapping = array();
$forms = array();

$this->buildFormPathMapping($form, $mapping);
$this->buildDataPathMapping($form, $mapping);
$this->buildNamePathMapping($form, $forms);
$this->resolveMappingPlaceholders($mapping, $forms);

// Validate the form in group "Default"
// Validation of the data in the custom group is done by validateData(),
// which is constrained by the Execute constraint
if ($form->hasAttribute('validation_constraint')) {
$violations = $this->validator->validateValue(
$form->getData(),
$form->getAttribute('validation_constraint'),
self::getFormValidationGroups($form)
);

if ($violations) {
foreach ($violations as $violation) {
$propertyPath = new PropertyPath($violation->getPropertyPath());
$template = $violation->getMessageTemplate();
$parameters = $violation->getMessageParameters();
$pluralization = $violation->getMessagePluralization();
$error = new FormError($template, $parameters, $pluralization);

$child = $form;
foreach ($propertyPath->getElements() as $element) {
$children = $child->getChildren();
if (!isset($children[$element])) {
$form->addError($error);
break;
}

$child = $children[$element];
}

$child->addError($error);
}
}
} elseif (count($violations = $this->validator->validate($form))) {
foreach ($violations as $violation) {
$propertyPath = $violation->getPropertyPath();
$template = $violation->getMessageTemplate();
$parameters = $violation->getMessageParameters();
$pluralization = $violation->getMessagePluralization();
$error = new FormError($template, $parameters, $pluralization);

foreach ($mapping as $mappedPath => $child) {
if (preg_match($mappedPath, $propertyPath)) {
$child->addError($error);
continue 2;
}
}

$form->addError($error);
}
}
}
}

private function buildFormPathMapping(FormInterface $form, array &$mapping, $formPath = 'children', $namePath = '')
{
foreach ($form->getAttribute('error_mapping') as $nestedDataPath => $nestedNamePath) {
Expand Down
8 changes: 6 additions & 2 deletions Extension/Validator/Type/FieldTypeValidatorExtension.php
Expand Up @@ -13,9 +13,12 @@

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\Extension\Validator\Validator\DelegatingValidator;
use Symfony\Component\Form\Extension\Validator\EventListener\DelegatingValidationListener;
use Symfony\Component\Validator\ValidatorInterface;

/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class FieldTypeValidatorExtension extends AbstractTypeExtension
{
private $validator;
Expand All @@ -39,7 +42,8 @@ public function buildForm(FormBuilder $builder, array $options)
->setAttribute('validation_groups', $options['validation_groups'])
->setAttribute('validation_constraint', $options['validation_constraint'])
->setAttribute('cascade_validation', $options['cascade_validation'])
->addValidator(new DelegatingValidator($this->validator));
->addEventSubscriber(new DelegatingValidationListener($this->validator))
;
}

public function getDefaultOptions()
Expand Down
5 changes: 2 additions & 3 deletions Form.php
Expand Up @@ -573,9 +573,6 @@ public function bind($clientData)
$validator->validate($this);
}

$event = new DataEvent($this, $clientData);
$this->dispatcher->dispatch(FormEvents::POST_VALIDATE, $event);

return $this;
}

Expand Down Expand Up @@ -808,6 +805,8 @@ public function getClientTransformers()
* Returns the Validators
*
* @return array An array of FormValidatorInterface
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function getValidators()
{
Expand Down
7 changes: 7 additions & 0 deletions FormBuilder.php
Expand Up @@ -17,6 +17,9 @@
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class FormBuilder
{
/**
Expand Down Expand Up @@ -261,6 +264,8 @@ public function getErrorBubbling()
* @param FormValidatorInterface $validator The validator
*
* @return FormBuilder The current builder
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function addValidator(FormValidatorInterface $validator)
{
Expand All @@ -273,6 +278,8 @@ public function addValidator(FormValidatorInterface $validator)
* Returns the validators used by the form.
*
* @return array An array of FormValidatorInterface
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function getValidators()
{
Expand Down
2 changes: 0 additions & 2 deletions FormEvents.php
Expand Up @@ -29,6 +29,4 @@ final class FormEvents
const BIND_NORM_DATA = 'form.bind_norm_data';

const SET_DATA = 'form.set_data';

const POST_VALIDATE = 'form.post_validate';
}
11 changes: 11 additions & 0 deletions FormValidatorInterface.php
Expand Up @@ -11,7 +11,18 @@

namespace Symfony\Component\Form;

/**
* This interface is deprecated. You should use a FormEvents::POST_BIND event
* listener instead.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
interface FormValidatorInterface
{
/**
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
function validate(FormInterface $form);
}
4 changes: 2 additions & 2 deletions Resources/config/validation.xml
Expand Up @@ -7,11 +7,11 @@
<class name="Symfony\Component\Form\Form">
<constraint name="Callback">
<value>
<value>Symfony\Component\Form\Extension\Validator\Validator\DelegatingValidator</value>
<value>Symfony\Component\Form\Extension\Validator\EventListener\DelegatingValidationListener</value>
<value>validateFormData</value>
</value>
<value>
<value>Symfony\Component\Form\Extension\Validator\Validator\DelegatingValidator</value>
<value>Symfony\Component\Form\Extension\Validator\EventListener\DelegatingValidationListener</value>
<value>validateFormChildren</value>
</value>
</constraint>
Expand Down

0 comments on commit 0f9606a

Please sign in to comment.