Ver Fonte

[Validator] Added abstract method Constraint::targets() to define whether constraints can be put onto properties, classes or both

Bernhard Schussek há 14 anos atrás
pai
commit
eed3c9a48c
44 ficheiros alterados com 409 adições e 99 exclusões
  1. 27 0
      src/Symfony/Component/Validator/Constraint.php
  2. 8 0
      src/Symfony/Component/Validator/Constraints/All.php
  3. 8 0
      src/Symfony/Component/Validator/Constraints/AssertFalse.php
  4. 8 0
      src/Symfony/Component/Validator/Constraints/AssertTrue.php
  5. 8 0
      src/Symfony/Component/Validator/Constraints/AssertType.php
  6. 8 0
      src/Symfony/Component/Validator/Constraints/Blank.php
  7. 8 0
      src/Symfony/Component/Validator/Constraints/Choice.php
  8. 8 0
      src/Symfony/Component/Validator/Constraints/Collection.php
  9. 8 0
      src/Symfony/Component/Validator/Constraints/Country.php
  10. 8 0
      src/Symfony/Component/Validator/Constraints/Date.php
  11. 8 0
      src/Symfony/Component/Validator/Constraints/DateTime.php
  12. 8 0
      src/Symfony/Component/Validator/Constraints/Email.php
  13. 8 0
      src/Symfony/Component/Validator/Constraints/File.php
  14. 8 0
      src/Symfony/Component/Validator/Constraints/Ip.php
  15. 8 0
      src/Symfony/Component/Validator/Constraints/Language.php
  16. 8 0
      src/Symfony/Component/Validator/Constraints/Locale.php
  17. 8 0
      src/Symfony/Component/Validator/Constraints/Max.php
  18. 8 0
      src/Symfony/Component/Validator/Constraints/MaxLength.php
  19. 8 0
      src/Symfony/Component/Validator/Constraints/Min.php
  20. 8 0
      src/Symfony/Component/Validator/Constraints/MinLength.php
  21. 8 0
      src/Symfony/Component/Validator/Constraints/NotBlank.php
  22. 8 0
      src/Symfony/Component/Validator/Constraints/NotNull.php
  23. 8 0
      src/Symfony/Component/Validator/Constraints/Null.php
  24. 8 0
      src/Symfony/Component/Validator/Constraints/Regex.php
  25. 8 0
      src/Symfony/Component/Validator/Constraints/Time.php
  26. 8 0
      src/Symfony/Component/Validator/Constraints/Url.php
  27. 8 0
      src/Symfony/Component/Validator/Constraints/Valid.php
  28. 4 2
      src/Symfony/Component/Validator/Mapping/ClassMetadata.php
  29. 7 0
      src/Symfony/Component/Validator/Mapping/MemberMetadata.php
  30. 13 0
      tests/Symfony/Tests/Component/Validator/Fixtures/ClassConstraint.php
  31. 5 0
      tests/Symfony/Tests/Component/Validator/Fixtures/ConstraintA.php
  32. 8 1
      tests/Symfony/Tests/Component/Validator/Fixtures/ConstraintB.php
  33. 5 0
      tests/Symfony/Tests/Component/Validator/Fixtures/ConstraintC.php
  34. 10 11
      tests/Symfony/Tests/Component/Validator/Fixtures/Entity.php
  35. 5 0
      tests/Symfony/Tests/Component/Validator/Fixtures/FailingConstraint.php
  36. 13 0
      tests/Symfony/Tests/Component/Validator/Fixtures/PropertyConstraint.php
  37. 9 0
      tests/Symfony/Tests/Component/Validator/Mapping/ClassMetadataTest.php
  38. 10 12
      tests/Symfony/Tests/Component/Validator/Mapping/Loader/AnnotationLoaderTest.php
  39. 4 2
      tests/Symfony/Tests/Component/Validator/Mapping/Loader/StaticMethodLoaderTest.php
  40. 6 6
      tests/Symfony/Tests/Component/Validator/Mapping/Loader/XmlFileLoaderTest.php
  41. 6 6
      tests/Symfony/Tests/Component/Validator/Mapping/Loader/YamlFileLoaderTest.php
  42. 38 37
      tests/Symfony/Tests/Component/Validator/Mapping/Loader/constraint-mapping.xml
  43. 22 22
      tests/Symfony/Tests/Component/Validator/Mapping/Loader/constraint-mapping.yml
  44. 9 0
      tests/Symfony/Tests/Component/Validator/Mapping/MemberMetadataTest.php

