Skip to content

Commit b78a76e

Browse files
committed
Support multiple types for collection keys & values
1 parent dc0d45d commit b78a76e

File tree

4 files changed

+136
-4
lines changed

4 files changed

+136
-4
lines changed

UPGRADE-5.3.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
UPGRADE FROM 5.2 to 5.3
2+
=======================
3+
4+
PropertyInfo
5+
------------
6+
7+
* Deprecated the `Type::getCollectionKeyType()` and `Type::getCollectionValueType()` methods, use `Type::getCollectionKeyTypes()` and `Type::getCollectionValueTypes()` instead.

src/Symfony/Component/PropertyInfo/CHANGELOG.md

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

4+
5.3.0
5+
-----
6+
7+
* Added support for multiple types for collection keys & values
8+
* Deprecated the `Type::getCollectionKeyType()` and `Type::getCollectionValueType()` methods, use `Type::getCollectionKeyTypes()` and `Type::getCollectionValueTypes()` instead.
9+
410
5.2.0
511
-----
612

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

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,24 @@
1212
namespace Symfony\Component\PropertyInfo\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
1516
use Symfony\Component\PropertyInfo\Type;
1617

1718
/**
1819
* @author Kévin Dunglas <dunglas@gmail.com>
1920
*/
2021
class TypeTest extends TestCase
2122
{
22-
public function testConstruct()
23+
use ExpectDeprecationTrait;
24+
25+
/**
26+
* @group legacy
27+
*/
28+
public function testLegacyConstruct()
2329
{
30+
$this->expectDeprecation('Since symfony/property-info 5.3: The "Symfony\Component\PropertyInfo\Type::getCollectionKeyType()" method is deprecated, use "getCollectionKeyTypes()" instead.');
31+
$this->expectDeprecation('Since symfony/property-info 5.3: The "Symfony\Component\PropertyInfo\Type::getCollectionValueType()" method is deprecated, use "getCollectionValueTypes()" instead.');
32+
2433
$type = new Type('object', true, 'ArrayObject', true, new Type('int'), new Type('string'));
2534

2635
$this->assertEquals(Type::BUILTIN_TYPE_OBJECT, $type->getBuiltinType());
@@ -37,6 +46,26 @@ public function testConstruct()
3746
$this->assertEquals(Type::BUILTIN_TYPE_STRING, $collectionValueType->getBuiltinType());
3847
}
3948

49+
public function testConstruct()
50+
{
51+
$type = new Type('object', true, 'ArrayObject', true, new Type('int'), new Type('string'));
52+
53+
$this->assertEquals(Type::BUILTIN_TYPE_OBJECT, $type->getBuiltinType());
54+
$this->assertTrue($type->isNullable());
55+
$this->assertEquals('ArrayObject', $type->getClassName());
56+
$this->assertTrue($type->isCollection());
57+
58+
$collectionKeyTypes = $type->getCollectionKeyTypes();
59+
$this->assertIsArray($collectionKeyTypes);
60+
$this->assertContainsOnlyInstancesOf('Symfony\Component\PropertyInfo\Type', $collectionKeyTypes);
61+
$this->assertEquals(Type::BUILTIN_TYPE_INT, $collectionKeyTypes[0]->getBuiltinType());
62+
63+
$collectionValueTypes = $type->getCollectionValueTypes();
64+
$this->assertIsArray($collectionValueTypes);
65+
$this->assertContainsOnlyInstancesOf('Symfony\Component\PropertyInfo\Type', $collectionValueTypes);
66+
$this->assertEquals(Type::BUILTIN_TYPE_STRING, $collectionValueTypes[0]->getBuiltinType());
67+
}
68+
4069
public function testIterable()
4170
{
4271
$type = new Type('iterable');
@@ -49,4 +78,30 @@ public function testInvalidType()
4978
$this->expectExceptionMessage('"foo" is not a valid PHP type.');
5079
new Type('foo');
5180
}
81+
82+
public function testArrayCollection()
83+
{
84+
$type = new Type('array', false, null, true, [new Type('int'), new Type('string')], [new Type('object', false, \ArrayObject::class, true), new Type('array', false, null, true)]);
85+
86+
$this->assertEquals(Type::BUILTIN_TYPE_ARRAY, $type->getBuiltinType());
87+
$this->assertFalse($type->isNullable());
88+
$this->assertTrue($type->isCollection());
89+
90+
[$firstKeyType, $secondKeyType] = $type->getCollectionKeyTypes();
91+
$this->assertEquals(Type::BUILTIN_TYPE_INT, $firstKeyType->getBuiltinType());
92+
$this->assertFalse($firstKeyType->isNullable());
93+
$this->assertFalse($firstKeyType->isCollection());
94+
$this->assertEquals(Type::BUILTIN_TYPE_STRING, $secondKeyType->getBuiltinType());
95+
$this->assertFalse($secondKeyType->isNullable());
96+
$this->assertFalse($secondKeyType->isCollection());
97+
98+
[$firstValueType, $secondValueType] = $type->getCollectionValueTypes();
99+
$this->assertEquals(Type::BUILTIN_TYPE_OBJECT, $firstValueType->getBuiltinType());
100+
$this->assertEquals(\ArrayObject::class, $firstValueType->getClassName());
101+
$this->assertFalse($firstValueType->isNullable());
102+
$this->assertTrue($firstValueType->isCollection());
103+
$this->assertEquals(Type::BUILTIN_TYPE_ARRAY, $secondValueType->getBuiltinType());
104+
$this->assertFalse($secondValueType->isNullable());
105+
$this->assertTrue($firstValueType->isCollection());
106+
}
52107
}

