From fb36c5a575d905983e71a52f9bdfeb07e303e857 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Wed, 10 Aug 2016 21:49:44 +0200 Subject: [PATCH] [Validator] fixed duplicate constraints with parent class interfaces This fixes https://github.com/symfony/symfony/issues/19516 --- .../Factory/LazyLoadingMetadataFactory.php | 4 +-- .../Validator/Tests/Fixtures/Entity.php | 2 +- .../Validator/Tests/Fixtures/EntityParent.php | 2 +- .../LazyLoadingMetadataFactoryTest.php | 35 ++++++++++++------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index 6c5c277ed8..b5b202de6d 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -116,9 +116,9 @@ class LazyLoadingMetadataFactory implements MetadataFactoryInterface $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } - // Include constraints from all implemented interfaces + // Include constraints from all implemented interfaces that have not been processed via parent class yet foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { - if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { + if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name || ($parent && $parent->implementsInterface($interface->name))) { continue; } $metadata->mergeConstraints($this->getMetadataFor($interface->name)); diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php b/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php index b5e9e0c982..e4eec6be32 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php @@ -19,7 +19,7 @@ use Symfony\Component\Validator\ExecutionContextInterface; * @Assert\GroupSequence({"Foo", "Entity"}) * @Assert\Callback({"Symfony\Component\Validator\Tests\Fixtures\CallbackClass", "callback"}) */ -class Entity extends EntityParent implements EntityInterface +class Entity extends EntityParent { /** * @Assert\NotNull diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php index 422bb28d0b..acbec3d32e 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraints\NotNull; -class EntityParent +class EntityParent implements EntityInterface { protected $firstName; private $internal; diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index 74ee912cb7..c78d2a72c8 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -20,13 +20,15 @@ class LazyLoadingMetadataFactoryTest extends \PHPUnit_Framework_TestCase { const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; + const INTERFACECLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterface'; - public function testLoadClassMetadata() + public function testLoadClassMetadataWithInterface() { $factory = new LazyLoadingMetadataFactory(new TestLoader()); $metadata = $factory->getMetadataFor(self::PARENTCLASS); $constraints = array( + new ConstraintA(array('groups' => array('Default', 'EntityInterface', 'EntityParent'))), new ConstraintA(array('groups' => array('Default', 'EntityParent'))), ); @@ -41,12 +43,13 @@ class LazyLoadingMetadataFactoryTest extends \PHPUnit_Framework_TestCase $constraints = array( new ConstraintA(array('groups' => array( 'Default', + 'EntityInterface', 'EntityParent', 'Entity', ))), new ConstraintA(array('groups' => array( 'Default', - 'EntityInterface', + 'EntityParent', 'Entity', ))), new ConstraintA(array('groups' => array( @@ -63,27 +66,36 @@ class LazyLoadingMetadataFactoryTest extends \PHPUnit_Framework_TestCase $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'); $factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache); - $tester = $this; - $constraints = array( + $parentClassConstraints = array( + new ConstraintA(array('groups' => array('Default', 'EntityInterface', 'EntityParent'))), new ConstraintA(array('groups' => array('Default', 'EntityParent'))), ); + $interfaceConstraints = array(new ConstraintA(array('groups' => array('Default', 'EntityInterface')))); $cache->expects($this->never()) ->method('has'); - $cache->expects($this->once()) + $cache->expects($this->exactly(2)) ->method('read') - ->with($this->equalTo(self::PARENTCLASS)) + ->withConsecutive( + array($this->equalTo(self::PARENTCLASS)), + array($this->equalTo(self::INTERFACECLASS)) + ) ->will($this->returnValue(false)); - $cache->expects($this->once()) + $cache->expects($this->exactly(2)) ->method('write') - ->will($this->returnCallback(function ($metadata) use ($tester, $constraints) { - $tester->assertEquals($constraints, $metadata->getConstraints()); - })); + ->withConsecutive( + $this->callback(function ($metadata) use ($interfaceConstraints) { + return $interfaceConstraints == $metadata->getConstraints(); + }), + $this->callback(function ($metadata) use ($parentClassConstraints) { + return $parentClassConstraints == $metadata->getConstraints(); + }) + ); $metadata = $factory->getMetadataFor(self::PARENTCLASS); $this->assertEquals(self::PARENTCLASS, $metadata->getClassName()); - $this->assertEquals($constraints, $metadata->getConstraints()); + $this->assertEquals($parentClassConstraints, $metadata->getConstraints()); } public function testReadMetadataFromCache() @@ -92,7 +104,6 @@ class LazyLoadingMetadataFactoryTest extends \PHPUnit_Framework_TestCase $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'); $factory = new LazyLoadingMetadataFactory($loader, $cache); - $tester = $this; $metadata = new ClassMetadata(self::PARENTCLASS); $metadata->addConstraint(new ConstraintA());