Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e01dfd6

Browse files
[PropertyInfo][Serializer] Add support of list and trigger deprecation when filling a list-typed property with an array
1 parent 4513a3a commit e01dfd6

File tree

13 files changed

+111
-19
lines changed

13 files changed

+111
-19
lines changed

UPGRADE-6.3.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ DependencyInjection
66

77
* Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`, use `inline_factories` and `inline_class_loader` instead
88
* Deprecate undefined and numeric keys with `service_locator` config, use string aliases instead
9+
* Deprecate denormalizing an array that is not a list into a `list` typed property with the `Serializer` component
910

1011
FrameworkBundle
1112
---------------

UPGRADE-7.0.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ Messenger
99
`Symfony\Component\Messenger\Transport\InMemory\InMemoryTransport` and
1010
`Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory`
1111

12+
Serializer
13+
----------
14+
15+
* Values being denormalized into `list` typed properties must be list themselves, otherwise the property must be typed with `array`
16+
1217
Workflow
1318
--------
1419

src/Symfony/Component/PropertyInfo/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.3
5+
---
6+
7+
* Add support of `list` typed properties
8+
49
6.1
510
---
611

src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public function typesProvider()
126126
['emptyVar', null, 'This should not be removed.', null],
127127
['arrayWithKeys', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_STRING))], null, null],
128128
['arrayOfMixed', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), null)], null, null],
129-
['listOfStrings', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))], null, null],
129+
['listOfStrings', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING), true)], null, null],
130130
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], null, null],
131131
];
132132
}

src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public function typesProvider()
126126
['emptyVar', null],
127127
['arrayWithKeys', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_STRING))]],
128128
['arrayOfMixed', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), null)]],
129-
['listOfStrings', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]],
129+
['listOfStrings', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING), true)]],
130130
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)]],
131131
['rootDummyItems', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, RootDummyItem::class))]],
132132
['rootDummyItem', [new Type(Type::BUILTIN_TYPE_OBJECT, false, RootDummyItem::class)]],
@@ -411,7 +411,7 @@ public function pseudoTypesProvider(): array
411411
['positiveInt', [new Type(Type::BUILTIN_TYPE_INT, false, null)]],
412412
['negativeInt', [new Type(Type::BUILTIN_TYPE_INT, false, null)]],
413413
['nonEmptyArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
414-
['nonEmptyList', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT))]],
414+
['nonEmptyList', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), list: true)]],
415415
['scalar', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_BOOL)]],
416416
['number', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT)]],
417417
['numeric', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_STRING)]],

src/Symfony/Component/PropertyInfo/Tests/TypeTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function testConstruct()
3737
$this->assertIsArray($collectionValueTypes);
3838
$this->assertContainsOnlyInstancesOf('Symfony\Component\PropertyInfo\Type', $collectionValueTypes);
3939
$this->assertEquals(Type::BUILTIN_TYPE_STRING, $collectionValueTypes[0]->getBuiltinType());
40+
$this->assertFalse($type->isList());
4041
}
4142

4243
public function testIterable()
@@ -45,6 +46,12 @@ public function testIterable()
4546
$this->assertSame('iterable', $type->getBuiltinType());
4647
}
4748

49+
public function testList()
50+
{
51+
$type = new Type('array', list: true);
52+
$this->assertTrue($type->isList());
53+
}
54+
4855
public function testInvalidType()
4956
{
5057
$this->expectException(\InvalidArgumentException::class);

src/Symfony/Component/PropertyInfo/Type.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@ class Type
3535

3636
/**
3737
* List of PHP builtin types.
38-
*
39-
* @var string[]
4038
*/
41-
public static $builtinTypes = [
39+
public static array $builtinTypes = [
4240
self::BUILTIN_TYPE_INT,
4341
self::BUILTIN_TYPE_FLOAT,
4442
self::BUILTIN_TYPE_STRING,
@@ -58,25 +56,26 @@ class Type
5856
*
5957
* @var string[]
6058
*/
61-
public static $builtinCollectionTypes = [
59+
public static array $builtinCollectionTypes = [
6260
self::BUILTIN_TYPE_ARRAY,
6361
self::BUILTIN_TYPE_ITERABLE,
6462
];
6563

66-
private $builtinType;
67-
private $nullable;
68-
private $class;
69-
private $collection;
70-
private $collectionKeyType;
71-
private $collectionValueType;
64+
private string $builtinType;
65+
private bool $nullable;
66+
private ?string $class;
67+
private bool $collection;
68+
private Type|array|null $collectionKeyType;
69+
private Type|array|null $collectionValueType;
70+
private bool $list;
7271

7372
/**
7473
* @param Type[]|Type|null $collectionKeyType
7574
* @param Type[]|Type|null $collectionValueType
7675
*
7776
* @throws \InvalidArgumentException
7877
*/
79-
public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, array|Type $collectionKeyType = null, array|Type $collectionValueType = null)
78+
public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, array|Type $collectionKeyType = null, array|Type $collectionValueType = null, bool $list = false)
8079
{
8180
if (!\in_array($builtinType, self::$builtinTypes)) {
8281
throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP type.', $builtinType));
@@ -88,6 +87,7 @@ public function __construct(string $builtinType, bool $nullable = false, string
8887
$this->collection = $collection;
8988
$this->collectionKeyType = $this->validateCollectionArgument($collectionKeyType, 5, '$collectionKeyType') ?? [];
9089
$this->collectionValueType = $this->validateCollectionArgument($collectionValueType, 6, '$collectionValueType') ?? [];
90+
$this->list = $list;
9191
}
9292

9393
private function validateCollectionArgument(array|Type|null $collectionArgument, int $argumentIndex, string $argumentName): ?array
@@ -162,4 +162,9 @@ public function getCollectionValueTypes(): array
162162
{
163163
return $this->collectionValueType;
164164
}
165+
166+
public function isList(): bool
167+
{
168+
return $this->list;
169+
}
165170
}

src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ private function createType(DocType $type, bool $nullable, string $docType = nul
141141
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType);
142142
}
143143

144-
if ((str_starts_with($docType, 'list<') || str_starts_with($docType, 'array<')) && $type instanceof Array_) {
144+
if ((($list = str_starts_with($docType, 'list<')) || str_starts_with($docType, 'array<')) && $type instanceof Array_) {
145145
// array<value> is converted to x[] which is handled above
146146
// so it's only necessary to handle array<key, value> here
147147
$collectionKeyType = $this->getTypes($type->getKeyType())[0];
@@ -154,7 +154,7 @@ private function createType(DocType $type, bool $nullable, string $docType = nul
154154
$collectionValueType = $collectionValueTypes[0];
155155
}
156156

157-
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType);
157+
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType, $list);
158158
}
159159

160160
if ($type instanceof PseudoType) {

src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
140140
}
141141
}
142142

143-
return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), true, $collectionKeyTypes, $collectionKeyValues)];
143+
return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), true, $collectionKeyTypes, $collectionKeyValues, list: 'list' === $node->type->name)];
144144
}
145145
if ($node instanceof ArrayShapeNode) {
146146
return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)];
@@ -175,7 +175,7 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
175175
'negative-int' => [new Type(Type::BUILTIN_TYPE_INT)],
176176
'double' => [new Type(Type::BUILTIN_TYPE_FLOAT)],
177177
'list',
178-
'non-empty-list' => [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT))],
178+
'non-empty-list' => [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), list: true)],
179179
'non-empty-array' => [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)],
180180
'mixed' => [], // mixed seems to be ignored in all other extractors
181181
'parent' => [new Type(Type::BUILTIN_TYPE_OBJECT, false, $node->name)],

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Add `XmlEncoder::SAVE_OPTIONS` context option
8+
* Deprecate denormalizing an array that is not a list into a `list` typed property
89

910
6.2
1011
---

0 commit comments

Comments
 (0)