Selaa lähdekoodia

[Form] The form is now validated seperatedly from its data. The form is validated in group "Default", the data in the group set in option "validation_groups"

Bernhard Schussek 14 vuotta sitten
vanhempi
commit
5e3fab214e

+ 21 - 0
src/Symfony/Component/Form/DataError.php

@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Form;
+
+/**
+ * Wraps errors in the form data
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
+ */
+class DataError extends Error
+{
+}

+ 65 - 0
src/Symfony/Component/Form/Error.php

@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Form;
+
+/**
+ * Wraps errors in forms
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
+ */
+class Error
+{
+    /**
+     * The template for the error message
+     * @var string
+     */
+    protected $messageTemplate;
+
+    /**
+     * The parameters that should be substituted in the message template
+     * @var array
+     */
+    protected $messageParameters;
+
+    /**
+     * Constructor
+     *
+     * @param string $messageTemplate      The template for the error message
+     * @param array $messageParameters     The parameters that should be
+     *                                     substituted in the message template.
+     */
+    public function __construct($messageTemplate, array $messageParameters = array())
+    {
+        $this->messageTemplate = $messageTemplate;
+        $this->messageParameters = $messageParameters;
+    }
+
+    /**
+     * Returns the error message template
+     *
+     * @return string
+     */
+    public function getMessageTemplate()
+    {
+        return $this->messageTemplate;
+    }
+
+    /**
+     * Returns the parameters to be inserted in the message template
+     *
+     * @return array
+     */
+    public function getMessageParameters()
+    {
+        return $this->messageParameters;
+    }
+}

+ 1 - 1
src/Symfony/Component/Form/Field.php

@@ -358,7 +358,7 @@ class Field extends Configurable implements FieldInterface
      *
      * @see FieldInterface
      */
-    public function addError(FieldError $error, PropertyPathIterator $pathIterator = null, $type = null)
+    public function addError(Error $error, PropertyPathIterator $pathIterator = null)
     {
         $this->errors[] = $error;
     }

+ 1 - 37
src/Symfony/Component/Form/FieldError.php

@@ -16,42 +16,6 @@ namespace Symfony\Component\Form;
  *
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
-class FieldError
+class FieldError extends Error
 {
-    protected $messageTemplate;
-
-    protected $messageParameters;
-
-    /**
-     * Constructor
-     *
-     * @param string $messageTemplate      The template for the error message
-     * @param array $messageParameters     The parameters that should be
-     *                                     substituted in the message template.
-     */
-    public function __construct($messageTemplate, array $messageParameters = array())
-    {
-        $this->messageTemplate = $messageTemplate;
-        $this->messageParameters = $messageParameters;
-    }
-
-    /**
-     * Returns the error message template
-     *
-     * @return string
-     */
-    public function getMessageTemplate()
-    {
-        return $this->messageTemplate;
-    }
-
-    /**
-     * Returns the parameters to be inserted in the message template
-     *
-     * @return array
-     */
-    public function getMessageParameters()
-    {
-        return $this->messageParameters;
-    }
 }

+ 2 - 3
src/Symfony/Component/Form/FieldInterface.php

@@ -154,11 +154,10 @@ interface FieldInterface
      * ...
      * </code>
      *
-     * @param FieldError $error
+     * @param Error $error
      * @param PropertyPathIterator $pathIterator
-     * @param ConstraintViolation$violation
      */
-    function addError(FieldError $error, PropertyPathIterator $pathIterator = null, $type = null);
+    function addError(Error $error, PropertyPathIterator $pathIterator = null);
 
     /**
      * Returns whether the field is valid.

+ 25 - 16
src/Symfony/Component/Form/Form.php

@@ -516,10 +516,10 @@ class Form extends Field implements \IteratorAggregate, FormInterface
     /**
      * {@inheritDoc}
      */