+ 27 - 0
src/Symfony/Component/Validator/Constraint.php

@@ -28,8 +28,24 @@ use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
  */
 abstract class Constraint
 {
+    /**
+     * The name of the group given to all constraints with no explicit group
+     * @var string
+     */
     const DEFAULT_GROUP = 'Default';
 
+    /**
+     * Marks a constraint that can be put onto classes
+     * @var string
+     */
+    const CLASS_CONSTRAINT = 'class';
+
+    /**
+     * Marks a constraint that can be put onto properties
+     * @var string
+     */
+    const PROPERTY_CONSTRAINT = 'property';
+
     /**
      * @var array
      */
@@ -173,4 +189,15 @@ abstract class Constraint
     {
         return get_class($this) . 'Validator';
     }
+
+    /**
+     * Returns whether the constraint can be put onto classes, properties or
+     * both
+     *
+     * This method should return one or more of the constants
+     * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT.
+     *
+     * @return string|array  One or more constant values
+     */
+    abstract public function targets();
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/All.php

@@ -24,4 +24,12 @@ class All extends \Symfony\Component\Validator\Constraint
     {
         return array('constraints');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/AssertFalse.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class AssertFalse extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value should be false';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/AssertTrue.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class AssertTrue extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value should be true';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/AssertType.php

@@ -31,4 +31,12 @@ class AssertType extends \Symfony\Component\Validator\Constraint
     {
         return array('type');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Blank.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Blank extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value should be blank';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Choice.php

@@ -29,4 +29,12 @@ class Choice extends \Symfony\Component\Validator\Constraint
     {
         return 'choices';
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Collection.php

@@ -23,4 +23,12 @@ class Collection extends \Symfony\Component\Validator\Constraint
     {
         return array('fields');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Country.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Country extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid country';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Date.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Date extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid date';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/DateTime.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class DateTime extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid datetime';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Email.php

@@ -15,4 +15,12 @@ class Email extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid email address';
     public $checkMX = false;
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/File.php

@@ -19,4 +19,12 @@ class File extends \Symfony\Component\Validator\Constraint
     public $notReadableMessage = 'The file is not readable';
     public $maxSizeMessage = 'The file is too large ({{ size }}). Allowed maximum size is {{ limit }}';
     public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Ip.php

@@ -45,4 +45,12 @@ class Ip extends \Symfony\Component\Validator\Constraint
             throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions)));
         }
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Language.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Language extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid language';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Locale.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Locale extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid locale';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Max.php

@@ -31,4 +31,12 @@ class Max extends \Symfony\Component\Validator\Constraint
     {
         return array('limit');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/MaxLength.php

@@ -32,4 +32,12 @@ class MaxLength extends \Symfony\Component\Validator\Constraint
     {
         return array('limit');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Min.php

@@ -31,4 +31,12 @@ class Min extends \Symfony\Component\Validator\Constraint
     {
         return array('limit');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/MinLength.php

@@ -32,4 +32,12 @@ class MinLength extends \Symfony\Component\Validator\Constraint
     {
         return array('limit');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/NotBlank.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class NotBlank extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value should not be blank';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/NotNull.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class NotNull extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value should not be null';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Null.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Null extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value should be null';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Regex.php

@@ -32,4 +32,12 @@ class Regex extends \Symfony\Component\Validator\Constraint
     {
         return array('pattern');
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Time.php

@@ -14,4 +14,12 @@ namespace Symfony\Component\Validator\Constraints;
 class Time extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid time';
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Url.php

@@ -15,4 +15,12 @@ class Url extends \Symfony\Component\Validator\Constraint
 {
     public $message = 'This value is not a valid URL';
     public $protocols = array('http', 'https');
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 8 - 0
src/Symfony/Component/Validator/Constraints/Valid.php

@@ -28,4 +28,12 @@ class Valid extends \Symfony\Component\Validator\Constraint
             throw new ConstraintDefinitionException('The constraint Valid does not accept any options');
         }
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
 }

+ 4 - 2
src/Symfony/Component/Validator/Mapping/ClassMetadata.php

@@ -96,8 +96,10 @@ class ClassMetadata extends ElementMetadata
      */
     public function addConstraint(Constraint $constraint)
     {
-        if ($constraint instanceof Valid) {
-            throw new ConstraintDefinitionException('The constraint Valid can only be put on properties or getters');
+        if (!in_array(Constraint::CLASS_CONSTRAINT, (array)$constraint->targets())) {
+            throw new ConstraintDefinitionException(sprintf(
+            		'The constraint %s cannot be put on classes',
+                    get_class($constraint)));
         }
 
         $constraint->addImplicitGroupName($this->getDefaultGroup());

+ 7 - 0
src/Symfony/Component/Validator/Mapping/MemberMetadata.php

@@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Mapping;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\Constraints\Valid;
 use Symfony\Component\Validator\Exception\ValidatorException;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
 
 abstract class MemberMetadata extends ElementMetadata
 {
@@ -42,6 +43,12 @@ abstract class MemberMetadata extends ElementMetadata
      */
     public function addConstraint(Constraint $constraint)
     {
+        if (!in_array(Constraint::PROPERTY_CONSTRAINT, (array)$constraint->targets())) {
+            throw new ConstraintDefinitionException(sprintf(
+            		'The constraint %s cannot be put on properties or getters',
+                    get_class($constraint)));
+        }
+
         if ($constraint instanceof Valid) {
             $this->cascaded = true;
         } else {

+ 13 - 0
tests/Symfony/Tests/Component/Validator/Fixtures/ClassConstraint.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Tests\Component\Validator\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+class ClassConstraint extends Constraint
+{
+    public function targets()
+    {
+        return self::CLASS_CONSTRAINT;
+    }
+}

+ 5 - 0
tests/Symfony/Tests/Component/Validator/Fixtures/ConstraintA.php

@@ -13,4 +13,9 @@ class ConstraintA extends Constraint
     {
         return 'property2';
     }
+
+    public function targets()
+    {
+        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+    }
 }

+ 8 - 1
tests/Symfony/Tests/Component/Validator/Fixtures/ConstraintB.php

@@ -4,4 +4,11 @@ namespace Symfony\Tests\Component\Validator\Fixtures;
 
 use Symfony\Component\Validator\Constraint;
 
-class ConstraintB extends Constraint {}
+class ConstraintB extends Constraint {
+
+    public function targets()
+    {
+        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+    }
+
+}

+ 5 - 0
tests/Symfony/Tests/Component/Validator/Fixtures/ConstraintC.php

@@ -12,4 +12,9 @@ class ConstraintC extends Constraint
     {
         return array('option1');
     }
+
+    public function targets()
+    {
+        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+    }
 }

+ 10 - 11
tests/Symfony/Tests/Component/Validator/Fixtures/Entity.php

@@ -6,23 +6,22 @@ require_once __DIR__.'/EntityParent.php';
 require_once __DIR__.'/EntityInterface.php';
 
 /**
- * @validation:NotNull
  * @Symfony\Tests\Component\Validator\Fixtures\ConstraintA
- * @validation:Min(3)
- * @validation:Choice({"A", "B"})
- * @validation:Set({
- *   @validation:All({@validation:NotNull, @validation:Min(3)}),
- *   @validation:All(constraints={@validation:NotNull, @validation:Min(3)})
- * })
- * @validation:Collection(fields={
- *   "foo" = {@validation:NotNull, @validation:Min(3)},
- *   "bar" = @validation:Min(5)
- * })
  * @validation:GroupSequence({"Foo", "Entity"})
  */
 class Entity extends EntityParent implements EntityInterface
 {
     /**
+     * @validation:NotNull
+     * @validation:Min(3)
+     * @validation:Set({
+     *   @validation:All({@validation:NotNull, @validation:Min(3)}),
+     *   @validation:All(constraints={@validation:NotNull, @validation:Min(3)})
+     * })
+     * @validation:Collection(fields={
+     *   "foo" = {@validation:NotNull, @validation:Min(3)},
+     *   "bar" = @validation:Min(5)
+     * })
      * @validation:Choice(choices={"A", "B"}, message="Must be one of %choices%")
      */
     protected $firstName;

+ 5 - 0
tests/Symfony/Tests/Component/Validator/Fixtures/FailingConstraint.php

@@ -7,4 +7,9 @@ use Symfony\Component\Validator\Constraint;
 class FailingConstraint extends Constraint
 {
     public $message = '';
+
+    public function targets()
+    {
+        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+    }
 }

+ 13 - 0
tests/Symfony/Tests/Component/Validator/Fixtures/PropertyConstraint.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Tests\Component\Validator\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+class PropertyConstraint extends Constraint
+{
+    public function targets()
+    {
+        return self::PROPERTY_CONSTRAINT;
+    }
+}

+ 9 - 0
tests/Symfony/Tests/Component/Validator/Mapping/ClassMetadataTest.php

@@ -18,10 +18,12 @@ use Symfony\Component\Validator\Mapping\PropertyMetadata;
 use Symfony\Tests\Component\Validator\Fixtures\Entity;
 use Symfony\Tests\Component\Validator\Fixtures\ConstraintA;
 use Symfony\Tests\Component\Validator\Fixtures\ConstraintB;
+use Symfony\Tests\Component\Validator\Fixtures\PropertyConstraint;
 
 require_once __DIR__.'/../Fixtures/Entity.php';
 require_once __DIR__.'/../Fixtures/ConstraintA.php';
 require_once __DIR__.'/../Fixtures/ConstraintB.php';
+require_once __DIR__.'/../Fixtures/PropertyConstraint.php';
 
 class ClassMetadataTest extends \PHPUnit_Framework_TestCase
 {
@@ -42,6 +44,13 @@ class ClassMetadataTest extends \PHPUnit_Framework_TestCase
         $this->metadata->addConstraint(new Valid());
     }
 
+    public function testAddConstraintRequiresClassConstraints()
+    {
+        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+
+        $this->metadata->addConstraint(new PropertyConstraint());
+    }
+
     public function testAddPropertyConstraints()
     {
         $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

+ 10 - 12
tests/Symfony/Tests/Component/Validator/Mapping/Loader/AnnotationLoaderTest.php

@@ -57,13 +57,12 @@ class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
 
         $expected = new ClassMetadata('Symfony\Tests\Component\Validator\Fixtures\Entity');
         $expected->setGroupSequence(array('Foo', 'Entity'));
-        $expected->addConstraint(new NotNull());
         $expected->addConstraint(new ConstraintA());
-        $expected->addConstraint(new Min(3));
-        $expected->addConstraint(new Choice(array('A', 'B')));
-        $expected->addConstraint(new All(array(new NotNull(), new Min(3))));
-        $expected->addConstraint(new All(array('constraints' => array(new NotNull(), new Min(3)))));
-        $expected->addConstraint(new Collection(array('fields' => array(
+        $expected->addPropertyConstraint('firstName', new NotNull());
+        $expected->addPropertyConstraint('firstName', new Min(3));
+        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Min(3))));
+        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Min(3)))));
+        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
             'foo' => array(new NotNull(), new Min(3)),
             'bar' => new Min(5),
         ))));
@@ -122,13 +121,12 @@ class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
         $expected->mergeConstraints($expected_parent);
 
         $expected->setGroupSequence(array('Foo', 'Entity'));
-        $expected->addConstraint(new NotNull());
         $expected->addConstraint(new ConstraintA());
-        $expected->addConstraint(new Min(3));
-        $expected->addConstraint(new Choice(array('A', 'B')));
-        $expected->addConstraint(new All(array(new NotNull(), new Min(3))));
-        $expected->addConstraint(new All(array('constraints' => array(new NotNull(), new Min(3)))));
-        $expected->addConstraint(new Collection(array('fields' => array(
+        $expected->addPropertyConstraint('firstName', new NotNull());
+        $expected->addPropertyConstraint('firstName', new Min(3));
+        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Min(3))));
+        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Min(3)))));
+        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
             'foo' => array(new NotNull(), new Min(3)),
             'bar' => new Min(5),
         ))));

