Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d3acdeb

Browse filesBrowse files
committed
[TypeInfo][Serializer][PropertyInfo][Validator] TypeInfo 7.1 compatibility
1 parent 31f22b8 commit d3acdeb
Copy full SHA for d3acdeb

File tree

12 files changed

+146
-33
lines changed
Filter options

12 files changed

+146
-33
lines changed

‎src/Symfony/Bridge/Doctrine/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"symfony/security-core": "^6.4|^7.0",
4040
"symfony/stopwatch": "^6.4|^7.0",
4141
"symfony/translation": "^6.4|^7.0",
42-
"symfony/type-info": "^7.2",
42+
"symfony/type-info": "^7.1",
4343
"symfony/uid": "^6.4|^7.0",
4444
"symfony/validator": "^6.4|^7.0",
4545
"symfony/var-dumper": "^6.4|^7.0",

‎src/Symfony/Bundle/FrameworkBundle/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"symfony/string": "^6.4|^7.0",
6565
"symfony/translation": "^6.4|^7.0",
6666
"symfony/twig-bundle": "^6.4|^7.0",
67-
"symfony/type-info": "^7.2",
67+
"symfony/type-info": "^7.1",
6868
"symfony/validator": "^6.4|^7.0",
6969
"symfony/workflow": "^6.4|^7.0",
7070
"symfony/yaml": "^6.4|^7.0",

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php
+25-3Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait;
2828
use Symfony\Component\PropertyInfo\Type as LegacyType;
2929
use Symfony\Component\TypeInfo\Type;
30+
use Symfony\Component\TypeInfo\Type\NullableType;
3031

