Skip to content

Commit 7afcfbb

Browse files
committed
[Serializer][PropertyInfo][Validator] TypeInfo 7.2 compatibility
1 parent 6066de1 commit 7afcfbb

File tree

2 files changed

+74
-10
lines changed

2 files changed

+74
-10
lines changed

Diff for: Normalizer/AbstractObjectNormalizer.php

+63-9
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@
3434
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
3535
use Symfony\Component\TypeInfo\Exception\LogicException as TypeInfoLogicException;
3636
use Symfony\Component\TypeInfo\Type;
37+
use Symfony\Component\TypeInfo\Type\BuiltinType;
3738
use Symfony\Component\TypeInfo\Type\CollectionType;
3839
use Symfony\Component\TypeInfo\Type\IntersectionType;
40+
use Symfony\Component\TypeInfo\Type\NullableType;
3941
use Symfony\Component\TypeInfo\Type\ObjectType;
4042
use Symfony\Component\TypeInfo\Type\UnionType;
43+
use Symfony\Component\TypeInfo\Type\WrappingTypeInterface;
4144
use Symfony\Component\TypeInfo\TypeIdentifier;
4245

4346
/**
@@ -644,7 +647,14 @@ private function validateAndDenormalizeLegacy(array $types, string $currentClass
644647
private function validateAndDenormalize(Type $type, string $currentClass, string $attribute, mixed $data, ?string $format, array $context): mixed
645648
{
646649
$expectedTypes = [];
647-
$isUnionType = $type->asNonNullable() instanceof UnionType;
650+
651+
// BC layer for type-info < 7.2
652+
if (method_exists(Type::class, 'asNonNullable')) {
653+
$isUnionType = $type->asNonNullable() instanceof UnionType;
654+
} else {
655+
$isUnionType = $type instanceof UnionType;
656+
}
657+
648658
$e = null;
649659
$extraAttributesException = null;
650660
$missingConstructorArgumentsException = null;
@@ -667,12 +677,23 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
667677
$collectionValueType = $t->getCollectionValueType();
668678
}
669679

670-
$t = $t->getBaseType();
680+
// BC layer for type-info < 7.2
681+
if (method_exists(Type::class, 'getBaseType')) {
682+
$t = $t->getBaseType();
683+
} else {
684+
while ($t instanceof WrappingTypeInterface) {
685+
$t = $t->getWrappedType();
686+
}
687+
}
671688

672689
// Fix a collection that contains the only one element
673690
// This is special to xml format only
674-
if ('xml' === $format && $collectionValueType && !$collectionValueType->isA(TypeIdentifier::MIXED) && (!\is_array($data) || !\is_int(key($data)))) {
675-
$data = [$data];
691+
if ('xml' === $format && $collectionValueType && (!\is_array($data) || !\is_int(key($data)))) {
692+
// BC layer for type-info < 7.2
693+
$isMixedType = method_exists(Type::class, 'isA') ? $collectionValueType->isA(TypeIdentifier::MIXED) : $collectionValueType->isIdentifiedBy(TypeIdentifier::MIXED);
694+
if (!$isMixedType) {
695+
$data = [$data];
696+
}
676697
}
677698

678699
// This try-catch should cover all NotNormalizableValueException (and all return branches after the first
@@ -695,7 +716,10 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
695716
return '';
696717
}
697718

698-
$isNullable = $isNullable ?: $type->isNullable();
719+
// BC layer for type-info < 7.2
720+
if (method_exists(Type::class, 'isNullable')) {
721+
$isNullable = $isNullable ?: $type->isNullable();
722+
}
699723
}
700724

701725
switch ($typeIdentifier) {
@@ -732,7 +756,16 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
732756

733757
if ($collectionValueType) {
734758
try {
735-
$collectionValueBaseType = $collectionValueType->getBaseType();
759+
$collectionValueBaseType = $collectionValueType;
760+
761+
// BC layer for type-info < 7.2
762+
if (!interface_exists(WrappingTypeInterface::class)) {
763+
$collectionValueBaseType = $collectionValueType->getBaseType();
764+
} else {
765+
while ($collectionValueBaseType instanceof WrappingTypeInterface) {
766+
$collectionValueBaseType = $collectionValueBaseType->getWrappedType();
767+
}
768+
}
736769
} catch (TypeInfoLogicException) {
737770
$collectionValueBaseType = Type::mixed();
738771
}
@@ -742,15 +775,29 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
742775
$class = $collectionValueBaseType->getClassName().'[]';
743776
$context['key_type'] = $collectionKeyType;
744777
$context['value_type'] = $collectionValueType;
745-
} elseif (TypeIdentifier::ARRAY === $collectionValueBaseType->getTypeIdentifier()) {
778+
} elseif (
779+
// BC layer for type-info < 7.2
780+
!class_exists(NullableType::class) && TypeIdentifier::ARRAY === $collectionValueBaseType->getTypeIdentifier()
781+
|| $collectionValueBaseType instanceof BuiltinType && TypeIdentifier::ARRAY === $collectionValueBaseType->getTypeIdentifier()
782+
) {
746783
// get inner type for any nested array
747784
$innerType = $collectionValueType;
785+
if ($innerType instanceof NullableType) {
786+
$innerType = $innerType->getWrappedType();
787+
}
748788

749789
// note that it will break for any other builtinType
750790
$dimensions = '[]';
751791
while ($innerType instanceof CollectionType) {
752792
$dimensions .= '[]';
753793
$innerType = $innerType->getCollectionValueType();
794+
if ($innerType instanceof NullableType) {
795+
$innerType = $innerType->getWrappedType();
796+
}
797+
}
798+
799+
while ($innerType instanceof WrappingTypeInterface) {
800+
$innerType = $innerType->getWrappedType();
754801
}
755802

756803
if ($innerType instanceof ObjectType) {
@@ -862,8 +909,15 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
862909
throw $missingConstructorArgumentsException;
863910
}
864911

865-
if (!$isUnionType && $e) {
866-
throw $e;
912+
// BC layer for type-info < 7.2
913+
if (!class_exists(NullableType::class)) {
914+
if (!$isUnionType && $e) {
915+
throw $e;
916+
}
917+
} else {
918+
if ($e && !($type instanceof UnionType && !$type instanceof NullableType)) {
919+
throw $e;
920+
}
867921
}
868922

869923
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {

Diff for: Normalizer/ArrayDenormalizer.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
1717
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
1818
use Symfony\Component\TypeInfo\Type;
19+
use Symfony\Component\TypeInfo\Type\BuiltinType;
1920
use Symfony\Component\TypeInfo\Type\UnionType;
21+
use Symfony\Component\TypeInfo\TypeIdentifier;
2022

2123
/**
2224
* Denormalizes arrays of objects.
@@ -59,7 +61,15 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a
5961
$typeIdentifiers = [];
6062
if (null !== $keyType = ($context['key_type'] ?? null)) {
6163
if ($keyType instanceof Type) {
62-
$typeIdentifiers = array_map(fn (Type $t): string => $t->getBaseType()->getTypeIdentifier()->value, $keyType instanceof UnionType ? $keyType->getTypes() : [$keyType]);
64+
// BC layer for type-info < 7.2
65+
if (method_exists(Type::class, 'getBaseType')) {
66+
$typeIdentifiers = array_map(fn (Type $t): string => $t->getBaseType()->getTypeIdentifier()->value, $keyType instanceof UnionType ? $keyType->getTypes() : [$keyType]);
67+
} else {
68+
/** @var list<BuiltinType<TypeIdentifier::INT>|BuiltinType<TypeIdentifier::STRING>> */
69+
$keyTypes = $keyType instanceof UnionType ? $keyType->getTypes() : [$keyType];
70+
71+
$typeIdentifiers = array_map(fn (BuiltinType $t): string => $t->getTypeIdentifier()->value, $keyTypes);
72+
}
6373
} else {
6474
$typeIdentifiers = array_map(fn (LegacyType $t): string => $t->getBuiltinType(), \is_array($keyType) ? $keyType : [$keyType]);
6575
}

0 commit comments

Comments
 (0)