+ 4 - 2
tests/Symfony/Tests/Component/Validator/Mapping/Loader/StaticMethodLoaderTest.php

@@ -11,9 +11,11 @@
 
 namespace Symfony\Tests\Component\Validator\Mapping\Loader;
 
+require_once __DIR__.'/../../Fixtures/ConstraintA.php';
+
 use Symfony\Component\Validator\Mapping\ClassMetadata;
 use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
-use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Tests\Component\Validator\Fixtures\ConstraintA;
 
 class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase
 {
@@ -75,6 +77,6 @@ class BaseStaticLoaderDocument
 {
     static public function loadMetadata(ClassMetadata $metadata)
     {
-        $metadata->addConstraint(new NotNull());
+        $metadata->addConstraint(new ConstraintA());
     }
 }

+ 6 - 6
tests/Symfony/Tests/Component/Validator/Mapping/Loader/XmlFileLoaderTest.php

@@ -49,13 +49,13 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
         $loader->loadClassMetadata($metadata);
 
         $expected = new ClassMetadata('Symfony\Tests\Component\Validator\Fixtures\Entity');
-        $expected->addConstraint(new NotNull());
         $expected->addConstraint(new ConstraintA());
-        $expected->addConstraint(new Min(3));
-        $expected->addConstraint(new Choice(array('A', 'B')));
-        $expected->addConstraint(new All(array(new NotNull(), new Min(3))));
-        $expected->addConstraint(new All(array('constraints' => array(new NotNull(), new Min(3)))));
-        $expected->addConstraint(new Collection(array('fields' => array(
+        $expected->addPropertyConstraint('firstName', new NotNull());
+        $expected->addPropertyConstraint('firstName', new Min(3));
+        $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
+        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Min(3))));
+        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Min(3)))));
+        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
             'foo' => array(new NotNull(), new Min(3)),
             'bar' => array(new Min(5)),
         ))));

