do not merge constraints within interfaces

This commit is contained in:
Ivan Grigoriev 2020-02-04 19:53:14 +03:00
parent 932a4f86ed
commit 67f336b808
No known key found for this signature in database
GPG Key ID: 52E6E2874B503A7C
6 changed files with 74 additions and 20 deletions

View File

@ -117,34 +117,25 @@ class LazyLoadingMetadataFactory implements MetadataFactoryInterface
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));
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Symfony\Component\Validator\Tests\Fixtures;
abstract class AbstractPropertyGetter implements PropertyGetterInterface
{
private $property;
public function getProperty()
{
return $this->property;
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Symfony\Component\Validator\Tests\Fixtures;
interface ChildGetterInterface extends PropertyGetterInterface
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace Symfony\Component\Validator\Tests\Fixtures;
/**
* This class has two paths to PropertyGetterInterface:
* PropertyGetterInterface <- AbstractPropertyGetter <- PropertyGetter
* PropertyGetterInterface <- ChildGetterInterface <- PropertyGetter
*/
class PropertyGetter extends AbstractPropertyGetter implements ChildGetterInterface
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace Symfony\Component\Validator\Tests\Fixtures;
interface PropertyGetterInterface
{
public function getProperty();
}

View File

@ -14,11 +14,14 @@ namespace Symfony\Component\Validator\Tests\Mapping\Factory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Mapping\Cache\Psr6Cache;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\PropertyGetter;
use Symfony\Component\Validator\Tests\Fixtures\PropertyGetterInterface;
class LazyLoadingMetadataFactoryTest extends TestCase
{
@ -70,7 +73,6 @@ class LazyLoadingMetadataFactoryTest extends TestCase
new ConstraintA(['groups' => [
'Default',
'EntityParentInterface',
'EntityInterfaceB',
'Entity',
]]),
];
@ -186,6 +188,15 @@ class LazyLoadingMetadataFactoryTest extends TestCase
$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 @@ class TestLoader implements LoaderInterface
$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;
}
}