Skip to content

Commit b4285f4

Browse files
authored
Merge pull request #1571 from scyzoryck/union-properties-array
feat(unions): Add support for simple arrays
2 parents f8adbc4 + 18f462f commit b4285f4

File tree

5 files changed

+34
-37
lines changed

5 files changed

+34
-37
lines changed

src/Handler/UnionHandler.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,15 @@ private function matchSimpleType(mixed $data, array $type, Context $context): mi
115115

116116
private function isPrimitiveType(string $type): bool
117117
{
118-
return in_array($type, ['int', 'integer', 'float', 'double', 'bool', 'boolean', 'string'], true);
118+
return in_array($type, ['int', 'integer', 'float', 'double', 'bool', 'boolean', 'string', 'array'], true);
119119
}
120120

121121
private function testPrimitive(mixed $data, string $type, string $format): bool
122122
{
123123
switch ($type) {
124+
case 'array':
125+
return is_array($data);
126+
124127
case 'integer':
125128
case 'int':
126129
return (string) (int) $data === (string) $data;
@@ -134,7 +137,7 @@ private function testPrimitive(mixed $data, string $type, string $format): bool
134137
return (string) (bool) $data === (string) $data;
135138

136139
case 'string':
137-
return (string) $data === (string) $data;
140+
return is_string($data);
138141
}
139142

140143
return false;

src/Metadata/Driver/TypedPropertiesDriver.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ public function __construct(DriverInterface $delegate, ?ParserInterface $typePar
6060
private function reorderTypes(array $types): array
6161
{
6262
uasort($types, static function ($a, $b) {
63-
$order = ['null' => 0, 'true' => 1, 'false' => 2, 'bool' => 3, 'int' => 4, 'float' => 5, 'string' => 6];
63+
$order = ['null' => 0, 'true' => 1, 'false' => 2, 'bool' => 3, 'int' => 4, 'float' => 5, 'array' => 6, 'string' => 7];
6464

65-
return ($order[$a['name']] ?? 7) <=> ($order[$b['name']] ?? 7);
65+
return ($order[$a['name']] ?? 8) <=> ($order[$b['name']] ?? 8);
6666
});
6767

6868
return $types;
@@ -119,7 +119,7 @@ public function loadMetadataForClass(ReflectionClass $class): ?ClassMetadata
119119
$this->reorderTypes(
120120
array_map(
121121
fn (string $type) => $this->typeParser->parse($type),
122-
array_filter($reflectionType->getTypes(), [$this, 'shouldTypeHint']),
122+
array_filter($reflectionType->getTypes(), [$this, 'shouldTypeHintInsideUnion']),
123123
),
124124
),
125125
],
@@ -181,11 +181,16 @@ private function shouldTypeHintUnion(?ReflectionType $reflectionType)
181181
}
182182

183183
foreach ($reflectionType->getTypes() as $type) {
184-
if ($this->shouldTypeHint($type)) {
184+
if ($this->shouldTypeHintInsideUnion($type)) {
185185
return true;
186186
}
187187
}
188188

189189
return false;
190190
}
191+
192+
private function shouldTypeHintInsideUnion(ReflectionNamedType $reflectionType)
193+
{
194+
return $this->shouldTypeHint($reflectionType) || 'array' === $reflectionType->getName();
195+
}
191196
}

tests/Fixtures/TypedProperties/UnionTypedProperties.php

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

77
class UnionTypedProperties
88
{
9-
private int|bool|float|string $data;
9+
private int|bool|float|string|array $data;
1010

1111
private int|bool|float|string|null $nullableData;
1212

tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ public function testInferUnionTypesShouldResultInManyTypes()
3434
'params' =>
3535
[
3636
[
37+
[
38+
'name' => 'array',
39+
'params' => [],
40+
],
3741
[
3842
'name' => 'string',
3943
'params' => [],

tests/Serializer/JsonSerializationTest.php

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ protected static function getContent($key)
154154
$outputs['data_float'] = '{"data":1.236}';
155155
$outputs['data_bool'] = '{"data":false}';
156156
$outputs['data_string'] = '{"data":"foo"}';
157+
$outputs['data_array'] = '{"data":[1,2,3]}';
157158
$outputs['data_true'] = '{"data":true}';
158159
$outputs['data_false'] = '{"data":false}';
159160
$outputs['data_author'] = '{"data":{"full_name":"foo"}}';
@@ -443,46 +444,30 @@ public static function getTypeHintedArraysAndStdClass()
443444
];
444445
}
445446

446-
public function testDeserializingUnionProperties()
447+
public static function getSimpleUnionProperties(): iterable
447448
{
448-
if (PHP_VERSION_ID < 80000) {
449-
$this->markTestSkipped(sprintf('%s requires PHP 8.0', TypedPropertiesDriver::class));
450-
451-
return;
452-
}
453-
454-
$object = new UnionTypedProperties(10000);
455-
self::assertEquals($object, $this->deserialize(static::getContent('data_integer'), UnionTypedProperties::class));
456-
457-
$object = new UnionTypedProperties(1.236);
458-
self::assertEquals($object, $this->deserialize(static::getContent('data_float'), UnionTypedProperties::class));
459-
460-
$object = new UnionTypedProperties(false);
461-
self::assertEquals($object, $this->deserialize(static::getContent('data_bool'), UnionTypedProperties::class));
462-
463-
$object = new UnionTypedProperties('foo');
464-
self::assertEquals($object, $this->deserialize(static::getContent('data_string'), UnionTypedProperties::class));
449+
yield 'int' => [10000, 'data_integer'];
450+
yield [1.236, 'data_float'];
451+
yield [false, 'data_bool'];
452+
yield ['foo', 'data_string'];
453+
yield [[1, 2, 3], 'data_array'];
465454
}
466455

467-
public function testSerializingUnionProperties()
456+
/**
457+
* @dataProvider getSimpleUnionProperties
458+
*/
459+
#[DataProvider('getSimpleUnionProperties')]
460+
public function testUnionProperties($data, string $expected): void
468461
{
469462
if (PHP_VERSION_ID < 80000) {
470463
$this->markTestSkipped(sprintf('%s requires PHP 8.0', TypedPropertiesDriver::class));
471464

472465
return;
473466
}
474467

475-
$serialized = $this->serialize(new UnionTypedProperties(10000));
476-
self::assertEquals(static::getContent('data_integer'), $serialized);
477-
478-
$serialized = $this->serialize(new UnionTypedProperties(1.236));
479-
self::assertEquals(static::getContent('data_float'), $serialized);
480-
481-
$serialized = $this->serialize(new UnionTypedProperties(false));
482-
self::assertEquals(static::getContent('data_bool'), $serialized);
483-
484-
$serialized = $this->serialize(new UnionTypedProperties('foo'));
485-
self::assertEquals(static::getContent('data_string'), $serialized);
468+
$object = new UnionTypedProperties($data);
469+
self::assertEquals($object, $this->deserialize(static::getContent($expected), UnionTypedProperties::class));
470+
self::assertEquals($this->serialize($object), static::getContent($expected));
486471
}
487472

488473
public function testTrueDataType()

0 commit comments

Comments
 (0)