+ 6 - 6
tests/Symfony/Tests/Component/Validator/Mapping/Loader/YamlFileLoaderTest.php

@@ -67,13 +67,13 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
         $loader->loadClassMetadata($metadata);
 
         $expected = new ClassMetadata('Symfony\Tests\Component\Validator\Fixtures\Entity');
-        $expected->addConstraint(new NotNull());
         $expected->addConstraint(new ConstraintA());
-        $expected->addConstraint(new Min(3));
-        $expected->addConstraint(new Choice(array('A', 'B')));
-        $expected->addConstraint(new All(array(new NotNull(), new Min(3))));
-        $expected->addConstraint(new All(array('constraints' => array(new NotNull(), new Min(3)))));
-        $expected->addConstraint(new Collection(array('fields' => array(
+        $expected->addPropertyConstraint('firstName', new NotNull());
+        $expected->addPropertyConstraint('firstName', new Min(3));
+        $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
+        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Min(3))));
+        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Min(3)))));
+        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
             'foo' => array(new NotNull(), new Min(3)),
             'bar' => array(new Min(5)),
         ))));

+ 38 - 37
tests/Symfony/Tests/Component/Validator/Mapping/Loader/constraint-mapping.xml

@@ -8,51 +8,52 @@
 
     <!-- CLASS CONSTRAINTS -->
 