-    public function addError(FieldError $error, PropertyPathIterator $pathIterator = null, $type = null)
+    public function addError(Error $error, PropertyPathIterator $pathIterator = null)
     {
         if (null !== $pathIterator) {
-            if ($type === self::FIELD_ERROR && $pathIterator->hasNext()) {
+            if ($error instanceof FieldError && $pathIterator->hasNext()) {
                 $pathIterator->next();
 
                 if ($pathIterator->isProperty() && $pathIterator->current() === 'fields') {
@@ -527,11 +527,11 @@ class Form extends Field implements \IteratorAggregate, FormInterface
                 }
 
                 if ($this->has($pathIterator->current()) && !$this->get($pathIterator->current())->isHidden()) {
-                    $this->get($pathIterator->current())->addError($error, $pathIterator, $type);
+                    $this->get($pathIterator->current())->addError($error, $pathIterator);
 
                     return;
                 }
-            } else if ($type === self::DATA_ERROR) {
+            } else if ($error instanceof DataError) {
                 $iterator = new RecursiveFieldIterator($this);
                 $iterator = new \RecursiveIteratorIterator($iterator);
 
@@ -542,7 +542,7 @@ class Form extends Field implements \IteratorAggregate, FormInterface
                                 $pathIterator->next();
                             }
 
-                            $field->addError($error, $pathIterator, $type);
+                            $field->addError($error, $pathIterator);
 
                             return;
                         }
@@ -729,25 +729,34 @@ class Form extends Field implements \IteratorAggregate, FormInterface
      */
     public function validate()
     {
-        if (null === $this->getOption('validator')) {
+        $validator = $this->getOption('validator');
+        $groups = $this->getOption('validation_groups');
+
+        if (null === $validator) {
             throw new MissingOptionsException('The option "validator" is required for validating', array('validator'));
         }
 
-        // Validate the submitted data
-        if ($violations = $this->getOption('validator')->validate($this, $this->getOption('validation_groups'))) {
-            // TODO: test me
+        // Validate the submitted data in the domain object in the sets
+        // validation group(s)
+        if ($violations = $validator->validate($this->getData(), $groups)) {
             foreach ($violations as $violation) {
                 $propertyPath = new PropertyPath($violation->getPropertyPath());
                 $iterator = $propertyPath->getIterator();
+                $iterator->next(); // point at the first data element
+                $error = new DataError($violation->getMessageTemplate(), $violation->getMessageParameters());
 
-                if ($iterator->current() == 'data') {
-                    $type = self::DATA_ERROR;
-                    $iterator->next(); // point at the first data element
-                } else {
-                    $type = self::FIELD_ERROR;
-                }
+                $this->addError($error, $iterator);
+            }
+        }
+
+        // Validate the submitted data in the fields in group "Default"
+        if ($violations = $validator->validate($this)) {
+            foreach ($violations as $violation) {
+                $propertyPath = new PropertyPath($violation->getPropertyPath());
+                $iterator = $propertyPath->getIterator();
+                $error = new FieldError($violation->getMessageTemplate(), $violation->getMessageParameters());
 
-                $this->addError(new FieldError($violation->getMessageTemplate(), $violation->getMessageParameters()), $iterator, $type);
+                $this->addError($error, $iterator);
             }
         }
     }

+ 0 - 3
src/Symfony/Component/Form/Resources/config/validation.xml

@@ -16,9 +16,6 @@
     <property name="fields">
       <constraint name="Valid" />
     </property>
-    <getter property="data">
-      <constraint name="Valid" />
-    </getter>
     <getter property="submittedWithExtraFields">
       <constraint name="AssertFalse">
         <option name="message">This form should not contain extra fields</option>

+ 31 - 28
tests/Symfony/Tests/Component/Form/FormTest.php

@@ -19,6 +19,7 @@ use Symfony\Component\Form\Form;
 use Symfony\Component\Form\FormContext;
 use Symfony\Component\Form\Field;
 use Symfony\Component\Form\FieldError;
+use Symfony\Component\Form\DataError;
 use Symfony\Component\Form\HiddenField;
 use Symfony\Component\Form\PropertyPath;
 use Symfony\Component\HttpFoundation\Request;
@@ -206,9 +207,19 @@ class FormTest extends \PHPUnit_Framework_TestCase
         ));
         $form->add($field);
 
-        $this->validator->expects($this->once())
-                                        ->method('validate')
-                                        ->with($this->equalTo($form), $this->equalTo(array('group')));
+        $this->validator->expects($this->exactly(2))
+            ->method('validate');
+
+// PHPUnit limitation here
+//        // form data is validated in custom group
+//        $this->validator->expects($this->once())
+//            ->method('validate')
+//            ->with($this->equalTo($form->getData()), $this->equalTo(array('group')));
+//
+//        // form itself is validated in group "Default"
+//        $this->validator->expects($this->once())
+//            ->method('validate')
+//            ->with($this->equalTo($form));
 
         // data is irrelevant
         $form->bind($this->createPostRequest());
@@ -453,7 +464,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('fields[firstName].data');
 
-        $form->addError($error, $path->getIterator(), Form::FIELD_ERROR);
+        $form->addError(new FieldError('Message'), $path->getIterator());
     }
 
     public function testAddErrorMapsFieldValidationErrorsOntoFieldsWithinNestedForms()
@@ -472,13 +483,11 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('fields[names].fields[firstName].data');
 
-        $form->addError($error, $path->getIterator(), Form::FIELD_ERROR);
+        $form->addError(new FieldError('Message'), $path->getIterator());
     }
 
     public function testAddErrorKeepsFieldValidationErrorsIfFieldNotFound()
     {
-        $error = new FieldError('Message');
-
         $field = $this->createMockField('foo');
         $field->expects($this->never())
                     ->method('addError');
@@ -488,15 +497,13 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('fields[bar].data');
 
-        $form->addError($error, $path->getIterator(), Form::FIELD_ERROR);
+        $form->addError(new FieldError('Message'), $path->getIterator());
 
-        $this->assertEquals(array($error), $form->getErrors());
+        $this->assertEquals(array(new FieldError('Message')), $form->getErrors());
     }
 
     public function testAddErrorKeepsFieldValidationErrorsIfFieldIsHidden()
     {
-        $error = new FieldError('Message');
-
         $field = $this->createMockField('firstName');
         $field->expects($this->any())
                     ->method('isHidden')
@@ -509,14 +516,14 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('fields[firstName].data');
 
-        $form->addError($error, $path->getIterator(), Form::FIELD_ERROR);
+        $form->addError(new FieldError('Message'), $path->getIterator());
 
-        $this->assertEquals(array($error), $form->getErrors());
+        $this->assertEquals(array(new FieldError('Message')), $form->getErrors());
     }
 
     public function testAddErrorMapsDataValidationErrorsOntoFields()
     {
-        $error = new FieldError('Message');
+        $error = new DataError('Message');
 
         // path is expected to point at "firstName"
         $expectedPath = new PropertyPath('firstName');
@@ -528,20 +535,18 @@ class FormTest extends \PHPUnit_Framework_TestCase
                     ->will($this->returnValue(new PropertyPath('firstName')));
         $field->expects($this->once())
                     ->method('addError')
-                    ->with($this->equalTo($error), $this->equalTo($expectedPathIterator), $this->equalTo(Form::DATA_ERROR));
+                    ->with($this->equalTo($error), $this->equalTo($expectedPathIterator));
 
         $form = new Form('author');
         $form->add($field);
 
         $path = new PropertyPath('firstName');
 
-        $form->addError($error, $path->getIterator(), Form::DATA_ERROR);
+        $form->addError($error, $path->getIterator());
     }
 
     public function testAddErrorKeepsDataValidationErrorsIfFieldNotFound()
     {
-        $error = new FieldError('Message');
-
         $field = $this->createMockField('foo');
         $field->expects($this->any())
                     ->method('getPropertyPath')
@@ -554,13 +559,11 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('bar');
 
-        $form->addError($error, $path->getIterator(), Form::DATA_ERROR);
+        $form->addError(new DataError('Message'), $path->getIterator());
     }
 
     public function testAddErrorKeepsDataValidationErrorsIfFieldIsHidden()
     {
-        $error = new FieldError('Message');
-
         $field = $this->createMockField('firstName');
         $field->expects($this->any())
                     ->method('isHidden')
@@ -576,12 +579,12 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('firstName');
 
-        $form->addError($error, $path->getIterator(), Form::DATA_ERROR);
+        $form->addError(new DataError('Message'), $path->getIterator());
     }
 
     public function testAddErrorMapsDataValidationErrorsOntoNestedFields()
     {
-        $error = new FieldError('Message');
+        $error = new DataError('Message');
 
         // path is expected to point at "street"
         $expectedPath = new PropertyPath('address.street');
@@ -594,19 +597,19 @@ class FormTest extends \PHPUnit_Framework_TestCase
                     ->will($this->returnValue(new PropertyPath('address')));
         $field->expects($this->once())
                     ->method('addError')
-                    ->with($this->equalTo($error), $this->equalTo($expectedPathIterator), $this->equalTo(Form::DATA_ERROR));
+                    ->with($this->equalTo($error), $this->equalTo($expectedPathIterator));
 
         $form = new Form('author');
         $form->add($field);
 
         $path = new PropertyPath('address.street');
 
-        $form->addError($error, $path->getIterator(), Form::DATA_ERROR);
+        $form->addError($error, $path->getIterator());
     }
 
     public function testAddErrorMapsErrorsOntoFieldsInVirtualGroups()
     {
-        $error = new FieldError('Message');
+        $error = new DataError('Message');
 
         // path is expected to point at "address"
         $expectedPath = new PropertyPath('address');
@@ -618,7 +621,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
                     ->will($this->returnValue(new PropertyPath('address')));
         $field->expects($this->once())
                     ->method('addError')
-                    ->with($this->equalTo($error), $this->equalTo($expectedPathIterator), $this->equalTo(Form::DATA_ERROR));
+                    ->with($this->equalTo($error), $this->equalTo($expectedPathIterator));
 
         $form = new Form('author');
         $nestedForm = new Form('nested', array('virtual' => true));
@@ -627,7 +630,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
 
         $path = new PropertyPath('address');
 
-        $form->addError($error, $path->getIterator(), Form::DATA_ERROR);
+        $form->addError($error, $path->getIterator());
     }
 
     public function testAddThrowsExceptionIfAlreadySubmitted()