3232use Symfony \Component \Serializer \Mapping \ClassMetadataInterface ;
3333use Symfony \Component \Serializer \Mapping \Factory \ClassMetadataFactoryInterface ;
3434use Symfony \Component \Serializer \NameConverter \NameConverterInterface ;
35+ use Symfony \Component \TypeInfo \Exception \LogicException as TypeInfoLogicException ;
3536use Symfony \Component \TypeInfo \Type ;
3637use Symfony \Component \TypeInfo \Type \BuiltinType ;
3738use Symfony \Component \TypeInfo \Type \CollectionType ;
@@ -646,6 +647,14 @@ private function validateAndDenormalizeLegacy(array $types, string $currentClass
646647 private function validateAndDenormalize (Type $ type , string $ currentClass , string $ attribute , mixed $ data , ?string $ format , array $ context ): mixed
647648 {
648649 $ expectedTypes = [];
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+
649658 $ e = null ;
650659 $ extraAttributesException = null ;
651660 $ missingConstructorArgumentsException = null ;
@@ -667,14 +676,23 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
667676 $ collectionValueType = $ t ->getCollectionValueType ();
668677 }
669678
670- while ($ t instanceof WrappingTypeInterface) {
671- $ t = $ t ->getWrappedType ();
679+ // BC layer for type-info < 7.2
680+ if (method_exists (Type::class, 'getBaseType ' )) {
681+ $ t = $ t ->getBaseType ();
682+ } else {
683+ while ($ t instanceof WrappingTypeInterface) {
684+ $ t = $ t ->getWrappedType ();
685+ }
672686 }
673687
674688 // Fix a collection that contains the only one element
675689 // This is special to xml format only
676- if ('xml ' === $ format && $ collectionValueType && !$ collectionValueType ->isIdentifiedBy (TypeIdentifier::MIXED ) && (!\is_array ($ data ) || !\is_int (key ($ data )))) {
677- $ data = [$ data ];
690+ if ('xml ' === $ format && $ collectionValueType && (!\is_array ($ data ) || !\is_int (key ($ data )))) {
691+ // BC layer for type-info < 7.2
692+ $ isMixedType = method_exists (Type::class, 'isA ' ) ? $ collectionValueType ->isA (TypeIdentifier::MIXED ) : $ collectionValueType ->isIdentifiedBy (TypeIdentifier::MIXED );
693+ if (!$ isMixedType ) {
694+ $ data = [$ data ];
695+ }
678696 }
679697
680698 // This try-catch should cover all NotNormalizableValueException (and all return branches after the first
@@ -731,17 +749,31 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
731749 }
732750
733751 if ($ collectionValueType ) {
734- $ collectionValueBaseType = $ collectionValueType ;
735- while ($ collectionValueBaseType instanceof WrappingTypeInterface) {
736- $ collectionValueBaseType = $ collectionValueBaseType ->getWrappedType ();
752+ try {
753+ $ collectionValueBaseType = $ collectionValueType ;
754+
755+ // BC layer for type-info < 7.2
756+ if (!interface_exists (WrappingTypeInterface::class)) {
757+ $ collectionValueBaseType = $ collectionValueType ->getBaseType ();
758+ } else {
759+ while ($ collectionValueBaseType instanceof WrappingTypeInterface) {
760+ $ collectionValueBaseType = $ collectionValueBaseType ->getWrappedType ();
761+ }
762+ }
763+ } catch (TypeInfoLogicException ) {
764+ $ collectionValueBaseType = Type::mixed ();
737765 }
738766
739767 if ($ collectionValueBaseType instanceof ObjectType) {
740768 $ typeIdentifier = TypeIdentifier::OBJECT ;
741769 $ class = $ collectionValueBaseType ->getClassName ().'[] ' ;
742770 $ context ['key_type ' ] = $ collectionKeyType ;
743771 $ context ['value_type ' ] = $ collectionValueType ;
744- } elseif ($ collectionValueBaseType instanceof BuiltinType && TypeIdentifier::ARRAY === $ collectionValueBaseType ->getTypeIdentifier ()) {
772+ } elseif (
773+ // BC layer for type-info < 7.2
774+ !class_exists (NullableType::class) && TypeIdentifier::ARRAY === $ collectionValueBaseType ->getTypeIdentifier ()
775+ || $ collectionValueBaseType instanceof BuiltinType && TypeIdentifier::ARRAY === $ collectionValueBaseType ->getTypeIdentifier ()
776+ ) {
745777 // get inner type for any nested array
746778 $ innerType = $ collectionValueType ;
747779 if ($ innerType instanceof NullableType) {
@@ -871,8 +903,15 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
871903 throw $ missingConstructorArgumentsException ;
872904 }
873905
874- if ($ e && !($ type instanceof UnionType && !$ type instanceof NullableType)) {
875- throw $ e ;
906+ // BC layer for type-info < 7.2
907+ if (!class_exists (NullableType::class)) {
908+ if (!$ isUnionType && $ e ) {
909+ throw $ e ;
910+ }
911+ } else {
912+ if ($ e && !($ type instanceof UnionType && !$ type instanceof NullableType)) {
913+ throw $ e ;
914+ }
876915 }
877916
878917 if ($ context [self ::DISABLE_TYPE_ENFORCEMENT ] ?? $ this ->defaultContext [self ::DISABLE_TYPE_ENFORCEMENT ] ?? false ) {
0 commit comments