3132
/**
3233
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -562,7 +563,14 @@ public static function typeProvider(): iterable
562563
yield ['f', Type::list(Type::object(\DateTimeImmutable::class)), null, null];
563564
yield ['g', Type::nullable(Type::array()), 'Nullable array.', null];
564565
yield ['h', Type::nullable(Type::string()), null, null];
565-
yield ['i', Type::union(Type::int(), Type::string(), Type::null()), null, null];
566+
567+
// BC layer for type-info < 7.2
568+
if (!class_exists(NullableType::class)) {
569+
yield ['i', Type::union(Type::int(), Type::string(), Type::null()), null, null];
570+
} else {
571+
yield ['i', Type::nullable(Type::union(Type::int(), Type::string())), null, null];
572+
}
573+
566574
yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class)), null, null];
567575
yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::list(Type::int())), null, null];
568576
yield ['donotexist', null, null, null];
@@ -629,7 +637,14 @@ public static function typeWithNoPrefixesProvider()
629637
yield ['f', null];
630638
yield ['g', Type::nullable(Type::array())];
631639
yield ['h', Type::nullable(Type::string())];
632-
yield ['i', Type::union(Type::int(), Type::string(), Type::null())];
640+
641+
// BC layer for type-info < 7.2
642+
if (!class_exists(NullableType::class)) {
643+
yield ['i', Type::union(Type::int(), Type::string(), Type::null())];
644+
} else {
645+
yield ['i', Type::nullable(Type::union(Type::int(), Type::string()))];
646+
}
647+
633648
yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class))];
634649
yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::list(Type::int()))];
635650
yield ['donotexist', null];
@@ -693,7 +708,14 @@ public static function typeWithCustomPrefixesProvider(): iterable
693708
yield ['f', Type::list(Type::object(\DateTimeImmutable::class))];
694709
yield ['g', Type::nullable(Type::array())];
695710
yield ['h', Type::nullable(Type::string())];
696-
yield ['i', Type::nullable(Type::union(Type::int(), Type::string()))];
711+
712+
// BC layer for type-info < 7.2
713+
if (!class_exists(NullableType::class)) {
714+
yield ['i', Type::union(Type::int(), Type::string(), Type::null())];
715+
} else {
716+
yield ['i', Type::nullable(Type::union(Type::int(), Type::string()))];
717+
}
718+
697719
yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class))];
698720
yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::list(Type::int()))];
699721
yield ['nonNullableCollectionOfNullableElements', Type::list(Type::nullable(Type::int()))];

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use Symfony\Component\PropertyInfo\Type as LegacyType;
3737
use Symfony\Component\TypeInfo\Exception\LogicException;
3838
use Symfony\Component\TypeInfo\Type;
39+
use Symfony\Component\TypeInfo\Type\WrappingTypeInterface;
3940

4041
require_once __DIR__.'/../Fixtures/Extractor/DummyNamespace.php';
4142

@@ -869,7 +870,14 @@ public function testPseudoTypes(string $property, ?Type $type)
869870
public static function pseudoTypesProvider(): iterable
870871
{
871872
yield ['classString', Type::string()];
872-
yield ['classStringGeneric', Type::string()];
873+
874+
// BC layer for type-info < 7.2
875+
if (!interface_exists(WrappingTypeInterface::class)) {
876+
yield ['classStringGeneric', Type::generic(Type::string(), Type::object(\stdClass::class))];
877+
} else {
878+
yield ['classStringGeneric', Type::string()];
879+
}
880+
873881
yield ['htmlEscapedString', Type::string()];
874882
yield ['lowercaseString', Type::string()];
875883
yield ['nonEmptyLowercaseString', Type::string()];

‎src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Symfony\Component\PropertyInfo\Tests\Fixtures\SnakeCaseDummy;
3434
use Symfony\Component\PropertyInfo\Type as LegacyType;
3535
use Symfony\Component\TypeInfo\Type;
36+
use Symfony\Component\TypeInfo\Type\NullableType;
3637

3738
/**
3839
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -771,7 +772,14 @@ public static function php80TypesProvider(): iterable
771772
yield ['foo', Type::nullable(Type::array())];
772773
yield ['bar', Type::nullable(Type::int())];
773774
yield ['timeout', Type::union(Type::int(), Type::float())];
774-
yield ['optional', Type::nullable(Type::union(Type::float(), Type::int()))];
775+
776+
// BC layer for type-info < 7.2
777+
if (!class_exists(NullableType::class)) {
778+
yield ['optional', Type::union(Type::nullable(Type::int()), Type::nullable(Type::float()))];
779+
} else {
780+
yield ['optional', Type::nullable(Type::union(Type::float(), Type::int()))];
781+
}
782+
775783
yield ['string', Type::union(Type::string(), Type::object(\Stringable::class))];
776784
yield ['payload', Type::mixed()];
777785
yield ['data', Type::mixed()];

‎src/Symfony/Component/PropertyInfo/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"require": {
2626
"php": ">=8.2",
2727
"symfony/string": "^6.4|^7.0",
28-
"symfony/type-info": "^7.2"
28+
"symfony/type-info": "^7.1"
2929
},
3030
"require-dev": {
3131
"symfony/serializer": "^6.4|^7.0",

‎src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+49-10Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
3333
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
3434
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
35+
use Symfony\Component\TypeInfo\Exception\LogicException as TypeInfoLogicException;
3536
use Symfony\Component\TypeInfo\Type;
3637
use Symfony\Component\TypeInfo\Type\BuiltinType;
3738
use 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) {

‎src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
+9-4Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a
5656
$typeIdentifiers = [];
5757
if (null !== $keyType = ($context['key_type'] ?? null)) {
5858
if ($keyType instanceof Type) {
59-
/** @var list<BuiltinType<TypeIdentifier::INT>|BuiltinType<TypeIdentifier::STRING>> */
60-
$keyTypes = $keyType instanceof UnionType ? $keyType->getTypes() : [$keyType];
61-
62-
$typeIdentifiers = array_map(fn (BuiltinType $t): string => $t->getTypeIdentifier()->value, $keyTypes);
59+
// BC layer for type-info < 7.2
60+
if (method_exists(Type::class, 'getBaseType')) {
61+
$typeIdentifiers = array_map(fn (Type $t): string => $t->getBaseType()->getTypeIdentifier()->value, $keyType instanceof UnionType ? $keyType->getTypes() : [$keyType]);
62+
} else {
63+
/** @var list<BuiltinType<TypeIdentifier::INT>|BuiltinType<TypeIdentifier::STRING>> */
64+
$keyTypes = $keyType instanceof UnionType ? $keyType->getTypes() : [$keyType];
65+
66+
$typeIdentifiers = array_map(fn (BuiltinType $t): string => $t->getTypeIdentifier()->value, $keyTypes);
67+
}
6368
} else {
6469
$typeIdentifiers = array_map(fn (LegacyType $t): string => $t->getBuiltinType(), \is_array($keyType) ? $keyType : [$keyType]);
6570
}

‎src/Symfony/Component/Serializer/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/composer.json
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"symfony/property-access": "^6.4|^7.0",
3939
"symfony/property-info": "^6.4|^7.0",
4040
"symfony/translation-contracts": "^2.5|^3",
41-
"symfony/type-info": "^7.2",
41+
"symfony/type-info": "^7.1",
4242
"symfony/uid": "^6.4|^7.0",
4343
"symfony/validator": "^6.4|^7.0",
4444
"symfony/var-dumper": "^6.4|^7.0",
@@ -51,7 +51,6 @@
5151
"symfony/dependency-injection": "<6.4",
5252
"symfony/property-access": "<6.4",
5353
"symfony/property-info": "<6.4",
54-
"symfony/type-info": "<7.2",
5554
"symfony/uid": "<6.4",
5655
"symfony/validator": "<6.4",
5756
"symfony/yaml": "<6.4"

