Skip to content

Commit e5adfa2

Browse files
committed
Merge branch '4.4' into 5.1
* 4.4: [Validator] RangeTest: fix expected deprecation [Yaml] Fix for #36624; Allow PHP constant as first key in block Use PHPUnit 9.3 on php 8. fix mapping errors from unmapped forms [Validator] Add target guards for Composite nested constraints
2 parents 872be1f + 388a3d7 commit e5adfa2

File tree

6 files changed

+127
-7
lines changed

6 files changed

+127
-7
lines changed

Constraints/Composite.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ public function addImplicitGroupName($group)
136136
*/
137137
abstract protected function getCompositeOption();
138138

139+
/**
140+
* @internal Used by metadata
141+
*
142+
* @return Constraint[]
143+
*/
144+
public function getNestedContraints()
145+
{
146+
/* @var Constraint[] $nestedConstraints */
147+
return $this->{$this->getCompositeOption()};
148+
}
149+
139150
/**
140151
* Initializes the nested constraints.
141152
*

Mapping/ClassMetadata.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Mapping;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Constraints\Composite;
1516
use Symfony\Component\Validator\Constraints\GroupSequence;
1617
use Symfony\Component\Validator\Constraints\Traverse;
1718
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
@@ -173,9 +174,7 @@ public function getDefaultGroup()
173174
*/
174175
public function addConstraint(Constraint $constraint)
175176
{
176-
if (!\in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) {
177-
throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', get_debug_type($constraint)));
178-
}
177+
$this->checkConstraint($constraint);
179178

180179
if ($constraint instanceof Traverse) {
181180
if ($constraint->traverse) {
@@ -474,4 +473,17 @@ private function addPropertyMetadata(PropertyMetadataInterface $metadata)
474473

475474
$this->members[$property][] = $metadata;
476475
}
476+
477+
private function checkConstraint(Constraint $constraint)
478+
{
479+
if (!\in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets(), true)) {
480+
throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', get_debug_type($constraint)));
481+
}
482+
483+
if ($constraint instanceof Composite) {
484+
foreach ($constraint->getNestedContraints() as $nestedContraint) {
485+
$this->checkConstraint($nestedContraint);
486+
}
487+
}
488+
}
477489
}

Mapping/MemberMetadata.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Mapping;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Constraints\Composite;
1516
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1617

1718
/**
@@ -71,9 +72,7 @@ public function __construct(string $class, string $name, string $property)
7172
*/
7273
public function addConstraint(Constraint $constraint)
7374
{
74-
if (!\in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) {
75-
throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on properties or getters.', get_debug_type($constraint)));
76-
}
75+
$this->checkConstraint($constraint);
7776

7877
parent::addConstraint($constraint);
7978

@@ -181,4 +180,17 @@ public function getReflectionMember($objectOrClassName)
181180
* @return \ReflectionMethod|\ReflectionProperty The reflection instance
182181
*/
183182
abstract protected function newReflectionMember($objectOrClassName);
183+
184+
private function checkConstraint(Constraint $constraint)
185+
{
186+
if (!\in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets(), true)) {
187+
throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on properties or getters.', get_debug_type($constraint)));
188+
}
189+
190+
if ($constraint instanceof Composite) {
191+
foreach ($constraint->getNestedContraints() as $nestedContraint) {
192+
$this->checkConstraint($nestedContraint);
193+
}
194+
}
195+
}
184196
}

Tests/Constraints/RangeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function provideDeprecationTriggeredIfMinMaxAndMinMessageOrMaxMessageSet(
5252

5353
/**
5454
* @group legacy
55-
* @expectedDeprecation Since symfony/validator 4.4: minMessage and maxMessage are deprecated when min and max options are set together. Use notInRangeMessage instead.
55+
* @expectedDeprecation Since symfony/validator 4.4: "minMessage" and "maxMessage" are deprecated when the "min" and "max" options are both set. Use "notInRangeMessage" instead.
5656
* @dataProvider provideDeprecationTriggeredIfMinMaxAndMinMessageOrMaxMessageSet
5757
*/
5858
public function testDeprecationTriggeredIfMinMaxAndMinMessageOrMaxMessageSet(array $options, bool $expectedDeprecatedMinMessageSet, bool $expectedDeprecatedMaxMessageSet)

Tests/Mapping/ClassMetadataTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Validator\Constraint;
16+
use Symfony\Component\Validator\Constraints\Composite;
1617
use Symfony\Component\Validator\Constraints\Valid;
18+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1719
use Symfony\Component\Validator\Mapping\ClassMetadata;
20+
use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
1821
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
1922
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
2023
use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;
@@ -52,6 +55,20 @@ public function testAddConstraintRequiresClassConstraints()
5255
$this->metadata->addConstraint(new PropertyConstraint());
5356
}
5457

58+
public function testAddCompositeConstraintRejectsNestedPropertyConstraints()
59+
{
60+
$this->expectException(ConstraintDefinitionException::class);
61+
$this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint" cannot be put on classes.');
62+
63+
$this->metadata->addConstraint(new ClassCompositeConstraint([new PropertyConstraint()]));
64+
}
65+
66+
public function testAddCompositeConstraintAcceptsNestedClassConstraints()
67+
{
68+
$this->metadata->addConstraint($constraint = new ClassCompositeConstraint([new ClassConstraint()]));
69+
$this->assertSame($this->metadata->getConstraints(), [$constraint]);
70+
}
71+
5572
public function testAddPropertyConstraints()
5673
{
5774
$this->metadata->addPropertyConstraint('firstName', new ConstraintA());
@@ -311,3 +328,23 @@ public function testGetPropertyMetadataReturnsEmptyArrayWithoutConfiguredMetadat
311328
$this->assertCount(0, $this->metadata->getPropertyMetadata('foo'), '->getPropertyMetadata() returns an empty collection if no metadata is configured for the given property');
312329
}
313330
}
331+
332+
class ClassCompositeConstraint extends Composite
333+
{
334+
public $nested;
335+
336+
public function getDefaultOption()
337+
{
338+
return $this->getCompositeOption();
339+
}
340+
341+
protected function getCompositeOption()
342+
{
343+
return 'nested';
344+
}
345+
346+
public function getTargets()
347+
{
348+
return [self::CLASS_CONSTRAINT];
349+
}
350+
}

Tests/Mapping/MemberMetadataTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@
1212
namespace Symfony\Component\Validator\Tests\Mapping;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Validator\Constraints\Collection;
16+
use Symfony\Component\Validator\Constraints\Composite;
17+
use Symfony\Component\Validator\Constraints\Required;
1518
use Symfony\Component\Validator\Constraints\Valid;
19+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1620
use Symfony\Component\Validator\Mapping\MemberMetadata;
1721
use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
1822
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
1923
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
24+
use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;
2025

2126
class MemberMetadataTest extends TestCase
2227
{
@@ -43,6 +48,34 @@ public function testAddConstraintRequiresClassConstraints()
4348
$this->metadata->addConstraint(new ClassConstraint());
4449
}
4550

51+
public function testAddCompositeConstraintRejectsNestedClassConstraints()
52+
{
53+
$this->expectException(ConstraintDefinitionException::class);
54+
$this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Tests\Fixtures\ClassConstraint" cannot be put on properties or getters.');
55+
56+
$this->metadata->addConstraint(new PropertyCompositeConstraint([new ClassConstraint()]));
57+
}
58+
59+
public function testAddCompositeConstraintRejectsDeepNestedClassConstraints()
60+
{
61+
$this->expectException(ConstraintDefinitionException::class);
62+
$this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Tests\Fixtures\ClassConstraint" cannot be put on properties or getters.');
63+
64+
$this->metadata->addConstraint(new Collection(['field1' => new Required([new ClassConstraint()])]));
65+
}
66+
67+
public function testAddCompositeConstraintAcceptsNestedPropertyConstraints()
68+
{
69+
$this->metadata->addConstraint($constraint = new PropertyCompositeConstraint([new PropertyConstraint()]));
70+
$this->assertSame($this->metadata->getConstraints(), [$constraint]);
71+
}
72+
73+
public function testAddCompositeConstraintAcceptsDeepNestedPropertyConstraints()
74+
{
75+
$this->metadata->addConstraint($constraint = new Collection(['field1' => new Required([new PropertyConstraint()])]));
76+
$this->assertSame($this->metadata->getConstraints(), [$constraint]);
77+
}
78+
4679
public function testSerialize()
4780
{
4881
$this->metadata->addConstraint(new ConstraintA(['property1' => 'A']));
@@ -82,3 +115,18 @@ protected function newReflectionMember($object): object
82115
{
83116
}
84117
}
118+
119+
class PropertyCompositeConstraint extends Composite
120+
{
121+
public $nested;
122+
123+
public function getDefaultOption()
124+
{
125+
return $this->getCompositeOption();
126+
}
127+
128+
protected function getCompositeOption()
129+
{
130+
return 'nested';
131+
}
132+
}

0 commit comments

Comments
 (0)