Skip to content

Commit e00d798

Browse files
committed
hardened tests and cascade array
1 parent 6d4234f commit e00d798

File tree

7 files changed

+87
-45
lines changed

7 files changed

+87
-45
lines changed

src/Symfony/Component/Validator/Mapping/ClassMetadata.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,14 @@ public function addConstraint(Constraint $constraint)
204204
}
205205

206206
if ($constraint instanceof Cascade) {
207+
if (\PHP_VERSION_ID < 70400) {
208+
throw new ConstraintDefinitionException(sprintf('The constraint "%s" requires PHP 7.4.', Cascade::class));
209+
}
210+
207211
$this->cascadingStrategy = CascadingStrategy::CASCADE;
208212

209213
foreach ($this->getReflectionClass()->getProperties() as $property) {
210-
if ($property->hasType() && class_exists($property->getType()->getName())) {
214+
if ($property->hasType() && (('array' === $type = $property->getType()->getName()) || class_exists(($type)))) {
211215
$this->addPropertyConstraint($property->getName(), new Valid());
212216
}
213217
}

src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntity.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@
1313

1414
class CascadingEntity
1515
{
16-
public ?CascadedChild $childOne;
16+
public string $scalar;
1717

18-
public static ?CascadedChild $childTwo;
18+
public CascadedChild $requiredChild;
1919

20-
public $children = [];
20+
public ?CascadedChild $optionalChild;
21+
22+
public static ?CascadedChild $staticChild;
23+
24+
/**
25+
* @var CascadedChild[]
26+
*/
27+
public array $children;
2128
}

src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php

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

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Validator\Constraint;
16+
use Symfony\Component\Validator\Constraints\Cascade;
1617
use Symfony\Component\Validator\Constraints\Valid;
18+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
19+
use Symfony\Component\Validator\Mapping\CascadingStrategy;
1720
use Symfony\Component\Validator\Mapping\ClassMetadata;
21+
use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity;
1822
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
1923
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
2024
use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;
@@ -310,4 +314,36 @@ public function testGetPropertyMetadataReturnsEmptyArrayWithoutConfiguredMetadat
310314
{
311315
$this->assertCount(0, $this->metadata->getPropertyMetadata('foo'), '->getPropertyMetadata() returns an empty collection if no metadata is configured for the given property');
312316
}
317+
318+
/**
319+
* @requires PHP < 7.4
320+
*/
321+
public function testCascadeConstraintIsNotAvailable()
322+
{
323+
$metadata = new ClassMetadata(CascadingEntity::class);
324+
325+
$this->expectException(ConstraintDefinitionException::class);
326+
$this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Constraints\Cascade" requires PHP 7.4.');
327+
328+
$metadata->addConstraint(new Cascade());
329+
}
330+
331+
/**
332+
* @requires PHP 7.4
333+
*/
334+
public function testCascadeConstraint()
335+
{
336+
$metadata = new ClassMetadata(CascadingEntity::class);
337+
338+
$metadata->addConstraint(new Cascade());
339+
340+
$this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy());
341+
$this->assertCount(4, $metadata->properties);
342+
$this->assertSame([
343+
'requiredChild',
344+
'optionalChild',
345+
'staticChild',
346+
'children',
347+
], $metadata->getConstrainedProperties());
348+
}
313349
}

src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Validator\Constraints\All;
1616
use Symfony\Component\Validator\Constraints\Callback;
17-
use Symfony\Component\Validator\Constraints\Cascade;
1817
use Symfony\Component\Validator\Constraints\Choice;
1918
use Symfony\Component\Validator\Constraints\Collection;
2019
use Symfony\Component\Validator\Constraints\IsTrue;
@@ -60,7 +59,6 @@ public function testLoadClassMetadata()
6059
$expected->addConstraint(new Callback('validateMe'));
6160
$expected->addConstraint(new Callback('validateMeStatic'));
6261
$expected->addConstraint(new Callback(['Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback']));
63-
$expected->addConstraint(new Cascade());
6462
$expected->addConstraint(new Traverse(false));
6563
$expected->addPropertyConstraint('firstName', new NotNull());
6664
$expected->addPropertyConstraint('firstName', new Range(['min' => 3]));

src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
<value>callback</value>
3232
</constraint>
3333

34-
<!-- Cascade -->
35-
<constraint name="Cascade" />
36-
3734
<!-- Traverse with boolean default option -->
3835
<constraint name="Traverse">
3936
false

src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,9 @@ public function testReferenceCascadeDisabledByDefault()
520520
$this->assertCount(0, $violations);
521521
}
522522