‎src/Symfony/Component/TypeInfo/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/TypeInfo/composer.json
+2-6Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,11 @@
3030
},
3131
"require-dev": {
3232
"phpstan/phpdoc-parser": "^1.0|^2.0",
33-
"symfony/dependency-injection": "^6.4|^7.0",
34-
"symfony/property-info": "^7.2"
33+
"symfony/dependency-injection": "^6.4|^7.0"
3534
},
3635
"conflict": {
3736
"phpstan/phpdoc-parser": "<1.0",
38-
"symfony/dependency-injection": "<6.4",
39-
"symfony/property-info": ">=7.1,<7.1.9",
40-
"symfony/serializer": ">=7.1,<7.1.9",
41-
"symfony/validator": ">=7.1,<7.1.9"
37+
"symfony/dependency-injection": "<6.4"
4238
},
4339
"autoload": {
4440
"psr-4": { "Symfony\\Component\\TypeInfo\\": "" },

‎src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php
+38-2Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
use Symfony\Component\TypeInfo\Type\BuiltinType;
2020
use Symfony\Component\TypeInfo\Type\CollectionType;
2121
use Symfony\Component\TypeInfo\Type\CompositeTypeInterface;
22+
use Symfony\Component\TypeInfo\Type\IntersectionType;
2223
use Symfony\Component\TypeInfo\Type\NullableType;
2324
use Symfony\Component\TypeInfo\Type\ObjectType;
24-
use Symfony\Component\TypeInfo\TypeIdentifier;
25+
use Symfony\Component\TypeInfo\Type\UnionType;
2526
use Symfony\Component\TypeInfo\Type\WrappingTypeInterface;
27+
use Symfony\Component\TypeInfo\TypeIdentifier;
2628
use Symfony\Component\Validator\Constraints\All;
2729
use Symfony\Component\Validator\Constraints\NotBlank;
2830
use Symfony\Component\Validator\Constraints\NotNull;
@@ -141,7 +143,22 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
141143
}
142144

143145
$type = $types;
144-
$nullable = $type->isNullable();
146+
147+
// BC layer for type-info < 7.2
148+
if (!class_exists(NullableType::class)) {
149+
$nullable = false;
150+
151+
if ($type instanceof UnionType && $type->isNullable()) {
152+
$nullable = true;
153+
$type = $type->asNonNullable();
154+
}
155+
} else {
156+
$nullable = $type->isNullable();
157+
158+
if ($type instanceof NullableType) {
159+
$type = $type->getWrappedType();
160+
}
161+
}
145162

146163
if ($type instanceof NullableType) {
147164
$type = $type->getWrappedType();
@@ -194,6 +211,25 @@ private function getTypeConstraintLegacy(string $builtinType, PropertyInfoType $
194211

195212
private function getTypeConstraint(TypeInfoType $type): ?Type
196213
{
214+
// BC layer for type-info < 7.2
215+
if (!interface_exists(CompositeTypeInterface::class)) {
216+
if ($type instanceof UnionType || $type instanceof IntersectionType) {
217+
return ($type->isA(TypeIdentifier::INT) || $type->isA(TypeIdentifier::FLOAT) || $type->isA(TypeIdentifier::STRING) || $type->isA(TypeIdentifier::BOOL)) ? new Type(['type' => 'scalar']) : null;
218+
}
219+
220+
$baseType = $type->getBaseType();
221+
222+
if ($baseType instanceof ObjectType) {
223+
return new Type(['type' => $baseType->getClassName()]);
224+
}
225+
226+
if (TypeIdentifier::MIXED !== $baseType->getTypeIdentifier()) {
227+
return new Type(['type' => $baseType->getTypeIdentifier()->value]);
228+
}
229+
230+
return null;
231+
}
232+
197233
if ($type instanceof CompositeTypeInterface) {
198234
return $type->isIdentifiedBy(
199235
TypeIdentifier::INT,

‎src/Symfony/Component/Validator/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"symfony/property-access": "^6.4|^7.0",
4040
"symfony/property-info": "^6.4|^7.0",
4141
"symfony/translation": "^6.4.3|^7.0.3",
42-
"symfony/type-info": "^7.2-RC1",
42+
"symfony/type-info": "^7.1",
4343
"egulias/email-validator": "^2.1.10|^3|^4"
4444
},
4545
"conflict": {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.