src/Symfony/Component/PropertyInfo/Type.php

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,12 @@ class Type
5757
private $collectionValueType;
5858

5959
/**
60+
* @param array|Type|null $collectionKeyType
61+
* @param array|Type|null $collectionValueType
62+
*
6063
* @throws \InvalidArgumentException
6164
*/
62-
public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, self $collectionKeyType = null, self $collectionValueType = null)
65+
public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, $collectionKeyType = null, $collectionValueType = null)
6366
{
6467
if (!\in_array($builtinType, self::$builtinTypes)) {
6568
throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP type.', $builtinType));
@@ -69,8 +72,31 @@ public function __construct(string $builtinType, bool $nullable = false, string
6972
$this->nullable = $nullable;
7073
$this->class = $class;
7174
$this->collection = $collection;
72-
$this->collectionKeyType = $collectionKeyType;
73-
$this->collectionValueType = $collectionValueType;
75+
$this->collectionKeyType = $this->validateCollectionArgument($collectionKeyType, 5, '$collectionKeyType');
76+
$this->collectionValueType = $this->validateCollectionArgument($collectionValueType, 6, '$collectionValueType');
77+
}
78+
79+
private function validateCollectionArgument($collectionArgument, int $argumentIndex, string $argumentName): ?array
80+
{
81+
if (null === $collectionArgument) {
82+
return null;
83+
}
84+
85+
if (null !== $collectionArgument && !\is_array($collectionArgument) && !$collectionArgument instanceof self) {
86+
throw new \TypeError(sprintf('"%s()": Argument #%d (%s) must be of type "array", "%s" or "null", "%s" given.', __METHOD__, $argumentIndex, $argumentName, self::class, get_debug_type($collectionArgument)));
87+
}
88+
89+
if (\is_array($collectionArgument)) {
90+
foreach ($collectionArgument as $type) {
91+
if (!$type instanceof self) {
92+
throw new \TypeError(sprintf('"%s()": Argument #%d (%s) must be an array with items of type "%s", "%s" given.', __METHOD__, $argumentIndex, $argumentName, self::class, get_debug_type($collectionArgument)));
93+
}
94+
}
95+
96+
return $collectionArgument;
97+
}
98+
99+
return [$collectionArgument];
74100
}
75101

76102
/**
@@ -107,8 +133,27 @@ public function isCollection(): bool
107133
* Gets collection key type.
108134
*
109135
* Only applicable for a collection type.
136+
*
137+
* @deprecated since Symfony 5.3, use "getCollectionKeyTypes()" instead
110138
*/
111139
public function getCollectionKeyType(): ?self
140+
{
141+
trigger_deprecation('symfony/property-info', '5.3', 'The "%s()" method is deprecated, use "getCollectionKeyTypes()" instead.', __METHOD__);
142+
143+
$type = $this->getCollectionKeyTypes();
144+
if (\is_array($type)) {
145+
[$type] = $type;
146+
}
147+
148+
return $type;
149+
}
150+
151+
/**
152+
* Gets collection key types.
153+
*
154+
* Only applicable for a collection type.
155+
*/
156+
public function getCollectionKeyTypes(): ?array
112157
{
113158
return $this->collectionKeyType;
114159
}
@@ -117,8 +162,27 @@ public function getCollectionKeyType(): ?self
117162
* Gets collection value type.
118163
*
119164
* Only applicable for a collection type.
165+
*
166+
* @deprecated since Symfony 5.3, use "getCollectionValueTypes()" instead
120167
*/
121168
public function getCollectionValueType(): ?self
169+
{
170+
trigger_deprecation('symfony/property-info', '5.3', 'The "%s()" method is deprecated, use "getCollectionValueTypes()" instead.', __METHOD__);
171+
172+
$type = $this->getCollectionValueTypes();
173+
if (\is_array($type)) {
174+
[$type] = $type;
175+
}
176+
177+
return $type;
178+
}
179+
180+
/**
181+
* Gets collection value types.
182+
*
183+
* Only applicable for a collection type.
184+
*/
185+
public function getCollectionValueTypes(): ?array
122186
{
123187
return $this->collectionValueType;
124188
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy