Skip to content

Commit afc96ee

Browse files
committed
Merge branch '5.4' into 6.4
* 5.4: fix compatibility with Twig 3.10 [Strings][EnglishInflector] Fix incorrect pluralisation of 'Album' handle union and intersection types for cascaded validations move wiring of the property info extractor to the ObjectNormalizer move Process component dep to require-dev Remove calls to `onConsecutiveCalls()` fix: remove unwanted type cast accept AbstractAsset instances when filtering schemas better distinguish URL schemes and windows drive letters convert empty CSV header names into numeric keys
2 parents 271b298 + d05268e commit afc96ee

File tree

5 files changed

+110
-6
lines changed

5 files changed

+110
-6
lines changed

Mapping/ClassMetadata.php

+30-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public function addConstraint(Constraint $constraint): static
198198
continue;
199199
}
200200

201-
if ($property->hasType() && (('array' === $type = $property->getType()->getName()) || class_exists($type))) {
201+
if ($this->canCascade($property->getType())) {
202202
$this->addPropertyConstraint($property->getName(), new Valid());
203203
}
204204
}
@@ -487,4 +487,33 @@ private function checkConstraint(Constraint $constraint): void
487487
}
488488
}
489489
}
490+
491+
private function canCascade(?\ReflectionType $type = null): bool
492+
{
493+
if (null === $type) {
494+
return false;
495+
}
496+
497+
if ($type instanceof \ReflectionIntersectionType) {
498+
foreach ($type->getTypes() as $nestedType) {
499+
if ($this->canCascade($nestedType)) {
500+
return true;
501+
}
502+
}
503+
504+
return false;
505+
}
506+
507+
if ($type instanceof \ReflectionUnionType) {
508+
foreach ($type->getTypes() as $nestedType) {
509+
if (!$this->canCascade($nestedType)) {
510+
return false;
511+
}
512+
}
513+
514+
return true;
515+
}
516+
517+
return $type instanceof \ReflectionNamedType && (\in_array($type->getName(), ['array', 'null'], true) || class_exists($type->getName()));
518+
}
490519
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Fixtures;
13+
14+
class CascadingEntityIntersection
15+
{
16+
public CascadedChild&\stdClass $classes;
17+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Fixtures;
13+
14+
class CascadingEntityUnion
15+
{
16+
public CascadedChild|\stdClass $classes;
17+
public CascadedChild|array $classAndArray;
18+
public CascadedChild|null $classAndNull;
19+
public array|null $arrayAndNull;
20+
public CascadedChild|array|null $classAndArrayAndNull;
21+
public int|string $scalars;
22+
public int|null $scalarAndNull;
23+
public CascadedChild|int $classAndScalar;
24+
public array|int $arrayAndScalar;
25+
}

Tests/Mapping/ClassMetadataTest.php

+30
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use Symfony\Component\Validator\Mapping\CascadingStrategy;
2323
use Symfony\Component\Validator\Mapping\ClassMetadata;
2424
use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity;
25+
use Symfony\Component\Validator\Tests\Fixtures\CascadingEntityIntersection;
26+
use Symfony\Component\Validator\Tests\Fixtures\CascadingEntityUnion;
2527
use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
2628
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
2729
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
@@ -342,6 +344,34 @@ public function testCascadeConstraint()
342344
], $metadata->getConstrainedProperties());
343345
}
344346

347+
public function testCascadeConstraintWithUnionTypeProperties()
348+
{
349+
$metadata = new ClassMetadata(CascadingEntityUnion::class);
350+
$metadata->addConstraint(new Cascade());
351+
352+
$this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy());
353+
$this->assertCount(5, $metadata->properties);
354+
$this->assertSame([
355+
'classes',
356+
'classAndArray',
357+
'classAndNull',
358+
'arrayAndNull',
359+
'classAndArrayAndNull',
360+
], $metadata->getConstrainedProperties());
361+
}
362+
363+
public function testCascadeConstraintWithIntersectionTypeProperties()
364+
{
365+
$metadata = new ClassMetadata(CascadingEntityIntersection::class);
366+
$metadata->addConstraint(new Cascade());
367+
368+
$this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy());
369+
$this->assertCount(1, $metadata->properties);
370+
$this->assertSame([
371+
'classes',
372+
], $metadata->getConstrainedProperties());
373+
}
374+
345375
public function testCascadeConstraintWithExcludedProperties()
346376
{
347377
$metadata = new ClassMetadata(CascadingEntity::class);

Tests/Mapping/Loader/PropertyInfoLoaderTest.php

+8-5
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ public function testLoadClassMetadata()
5454
'noAutoMapping',
5555
])
5656
;
57+
5758
$propertyInfoStub
5859
->method('getTypes')
59-
->will($this->onConsecutiveCalls(
60+
->willReturn(
6061
[new Type(Type::BUILTIN_TYPE_STRING, true)],
6162
[new Type(Type::BUILTIN_TYPE_STRING)],
6263
[new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_BOOL)],
@@ -69,11 +70,12 @@ public function testLoadClassMetadata()
6970
[new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, null, new Type(Type::BUILTIN_TYPE_FLOAT))],
7071
[new Type(Type::BUILTIN_TYPE_STRING)],
7172
[new Type(Type::BUILTIN_TYPE_STRING)]
72-
))
73+
)
7374
;
75+
7476
$propertyInfoStub
7577
->method('isWritable')
76-
->will($this->onConsecutiveCalls(
78+
->willReturn(
7779
true,
7880
true,
7981
true,
@@ -86,7 +88,7 @@ public function testLoadClassMetadata()
8688
true,
8789
false,
8890
true
89-
))
91+
)
9092
;
9193

9294
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub, '{.*}');
@@ -221,9 +223,10 @@ public function testClassNoAutoMapping()
221223
->method('getProperties')
222224
->willReturn(['string', 'autoMappingExplicitlyEnabled'])
223225
;
226+
224227
$propertyInfoStub
225228
->method('getTypes')
226-
->willReturnOnConsecutiveCalls(
229+
->willReturn(
227230
[new Type(Type::BUILTIN_TYPE_STRING)],
228231
[new Type(Type::BUILTIN_TYPE_BOOL)]
229232
);

0 commit comments

Comments
 (0)