523+
/**
524+
* @requires PHP 7.4
525+
*/
523526
public function testReferenceCascadeEnabledIgnoresUntyped()
524527
{
525528
$entity = new Entity();
@@ -548,7 +551,7 @@ public function testReferenceCascadeEnabledIgnoresUntyped()
548551
public function testTypedReferenceCascadeEnabled()
549552
{
550553
$entity = new CascadingEntity();
551-
$entity->childOne = new CascadedChild();
554+
$entity->requiredChild = new CascadedChild();
552555

553556
$callback = function ($value, ExecutionContextInterface $context) {
554557
$context->buildViolation('Invalid child')

src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -168,51 +168,33 @@ public function testAllConstraintValidateAllGroupsForNestedConstraints()
168168
/**
169169
* @requires PHP 7.4
170170
*/
171-
public function testValidateDoNotCascadeNestedObjectsByDefault()
172-
{
173-
$this->metadataFactory->addMetadata(new ClassMetadata(CascadingEntity::class));
174-
$this->metadataFactory->addMetadata((new ClassMetadata(CascadedChild::class))
175-
->addPropertyConstraint('name', new NotNull())
176-
);
177-
178-
$entity = new CascadingEntity();
179-
$entity->childOne = new CascadedChild();
180-
CascadingEntity::$childTwo = new CascadedChild();
181-
182-
$violations = $this->validator->validate($entity);
183-
184-
$this->assertCount(0, $violations);
185-
186-
CascadingEntity::$childTwo = null;
187-
}
188-
189-
/**
190-
* @requires PHP 7.4
191-
*/
192-
public function testValidateDoNotCascadeNestedArrayByDefault()
171+
public function testValidateDoNotCascadeNestedObjectsAndArraysByDefault()
193172
{
194173
$this->metadataFactory->addMetadata(new ClassMetadata(CascadingEntity::class));
195174
$this->metadataFactory->addMetadata((new ClassMetadata(CascadedChild::class))
196175
->addPropertyConstraint('name', new NotNull())
197176
);
198177

199178
$entity = new CascadingEntity();
179+
$entity->requiredChild = new CascadedChild();
180+
$entity->optionalChild = new CascadedChild();
200181
$entity->children[] = new CascadedChild();
201-
$entity->children[] = new CascadedChild();
182+
CascadingEntity::$staticChild = new CascadedChild();
202183

203184
$violations = $this->validator->validate($entity);
204185

205186
$this->assertCount(0, $violations);
187+
188+
CascadingEntity::$staticChild = null;
206189
}
207190

208191
/**
209192
* @requires PHP 7.4
210193
*/
211-
public function testValidateCascadeNestedArrayByDefaultIfConstrained()
194+
public function testValidateTraverseNestedArrayByDefaultIfConstrainedWithoutCascading()
212195
{
213196
$this->metadataFactory->addMetadata((new ClassMetadata(CascadingEntity::class))
214197
->addPropertyConstraint('children', new All([
215-
new NotNull(),
216198
new Type(CascadedChild::class),
217199
]))
218200
);
@@ -222,6 +204,7 @@ public function testValidateCascadeNestedArrayByDefaultIfConstrained()
222204

223205
$entity = new CascadingEntity();
224206
$entity->children[] = new \stdClass();
207+
$entity->children[] = new CascadedChild();
225208

226209
$violations = $this->validator->validate($entity);
227210

@@ -235,24 +218,32 @@ public function testValidateCascadeNestedArrayByDefaultIfConstrained()
235218
public function testValidateCascadeWithValid()
236219
{
237220
$this->metadataFactory->addMetadata((new ClassMetadata(CascadingEntity::class))
238-
->addPropertyConstraint('childOne', new Valid())
239-
->addPropertyConstraint('childTwo', new Valid())
221+
->addPropertyConstraint('requiredChild', new Valid())
222+
->addPropertyConstraint('optionalChild', new Valid())
223+
->addPropertyConstraint('staticChild', new Valid())
224+
->addPropertyConstraint('children', new Valid())
240225
);
241226
$this->metadataFactory->addMetadata((new ClassMetadata(CascadedChild::class))
242227
->addPropertyConstraint('name', new NotNull())
243228
);
244229

245230
$entity = new CascadingEntity();
246-
$entity->childOne = new CascadedChild();
247-
CascadingEntity::$childTwo = new CascadedChild();
231+
$entity->requiredChild = new CascadedChild();
232+
$entity->children[] = new CascadedChild();
233+
$entity->children[] = null;
234+
CascadingEntity::$staticChild = new CascadedChild();
248235

249236
$violations = $this->validator->validate($entity);
250237

251-
$this->assertCount(2, $violations);
238+
$this->assertCount(3, $violations);
252239
$this->assertInstanceOf(NotNull::class, $violations->get(0)->getConstraint());
253240
$this->assertInstanceOf(NotNull::class, $violations->get(1)->getConstraint());
241+
$this->assertInstanceOf(NotNull::class, $violations->get(2)->getConstraint());
242+
$this->assertSame('requiredChild.name', $violations->get(0)->getPropertyPath());
243+
$this->assertSame('staticChild.name', $violations->get(1)->getPropertyPath());
244+
$this->assertSame('children[0].name', $violations->get(2)->getPropertyPath());
254245

255-
CascadingEntity::$childTwo = null;
246+
CascadingEntity::$staticChild = null;
256247
}
257248

258249
/**
@@ -268,15 +259,21 @@ public function testValidateWithExplicitCascade()
268259
);
269260

270261
$entity = new CascadingEntity();
271-
$entity->childOne = new CascadedChild();
272-
CascadingEntity::$childTwo = new CascadedChild();
262+
$entity->requiredChild = new CascadedChild();
263+
$entity->children[] = new CascadedChild();
264+
$entity->children[] = null;
265+
CascadingEntity::$staticChild = new CascadedChild();
273266

274267
$violations = $this->validator->validate($entity);
275268

276-
$this->assertCount(2, $violations);
269+
$this->assertCount(3, $violations);
277270
$this->assertInstanceOf(NotNull::class, $violations->get(0)->getConstraint());
278271
$this->assertInstanceOf(NotNull::class, $violations->get(1)->getConstraint());
272+
$this->assertInstanceOf(NotNull::class, $violations->get(2)->getConstraint());
273+
$this->assertSame('requiredChild.name', $violations->get(0)->getPropertyPath());
274+
$this->assertSame('staticChild.name', $violations->get(1)->getPropertyPath());
275+
$this->assertSame('children[0].name', $violations->get(2)->getPropertyPath());
279276

280-
CascadingEntity::$childTwo = null;
277+
CascadingEntity::$staticChild = null;
281278
}
282279
}

0 commit comments

Comments
 (0)