-    <!-- Constraint without value -->
-    <constraint name="NotNull" />
-
     <!-- Custom constraint -->
     <constraint name="Symfony\Tests\Component\Validator\Fixtures\ConstraintA" />
-    
-    <!-- Constraint with single value -->
-    <constraint name="Min">3</constraint>
-    
-    <!-- Constraint with multiple values -->
-    <constraint name="Choice">
-      <value>A</value>
-      <value>B</value>
-    </constraint>
-    
-    <!-- Constraint with child constraints -->
-    <constraint name="All">
+
+    <!-- PROPERTY CONSTRAINTS -->
+
+    <property name="firstName">
+  
+      <!-- Constraint without value -->
       <constraint name="NotNull" />
+      
+      <!-- Constraint with single value -->
       <constraint name="Min">3</constraint>
-    </constraint>
-    
-    <!-- Option with child constraints -->
-    <constraint name="All">
-      <option name="constraints">
+      
+      <!-- Constraint with multiple values -->
+      <constraint name="Choice">
+        <value>A</value>
+        <value>B</value>
+      </constraint>
+      
+      <!-- Constraint with child constraints -->
+      <constraint name="All">
         <constraint name="NotNull" />
         <constraint name="Min">3</constraint>
-      </option>
-    </constraint>
-    
-    <!-- Value with child constraints -->
-    <constraint name="Collection">
-      <option name="fields">
-        <value key="foo">
+      </constraint>
+      
+      <!-- Option with child constraints -->
+      <constraint name="All">
+        <option name="constraints">
           <constraint name="NotNull" />
           <constraint name="Min">3</constraint>
