diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index 6bd16c1c7dca..b17ff691fba4 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -117,34 +117,25 @@ public function getMetadataFor($value) private function mergeConstraints(ClassMetadata $metadata) { + if ($metadata->getReflectionClass()->isInterface()) { + return; + } + // Include constraints from the parent class if ($parent = $metadata->getReflectionClass()->getParentClass()) { $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } - $interfaces = $metadata->getReflectionClass()->getInterfaces(); - - $interfaces = array_filter($interfaces, function ($interface) use ($parent, $interfaces) { - $interfaceName = $interface->getName(); - - if ($parent && $parent->implementsInterface($interfaceName)) { - return false; - } - - foreach ($interfaces as $i) { - if ($i !== $interface && $i->implementsInterface($interfaceName)) { - return false; - } - } - - return true; - }); - // Include constraints from all directly implemented interfaces - foreach ($interfaces as $interface) { + foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { continue; } + + if ($parent && \in_array($interface->getName(), $parent->getInterfaceNames(), true)) { + continue; + } + $metadata->mergeConstraints($this->getMetadataFor($interface->name)); } } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php b/src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php new file mode 100644 index 000000000000..3df0b9469ddf --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php @@ -0,0 +1,13 @@ +property; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php b/src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php new file mode 100644 index 000000000000..65c144bbeadb --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php @@ -0,0 +1,7 @@ + [ 'Default', 'EntityParentInterface', - 'EntityInterfaceB', 'Entity', ]]), ]; @@ -186,6 +188,15 @@ public function testGroupsFromParent() $this->assertContains('EntityStaticCar', $groups); $this->assertContains('EntityStaticVehicle', $groups); } + + public function testMultipathInterfaceConstraint() + { + $factory = new LazyLoadingMetadataFactory(new PropertyGetterInterfaceConstraintLoader()); + $metadata = $factory->getMetadataFor(PropertyGetter::class); + $constraints = $metadata->getPropertyMetadata('property'); + + $this->assertCount(1, $constraints); + } } class TestLoader implements LoaderInterface @@ -195,3 +206,15 @@ public function loadClassMetadata(ClassMetadata $metadata) $metadata->addConstraint(new ConstraintA()); } } + +class PropertyGetterInterfaceConstraintLoader implements LoaderInterface +{ + public function loadClassMetadata(ClassMetadata $metadata) + { + if (PropertyGetterInterface::class === $metadata->getClassName()) { + $metadata->addGetterConstraint('property', new NotBlank()); + } + + return true; + } +}