From d8baa29d7ee1e3d2e15e2c6856896ecee2b31a7b Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 31 May 2024 10:51:07 +0200 Subject: [PATCH 1/7] chore(symfony): deprecations --- phpstan.neon.dist | 2 -- src/Doctrine/Odm/Tests/Fixtures/CustomConverter.php | 7 ++++--- src/Doctrine/Orm/Tests/Fixtures/CustomConverter.php | 7 ++++--- .../Fixtures/Serializer/NameConverter/CustomConverter.php | 7 ++++--- .../Fixtures/Serializer/NameConverter/CustomConverter.php | 7 ++++--- .../Bundle/DependencyInjection/ApiPlatformExtension.php | 2 +- .../Serializer/NameConverter/CustomConverter.php | 7 ++++--- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e8a8c9f178b..dc605bbf7f1 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -102,5 +102,3 @@ parameters: - '#Access to undefined constant Symfony\\Component\\HttpKernel\\HttpKernelInterface::MASTER_REQUEST\.#' - '#Attribute class PHPUnit\\Framework\\Attributes\\DataProvider does not exist.#' # Because of a bc-layer in MetadataAwareNameConverter it does not implement AdvancedNameConverterInterface - - '#Instanceof between Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface\|null and Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter will always evaluate to false\.#' - - '#Instanceof between Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface and Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter will always evaluate to false\.#' diff --git a/src/Doctrine/Odm/Tests/Fixtures/CustomConverter.php b/src/Doctrine/Odm/Tests/Fixtures/CustomConverter.php index 35f9b57ad29..7071d9a202d 100644 --- a/src/Doctrine/Odm/Tests/Fixtures/CustomConverter.php +++ b/src/Doctrine/Odm/Tests/Fixtures/CustomConverter.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Fixtures; +use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -20,7 +21,7 @@ * Custom converter that will only convert a property named "nameConverted" * with the same logic as Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter. */ -class CustomConverter implements NameConverterInterface +class CustomConverter implements AdvancedNameConverterInterface { private NameConverterInterface $nameConverter; @@ -29,12 +30,12 @@ public function __construct() $this->nameConverter = new CamelCaseToSnakeCaseNameConverter(); } - public function normalize(string $propertyName): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'nameConverted' === $propertyName ? $this->nameConverter->normalize($propertyName) : $propertyName; } - public function denormalize(string $propertyName): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'name_converted' === $propertyName ? $this->nameConverter->denormalize($propertyName) : $propertyName; } diff --git a/src/Doctrine/Orm/Tests/Fixtures/CustomConverter.php b/src/Doctrine/Orm/Tests/Fixtures/CustomConverter.php index 956eca7d07f..e0a06d84a4e 100644 --- a/src/Doctrine/Orm/Tests/Fixtures/CustomConverter.php +++ b/src/Doctrine/Orm/Tests/Fixtures/CustomConverter.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Fixtures; +use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -20,7 +21,7 @@ * Custom converter that will only convert a property named "nameConverted" * with the same logic as Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter. */ -class CustomConverter implements NameConverterInterface +class CustomConverter implements AdvancedNameConverterInterface { private NameConverterInterface $nameConverter; @@ -29,12 +30,12 @@ public function __construct() $this->nameConverter = new CamelCaseToSnakeCaseNameConverter(); } - public function normalize(string $propertyName): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'nameConverted' === $propertyName ? $this->nameConverter->normalize($propertyName) : $propertyName; } - public function denormalize(string $propertyName): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'name_converted' === $propertyName ? $this->nameConverter->denormalize($propertyName) : $propertyName; } diff --git a/src/GraphQl/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php b/src/GraphQl/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php index 3c4efde93d9..74ce9c165ae 100644 --- a/src/GraphQl/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php +++ b/src/GraphQl/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php @@ -13,6 +13,7 @@ namespace ApiPlatform\GraphQl\Tests\Fixtures\Serializer\NameConverter; +use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -20,7 +21,7 @@ * Custom converter that will only convert a property named "nameConverted" * with the same logic as Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter. */ -class CustomConverter implements NameConverterInterface +class CustomConverter implements AdvancedNameConverterInterface { private NameConverterInterface $nameConverter; @@ -29,12 +30,12 @@ public function __construct() $this->nameConverter = new CamelCaseToSnakeCaseNameConverter(); } - public function normalize(string $propertyName): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'nameConverted' === $propertyName ? $this->nameConverter->normalize($propertyName) : $propertyName; } - public function denormalize(string $propertyName): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'name_converted' === $propertyName ? $this->nameConverter->denormalize($propertyName) : $propertyName; } diff --git a/src/Serializer/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php b/src/Serializer/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php index 4e940ffa6dd..c2baa0be9b9 100644 --- a/src/Serializer/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php +++ b/src/Serializer/Tests/Fixtures/Serializer/NameConverter/CustomConverter.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Serializer\Tests\Fixtures\Serializer\NameConverter; +use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -20,7 +21,7 @@ * Custom converter that will only convert a property named "nameConverted" * with the same logic as Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter. */ -class CustomConverter implements NameConverterInterface +class CustomConverter implements AdvancedNameConverterInterface { private NameConverterInterface $nameConverter; @@ -29,12 +30,12 @@ public function __construct() $this->nameConverter = new CamelCaseToSnakeCaseNameConverter(); } - public function normalize(string $propertyName): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'nameConverted' === $propertyName ? $this->nameConverter->normalize($propertyName) : $propertyName; } - public function denormalize(string $propertyName): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'name_converted' === $propertyName ? $this->nameConverter->denormalize($propertyName) : $propertyName; } diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index c07c6a07db3..0965bbcfaa4 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -59,12 +59,12 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Finder\Finder; use Symfony\Component\HttpClient\ScopingHttpClient; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Validator\Validator\ValidatorInterface; diff --git a/tests/Fixtures/TestBundle/Serializer/NameConverter/CustomConverter.php b/tests/Fixtures/TestBundle/Serializer/NameConverter/CustomConverter.php index e2837b7228c..6421819b03c 100644 --- a/tests/Fixtures/TestBundle/Serializer/NameConverter/CustomConverter.php +++ b/tests/Fixtures/TestBundle/Serializer/NameConverter/CustomConverter.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter; +use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -20,7 +21,7 @@ * Custom converter that will only convert a property named "nameConverted" * with the same logic as Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter. */ -class CustomConverter implements NameConverterInterface +class CustomConverter implements AdvancedNameConverterInterface { private NameConverterInterface $nameConverter; @@ -29,12 +30,12 @@ public function __construct() $this->nameConverter = new CamelCaseToSnakeCaseNameConverter(); } - public function normalize(string $propertyName): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'nameConverted' === $propertyName ? $this->nameConverter->normalize($propertyName) : $propertyName; } - public function denormalize(string $propertyName): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return 'name_converted' === $propertyName ? $this->nameConverter->denormalize($propertyName) : $propertyName; } From 0f6e389b46053ee56183fd3ba70e81f1e4444187 Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 31 May 2024 15:44:08 +0200 Subject: [PATCH 2/7] temp --- .../Odm/PropertyInfo/DoctrineExtractor.php | 45 +-- .../Util/PropertyInfoToTypeInfoHelperTest.php | 123 ++++++++ .../Util/PropertyInfoToTypeInfoHelper.php | 298 ++++++++++++++++++ 3 files changed, 447 insertions(+), 19 deletions(-) create mode 100644 src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php create mode 100644 src/Metadata/Util/PropertyInfoToTypeInfoHelper.php diff --git a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php index 93ce4a4d5d0..7967a6f2192 100644 --- a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php +++ b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Odm\PropertyInfo; +use ApiPlatform\Metadata\Util\PropertyInfoToTypeInfoHelper; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDbClassMetadata; use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; @@ -22,7 +23,8 @@ use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\PropertyInfo\Type as LegacyType; +use Symfony\Component\TypeInfo\Type; /** * Extracts data using Doctrine MongoDB ODM metadata. @@ -53,9 +55,9 @@ public function getProperties($class, array $context = []): ?array /** * {@inheritdoc} * - * @return Type[]|null + * @return LegacyType[]|null */ - public function getTypes($class, $property, array $context = []): ?array + public function getTypes(string $class, string $property, array $context = []): ?array { if (null === $metadata = $this->getMetadata($class)) { return null; @@ -72,19 +74,19 @@ public function getTypes($class, $property, array $context = []): ?array if ($metadata->isSingleValuedAssociation($property)) { $nullable = $metadata instanceof MongoDbClassMetadata && $metadata->isNullable($property); - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $class)]; + return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, $class)]; } - $collectionKeyType = Type::BUILTIN_TYPE_INT; + $collectionKeyType = LegacyType::BUILTIN_TYPE_INT; return [ - new Type( - Type::BUILTIN_TYPE_OBJECT, + new LegacyType( + LegacyType::BUILTIN_TYPE_OBJECT, false, Collection::class, true, - new Type($collectionKeyType), - new Type(Type::BUILTIN_TYPE_OBJECT, false, $class) + new LegacyType($collectionKeyType), + new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, $class) ), ]; } @@ -94,18 +96,18 @@ public function getTypes($class, $property, array $context = []): ?array $nullable = $metadata instanceof MongoDbClassMetadata && $metadata->isNullable($property); $enumType = null; if (null !== $enumClass = $metadata instanceof MongoDbClassMetadata ? $metadata->getFieldMapping($property)['enumType'] ?? null : null) { - $enumType = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass); + $enumType = new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, $enumClass); } switch ($typeOfField) { case MongoDbType::DATE: - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, \DateTime::class)]; + return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, \DateTime::class)]; case MongoDbType::DATE_IMMUTABLE: - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, \DateTimeImmutable::class)]; + return [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, $nullable, \DateTimeImmutable::class)]; case MongoDbType::HASH: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; + return [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; case MongoDbType::COLLECTION: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT))]; + return [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, $nullable, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT))]; case MongoDbType::INT: case MongoDbType::STRING: if ($enumType) { @@ -115,7 +117,7 @@ public function getTypes($class, $property, array $context = []): ?array $builtinType = $this->getPhpType($typeOfField); - return $builtinType ? [new Type($builtinType, $nullable)] : null; + return $builtinType ? [new LegacyType($builtinType, $nullable)] : null; } return null; @@ -154,16 +156,21 @@ private function getMetadata(string $class): ?ClassMetadata } } + public function getType(string $class, string $property, array $context = []): ?Type + { + return PropertyInfoToTypeInfoHelper::convertLegacyTypesToType($this->getTypes($class, $property, $context)); + } + /** * Gets the corresponding built-in PHP type. */ private function getPhpType(string $doctrineType): ?string { return match ($doctrineType) { - MongoDbType::INTEGER, MongoDbType::INT, MongoDbType::INTID, MongoDbType::KEY => Type::BUILTIN_TYPE_INT, - MongoDbType::FLOAT => Type::BUILTIN_TYPE_FLOAT, - MongoDbType::STRING, MongoDbType::ID, MongoDbType::OBJECTID, MongoDbType::TIMESTAMP, MongoDbType::BINDATA, MongoDbType::BINDATABYTEARRAY, MongoDbType::BINDATACUSTOM, MongoDbType::BINDATAFUNC, MongoDbType::BINDATAMD5, MongoDbType::BINDATAUUID, MongoDbType::BINDATAUUIDRFC4122 => Type::BUILTIN_TYPE_STRING, - MongoDbType::BOOLEAN, MongoDbType::BOOL => Type::BUILTIN_TYPE_BOOL, + MongoDbType::INTEGER, MongoDbType::INT, MongoDbType::INTID, MongoDbType::KEY => LegacyType::BUILTIN_TYPE_INT, + MongoDbType::FLOAT => LegacyType::BUILTIN_TYPE_FLOAT, + MongoDbType::STRING, MongoDbType::ID, MongoDbType::OBJECTID, MongoDbType::TIMESTAMP, MongoDbType::BINDATA, MongoDbType::BINDATABYTEARRAY, MongoDbType::BINDATACUSTOM, MongoDbType::BINDATAFUNC, MongoDbType::BINDATAMD5, MongoDbType::BINDATAUUID, MongoDbType::BINDATAUUIDRFC4122 => LegacyType::BUILTIN_TYPE_STRING, + MongoDbType::BOOLEAN, MongoDbType::BOOL => LegacyType::BUILTIN_TYPE_BOOL, default => null, }; } diff --git a/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php b/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php new file mode 100644 index 00000000000..ad271baeff2 --- /dev/null +++ b/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Metadata\Tests\Util; + +use ApiPlatform\Metadata\Util\PropertyInfoToTypeInfoHelper; +use PHPUnit\Framework\TestCase; +use Symfony\Component\PropertyInfo\Type as LegacyType; +use Symfony\Component\TypeInfo\Type; +use Symfony\Component\TypeInfo\TypeIdentifier; + +/** + * @group legacy + */ +class PropertyInfoToTypeInfoHelperTest extends TestCase +{ + /** + * @dataProvider convertTypeToLegacyTypesDataProvider + * + * @param list|null $legacyTypes + */ + public function testConvertTypeToLegacyTypes(?array $legacyTypes, ?Type $type, bool $keepNullType = true): void + { + $this->assertEquals($legacyTypes, PropertyInfoToTypeInfoHelper::convertTypeToLegacyTypes($type, $keepNullType)); + } + + /** + * @return iterable|null, 1: ?Type, 2?: bool}> + */ + public function convertTypeToLegacyTypesDataProvider(): iterable + { + yield [null, null]; + yield [null, Type::mixed()]; + yield [null, Type::never()]; + yield [null, Type::union(Type::int(), Type::intersection(Type::string(), Type::bool()))]; + yield [null, Type::intersection(Type::int(), Type::union(Type::string(), Type::bool()))]; + yield [null, Type::null(), false]; + yield [[new LegacyType('null')], Type::null()]; + yield [[new LegacyType('null')], Type::void()]; + yield [[new LegacyType('int')], Type::int()]; + yield [[new LegacyType('object', false, \stdClass::class)], Type::object(\stdClass::class)]; + yield [ + [new LegacyType('object', false, \Traversable::class, true, null, new LegacyType('int'))], + Type::generic(Type::object(\Traversable::class), Type::int()), + ]; + yield [ + [new LegacyType('array', false, null, true, new LegacyType('int'), new LegacyType('string'))], + Type::generic(Type::builtin(TypeIdentifier::ARRAY), Type::int(), Type::string()), + ]; + yield [ + [new LegacyType('array', false, null, true, new LegacyType('int'), new LegacyType('string'))], + Type::collection(Type::builtin(TypeIdentifier::ARRAY), Type::string(), Type::int()), + ]; + yield [[new LegacyType('int', true)], Type::nullable(Type::int())]; + yield [[new LegacyType('int'), new LegacyType('string')], Type::union(Type::int(), Type::string())]; + yield [ + [new LegacyType('int', true), new LegacyType('string', true)], + Type::union(Type::int(), Type::string(), Type::null()), + ]; + yield [[new LegacyType('int'), new LegacyType('string')], Type::intersection(Type::int(), Type::string())]; + + $type = Type::int(); + $type->isCollection = true; + yield [[new LegacyType('int', false, null, true)], $type]; + } + + /** + * @dataProvider convertLegacyTypesToTypeDataProvider + * + * @param list|null $legacyTypes + */ + public function testConvertLegacyTypesToType(?Type $type, ?array $legacyTypes): void + { + $this->assertEquals($type, PropertyInfoToTypeInfoHelper::convertLegacyTypesToType($legacyTypes)); + } + + /** + * @return iterable|null}> + */ + public function convertLegacyTypesToTypeDataProvider(): iterable + { + yield [null, null]; + yield [Type::null(), [new LegacyType('null')]]; + yield [Type::void(), [new LegacyType('void')]]; + yield [Type::int(), [new LegacyType('int')]]; + yield [Type::object(\stdClass::class), [new LegacyType('object', false, \stdClass::class)]]; + yield [ + Type::generic(Type::object('Foo'), Type::string(), Type::int()), + [new LegacyType('object', false, 'Foo', false, [new LegacyType('string')], new LegacyType('int'))], + ]; + yield [Type::nullable(Type::int()), [new LegacyType('int', true)]]; + yield [Type::union(Type::int(), Type::string()), [new LegacyType('int'), new LegacyType('string')]]; + yield [ + Type::union(Type::int(), Type::string(), Type::null()), + [new LegacyType('int', true), new LegacyType('string', true)], + ]; + + $type = Type::collection(Type::builtin(TypeIdentifier::ARRAY), Type::int(), Type::string()); + $type->isCollection = true; + $type->getType()->isCollection = true; + $type->getType()->getType()->isCollection = true; + yield [$type, [new LegacyType('array', false, null, true, [new LegacyType('string')], new LegacyType('int'))]]; + } +} diff --git a/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php b/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php new file mode 100644 index 00000000000..2c96e2b717f --- /dev/null +++ b/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php @@ -0,0 +1,298 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Metadata\Util; + +use Symfony\Component\PropertyInfo\Type as LegacyType; +use Symfony\Component\TypeInfo\Exception\InvalidArgumentException; +use Symfony\Component\TypeInfo\Exception\LogicException; +use Symfony\Component\TypeInfo\Type; +use Symfony\Component\TypeInfo\Type\BuiltinType; +use Symfony\Component\TypeInfo\Type\CollectionType; +use Symfony\Component\TypeInfo\Type\GenericType; +use Symfony\Component\TypeInfo\Type\IntersectionType; +use Symfony\Component\TypeInfo\Type\ObjectType; +use Symfony\Component\TypeInfo\Type\UnionType; +use Symfony\Component\TypeInfo\TypeIdentifier; + +/** + * A helper about PropertyInfo Type conversion. + * + * @see https://github.com/mtarld/symfony/commits/backup/chore/deprecate-property-info-type/ + * + * @author Mathias Arlaud + * + * @internal + */ +final class PropertyInfoToTypeInfoHelper +{ + /** + * Converts a {@see Type} to what is should have been in the "symfony/property-info" component. + * + * @return list|null + */ + public static function convertTypeToLegacyTypes(?Type $type, bool $keepNullType = true): ?array + { + if (null === $type) { + return null; + } + + try { + $typeIdentifier = $type->getBaseType()->getTypeIdentifier(); + } catch (LogicException) { + $typeIdentifier = null; + } + + if (\in_array($typeIdentifier, [TypeIdentifier::MIXED, TypeIdentifier::NEVER, true], true)) { + return null; + } + + if (TypeIdentifier::NULL === $typeIdentifier) { + return $keepNullType ? [new LegacyType('null')] : null; + } + + if (TypeIdentifier::VOID === $typeIdentifier) { + return [new LegacyType('null')]; + } + + try { + $legacyType = self::convertTypeToLegacy($type); + } catch (LogicException) { + return null; + } + + if (!\is_array($legacyType)) { + $legacyType = [$legacyType]; + } + + return $legacyType; + } + + /** + * Converts a {@see LegacyType} to what is should have been in the "symfony/type-info" component. + * + * @param list|null $types + */ + public static function convertLegacyTypesToType(?array $legacyTypes): ?Type + { + if (!$legacyTypes) { + return null; + } + + $types = []; + $nullable = false; + + foreach (array_map(self::convertLegacyTypeToType(...), $legacyTypes) as $type) { + if ($type->isNullable()) { + $nullable = true; + + if ($type instanceof BuiltinType && TypeIdentifier::NULL === $type->getTypeIdentifier()) { + continue; + } + + $type = self::unwrapNullableType($type); + } + + if ($type instanceof UnionType) { + $types = [$types, ...$type->getTypes()]; + + continue; + } + + $types[] = $type; + } + + if ($nullable && [] === $types) { + return Type::null(); + } + + $type = \count($types) > 1 ? Type::union(...$types) : $types[0]; + if ($nullable) { + $type = Type::nullable($type); + } + + return $type; + } + + /** + * @param list $collectionKeyTypes + * @param list $collectionValueTypes + */ + public static function createTypeFromLegacyValues(string $builtinType, bool $nullable, ?string $class, bool $collection, array $collectionKeyTypes, array $collectionValueTypes): Type + { + $variableTypes = []; + + if ($collectionKeyTypes) { + $collectionKeyTypes = array_unique(array_map(self::convertLegacyTypeToType(...), $collectionKeyTypes)); + $variableTypes[] = \count($collectionKeyTypes) > 1 ? Type::union(...$collectionKeyTypes) : $collectionKeyTypes[0]; + } + + if ($collectionValueTypes) { + if (!$collectionKeyTypes) { + $variableTypes[] = [] === $collectionKeyTypes ? Type::mixed() : Type::union(Type::int(), Type::string()); + } + + $collectionValueTypes = array_unique(array_map(self::convertLegacyTypeToType(...), $collectionValueTypes)); + $variableTypes[] = \count($collectionValueTypes) > 1 ? Type::union(...$collectionValueTypes) : $collectionValueTypes[0]; + } + + if ($collectionKeyTypes && !$collectionValueTypes) { + $variableTypes[] = Type::mixed(); + } + + try { + $type = null !== $class ? Type::object($class) : Type::builtin(TypeIdentifier::from($builtinType)); + } catch (\ValueError) { + throw new InvalidArgumentException(sprintf('"%s" is not a valid PHP type.', $builtinType)); + } + + if (\count($variableTypes)) { + $type = Type::generic($type, ...$variableTypes); + } + + if ($collection) { + $type = Type::collection($type); + } + + if ($nullable && !$type->isNullable()) { + $type = Type::nullable($type); + } + + return $type; + } + + public static function unwrapNullableType(Type $type): Type + { + if (!$type instanceof UnionType) { + return $type; + } + + return $type->asNonNullable(); + } + + /** + * Recursive method that converts {@see Type} to its related {@see LegacyType} (or list of {@see @LegacyType}). + * + * @return LegacyType|list + */ + private static function convertTypeToLegacy(Type $type): LegacyType|array + { + if ($type instanceof UnionType) { + $nullable = $type->isNullable(); + + $unionTypes = []; + foreach ($type->getTypes() as $unionType) { + if ('null' === (string) $unionType) { + continue; + } + + if ($unionType instanceof IntersectionType) { + throw new LogicException(sprintf('DNF types are not supported by "%s".', LegacyType::class)); + } + + $unionType->setNullable($nullable); + $unionTypes[] = $unionType; + } + + /** @var list $legacyTypes */ + $legacyTypes = array_map(self::convertTypeToLegacy(...), $unionTypes); + + if (1 === \count($legacyTypes)) { + return $legacyTypes[0]; + } + + return $legacyTypes; + } + + if ($type instanceof IntersectionType) { + foreach ($type->getTypes() as $intersectionType) { + if ($intersectionType instanceof UnionType) { + throw new LogicException(sprintf('DNF types are not supported by "%s".', LegacyType::class)); + } + } + + /** @var list $legacyTypes */ + $legacyTypes = array_map(self::convertTypeToLegacy(...), $type->getTypes()); + + if (1 === \count($legacyTypes)) { + return $legacyTypes[0]; + } + + return $legacyTypes; + } + + if ($type instanceof CollectionType) { + $nestedType = $type->getType(); + $nestedType->setCollection(true); + + return self::convertTypeToLegacy($nestedType); + } + + $typeIdentifier = TypeIdentifier::MIXED; + $className = null; + $collectionKeyType = $collectionValueType = null; + + if ($type instanceof ObjectType) { + $typeIdentifier = $type->getTypeIdentifier(); + $className = $type->getClassName(); + } + + if ($type instanceof GenericType) { + $nestedType = self::unwrapNullableType($type->getType()); + + if ($nestedType instanceof BuiltinType) { + $typeIdentifier = $nestedType->getTypeIdentifier(); + } elseif ($nestedType instanceof ObjectType) { + $typeIdentifier = $nestedType->getTypeIdentifier(); + $className = $nestedType->getClassName(); + } + + $variableTypes = $type->getVariableTypes(); + + if (2 === \count($variableTypes)) { + $collectionKeyType = self::convertTypeToLegacy($variableTypes[0]); + $collectionValueType = self::convertTypeToLegacy($variableTypes[1]); + } elseif (1 === \count($variableTypes)) { + $collectionValueType = self::convertTypeToLegacy($variableTypes[0]); + } + } + + if ($type instanceof BuiltinType) { + $typeIdentifier = $type->getTypeIdentifier(); + } + + return new LegacyType( + builtinType: $typeIdentifier->value, + nullable: $type->isNullable(), + class: $className, + collection: $type instanceof GenericType || $type->isCollection, // legacy generic is always considered as a collection + collectionKeyType: $collectionKeyType, + collectionValueType: $collectionValueType, + ); + } + + /** + * Recursive method that converts {@see LegacyType} to its related {@see Type}. + */ + private static function convertLegacyTypeToType(LegacyType $legacyType): Type + { + return self::createTypeFromLegacyValues( + $legacyType->getBuiltinType(), + $legacyType->isNullable(), + $legacyType->getClassName(), + $legacyType->isCollection(), + $legacyType->getCollectionKeyTypes(), + $legacyType->getCollectionValueTypes(), + ); + } +} From 0ca1f1f4bc2f3931fc0aaae300ae41fdf059df3e Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 31 May 2024 16:32:19 +0200 Subject: [PATCH 3/7] test: constraint Url needs "requireTld" --- .../Util/PropertyInfoToTypeInfoHelperTest.php | 55 +------ .../Util/PropertyInfoToTypeInfoHelper.php | 148 ------------------ src/Metadata/composer.json | 3 +- tests/.ignored-deprecations-legacy-events | 1 + 4 files changed, 4 insertions(+), 203 deletions(-) diff --git a/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php b/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php index ad271baeff2..bd082e29bcf 100644 --- a/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php +++ b/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php @@ -33,56 +33,6 @@ */ class PropertyInfoToTypeInfoHelperTest extends TestCase { - /** - * @dataProvider convertTypeToLegacyTypesDataProvider - * - * @param list|null $legacyTypes - */ - public function testConvertTypeToLegacyTypes(?array $legacyTypes, ?Type $type, bool $keepNullType = true): void - { - $this->assertEquals($legacyTypes, PropertyInfoToTypeInfoHelper::convertTypeToLegacyTypes($type, $keepNullType)); - } - - /** - * @return iterable|null, 1: ?Type, 2?: bool}> - */ - public function convertTypeToLegacyTypesDataProvider(): iterable - { - yield [null, null]; - yield [null, Type::mixed()]; - yield [null, Type::never()]; - yield [null, Type::union(Type::int(), Type::intersection(Type::string(), Type::bool()))]; - yield [null, Type::intersection(Type::int(), Type::union(Type::string(), Type::bool()))]; - yield [null, Type::null(), false]; - yield [[new LegacyType('null')], Type::null()]; - yield [[new LegacyType('null')], Type::void()]; - yield [[new LegacyType('int')], Type::int()]; - yield [[new LegacyType('object', false, \stdClass::class)], Type::object(\stdClass::class)]; - yield [ - [new LegacyType('object', false, \Traversable::class, true, null, new LegacyType('int'))], - Type::generic(Type::object(\Traversable::class), Type::int()), - ]; - yield [ - [new LegacyType('array', false, null, true, new LegacyType('int'), new LegacyType('string'))], - Type::generic(Type::builtin(TypeIdentifier::ARRAY), Type::int(), Type::string()), - ]; - yield [ - [new LegacyType('array', false, null, true, new LegacyType('int'), new LegacyType('string'))], - Type::collection(Type::builtin(TypeIdentifier::ARRAY), Type::string(), Type::int()), - ]; - yield [[new LegacyType('int', true)], Type::nullable(Type::int())]; - yield [[new LegacyType('int'), new LegacyType('string')], Type::union(Type::int(), Type::string())]; - yield [ - [new LegacyType('int', true), new LegacyType('string', true)], - Type::union(Type::int(), Type::string(), Type::null()), - ]; - yield [[new LegacyType('int'), new LegacyType('string')], Type::intersection(Type::int(), Type::string())]; - - $type = Type::int(); - $type->isCollection = true; - yield [[new LegacyType('int', false, null, true)], $type]; - } - /** * @dataProvider convertLegacyTypesToTypeDataProvider * @@ -100,7 +50,7 @@ public function convertLegacyTypesToTypeDataProvider(): iterable { yield [null, null]; yield [Type::null(), [new LegacyType('null')]]; - yield [Type::void(), [new LegacyType('void')]]; + // yield [Type::void(), [new LegacyType('void')]]; yield [Type::int(), [new LegacyType('int')]]; yield [Type::object(\stdClass::class), [new LegacyType('object', false, \stdClass::class)]]; yield [ @@ -115,9 +65,6 @@ public function convertLegacyTypesToTypeDataProvider(): iterable ]; $type = Type::collection(Type::builtin(TypeIdentifier::ARRAY), Type::int(), Type::string()); - $type->isCollection = true; - $type->getType()->isCollection = true; - $type->getType()->getType()->isCollection = true; yield [$type, [new LegacyType('array', false, null, true, [new LegacyType('string')], new LegacyType('int'))]]; } } diff --git a/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php b/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php index 2c96e2b717f..06303836d8b 100644 --- a/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php +++ b/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php @@ -15,13 +15,8 @@ use Symfony\Component\PropertyInfo\Type as LegacyType; use Symfony\Component\TypeInfo\Exception\InvalidArgumentException; -use Symfony\Component\TypeInfo\Exception\LogicException; use Symfony\Component\TypeInfo\Type; use Symfony\Component\TypeInfo\Type\BuiltinType; -use Symfony\Component\TypeInfo\Type\CollectionType; -use Symfony\Component\TypeInfo\Type\GenericType; -use Symfony\Component\TypeInfo\Type\IntersectionType; -use Symfony\Component\TypeInfo\Type\ObjectType; use Symfony\Component\TypeInfo\Type\UnionType; use Symfony\Component\TypeInfo\TypeIdentifier; @@ -36,48 +31,6 @@ */ final class PropertyInfoToTypeInfoHelper { - /** - * Converts a {@see Type} to what is should have been in the "symfony/property-info" component. - * - * @return list|null - */ - public static function convertTypeToLegacyTypes(?Type $type, bool $keepNullType = true): ?array - { - if (null === $type) { - return null; - } - - try { - $typeIdentifier = $type->getBaseType()->getTypeIdentifier(); - } catch (LogicException) { - $typeIdentifier = null; - } - - if (\in_array($typeIdentifier, [TypeIdentifier::MIXED, TypeIdentifier::NEVER, true], true)) { - return null; - } - - if (TypeIdentifier::NULL === $typeIdentifier) { - return $keepNullType ? [new LegacyType('null')] : null; - } - - if (TypeIdentifier::VOID === $typeIdentifier) { - return [new LegacyType('null')]; - } - - try { - $legacyType = self::convertTypeToLegacy($type); - } catch (LogicException) { - return null; - } - - if (!\is_array($legacyType)) { - $legacyType = [$legacyType]; - } - - return $legacyType; - } - /** * Converts a {@see LegacyType} to what is should have been in the "symfony/type-info" component. * @@ -180,107 +133,6 @@ public static function unwrapNullableType(Type $type): Type return $type->asNonNullable(); } - /** - * Recursive method that converts {@see Type} to its related {@see LegacyType} (or list of {@see @LegacyType}). - * - * @return LegacyType|list - */ - private static function convertTypeToLegacy(Type $type): LegacyType|array - { - if ($type instanceof UnionType) { - $nullable = $type->isNullable(); - - $unionTypes = []; - foreach ($type->getTypes() as $unionType) { - if ('null' === (string) $unionType) { - continue; - } - - if ($unionType instanceof IntersectionType) { - throw new LogicException(sprintf('DNF types are not supported by "%s".', LegacyType::class)); - } - - $unionType->setNullable($nullable); - $unionTypes[] = $unionType; - } - - /** @var list $legacyTypes */ - $legacyTypes = array_map(self::convertTypeToLegacy(...), $unionTypes); - - if (1 === \count($legacyTypes)) { - return $legacyTypes[0]; - } - - return $legacyTypes; - } - - if ($type instanceof IntersectionType) { - foreach ($type->getTypes() as $intersectionType) { - if ($intersectionType instanceof UnionType) { - throw new LogicException(sprintf('DNF types are not supported by "%s".', LegacyType::class)); - } - } - - /** @var list $legacyTypes */ - $legacyTypes = array_map(self::convertTypeToLegacy(...), $type->getTypes()); - - if (1 === \count($legacyTypes)) { - return $legacyTypes[0]; - } - - return $legacyTypes; - } - - if ($type instanceof CollectionType) { - $nestedType = $type->getType(); - $nestedType->setCollection(true); - - return self::convertTypeToLegacy($nestedType); - } - - $typeIdentifier = TypeIdentifier::MIXED; - $className = null; - $collectionKeyType = $collectionValueType = null; - - if ($type instanceof ObjectType) { - $typeIdentifier = $type->getTypeIdentifier(); - $className = $type->getClassName(); - } - - if ($type instanceof GenericType) { - $nestedType = self::unwrapNullableType($type->getType()); - - if ($nestedType instanceof BuiltinType) { - $typeIdentifier = $nestedType->getTypeIdentifier(); - } elseif ($nestedType instanceof ObjectType) { - $typeIdentifier = $nestedType->getTypeIdentifier(); - $className = $nestedType->getClassName(); - } - - $variableTypes = $type->getVariableTypes(); - - if (2 === \count($variableTypes)) { - $collectionKeyType = self::convertTypeToLegacy($variableTypes[0]); - $collectionValueType = self::convertTypeToLegacy($variableTypes[1]); - } elseif (1 === \count($variableTypes)) { - $collectionValueType = self::convertTypeToLegacy($variableTypes[0]); - } - } - - if ($type instanceof BuiltinType) { - $typeIdentifier = $type->getTypeIdentifier(); - } - - return new LegacyType( - builtinType: $typeIdentifier->value, - nullable: $type->isNullable(), - class: $className, - collection: $type instanceof GenericType || $type->isCollection, // legacy generic is always considered as a collection - collectionKeyType: $collectionKeyType, - collectionValueType: $collectionValueType, - ); - } - /** * Recursive method that converts {@see LegacyType} to its related {@see Type}. */ diff --git a/src/Metadata/composer.json b/src/Metadata/composer.json index 27039b5ba4f..e3ac0a5dc50 100644 --- a/src/Metadata/composer.json +++ b/src/Metadata/composer.json @@ -46,7 +46,8 @@ "symfony/routing": "^6.4 || ^7.0", "symfony/var-dumper": "^6.4 || ^7.0", "symfony/web-link": "^6.4 || ^7.0", - "symfony/yaml": "^6.4 || ^7.0" + "symfony/yaml": "^6.4 || ^7.0", + "symfony/type-info": "^7.1" }, "suggest": { "phpstan/phpdoc-parser": "For PHP documentation support.", diff --git a/tests/.ignored-deprecations-legacy-events b/tests/.ignored-deprecations-legacy-events index 799c2910648..38ea17ea2ec 100644 --- a/tests/.ignored-deprecations-legacy-events +++ b/tests/.ignored-deprecations-legacy-events @@ -25,3 +25,4 @@ %ApiPlatform\\Api\\FilterInterface is deprecated in favor of ApiPlatform\\Metadata\\FilterInterface% %The "Symfony\\Bundle\\MakerBundle\\Maker\\MakeAuthenticator" class is deprecated, use any of the Security\\Make\* commands instead% +%Since symfony/validator 7.1: Not passing a value for the "requireTld" option to the Url constraint is deprecated. Its default value will change to "true".% From 191600dda8d9b5f6dff9cd31fe1f96ca7ac3809e Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 31 May 2024 17:13:43 +0200 Subject: [PATCH 4/7] deprec behat extension --- phpunit.xml.dist | 2 ++ phpunit10.xml.dist | 2 ++ tests/Fixtures/app/AppKernel.php | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 2afecb3bf9a..230919fb769 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -12,6 +12,8 @@ + + diff --git a/phpunit10.xml.dist b/phpunit10.xml.dist index 5ada730253f..9c8c1d2588a 100644 --- a/phpunit10.xml.dist +++ b/phpunit10.xml.dist @@ -10,6 +10,8 @@ + + diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 041db0c8101..651b515702c 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -74,11 +74,14 @@ public function registerBundles(): array new MercureBundle(), new SecurityBundle(), new WebProfilerBundle(), - new FriendsOfBehatSymfonyExtensionBundle(), new FrameworkBundle(), new MakerBundle(), ]; + if (null === ($_ENV['APP_PHPUNIT'] ?? null)) { + $bundles[] = new FriendsOfBehatSymfonyExtensionBundle(); + } + if (class_exists(DoctrineMongoDBBundle::class)) { $bundles[] = new DoctrineMongoDBBundle(); } From ce6c5c80a2e5f008b4eb0d81214c63b044718057 Mon Sep 17 00:00:00 2001 From: soyuka Date: Sat, 1 Jun 2024 00:22:32 +0200 Subject: [PATCH 5/7] mhh --- .github/workflows/ci.yml | 8 +++++++- src/Metadata/composer.json | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 407424722b6..c3256f9390d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -259,10 +259,16 @@ jobs: tools: pecl, composer extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite, mongodb ini-values: memory_limit=-1 - - name: Run ${{ matrix.component }} tests + - name: Run ${{ matrix.component }} install run: | composer update composer ${{matrix.component}} update + - name: PHP version tweaks + if: matrix.component == 'api-platform/metadata' && matrix.php != '8.1' + run: composer require symfony/type-info + working-directory: 'src/Metadata' + - name: Run ${{ matrix.component }} tests + run: | mkdir -p /tmp/build/logs/phpunit composer ${{matrix.component}} test --log-junit "/tmp/build/logs/phpunit/junit.xml" ${{ matrix.coverage && '--coverage-clover /tmp/build/logs/phpunit/clover.xml' || '' }} - name: Upload test artifacts diff --git a/src/Metadata/composer.json b/src/Metadata/composer.json index e3ac0a5dc50..27039b5ba4f 100644 --- a/src/Metadata/composer.json +++ b/src/Metadata/composer.json @@ -46,8 +46,7 @@ "symfony/routing": "^6.4 || ^7.0", "symfony/var-dumper": "^6.4 || ^7.0", "symfony/web-link": "^6.4 || ^7.0", - "symfony/yaml": "^6.4 || ^7.0", - "symfony/type-info": "^7.1" + "symfony/yaml": "^6.4 || ^7.0" }, "suggest": { "phpstan/phpdoc-parser": "For PHP documentation support.", From 9600e159ff75af48a13e8e59c3f95b26d5beed7f Mon Sep 17 00:00:00 2001 From: soyuka Date: Sat, 1 Jun 2024 10:45:49 +0200 Subject: [PATCH 6/7] mhh --- src/Metadata/Util/PropertyInfoToTypeInfoHelper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php b/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php index 06303836d8b..ba3f0867df4 100644 --- a/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php +++ b/src/Metadata/Util/PropertyInfoToTypeInfoHelper.php @@ -34,7 +34,7 @@ final class PropertyInfoToTypeInfoHelper /** * Converts a {@see LegacyType} to what is should have been in the "symfony/type-info" component. * - * @param list|null $types + * @param list|null $legacyTypes */ public static function convertLegacyTypesToType(?array $legacyTypes): ?Type { @@ -92,7 +92,7 @@ public static function createTypeFromLegacyValues(string $builtinType, bool $nul if ($collectionValueTypes) { if (!$collectionKeyTypes) { - $variableTypes[] = [] === $collectionKeyTypes ? Type::mixed() : Type::union(Type::int(), Type::string()); + $variableTypes[] = \is_array($collectionKeyTypes) ? Type::mixed() : Type::union(Type::int(), Type::string()); // @phpstan-ignore-line } $collectionValueTypes = array_unique(array_map(self::convertLegacyTypeToType(...), $collectionValueTypes)); From 85e69d2da786370d1bccf8b4c11c4aeccda6191b Mon Sep 17 00:00:00 2001 From: soyuka Date: Sat, 1 Jun 2024 11:08:26 +0200 Subject: [PATCH 7/7] mhh --- phpstan.neon.dist | 1 - .../Util/PropertyInfoToTypeInfoHelperTest.php | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index dc605bbf7f1..03e6f9f4d42 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -101,4 +101,3 @@ parameters: - '#Class Symfony\\Component\\Serializer\\Normalizer\\CacheableSupportsMethodInterface not found\.#' - '#Access to undefined constant Symfony\\Component\\HttpKernel\\HttpKernelInterface::MASTER_REQUEST\.#' - '#Attribute class PHPUnit\\Framework\\Attributes\\DataProvider does not exist.#' - # Because of a bc-layer in MetadataAwareNameConverter it does not implement AdvancedNameConverterInterface diff --git a/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php b/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php index bd082e29bcf..a39d6046526 100644 --- a/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php +++ b/src/Metadata/Tests/Util/PropertyInfoToTypeInfoHelperTest.php @@ -40,31 +40,39 @@ class PropertyInfoToTypeInfoHelperTest extends TestCase */ public function testConvertLegacyTypesToType(?Type $type, ?array $legacyTypes): void { + if (!class_exists(Type::class)) { + $this->markTestSkipped('symfony/type-info requires PHP > 8.2'); + } + $this->assertEquals($type, PropertyInfoToTypeInfoHelper::convertLegacyTypesToType($legacyTypes)); } /** - * @return iterable|null}> + * @return iterable|null}> */ public function convertLegacyTypesToTypeDataProvider(): iterable { + if (!class_exists(Type::class)) { + return; + } + yield [null, null]; yield [Type::null(), [new LegacyType('null')]]; // yield [Type::void(), [new LegacyType('void')]]; yield [Type::int(), [new LegacyType('int')]]; yield [Type::object(\stdClass::class), [new LegacyType('object', false, \stdClass::class)]]; yield [ - Type::generic(Type::object('Foo'), Type::string(), Type::int()), + Type::generic(Type::object('Foo'), Type::string(), Type::int()), // @phpstan-ignore-line [new LegacyType('object', false, 'Foo', false, [new LegacyType('string')], new LegacyType('int'))], ]; - yield [Type::nullable(Type::int()), [new LegacyType('int', true)]]; + yield [Type::nullable(Type::int()), [new LegacyType('int', true)]]; // @phpstan-ignore-line yield [Type::union(Type::int(), Type::string()), [new LegacyType('int'), new LegacyType('string')]]; yield [ Type::union(Type::int(), Type::string(), Type::null()), [new LegacyType('int', true), new LegacyType('string', true)], ]; - $type = Type::collection(Type::builtin(TypeIdentifier::ARRAY), Type::int(), Type::string()); + $type = Type::collection(Type::builtin(TypeIdentifier::ARRAY), Type::int(), Type::string()); // @phpstan-ignore-line yield [$type, [new LegacyType('array', false, null, true, [new LegacyType('string')], new LegacyType('int'))]]; } }