-        </value>
-        <value key="bar">
-          <constraint name="Min">5</constraint>
-        </value>
-      </option>
-    </constraint>
-
-    <!-- PROPERTY CONSTRAINTS -->
-
-    <property name="firstName">
+        </option>
+      </constraint>
+      
+      <!-- Value with child constraints -->
+      <constraint name="Collection">
+        <option name="fields">
+          <value key="foo">
+            <constraint name="NotNull" />
+            <constraint name="Min">3</constraint>
+          </value>
+          <value key="bar">
+            <constraint name="Min">5</constraint>
+          </value>
+        </option>
+      </constraint>
+      
       <!-- Constraint with options -->
       <constraint name="Choice">
         <!-- Option with single value -->

+ 22 - 22
tests/Symfony/Tests/Component/Validator/Mapping/Loader/constraint-mapping.yml

@@ -1,33 +1,33 @@
 Symfony\Tests\Component\Validator\Fixtures\Entity:
   constraints:
-    # Constraint without value
-    - NotNull: ~
     # Custom constraint
     - Symfony\Tests\Component\Validator\Fixtures\ConstraintA: ~
-    # Constraint with single value
-    - Min: 3
-    # Constraint with multiple values
-    - Choice: [A, B]
-    # Constraint with child constraints
-    - All:
-        - NotNull: ~
-        - Min: 3
-    # Option with child constraints
-    - All:
-        constraints:
+      
+  properties:
+    firstName:
+      # Constraint without value
+      - NotNull: ~
+      # Constraint with single value
+      - Min: 3
+      # Constraint with multiple values
+      - Choice: [A, B]
+      # Constraint with child constraints
+      - All:
           - NotNull: ~
           - Min: 3
-    # Value with child constraints
-    - Collection:
-        fields:
-          foo:
+      # Option with child constraints
+      - All:
+          constraints:
             - NotNull: ~
             - Min: 3
-          bar:
-            - Min: 5
-      
-  properties:
-    firstName:
+      # Value with child constraints
+      - Collection:
+          fields:
+            foo:
+              - NotNull: ~
+              - Min: 3
+            bar:
+              - Min: 5
       # Constraint with options
       - Choice: { choices: [A, B], message: Must be one of %choices% }
         

+ 9 - 0
tests/Symfony/Tests/Component/Validator/Mapping/MemberMetadataTest.php

@@ -13,9 +13,11 @@ namespace Symfony\Tests\Component\Validator\Mapping;
 
 require_once __DIR__.'/../Fixtures/ConstraintA.php';
 require_once __DIR__.'/../Fixtures/ConstraintB.php';
+require_once __DIR__.'/../Fixtures/ClassConstraint.php';
 
 use Symfony\Tests\Component\Validator\Fixtures\ConstraintA;
 use Symfony\Tests\Component\Validator\Fixtures\ConstraintB;
+use Symfony\Tests\Component\Validator\Fixtures\ClassConstraint;
 use Symfony\Component\Validator\Constraints\Valid;
 use Symfony\Component\Validator\Mapping\MemberMetadata;
 
@@ -50,6 +52,13 @@ class MemberMetadataTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($this->metadata->isCascaded());
     }
 
+    public function testAddConstraintRequiresClassConstraints()
+    {
+        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+
+        $this->metadata->addConstraint(new ClassConstraint());
+    }
+
     public function testSerialize()
     {
         $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));