From 68cebd667aa41ee310383826c7ae83733b7e0a4f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 18 Nov 2010 23:10:21 +0100 Subject: [PATCH] [Validator] Group sequences must now always contain the group "" and never the group "Default" since that group is redefined by the group sequence --- .../Exception/GroupDefinitionException.php | 16 +++++++ .../Validator/Mapping/ClassMetadata.php | 42 ++++++++++++++----- .../Component/Validator/GraphWalkerTest.php | 12 +++--- .../Validator/Mapping/ClassMetadataTest.php | 34 +++++++++++---- 4 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 src/Symfony/Component/Validator/Exception/GroupDefinitionException.php diff --git a/src/Symfony/Component/Validator/Exception/GroupDefinitionException.php b/src/Symfony/Component/Validator/Exception/GroupDefinitionException.php new file mode 100644 index 000000000000..532b40678660 --- /dev/null +++ b/src/Symfony/Component/Validator/Exception/GroupDefinitionException.php @@ -0,0 +1,16 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +class GroupDefinitionException extends ValidatorException +{ +} \ No newline at end of file diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index c1b747819792..c20ebfbaa0a9 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -14,11 +14,12 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\GroupDefinitionException; class ClassMetadata extends ElementMetadata { public $name; - public $shortName; + public $defaultGroup; public $members = array(); public $properties = array(); public $getters = array(); @@ -33,7 +34,8 @@ class ClassMetadata extends ElementMetadata public function __construct($class) { $this->name = $class; - $this->shortName = substr($class, strrpos($class, '\\') + 1); + // class name without namespace + $this->defaultGroup = substr($class, strrpos($class, '\\') + 1); } /** @@ -49,7 +51,7 @@ public function __sleep() 'members', 'name', 'properties', - 'shortName' + 'defaultGroup' )); } @@ -64,13 +66,23 @@ public function getClassName() } /** - * Returns the class name without namespace + * Returns the name of the default group for this class * - * @return string The local class name in the namespace + * For each class, the group "Default" is an alias for the group + * "", where is the non-namespaced name of the + * class. All constraints implicitely or explicitely assigned to group + * "Default" belong to both of these groups, unless the class defines + * a group sequence. + * + * If a class defines a group sequence, validating the class in "Default" + * will validate the group sequence. The constraints assinged to "Default" + * can still be validated by validating the class in "". + * + * @return string The name of the default group */ - public function getShortClassName() + public function getDefaultGroup() { - return $this->shortName; + return $this->defaultGroup; } /** @@ -82,7 +94,7 @@ public function addConstraint(Constraint $constraint) throw new ConstraintDefinitionException('The constraint Valid can only be put on properties or getters'); } - $constraint->addImplicitGroupName($this->getShortClassName()); + $constraint->addImplicitGroupName($this->getDefaultGroup()); parent::addConstraint($constraint); } @@ -103,7 +115,7 @@ public function addPropertyConstraint($property, Constraint $constraint) $this->addMemberMetadata($this->properties[$property]); } - $constraint->addImplicitGroupName($this->getShortClassName()); + $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->properties[$property]->addConstraint($constraint); @@ -129,7 +141,7 @@ public function addGetterConstraint($property, Constraint $constraint) $this->addMemberMetadata($this->getters[$property]); } - $constraint->addImplicitGroupName($this->getShortClassName()); + $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->getters[$property]->addConstraint($constraint); @@ -152,7 +164,7 @@ public function mergeConstraints(ClassMetadata $source) $member = clone $member; foreach ($member->getConstraints() as $constraint) { - $constraint->addImplicitGroupName($this->getShortClassName()); + $constraint->addImplicitGroupName($this->getDefaultGroup()); } $this->addMemberMetadata($member); @@ -213,6 +225,14 @@ public function getConstrainedProperties() */ public function setGroupSequence(array $groups) { + if (in_array(Constraint::DEFAULT_GROUP, $groups, true)) { + throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP)); + } + + if (!in_array($this->getDefaultGroup(), $groups, true)) { + throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup())); + } + $this->groupSequence = $groups; return $this; diff --git a/tests/Symfony/Tests/Component/Validator/GraphWalkerTest.php b/tests/Symfony/Tests/Component/Validator/GraphWalkerTest.php index 520e6c1d215f..aebdbec4af12 100644 --- a/tests/Symfony/Tests/Component/Validator/GraphWalkerTest.php +++ b/tests/Symfony/Tests/Component/Validator/GraphWalkerTest.php @@ -72,9 +72,9 @@ public function testWalkClassInDefaultGroupTraversesGroupSequence() 'groups' => 'First', ))); $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array( - 'groups' => 'Second', + 'groups' => 'Default', ))); - $this->metadata->setGroupSequence(array('First', 'Second')); + $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup())); $this->walker->walkClass($this->metadata, $entity, 'Default', ''); @@ -98,7 +98,7 @@ public function testWalkClassInGroupSequencePropagatesDefaultGroup() $entity->reference = new Reference(); $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->metadata->setGroupSequence(array('First')); + $this->metadata->setGroupSequence(array($this->metadata->getDefaultGroup())); $referenceMetadata = new ClassMetadata(get_class($entity->reference)); $referenceMetadata->addConstraint(new FailingConstraint(array( @@ -132,11 +132,11 @@ public function testWalkClassInOtherGroupTraversesNoGroupSequence() 'groups' => 'First', ))); $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array( - 'groups' => 'Second', + 'groups' => $this->metadata->getDefaultGroup(), ))); - $this->metadata->setGroupSequence(array('First', 'Second')); + $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup())); - $this->walker->walkClass($this->metadata, $entity, 'Second', ''); + $this->walker->walkClass($this->metadata, $entity, $this->metadata->getDefaultGroup(), ''); // Only group "Second" was validated $violations = new ConstraintViolationList(); diff --git a/tests/Symfony/Tests/Component/Validator/Mapping/ClassMetadataTest.php b/tests/Symfony/Tests/Component/Validator/Mapping/ClassMetadataTest.php index 8ed5b743fbcb..522f5c9ee92c 100644 --- a/tests/Symfony/Tests/Component/Validator/Mapping/ClassMetadataTest.php +++ b/tests/Symfony/Tests/Component/Validator/Mapping/ClassMetadataTest.php @@ -2,16 +2,17 @@ namespace Symfony\Tests\Component\Validator\Mapping; -require_once __DIR__.'/../Fixtures/Entity.php'; -require_once __DIR__.'/../Fixtures/ConstraintA.php'; -require_once __DIR__.'/../Fixtures/ConstraintB.php'; - -use Symfony\Tests\Component\Validator\Fixtures\Entity; -use Symfony\Tests\Component\Validator\Fixtures\ConstraintA; -use Symfony\Tests\Component\Validator\Fixtures\ConstraintB; +use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\ClassMetadata; 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; + +require_once __DIR__.'/../Fixtures/Entity.php'; +require_once __DIR__.'/../Fixtures/ConstraintA.php'; +require_once __DIR__.'/../Fixtures/ConstraintB.php'; class ClassMetadataTest extends \PHPUnit_Framework_TestCase { @@ -139,5 +140,24 @@ public function testSerialize() $this->assertEquals($this->metadata, $metadata); } + + public function testGroupSequencesWorkIfContainingDefaultGroup() + { + $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup())); + } + + public function testGroupSequencesFailIfNotContainingDefaultGroup() + { + $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException'); + + $this->metadata->setGroupSequence(array('Foo', 'Bar')); + } + + public function testGroupSequencesFailIfContainingDefault() + { + $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException'); + + $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup(), Constraint::DEFAULT_GROUP)); + } }