10000 do not merge constraints within interfaces · symfony/symfony@ba54d3e · GitHub
[go: up one dir, main page]

Skip to content

Commit ba54d3e

Browse files
committed
do not merge constraints within interfaces
1 parent c2e0aab commit ba54d3e

File tree

6 files changed

+76
-24
lines changed

6 files changed

+76
-24
lines changed

src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,35 +117,24 @@ public function getMetadataFor($value)
117117

118118
private function mergeConstraints(ClassMetadata $metadata)
119119
{
120-
// Include constraints from the parent class
121-
if ($parent = $metadata->getReflectionClass()->getParentClass()) {
122-
$metadata->mergeConstraints($this->getMetadataFor($parent->name));
123-
}
124-
125-
$interfaces = $metadata->getReflectionClass()->getInterfaces();
126-
127-
$interfaces = array_filter($interfaces, function ($interface) use ($parent, $interfaces) {
128-
$interfaceName = $interface->getName();
129-
130-
if ($parent && $parent->implementsInterface($interfaceName)) {
131-
return false;
120+
if (!$metadata->getReflectionClass()->isInterface()) {
121+
// Include constraints from the parent class
122+
if ($parent = $metadata->getReflectionClass()->getParentClass()) {
123+
$metadata->mergeConstraints($this->getMetadataFor($parent->name));
132124
}
133125

134-
foreach ($interfaces as $i) {
135-
if ($i !== $interface && $i->implementsInterface($interfaceName)) {
136-
return false;
126+
// Include constraints from all directly implemented interfaces
127+
foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) {
128+
if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) {
129+
continue;
137130
}
138-
}
139131

140-
return true;
141-
});
132+
if ($parent && \in_array($interface->getName(), $parent->getInterfaceNames(), true)) {
133+
continue;
134+
}
142135

143-
// Include constraints from all directly implemented interfaces
144-
foreach ($interfaces as $interface) {
145-
if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) {
146-
continue;
136+
$metadata->mergeConstraints($this->getMetadataFor($interface->name));
147137
}
148-
$metadata->mergeConstraints($this->getMetadataFor($interface->name));
149138
}
150139
}
151140

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
abstract class AbstractPropertyGetter implements PropertyGetterInterface
6+
{
7+
private $property;
8+
9+
public function getProperty()
10+
{
11+
return $this->property;
12+
}
13+
}
10000
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
interface ChildGetterInterface extends PropertyGetterInterface
6+
{
7+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
/**
6+
* This class has two paths to PropertyGetterInterface:
7+
* PropertyGetterInterface <- AbstractPropertyGetter <- PropertyGetter
8+
* PropertyGetterInterface <- ChildGetterInterface <- PropertyGetter
9+
*/
10+
class PropertyGetter extends AbstractPropertyGetter implements ChildGetterInterface
11+
{
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
interface PropertyGetterInterface
6+
{
7+
public function getProperty();
8+
}

src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1616
use Symfony\Component\Validator\Constraints\Callback;
17+
use Symfony\Component\Validator\Constraints\NotBlank;
1718
use Symfony\Component\Validator\Mapping\Cache\Psr6Cache;
1819
use Symfony\Component\Validator\Mapping\ClassMetadata;
1920
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
2021
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
2122
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
23+
use Symfony\Component\Validator\Tests\Fixtures\PropertyGetter;
24+
use Symfony\Component\Validator\Tests\Fixtures\PropertyGetterInterface;
2225

2326
class LazyLoadingMetadataFactoryTest extends TestCase
2427
{
@@ -70,7 +73,6 @@ public function testMergeParentConstraints()
7073
new ConstraintA(['groups' => [
7174
'Default',
7275
'EntityParentInterface',
73-
'EntityInterfaceB',
7476
'Entity',
7577
]]),
7678
];
@@ -186,6 +188,15 @@ public function testGroupsFromParent()
186188
$this->assertContains('EntityStaticCar', $groups);
187189
$this->assertContains('EntityStaticVehicle', $groups);
188190
}
191+
192+
public function testMultipathInterfaceConstraint()
193+
{
194+
$factory = new LazyLoadingMetadataFactory(new PropertyGetterInterfaceConstraintLoader());
195+
$metadata = $factory->getMetadataFor(PropertyGetter::class);
196+
$constraints = $metadata->getPropertyMetadata('property');
197+
198+
$this->assertCount(1, $constraints);
199+
}
189200
}
190201

191202
class TestLoader implements LoaderInterface
@@ -195,3 +206,15 @@ public function loadClassMetadata(ClassMetadata $metadata)
195206
$metadata->addConstraint(new ConstraintA());
196207
}
197208
}
209+
210+
class PropertyGetterInterfaceConstraintLoader implements LoaderInterface
211+
{
212+
public function loadClassMetadata(ClassMetadata $metadata)
213+
{
214+
if (PropertyGetterInterface::class === $metadata->getClassName()) {
215+
$metadata->addGetterConstraint('property', new NotBlank());
216+
}
217+
218+
return true;
219+
}
220+
}

0 commit comments

Comments
 (0)
0