From b4619931d4aa4e658399a92564115804f233cd6f Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 4 Jan 2022 12:38:41 +0100 Subject: [PATCH 1/7] phpstan --- src/deprecation.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/deprecation.php b/src/deprecation.php index f9b9394314d..620039ada18 100644 --- a/src/deprecation.php +++ b/src/deprecation.php @@ -363,6 +363,8 @@ ApiPlatform\Core\OpenApi\Model\OAuthFlows::class => ApiPlatform\OpenApi\Model\OAuthFlows::class, ApiPlatform\Core\OpenApi\Model\Parameter::class => ApiPlatform\OpenApi\Model\Parameter::class, ApiPlatform\Core\OpenApi\Model\Paths::class => ApiPlatform\OpenApi\Model\Paths::class, + ApiPlatform\Core\OpenApi\Model\PathItem::class => ApiPlatform\OpenApi\Model\PathItem::class, + ApiPlatform\Core\OpenApi\Model\Operation::class => ApiPlatform\OpenApi\Model\Operation::class, ApiPlatform\Core\OpenApi\Model\RequestBody::class => ApiPlatform\OpenApi\Model\RequestBody::class, ApiPlatform\Core\OpenApi\Model\Response::class => ApiPlatform\OpenApi\Model\Response::class, ApiPlatform\Core\OpenApi\Model\Schema::class => ApiPlatform\OpenApi\Model\Schema::class, @@ -480,7 +482,7 @@ class_alias($deprecatedInterfaces[$className], $className); } // We try to use the new interface but it isn't aliased yet - if (in_array($className, $deprecatedInterfaces, true) && !class_exists($className)) { + if (in_array($className, (array) $deprecatedInterfaces, true) && !class_exists($className)) { $oldClassName = array_search($className, $deprecatedInterfaces, true); class_alias($oldClassName, $className); } From 18cfb27bb601148fe05c2907e2fe6f80540448cb Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 4 Jan 2022 20:39:13 +0100 Subject: [PATCH 2/7] fix: move resource name collection factory --- src/Action/EntrypointAction.php | 2 +- src/Api/Entrypoint.php | 2 +- src/Api/ResourceClassResolver.php | 2 +- .../AnnotationsProvider/ApiPlatformProvider.php | 2 +- .../Bridge/Symfony/Bundle/Action/SwaggerUiAction.php | 2 +- src/Core/Bridge/Symfony/Bundle/Command/RectorCommand.php | 2 +- .../Bridge/Symfony/Bundle/Command/SwaggerCommand.php | 2 +- src/Core/Bridge/Symfony/Maker/MakeDataPersister.php | 2 +- src/Core/Bridge/Symfony/Maker/MakeDataProvider.php | 2 +- src/Core/GraphQl/Type/SchemaBuilder.php | 2 +- .../Factory/InheritedPropertyMetadataFactory.php | 2 +- .../Factory/InheritedPropertyNameCollectionFactory.php | 2 +- src/Core/OpenApi/Factory/OpenApiFactory.php | 2 +- src/Documentation/Action/DocumentationAction.php | 2 +- src/Documentation/Documentation.php | 2 +- src/GraphQl/Type/SchemaBuilder.php | 2 +- src/JsonLd/Action/ContextAction.php | 2 +- src/JsonLd/ContextBuilder.php | 2 +- .../Factory/AnnotationResourceNameCollectionFactory.php | 4 ++-- .../Factory/CachedResourceNameCollectionFactory.php | 4 ++-- .../Factory/ExtractorResourceNameCollectionFactory.php | 4 ++-- ...resourceMetadataResourceMetadataCollectionFactory.php | 1 - .../Factory/ResourceNameCollectionFactoryInterface.php | 4 ++-- .../Metadata/Resource/ResourceNameCollection.php | 2 +- src/OpenApi/Factory/OpenApiFactory.php | 2 +- .../Bundle/Resources/config/metadata/annotation.xml | 2 +- .../Bundle/Resources/config/metadata/metadata.xml | 4 ++-- src/Symfony/Bundle/Resources/config/metadata/xml.xml | 2 +- src/Symfony/Bundle/Resources/config/metadata/yaml.xml | 2 +- src/Symfony/Routing/ApiLoader.php | 2 +- src/deprecation.php | 4 +++- tests/Action/EntrypointActionTest.php | 4 ++-- tests/Core/Annotation/ApiFilterTest.php | 2 +- tests/Core/Api/EntrypointTest.php | 2 +- tests/Core/Api/ResourceClassResolverTest.php | 4 ++-- .../AnnotationsProvider/ApiPlatformProviderTest.php | 4 ++-- .../Symfony/Bundle/Command/SwaggerCommandUnitTest.php | 4 ++-- tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php | 9 ++++++--- .../Factory/InheritedPropertyMetadataFactoryTest.php | 4 ++-- .../InheritedPropertyNameCollectionFactoryTest.php | 4 ++-- .../AnnotationResourceNameCollectionFactoryTest.php | 6 +++--- .../Factory/CachedResourceNameCollectionFactoryTest.php | 6 +++--- .../Factory/ExtractorResourceMetadataFactoryTest.php | 2 +- .../ExtractorResourceNameCollectionFactoryTest.php | 4 ++-- .../Metadata/Resource/ResourceNameCollectionTest.php | 2 +- tests/Core/OpenApi/Factory/OpenApiFactoryTest.php | 4 ++-- .../Swagger/Serializer/DocumentationNormalizerV2Test.php | 2 +- .../Swagger/Serializer/DocumentationNormalizerV3Test.php | 2 +- .../Orm/Extension/FilterEagerLoadingExtensionTest.php | 4 ++-- tests/Documentation/Action/DocumentationActionTest.php | 4 ++-- tests/GraphQl/Type/SchemaBuilderTest.php | 4 ++-- tests/Hal/Serializer/EntrypointNormalizerTest.php | 2 +- tests/Hydra/Serializer/DocumentationNormalizerTest.php | 2 +- tests/Hydra/Serializer/EntrypointNormalizerTest.php | 2 +- tests/JsonApi/Serializer/EntrypointNormalizerTest.php | 2 +- tests/JsonLd/Action/ContextActionTest.php | 4 ++-- tests/JsonLd/ContextBuilderTest.php | 4 ++-- tests/OpenApi/Factory/OpenApiFactoryTest.php | 4 ++-- tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php | 2 +- tests/OpenApi/Serializer/OpenApiNormalizerTest.php | 4 ++-- tests/Symfony/Bundle/Action/SwaggerUiActionTest.php | 4 ++-- .../DependencyInjection/ApiPlatformExtensionTest.php | 2 +- tests/Symfony/Routing/ApiLoaderTest.php | 4 ++-- 63 files changed, 95 insertions(+), 91 deletions(-) rename src/{Core => }/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php (96%) rename src/{Core => }/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php (90%) rename src/{Core => }/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php (92%) rename src/{Core => }/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php (82%) rename src/{Core => }/Metadata/Resource/ResourceNameCollection.php (95%) diff --git a/src/Action/EntrypointAction.php b/src/Action/EntrypointAction.php index ff06e44136a..c256865f35a 100644 --- a/src/Action/EntrypointAction.php +++ b/src/Action/EntrypointAction.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Action; use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; /** * Generates the API entrypoint. diff --git a/src/Api/Entrypoint.php b/src/Api/Entrypoint.php index 8375128e61a..ed654c01cdb 100644 --- a/src/Api/Entrypoint.php +++ b/src/Api/Entrypoint.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Api; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; /** * The first path you will see in the API. diff --git a/src/Api/ResourceClassResolver.php b/src/Api/ResourceClassResolver.php index 2bff932a0a9..b1bec160917 100644 --- a/src/Api/ResourceClassResolver.php +++ b/src/Api/ResourceClassResolver.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Api; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Util\ClassInfoTrait; /** diff --git a/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php b/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php index 03e90bbd7bd..7fec3d40f61 100644 --- a/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php +++ b/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php @@ -18,9 +18,9 @@ use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; use ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; use Psr\Container\ContainerInterface; diff --git a/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php b/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php index 07c083824fe..87b150ae885 100644 --- a/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php +++ b/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction as OpenApiSwaggerUiAction; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Core/Bridge/Symfony/Bundle/Command/RectorCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/RectorCommand.php index 0007c53b4db..f95f9ea01d7 100644 --- a/src/Core/Bridge/Symfony/Bundle/Command/RectorCommand.php +++ b/src/Core/Bridge/Symfony/Bundle/Command/RectorCommand.php @@ -17,8 +17,8 @@ use ApiPlatform\Core\Bridge\Rector\Service\SubresourceTransformer; use ApiPlatform\Core\Bridge\Rector\Set\ApiPlatformSetList; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use PhpParser\Lexer\Emulative; use PhpParser\NodeTraverser; use PhpParser\Parser\Php7; diff --git a/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php index 11bc8a053d4..229eec10967 100644 --- a/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php +++ b/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Command; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Exception\InvalidOptionException; diff --git a/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php b/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php index 0a40200c449..13daf7d6a74 100644 --- a/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php +++ b/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Bridge\Symfony\Maker; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use Symfony\Bundle\MakerBundle\ConsoleStyle; use Symfony\Bundle\MakerBundle\DependencyBuilder; use Symfony\Bundle\MakerBundle\Generator; diff --git a/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php b/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php index 3bd380d7579..9db71ced56f 100644 --- a/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php +++ b/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Bridge\Symfony\Maker; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use Symfony\Bundle\MakerBundle\ConsoleStyle; use Symfony\Bundle\MakerBundle\DependencyBuilder; use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; diff --git a/src/Core/GraphQl/Type/SchemaBuilder.php b/src/Core/GraphQl/Type/SchemaBuilder.php index b90d5f63b4c..f9107e55f28 100644 --- a/src/Core/GraphQl/Type/SchemaBuilder.php +++ b/src/Core/GraphQl/Type/SchemaBuilder.php @@ -16,9 +16,9 @@ use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; use ApiPlatform\Core\GraphQl\Type\TypesFactoryInterface as TypesFactoryLegacyInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\GraphQl\Type\TypesContainerInterface; use ApiPlatform\GraphQl\Type\TypesFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\WrappingType; use GraphQL\Type\Schema; diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php index 1ecdfe48249..699930cedb8 100644 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php +++ b/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Core\Metadata\Property\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; /** * @deprecated since 2.6, to be removed in 3.0 diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php index e616332b21a..6c38c542420 100644 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php +++ b/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Core\Metadata\Property\Factory; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; /** * @deprecated since 2.6, to be removed in 3.0 diff --git a/src/Core/OpenApi/Factory/OpenApiFactory.php b/src/Core/OpenApi/Factory/OpenApiFactory.php index ea56a7e80bb..6ebdacb6111 100644 --- a/src/Core/OpenApi/Factory/OpenApiFactory.php +++ b/src/Core/OpenApi/Factory/OpenApiFactory.php @@ -19,12 +19,12 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model; use ApiPlatform\OpenApi\Model\ExternalDocumentation; diff --git a/src/Documentation/Action/DocumentationAction.php b/src/Documentation/Action/DocumentationAction.php index 6d2581671e9..903dc79c74d 100644 --- a/src/Documentation/Action/DocumentationAction.php +++ b/src/Documentation/Action/DocumentationAction.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Documentation\Action; use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Documentation\DocumentationInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Documentation/Documentation.php b/src/Documentation/Documentation.php index b60ec48ee69..8f674167489 100644 --- a/src/Documentation/Documentation.php +++ b/src/Documentation/Documentation.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Documentation; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; /** * Generates the API documentation. diff --git a/src/GraphQl/Type/SchemaBuilder.php b/src/GraphQl/Type/SchemaBuilder.php index 68aa52fc611..ad5f820a402 100644 --- a/src/GraphQl/Type/SchemaBuilder.php +++ b/src/GraphQl/Type/SchemaBuilder.php @@ -13,10 +13,10 @@ namespace ApiPlatform\GraphQl\Type; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Metadata\GraphQl\Subscription; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\WrappingType; use GraphQL\Type\Schema; diff --git a/src/JsonLd/Action/ContextAction.php b/src/JsonLd/Action/ContextAction.php index 7d013cd3198..bbb21fa781a 100644 --- a/src/JsonLd/Action/ContextAction.php +++ b/src/JsonLd/Action/ContextAction.php @@ -14,11 +14,11 @@ namespace ApiPlatform\JsonLd\Action; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index 1f8dec1d85c..fade32113c9 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -18,12 +18,12 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Util\ClassInfoTrait; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php b/src/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php similarity index 96% rename from src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php rename to src/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php index c63390b249e..257fc8264da 100644 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php +++ b/src/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php @@ -11,13 +11,13 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Metadata\Resource\Factory; +namespace ApiPlatform\Metadata\Resource\Factory; use ApiPlatform\Core\Annotation\ApiResource as ApiResourceAnnotation; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation; use ApiPlatform\Metadata\Operation; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Util\ReflectionClassRecursiveIterator; use Doctrine\Common\Annotations\Reader; diff --git a/src/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php b/src/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php similarity index 90% rename from src/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php rename to src/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php index eb7cf21acf7..1a51b6094c8 100644 --- a/src/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php +++ b/src/Metadata/Resource/Factory/CachedResourceNameCollectionFactory.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Metadata\Resource\Factory; +namespace ApiPlatform\Metadata\Resource\Factory; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Util\CachedTrait; use Psr\Cache\CacheItemPoolInterface; diff --git a/src/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php b/src/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php similarity index 92% rename from src/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php rename to src/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php index 2ce5b213454..8f5354015d2 100644 --- a/src/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php +++ b/src/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactory.php @@ -11,11 +11,11 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Metadata\Resource\Factory; +namespace ApiPlatform\Metadata\Resource\Factory; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; /** * Creates a resource name collection from {@see ApiResource} configuration files. diff --git a/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php index a84d09fcb8e..934c2c3385a 100644 --- a/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Metadata\Resource\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; diff --git a/src/Core/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php b/src/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php similarity index 82% rename from src/Core/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php rename to src/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php index f5b4b0e69ac..2fbe9b16098 100644 --- a/src/Core/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php +++ b/src/Metadata/Resource/Factory/ResourceNameCollectionFactoryInterface.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Metadata\Resource\Factory; +namespace ApiPlatform\Metadata\Resource\Factory; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; /** * Creates a resource name collection value object. diff --git a/src/Core/Metadata/Resource/ResourceNameCollection.php b/src/Metadata/Resource/ResourceNameCollection.php similarity index 95% rename from src/Core/Metadata/Resource/ResourceNameCollection.php rename to src/Metadata/Resource/ResourceNameCollection.php index 6533c4a84ca..c7a48611a75 100644 --- a/src/Core/Metadata/Resource/ResourceNameCollection.php +++ b/src/Metadata/Resource/ResourceNameCollection.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Metadata\Resource; +namespace ApiPlatform\Metadata\Resource; /** * A collection of resource class names. diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index 96b0ab5b00f..d6a0dea257b 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\FilterLocatorTrait; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactoryInterface; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\OpenApi\Model; use ApiPlatform\OpenApi\Model\ExternalDocumentation; diff --git a/src/Symfony/Bundle/Resources/config/metadata/annotation.xml b/src/Symfony/Bundle/Resources/config/metadata/annotation.xml index 133b423bef6..990cefb38ce 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/annotation.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/annotation.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + %api_platform.resource_class_directories% diff --git a/src/Symfony/Bundle/Resources/config/metadata/metadata.xml b/src/Symfony/Bundle/Resources/config/metadata/metadata.xml index ddb1dab38e2..e5473365253 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/metadata.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/metadata.xml @@ -7,11 +7,11 @@ - + - + diff --git a/src/Symfony/Bundle/Resources/config/metadata/xml.xml b/src/Symfony/Bundle/Resources/config/metadata/xml.xml index 419297ba9ce..a8a91ad77d6 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/xml.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/xml.xml @@ -16,7 +16,7 @@ - + diff --git a/src/Symfony/Bundle/Resources/config/metadata/yaml.xml b/src/Symfony/Bundle/Resources/config/metadata/yaml.xml index f046fa571ec..d4a0c9ca3a2 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/yaml.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/yaml.xml @@ -15,7 +15,7 @@ - + diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index 3d6339dbc69..cbf0539b1af 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -17,13 +17,13 @@ use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Exception\InvalidResourceException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\PathResolver\OperationPathResolverInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\Loader; diff --git a/src/deprecation.php b/src/deprecation.php index 620039ada18..a3f5fa2d6ce 100644 --- a/src/deprecation.php +++ b/src/deprecation.php @@ -28,8 +28,8 @@ ApiPlatform\Core\Annotation\ApiResource::class => ApiPlatform\Metadata\ApiResource::class, ApiPlatform\Core\Annotation\ApiProperty::class => ApiPlatform\Metadata\ApiProperty::class, ApiPlatform\Core\Annotation\ApiFilter::class => ApiPlatform\Metadata\ApiFilter::class, - ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class, + ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class, ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory::class, ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::class, ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\DefaultPropertyMetadataFactory::class, @@ -42,6 +42,8 @@ ApiPlatform\Core\Metadata\Property\PropertyNameCollection::class => ApiPlatform\Metadata\Property\PropertyNameCollection::class, + ApiPlatform\Core\Metadata\Resource\ResourceNameCollectionFactoryInterface::class => ApiPlatform\Metadata\Resource\ResourceNameCollectionFactoryInterface::class, + // Exceptions ApiPlatform\Core\Exception\DeserializationException::class => ApiPlatform\Exception\DeserializationException::class, ApiPlatform\Core\Exception\FilterValidationException::class => ApiPlatform\Exception\FilterValidationException::class, diff --git a/tests/Action/EntrypointActionTest.php b/tests/Action/EntrypointActionTest.php index 1bcb8bf25ed..1ee49540df1 100644 --- a/tests/Action/EntrypointActionTest.php +++ b/tests/Action/EntrypointActionTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Action\EntrypointAction; use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Core/Annotation/ApiFilterTest.php b/tests/Core/Annotation/ApiFilterTest.php index 45b175ecaa8..fa1b75e1922 100644 --- a/tests/Core/Annotation/ApiFilterTest.php +++ b/tests/Core/Annotation/ApiFilterTest.php @@ -34,7 +34,7 @@ public function testInvalidConstructor() public function testInvalidFilter() { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The filter class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" does not implement "ApiPlatform\\Api\\FilterInterface". Did you forget a use statement?'); + $this->expectExceptionMessage('The filter class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" does not implement "ApiPlatform\\Core\\Api\\FilterInterface". Did you forget a use statement?'); new ApiFilter(['value' => Dummy::class]); // @phpstan-ignore-line } diff --git a/tests/Core/Api/EntrypointTest.php b/tests/Core/Api/EntrypointTest.php index af656e2a3e4..85b0a3d7756 100644 --- a/tests/Core/Api/EntrypointTest.php +++ b/tests/Core/Api/EntrypointTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Core\Tests\Api; use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/Core/Api/ResourceClassResolverTest.php b/tests/Core/Api/ResourceClassResolverTest.php index af3d28ae50d..c775778da41 100644 --- a/tests/Core/Api/ResourceClassResolverTest.php +++ b/tests/Core/Api/ResourceClassResolverTest.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Tests\Api; use ApiPlatform\Api\ResourceClassResolver; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\Tests\Fixtures\DummyResourceImplementation; use ApiPlatform\Tests\Fixtures\DummyResourceInterface; diff --git a/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php b/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php index ba0a76676a3..b3e1f2afee9 100644 --- a/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php +++ b/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php @@ -19,11 +19,11 @@ use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; use ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use Nelmio\ApiDocBundle\Annotation\ApiDoc; diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php index d43fdf5ce96..2a677c2a085 100644 --- a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php +++ b/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Command; use ApiPlatform\Core\Bridge\Symfony\Bundle\Command\SwaggerCommand; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Console\Input\ArrayInput; diff --git a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php b/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php index c11a2902a69..7f426f14d5b 100644 --- a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php @@ -20,13 +20,13 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidResourceException; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\PathResolver\CustomOperationPathResolver; use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\Symfony\Routing\ApiLoader; @@ -316,6 +316,8 @@ private function getApiLoaderWithResourceMetadata(ResourceMetadata $resourceMeta private function getRoute(string $path, string $controller, string $resourceClass, string $operationName, array $methods, bool $collection = false, array $requirements = [], array $extraDefaults = ['_stateless' => null], array $options = [], string $host = '', array $schemes = [], string $condition = ''): Route { + $legacyOperationName = str_replace('api_dummies_', '', str_replace($collection ? '_collection' : '_item', '', $operationName)); + return new Route( $path, [ @@ -324,7 +326,8 @@ private function getRoute(string $path, string $controller, string $resourceClas '_api_resource_class' => $resourceClass, '_api_identifiers' => ['id'], '_api_has_composite_identifier' => false, - sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item') => $operationName, + sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item') => $legacyOperationName, + '_api_operation_name' => $operationName, ] + $extraDefaults, $requirements, $options, diff --git a/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php index a37a8fdd4a8..3297ca07b9c 100644 --- a/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php +++ b/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php @@ -15,10 +15,10 @@ use ApiPlatform\Core\Metadata\Property\Factory\InheritedPropertyMetadataFactory; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; use PHPUnit\Framework\TestCase; diff --git a/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php b/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php index 838f24f7f28..a828bf2801b 100644 --- a/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php +++ b/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php @@ -16,9 +16,9 @@ use ApiPlatform\Core\Metadata\Property\Factory\InheritedPropertyNameCollectionFactory; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; use PHPUnit\Framework\TestCase; diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php index 2ec025e0b87..cf21169d5f6 100644 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php +++ b/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceNameCollectionFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Metadata\Resource\Factory\AnnotationResourceNameCollectionFactory; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use Doctrine\Common\Annotations\Reader; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; diff --git a/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php index 4c586f6c8e2..3965c3375f0 100644 --- a/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php +++ b/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\CachedResourceNameCollectionFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Metadata\Resource\Factory\CachedResourceNameCollectionFactory; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheException; diff --git a/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php index 855c17cd43a..629aee72ef3 100644 --- a/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php +++ b/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php @@ -17,13 +17,13 @@ use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; use ApiPlatform\Core\Metadata\Resource\Factory\ExtractorResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ShortNameResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; +use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; use ApiPlatform\Tests\Fixtures\DummyResourceInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; diff --git a/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php index 24ad599ad10..a8617b5216a 100644 --- a/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php +++ b/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; use PHPUnit\Framework\TestCase; diff --git a/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php b/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php index c52985bae2f..a36905990eb 100644 --- a/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php +++ b/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\Metadata\Resource; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php b/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php index 88b5b6d9233..0d135462797 100644 --- a/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php @@ -21,9 +21,7 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; @@ -32,6 +30,8 @@ use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Model; use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\OpenApi\Options; diff --git a/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php b/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php index 5ec439c5af6..58bd0c9bb32 100644 --- a/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php +++ b/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php @@ -28,7 +28,6 @@ use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; @@ -37,6 +36,7 @@ use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\PathResolver\CustomOperationPathResolver; use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\PathResolver\OperationPathResolverInterface; diff --git a/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php b/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php index 74b395c5429..c5fbdf0dc3f 100644 --- a/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php +++ b/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php @@ -27,7 +27,6 @@ use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; @@ -38,6 +37,7 @@ use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\JsonSchema\TypeFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Model; use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\PathResolver\CustomOperationPathResolver; diff --git a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php index a11c542dd31..f25b480490f 100644 --- a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Api\ResourceClassResolver; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeItem; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeLabel; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; diff --git a/tests/Documentation/Action/DocumentationActionTest.php b/tests/Documentation/Action/DocumentationActionTest.php index cdfa3538891..ce6aafefd6c 100644 --- a/tests/Documentation/Action/DocumentationActionTest.php +++ b/tests/Documentation/Action/DocumentationActionTest.php @@ -14,11 +14,11 @@ namespace ApiPlatform\Tests\Documentation\Action; use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Action\DocumentationAction; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model\Info; use ApiPlatform\OpenApi\Model\Paths; diff --git a/tests/GraphQl/Type/SchemaBuilderTest.php b/tests/GraphQl/Type/SchemaBuilderTest.php index 3f88a700d7e..612c7ab10b2 100644 --- a/tests/GraphQl/Type/SchemaBuilderTest.php +++ b/tests/GraphQl/Type/SchemaBuilderTest.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\SchemaBuilder; @@ -27,7 +25,9 @@ use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Metadata\GraphQl\Subscription; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index e0bd9ebc32e..49fa5282bc3 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -18,9 +18,9 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\EntrypointNormalizer; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index 0c6475e7257..9222d3a5484 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -22,7 +22,6 @@ use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; @@ -36,6 +35,7 @@ use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 5dfc1f65e64..1c53b4414f7 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\ApiResource; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FooDummy; use PHPUnit\Framework\TestCase; diff --git a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php index 25033f978ef..f9575fcdece 100644 --- a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php +++ b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php @@ -18,10 +18,10 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonApi\Serializer\EntrypointNormalizer; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; diff --git a/tests/JsonLd/Action/ContextActionTest.php b/tests/JsonLd/Action/ContextActionTest.php index 14a5a073f29..ca1ab6ab322 100644 --- a/tests/JsonLd/Action/ContextActionTest.php +++ b/tests/JsonLd/Action/ContextActionTest.php @@ -14,12 +14,12 @@ namespace ApiPlatform\Tests\JsonLd\Action; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonLd\Action\ContextAction; use ApiPlatform\JsonLd\ContextBuilderInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; diff --git a/tests/JsonLd/ContextBuilderTest.php b/tests/JsonLd/ContextBuilderTest.php index e13bba37167..5e9f1b71575 100644 --- a/tests/JsonLd/ContextBuilderTest.php +++ b/tests/JsonLd/ContextBuilderTest.php @@ -18,12 +18,12 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/OpenApi/Factory/OpenApiFactoryTest.php b/tests/OpenApi/Factory/OpenApiFactoryTest.php index 8ca88e431fa..c2095e3bb8b 100644 --- a/tests/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/OpenApi/Factory/OpenApiFactoryTest.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Tests\OpenApi\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; @@ -34,7 +32,9 @@ use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Factory\OpenApiFactory; use ApiPlatform\OpenApi\Model; use ApiPlatform\OpenApi\Model\ExternalDocumentation; diff --git a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php index 77949011b64..113c90a232f 100644 --- a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php +++ b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\OpenApi\Serializer; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php index 407652518d0..c2d6269ab2e 100644 --- a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php +++ b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php @@ -19,9 +19,7 @@ use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory as LegacyOpenApiFactory; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; @@ -37,7 +35,9 @@ use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Factory\OpenApiFactory; use ApiPlatform\OpenApi\Model; use ApiPlatform\OpenApi\OpenApi; diff --git a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php index bd543e66b37..162b7a9edd7 100644 --- a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 50397f58d0a..04cb92cec05 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -30,7 +30,6 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\DataTransformer\DataTransformerInitializerInterface; use ApiPlatform\DataTransformer\DataTransformerInterface; @@ -80,6 +79,7 @@ use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Options; use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer; diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index bd9102d7e97..a7293ff9fd6 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -17,8 +17,6 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; @@ -30,7 +28,9 @@ use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\PathResolver\CustomOperationPathResolver; use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\Symfony\Routing\ApiLoader; From 7ae769cb39bd15b7c23daf6d86528b8a64f11562 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 4 Jan 2022 22:12:11 +0100 Subject: [PATCH 3/7] fix tests --- .../DependencyInjection/ApiPlatformExtensionTest.php | 8 ++++++-- .../Compiler/AnnotationFilterPassTest.php | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 04cb92cec05..89e3fbc5042 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -26,6 +26,7 @@ use ApiPlatform\Core\DataPersister\DataPersisterInterface; use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; +use ApiPlatform\Core\DataProvider\Pagination as LegacyPagination; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; @@ -1133,7 +1134,8 @@ private function getPartialContainerBuilderProphecy($configuration = null) 'api_platform.operation_path_resolver.generator', 'api_platform.operation_path_resolver.router', 'api_platform.operation_path_resolver.underscore', - 'api_platform.pagination', + 'api_platform.pagination.legacy', + 'api_platform.pagination.next', 'api_platform.pagination_options', 'api_platform.path_segment_name_generator.dash', 'api_platform.path_segment_name_generator.underscore', @@ -1199,6 +1201,7 @@ private function getPartialContainerBuilderProphecy($configuration = null) 'api_platform.metadata.resource.name_collection_factory' => 'api_platform.metadata.resource.name_collection_factory.xml', 'api_platform.operation_path_resolver' => 'api_platform.operation_path_resolver.router', 'api_platform.operation_path_resolver.default' => 'api_platform.operation_path_resolver.underscore', + 'api_platform.pagination' => 'api_platform.pagination.next', 'api_platform.path_segment_name_generator' => 'api_platform.path_segment_name_generator.underscore', 'api_platform.property_accessor' => 'property_accessor', 'api_platform.property_info' => 'property_info', @@ -1215,7 +1218,8 @@ private function getPartialContainerBuilderProphecy($configuration = null) LegacyPropertyNameCollectionFactoryInterface::class => 'api_platform.metadata.property.name_collection_factory', NotFoundAction::class => 'api_platform.action.not_found', OperationAwareFormatsProviderInterface::class => 'api_platform.formats_provider', - Pagination::class => 'api_platform.pagination', + LegacyPagination::class => 'api_platform.pagination.legacy', + Pagination::class => 'api_platform.pagination.next', PaginationOptions::class => 'api_platform.pagination_options', ProcessorInterface::class => 'api_platform.state_processor', PropertyFilter::class => 'api_platform.serializer.property_filter', diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php index b5971080ba5..5d5203c0e6b 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Api\FilterInterface; use ApiPlatform\Core\Annotation\ApiFilter; +use ApiPlatform\Core\Api\FilterInterface; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; From 9d5a6b1559f1b26871fb64e3a5b2cfea4227f025 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 4 Jan 2022 22:38:42 +0100 Subject: [PATCH 4/7] restore property metadata? --- .../Factory/CachedPropertyMetadataFactory.php | 50 ++++ .../DefaultPropertyMetadataFactory.php | 57 +++++ .../ExtractorPropertyMetadataFactory.php | 160 +++++++++++++ .../PropertyMetadataFactoryInterface.php | 32 +++ .../SerializerPropertyMetadataFactory.php | 226 ++++++++++++++++++ .../PropertyMetadataFactoryInterface.php | 5 +- .../ApiPlatformExtension.php | 13 + 7 files changed, 540 insertions(+), 3 deletions(-) create mode 100644 src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php create mode 100644 src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php create mode 100644 src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php create mode 100644 src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php create mode 100644 src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php diff --git a/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php new file mode 100644 index 00000000000..ac86aba7dba --- /dev/null +++ b/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php @@ -0,0 +1,50 @@ + + * + * 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\Core\Metadata\Property\Factory; + +use ApiPlatform\Core\Cache\CachedTrait; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use Psr\Cache\CacheItemPoolInterface; + +/** + * Caches property metadata. + * + * @author Teoh Han Hui + */ +final class CachedPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + use CachedTrait; + + public const CACHE_KEY_PREFIX = 'property_metadata_'; + + private $decorated; + + public function __construct(CacheItemPoolInterface $cacheItemPool, PropertyMetadataFactoryInterface $decorated) + { + $this->cacheItemPool = $cacheItemPool; + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + $cacheKey = self::CACHE_KEY_PREFIX.md5(serialize([$resourceClass, $property, $options])); + + return $this->getCached($cacheKey, function () use ($resourceClass, $property, $options) { + return $this->decorated->create($resourceClass, $property, $options); + }); + } +} diff --git a/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php new file mode 100644 index 00000000000..9c951077753 --- /dev/null +++ b/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php @@ -0,0 +1,57 @@ + + * + * 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\Core\Metadata\Property\Factory; + +use ApiPlatform\Core\Exception\PropertyNotFoundException; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; + +/** + * Populates defaults values of the ressource properties using the default PHP values of properties. + */ +final class DefaultPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + private $decorated; + + public function __construct(PropertyMetadataFactoryInterface $decorated = null) + { + $this->decorated = $decorated; + } + + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + if (null === $this->decorated) { + $propertyMetadata = new PropertyMetadata(); + } else { + try { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + } catch (PropertyNotFoundException $propertyNotFoundException) { + $propertyMetadata = new PropertyMetadata(); + } + } + + try { + $reflectionClass = new \ReflectionClass($resourceClass); + } catch (\ReflectionException $reflectionException) { + return $propertyMetadata; + } + + $defaultProperties = $reflectionClass->getDefaultProperties(); + + if (!\array_key_exists($property, $defaultProperties) || null === ($defaultProperty = $defaultProperties[$property])) { + return $propertyMetadata; + } + + return $propertyMetadata->withDefault($defaultProperty); + } +} diff --git a/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php new file mode 100644 index 00000000000..89f86c69cb6 --- /dev/null +++ b/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php @@ -0,0 +1,160 @@ + + * + * 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\Core\Metadata\Property\Factory; + +use ApiPlatform\Core\Exception\PropertyNotFoundException; +use ApiPlatform\Core\Metadata\Extractor\ExtractorInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; +use Symfony\Component\PropertyInfo\Type; + +/** + * Creates properties's metadata using an extractor. + * + * @author Kévin Dunglas + */ +final class ExtractorPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + private $extractor; + private $decorated; + + public function __construct(ExtractorInterface $extractor, PropertyMetadataFactoryInterface $decorated = null) + { + $this->extractor = $extractor; + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + $parentPropertyMetadata = null; + if ($this->decorated) { + try { + $parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options); + } catch (PropertyNotFoundException $propertyNotFoundException) { + // Ignore not found exception from decorated factories + } + } + + $isInterface = interface_exists($resourceClass); + + if ( + !property_exists($resourceClass, $property) && !$isInterface || + null === ($propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? null) + ) { + return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); + } + + if ($parentPropertyMetadata) { + return $this->update($parentPropertyMetadata, $propertyMetadata); + } + + return ($metadata = new PropertyMetadata( + null, + $propertyMetadata['description'], + $propertyMetadata['readable'], + $propertyMetadata['writable'], + $propertyMetadata['readableLink'], + $propertyMetadata['writableLink'], + $propertyMetadata['required'], + $propertyMetadata['identifier'], + $propertyMetadata['iri'], + null, + $propertyMetadata['attributes'] + ))->withSubresource($this->createSubresourceMetadata($propertyMetadata['subresource'], $metadata)); + } + + /** + * Returns the metadata from the decorated factory if available or throws an exception. + * + * @throws PropertyNotFoundException + */ + private function handleNotFound(?PropertyMetadata $parentPropertyMetadata, string $resourceClass, string $property): PropertyMetadata + { + if ($parentPropertyMetadata) { + return $parentPropertyMetadata; + } + + throw new PropertyNotFoundException(sprintf('Property "%s" of the resource class "%s" not found.', $property, $resourceClass)); + } + + /** + * Creates a new instance of metadata if the property is not already set. + */ + private function update(PropertyMetadata $propertyMetadata, array $metadata): PropertyMetadata + { + $metadataAccessors = [ + 'description' => 'get', + 'readable' => 'is', + 'writable' => 'is', + 'writableLink' => 'is', + 'readableLink' => 'is', + 'required' => 'is', + 'identifier' => 'is', + 'iri' => 'get', + 'attributes' => 'get', + ]; + + foreach ($metadataAccessors as $metadataKey => $accessorPrefix) { + if (null === $metadata[$metadataKey]) { + continue; + } + + $propertyMetadata = $propertyMetadata->{'with'.ucfirst($metadataKey)}($metadata[$metadataKey]); + } + + if ($propertyMetadata->hasSubresource()) { + return $propertyMetadata; + } + + return $propertyMetadata->withSubresource($this->createSubresourceMetadata($metadata['subresource'], $propertyMetadata)); + } + + /** + * Creates a SubresourceMetadata. + * + * @param bool|array|null $subresource the subresource metadata coming from XML or YAML + * @param PropertyMetadata $propertyMetadata the current property metadata + */ + private function createSubresourceMetadata($subresource, PropertyMetadata $propertyMetadata): ?SubresourceMetadata + { + if (!$subresource) { + return null; + } + + $type = $propertyMetadata->getType(); + $maxDepth = \is_array($subresource) ? $subresource['maxDepth'] ?? null : null; + + if (null !== $type) { + $isCollection = $type->isCollection(); + if ( + $isCollection && + $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() + ) { + $resourceClass = $collectionValueType->getClassName(); + } else { + $resourceClass = $type->getClassName(); + } + } elseif (\is_array($subresource) && isset($subresource['resourceClass'])) { + $resourceClass = $subresource['resourceClass']; + $isCollection = $subresource['collection'] ?? true; + } else { + return null; + } + + return new SubresourceMetadata($resourceClass, $isCollection, $maxDepth); + } +} diff --git a/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php b/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php new file mode 100644 index 00000000000..5cb5cc1f76f --- /dev/null +++ b/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php @@ -0,0 +1,32 @@ + + * + * 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\Core\Metadata\Property\Factory; + +use ApiPlatform\Core\Exception\PropertyNotFoundException; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; + +/** + * Creates a property metadata value object. + * + * @author Kévin Dunglas + */ +interface PropertyMetadataFactoryInterface +{ + /** + * Creates a property metadata. + * + * @throws PropertyNotFoundException + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata; +} diff --git a/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php new file mode 100644 index 00000000000..1078d3af945 --- /dev/null +++ b/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php @@ -0,0 +1,226 @@ + + * + * 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\Core\Metadata\Property\Factory; + +use ApiPlatform\Core\Api\ResourceClassResolverInterface; +use ApiPlatform\Core\Exception\ResourceClassNotFoundException; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Util\ResourceClassInfoTrait; +use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; +use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface as SerializerClassMetadataFactoryInterface; + +/** + * Populates read/write and link status using serialization groups. + * + * @author Kévin Dunglas + * @author Teoh Han Hui + */ +final class SerializerPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + use ResourceClassInfoTrait; + + private $serializerClassMetadataFactory; + private $decorated; + + public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, SerializerClassMetadataFactoryInterface $serializerClassMetadataFactory, PropertyMetadataFactoryInterface $decorated, ResourceClassResolverInterface $resourceClassResolver = null) + { + $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->serializerClassMetadataFactory = $serializerClassMetadataFactory; + $this->decorated = $decorated; + $this->resourceClassResolver = $resourceClassResolver; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + + // BC to be removed in 3.0 + if (null !== ($childResourceClass = $propertyMetadata->getChildInherited())) { + $resourceClass = $childResourceClass; + } + + try { + [$normalizationGroups, $denormalizationGroups] = $this->getEffectiveSerializerGroups($options, $resourceClass); + } catch (ResourceClassNotFoundException $e) { + // TODO: for input/output classes, the serializer groups must be read from the actual resource class + return $propertyMetadata; + } + + $propertyMetadata = $this->transformReadWrite($propertyMetadata, $resourceClass, $property, $normalizationGroups, $denormalizationGroups); + + return $this->transformLinkStatus($propertyMetadata, $normalizationGroups, $denormalizationGroups); + } + + /** + * Sets readable/writable based on matching normalization/denormalization groups and property's ignorance. + * + * A false value is never reset as it could be unreadable/unwritable for other reasons. + * If normalization/denormalization groups are not specified and the property is not ignored, the property is implicitly readable/writable. + * + * @param string[]|null $normalizationGroups + * @param string[]|null $denormalizationGroups + */ + private function transformReadWrite(PropertyMetadata $propertyMetadata, string $resourceClass, string $propertyName, array $normalizationGroups = null, array $denormalizationGroups = null): PropertyMetadata + { + $serializerAttributeMetadata = $this->getSerializerAttributeMetadata($resourceClass, $propertyName); + $groups = $serializerAttributeMetadata ? $serializerAttributeMetadata->getGroups() : []; + $ignored = $serializerAttributeMetadata && method_exists($serializerAttributeMetadata, 'isIgnored') ? $serializerAttributeMetadata->isIgnored() : false; + + if (false !== $propertyMetadata->isReadable()) { + $propertyMetadata = $propertyMetadata->withReadable(!$ignored && (null === $normalizationGroups || array_intersect($normalizationGroups, $groups))); + } + + if (false !== $propertyMetadata->isWritable()) { + $propertyMetadata = $propertyMetadata->withWritable(!$ignored && (null === $denormalizationGroups || array_intersect($denormalizationGroups, $groups))); + } + + return $propertyMetadata; + } + + /** + * Sets readableLink/writableLink based on matching normalization/denormalization groups. + * + * If normalization/denormalization groups are not specified, + * set link status to false since embedding of resource must be explicitly enabled + * + * @param string[]|null $normalizationGroups + * @param string[]|null $denormalizationGroups + */ + private function transformLinkStatus(PropertyMetadata $propertyMetadata, array $normalizationGroups = null, array $denormalizationGroups = null): PropertyMetadata + { + // No need to check link status if property is not readable and not writable + if (false === $propertyMetadata->isReadable() && false === $propertyMetadata->isWritable()) { + return $propertyMetadata; + } + + $type = $propertyMetadata->getType(); + if (null === $type) { + return $propertyMetadata; + } + + if ( + $type->isCollection() && + $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() + ) { + $relatedClass = $collectionValueType->getClassName(); + } else { + $relatedClass = $type->getClassName(); + } + + // if property is not a resource relation, don't set link status (as it would have no meaning) + if (null === $relatedClass || !$this->isResourceClass($relatedClass)) { + return $propertyMetadata; + } + + // find the resource class + // this prevents serializer groups on non-resource child class from incorrectly influencing the decision + if (null !== $this->resourceClassResolver) { + $relatedClass = $this->resourceClassResolver->getResourceClass(null, $relatedClass); + } + + $relatedGroups = $this->getClassSerializerGroups($relatedClass); + + if (null === $propertyMetadata->isReadableLink()) { + $propertyMetadata = $propertyMetadata->withReadableLink(null !== $normalizationGroups && !empty(array_intersect($normalizationGroups, $relatedGroups))); + } + + if (null === $propertyMetadata->isWritableLink()) { + $propertyMetadata = $propertyMetadata->withWritableLink(null !== $denormalizationGroups && !empty(array_intersect($denormalizationGroups, $relatedGroups))); + } + + return $propertyMetadata; + } + + /** + * Gets the effective serializer groups used in normalization/denormalization. + * + * Groups are extracted in the following order: + * + * - From the "serializer_groups" key of the $options array. + * - From metadata of the given operation ("collection_operation_name" and "item_operation_name" keys). + * - From metadata of the current resource. + * + * @throws ResourceClassNotFoundException + * + * @return (string[]|null)[] + */ + private function getEffectiveSerializerGroups(array $options, string $resourceClass): array + { + if (isset($options['serializer_groups'])) { + $groups = (array) $options['serializer_groups']; + + return [$groups, $groups]; + } + + $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); + if (isset($options['collection_operation_name'])) { + $normalizationContext = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], 'normalization_context', null, true); + $denormalizationContext = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], 'denormalization_context', null, true); + } elseif (isset($options['item_operation_name'])) { + $normalizationContext = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], 'normalization_context', null, true); + $denormalizationContext = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], 'denormalization_context', null, true); + } elseif (isset($options['graphql_operation_name'])) { + $normalizationContext = $resourceMetadata->getGraphqlAttribute($options['graphql_operation_name'], 'normalization_context', null, true); + $denormalizationContext = $resourceMetadata->getGraphqlAttribute($options['graphql_operation_name'], 'denormalization_context', null, true); + } else { + $normalizationContext = $resourceMetadata->getAttribute('normalization_context'); + $denormalizationContext = $resourceMetadata->getAttribute('denormalization_context'); + } + + return [ + isset($normalizationContext['groups']) ? (array) $normalizationContext['groups'] : null, + isset($denormalizationContext['groups']) ? (array) $denormalizationContext['groups'] : null, + ]; + } + + private function getSerializerAttributeMetadata(string $class, string $attribute): ?AttributeMetadataInterface + { + $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); + + foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { + if ($attribute === $serializerAttributeMetadata->getName()) { + return $serializerAttributeMetadata; + } + } + + return null; + } + + /** + * Gets all serializer groups used in a class. + * + * @return string[] + */ + private function getClassSerializerGroups(string $class): array + { + $resourceMetadata = $this->resourceMetadataFactory->create($class); + if ($outputClass = $resourceMetadata->getAttribute('output')['class'] ?? null) { + $class = $outputClass; + } + + $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); + + $groups = []; + foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { + $groups = array_merge($groups, $serializerAttributeMetadata->getGroups()); + } + + return array_unique($groups); + } +} diff --git a/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php b/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php index 30267b25cae..36ccc459d06 100644 --- a/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php +++ b/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Metadata\Property\Factory; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; @@ -29,7 +28,7 @@ interface PropertyMetadataFactoryInterface * * @throws PropertyNotFoundException * - * @return PropertyMetadata|ApiProperty + * @return ApiProperty */ - public function create(string $resourceClass, string $property, array $options = []); + public function create(string $resourceClass, string $property, array $options = []): ApiProperty; } diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 11f9c6bd2a3..5cc6785cb95 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -861,6 +861,19 @@ private function registerLegacyServices(ContainerBuilder $container, array $conf $container->getDefinition('api_platform.metadata.resource_extractor.yaml')->setClass(YamlExtractor::class); $container->getDefinition('api_platform.metadata.property_extractor.yaml')->setClass(YamlExtractor::class); } + + // avoid using namespaces to keep out of deprecation warnings + $remapDefinitionClasses = [ + 'api_platform.metadata.property.metadata_factory.cached' => 'ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyMetadataFactory', + 'api_platform.metadata.property.metadata_factory.default_property' => 'ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory', + 'api_platform.metadata.property.metadata_factory.serializer' => 'ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory', + 'api_platform.metadata.property.metadata_factory.xml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory', + 'api_platform.metadata.property.metadata_factory.yaml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory' + ]; + + foreach($remapDefinitionClasses as $id => $class) { + $container->getDefinition($id)->setClass($class); + } } private function registerRectorConfiguration(ContainerBuilder $container, XmlFileLoader $loader): void From d2e542d5c8033012f3d7326d138c5b96ca7c7563 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 11 Jan 2022 13:50:10 +0100 Subject: [PATCH 5/7] TEMPORARY COMMIT --- .../DoctrineOrmPropertyMetadataFactory.php | 87 ++++ .../PropertyInfoPropertyMetadataFactory.php | 89 ++++ .../ValidatorPropertyMetadataFactory.php | 203 +++++++++ .../AnnotationPropertyMetadataFactory.php | 2 +- .../AnnotationSubresourceMetadataFactory.php | 2 +- .../DoctrineOrmPropertyMetadataFactory.php | 5 +- .../AttributePropertyMetadataFactory.php | 2 +- .../ExtractorPropertyMetadataFactory.php | 2 +- .../PropertyInfoPropertyMetadataFactory.php | 4 +- ...pertyInfoPropertyNameCollectionFactory.php | 6 +- .../PropertyMetadataFactoryInterface.php | 2 - .../SerializerPropertyMetadataFactory.php | 2 +- .../ApiPlatformExtension.php | 8 +- .../Resources/config/metadata/metadata.xml | 6 +- .../ValidatorPropertyMetadataFactory.php | 25 +- tests/Core/Api/IdentifiersExtractorTest.php | 12 +- .../Util/IdentifierManagerTraitTest.php | 6 +- .../Doctrine/Orm/ItemDataProviderTest.php | 6 +- .../ValidatorPropertyMetadataFactoryTest.php | 399 ++++++++++++++++++ .../ValidatorPropertyMetadataFactoryTest.php | 2 +- 20 files changed, 822 insertions(+), 48 deletions(-) create mode 100644 src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php create mode 100644 src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php create mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php rename src/Metadata/Property/{ => Factory}/PropertyInfoPropertyMetadataFactory.php (97%) rename src/Metadata/Property/{ => Factory}/PropertyInfoPropertyNameCollectionFactory.php (85%) create mode 100644 tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php diff --git a/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php b/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php new file mode 100644 index 00000000000..5726fa64c7c --- /dev/null +++ b/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php @@ -0,0 +1,87 @@ + + * + * 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\Core\Bridge\Doctrine\Orm\Metadata\Property; + +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\Persistence\ManagerRegistry; + +/** + * Use Doctrine metadata to populate the identifier property. + * + * @author Kévin Dunglas + */ +final class DoctrineOrmPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + private $decorated; + private $managerRegistry; + + public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) + { + $this->managerRegistry = $managerRegistry; + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + + if (null !== $propertyMetadata->isIdentifier()) { + return $propertyMetadata; + } + + $manager = $this->managerRegistry->getManagerForClass($resourceClass); + if (!$manager) { + return $propertyMetadata; + } + $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); + + $identifiers = $doctrineClassMetadata->getIdentifier(); + foreach ($identifiers as $identifier) { + if ($identifier === $property) { + $propertyMetadata = $propertyMetadata->withIdentifier(true); + + if (null !== $propertyMetadata->isWritable()) { + break; + } + + if ($doctrineClassMetadata instanceof ClassMetadataInfo) { + $writable = $doctrineClassMetadata->isIdentifierNatural(); + } else { + $writable = false; + } + + $propertyMetadata = $propertyMetadata->withWritable($writable); + + break; + } + } + + if (null === $propertyMetadata->isIdentifier()) { + $propertyMetadata = $propertyMetadata->withIdentifier(false); + } + + if ($doctrineClassMetadata instanceof ClassMetadataInfo && \in_array($property, $doctrineClassMetadata->getFieldNames(), true)) { + /** @var mixed[] */ + $fieldMapping = $doctrineClassMetadata->getFieldMapping($property); + $propertyMetadata = $propertyMetadata->withDefault($fieldMapping['options']['default'] ?? $propertyMetadata->getDefault()); + } + + return $propertyMetadata; + } +} diff --git a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php b/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php new file mode 100644 index 00000000000..26d7a76b657 --- /dev/null +++ b/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php @@ -0,0 +1,89 @@ + + * + * 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\Core\Bridge\Symfony\PropertyInfo\Metadata\Property; + +use ApiPlatform\Core\Exception\PropertyNotFoundException; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; + +/** + * PropertyInfo metadata loader decorator. + * + * @author Kévin Dunglas + */ +final class PropertyInfoPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + private $propertyInfo; + private $decorated; + + public function __construct(PropertyInfoExtractorInterface $propertyInfo, PropertyMetadataFactoryInterface $decorated = null) + { + $this->propertyInfo = $propertyInfo; + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + if (null === $this->decorated) { + $propertyMetadata = new PropertyMetadata(); + } else { + try { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + } catch (PropertyNotFoundException $propertyNotFoundException) { + $propertyMetadata = new PropertyMetadata(); + } + } + + if (null === $propertyMetadata->getType()) { + $types = $this->propertyInfo->getTypes($resourceClass, $property, $options); + if (isset($types[0])) { + $propertyMetadata = $propertyMetadata->withType($types[0]); + } + } + + if (null === $propertyMetadata->getDescription() && null !== $description = $this->propertyInfo->getShortDescription($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withDescription($description); + } + + if (null === $propertyMetadata->isReadable() && null !== $readable = $this->propertyInfo->isReadable($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withReadable($readable); + } + + if (null === $propertyMetadata->isWritable() && null !== $writable = $this->propertyInfo->isWritable($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withWritable($writable); + } + + if (method_exists($this->propertyInfo, 'isInitializable')) { + if (null === $propertyMetadata->isInitializable() && null !== $initializable = $this->propertyInfo->isInitializable($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withInitializable($initializable); + } + } else { + // BC layer for Symfony < 4.2 + $ref = new \ReflectionClass($resourceClass); + if ($ref->isInstantiable() && $constructor = $ref->getConstructor()) { + foreach ($constructor->getParameters() as $constructorParameter) { + if ($constructorParameter->name === $property && null === $propertyMetadata->isInitializable()) { + $propertyMetadata = $propertyMetadata->withInitializable(true); + } + } + } + } + + return $propertyMetadata; + } +} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php new file mode 100644 index 00000000000..f1d6d1aee52 --- /dev/null +++ b/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php @@ -0,0 +1,203 @@ + + * + * 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\Core\Bridge\Symfony\Validator\Metadata\Property; + +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\Bic; +use Symfony\Component\Validator\Constraints\CardScheme; +use Symfony\Component\Validator\Constraints\Compound; +use Symfony\Component\Validator\Constraints\Currency; +use Symfony\Component\Validator\Constraints\Date; +use Symfony\Component\Validator\Constraints\DateTime; +use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\File; +use Symfony\Component\Validator\Constraints\Iban; +use Symfony\Component\Validator\Constraints\Image; +use Symfony\Component\Validator\Constraints\Isbn; +use Symfony\Component\Validator\Constraints\Issn; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\NotNull; +use Symfony\Component\Validator\Constraints\Sequentially; +use Symfony\Component\Validator\Constraints\Time; +use Symfony\Component\Validator\Constraints\Url; +use Symfony\Component\Validator\Constraints\Uuid; +use Symfony\Component\Validator\Mapping\ClassMetadataInterface as ValidatorClassMetadataInterface; +use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface as ValidatorMetadataFactoryInterface; +use Symfony\Component\Validator\Mapping\PropertyMetadataInterface as ValidatorPropertyMetadataInterface; + +/** + * Decorates a metadata loader using the validator. + * + * @author Kévin Dunglas + */ +final class ValidatorPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + /** + * @var string[] A list of constraint classes making the entity required + */ + public const REQUIRED_CONSTRAINTS = [NotBlank::class, NotNull::class]; + + public const SCHEMA_MAPPED_CONSTRAINTS = [ + Url::class => 'http://schema.org/url', + Email::class => 'http://schema.org/email', + Uuid::class => 'http://schema.org/identifier', + CardScheme::class => 'http://schema.org/identifier', + Bic::class => 'http://schema.org/identifier', + Iban::class => 'http://schema.org/identifier', + Date::class => 'http://schema.org/Date', + DateTime::class => 'http://schema.org/DateTime', + Time::class => 'http://schema.org/Time', + Image::class => 'http://schema.org/image', + File::class => 'http://schema.org/MediaObject', + Currency::class => 'http://schema.org/priceCurrency', + Isbn::class => 'http://schema.org/isbn', + Issn::class => 'http://schema.org/issn', + ]; + + private $decorated; + private $validatorMetadataFactory; + /** + * @var iterable + */ + private $restrictionsMetadata; + + /** + * @param PropertySchemaRestrictionMetadataInterface[] $restrictionsMetadata + */ + public function __construct(ValidatorMetadataFactoryInterface $validatorMetadataFactory, PropertyMetadataFactoryInterface $decorated, iterable $restrictionsMetadata = []) + { + $this->validatorMetadataFactory = $validatorMetadataFactory; + $this->decorated = $decorated; + $this->restrictionsMetadata = $restrictionsMetadata; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + + $required = $propertyMetadata->isRequired(); + $iri = $propertyMetadata->getIri(); + $schema = $propertyMetadata->getSchema(); + + if (null !== $required && $iri && $schema) { + return $propertyMetadata; + } + + $validatorClassMetadata = $this->validatorMetadataFactory->getMetadataFor($resourceClass); + + if (!$validatorClassMetadata instanceof ValidatorClassMetadataInterface) { + throw new \UnexpectedValueException(sprintf('Validator class metadata expected to be of type "%s".', ValidatorClassMetadataInterface::class)); + } + + $validationGroups = $this->getValidationGroups($validatorClassMetadata, $options); + $restrictions = []; + + foreach ($validatorClassMetadata->getPropertyMetadata($property) as $validatorPropertyMetadata) { + foreach ($this->getPropertyConstraints($validatorPropertyMetadata, $validationGroups) as $constraint) { + if (null === $required && $this->isRequired($constraint)) { + $required = true; + } + + if (!$iri) { + $iri = self::SCHEMA_MAPPED_CONSTRAINTS[\get_class($constraint)] ?? null; + } + + foreach ($this->restrictionsMetadata as $restrictionMetadata) { + if ($restrictionMetadata->supports($constraint, $propertyMetadata)) { + $restrictions[] = $restrictionMetadata->create($constraint, $propertyMetadata); + } + } + } + } + + if ($iri) { + $propertyMetadata = $propertyMetadata->withIri($iri); + } + + $propertyMetadata = $propertyMetadata->withRequired($required ?? false); + + if (!empty($restrictions)) { + if (null === $schema) { + $schema = []; + } + + $schema += array_merge(...$restrictions); + $propertyMetadata = $propertyMetadata->withSchema($schema); + } + + return $propertyMetadata; + } + + /** + * Returns the list of validation groups. + */ + private function getValidationGroups(ValidatorClassMetadataInterface $classMetadata, array $options): array + { + if (isset($options['validation_groups'])) { + return $options['validation_groups']; + } + + if (!method_exists($classMetadata, 'getDefaultGroup')) { + throw new \UnexpectedValueException(sprintf('Validator class metadata expected to have method "%s".', 'getDefaultGroup')); + } + + return [$classMetadata->getDefaultGroup()]; + } + + /** + * Tests if the property is required because of its validation groups. + */ + private function getPropertyConstraints( + ValidatorPropertyMetadataInterface $validatorPropertyMetadata, + array $groups + ): array { + $constraints = []; + + foreach ($groups as $validationGroup) { + if (!\is_string($validationGroup)) { + continue; + } + + foreach ($validatorPropertyMetadata->findConstraints($validationGroup) as $propertyConstraint) { + if ($propertyConstraint instanceof Sequentially || $propertyConstraint instanceof Compound) { + $constraints[] = method_exists($propertyConstraint, 'getNestedContraints') ? $propertyConstraint->getNestedContraints() : $propertyConstraint->getNestedConstraints(); + } else { + $constraints[] = [$propertyConstraint]; + } + } + } + + return array_merge([], ...$constraints); + } + + /** + * Is this constraint making the related property required? + */ + private function isRequired(Constraint $constraint): bool + { + foreach (self::REQUIRED_CONSTRAINTS as $requiredConstraint) { + if ($constraint instanceof $requiredConstraint) { + return true; + } + } + + return false; + } +} diff --git a/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php index d6770ae3108..9aa61ce3501 100644 --- a/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php +++ b/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php @@ -43,7 +43,7 @@ public function __construct(Reader $reader = null, PropertyMetadataFactoryInterf /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata { $parentPropertyMetadata = null; if ($this->decorated) { diff --git a/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php b/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php index 98bbb9985f9..7355747cb94 100644 --- a/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php +++ b/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php @@ -43,7 +43,7 @@ public function __construct(Reader $reader, PropertyMetadataFactoryInterface $de /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata { /** @var ApiPropertyMetadata|PropertyMetadata */ $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); diff --git a/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php b/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php index e3b3efd04de..611640e1424 100644 --- a/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php +++ b/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Doctrine\Orm\Metadata\Property; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Persistence\ManagerRegistry; @@ -36,7 +37,7 @@ public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFa /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): ApiProperty { $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); diff --git a/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php b/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php index c802050d9cf..04c5199dc49 100644 --- a/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php @@ -35,7 +35,7 @@ public function __construct(PropertyMetadataFactoryInterface $decorated = null) /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): ApiProperty { $parentPropertyMetadata = null; if ($this->decorated) { diff --git a/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php b/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php index 6b2b7823345..43d7ff537a4 100644 --- a/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php @@ -42,7 +42,7 @@ public function __construct(PropertyExtractorInterface $extractor, PropertyMetad /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): ApiProperty { $parentPropertyMetadata = null; if ($this->decorated) { diff --git a/src/Metadata/Property/PropertyInfoPropertyMetadataFactory.php b/src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php similarity index 97% rename from src/Metadata/Property/PropertyInfoPropertyMetadataFactory.php rename to src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php index 8123c800d16..ae0fcd957ae 100644 --- a/src/Metadata/Property/PropertyInfoPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Metadata\Property; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; @@ -38,7 +38,7 @@ public function __construct(PropertyInfoExtractorInterface $propertyInfo, Proper /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): ApiProperty { if (null === $this->decorated) { $propertyMetadata = new ApiProperty(); diff --git a/src/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php similarity index 85% rename from src/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php rename to src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php index 54819c8b718..8ff55aeba3a 100644 --- a/src/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php @@ -11,10 +11,10 @@ declare(strict_types=1); -namespace ApiPlatform\Metadata\Property; +namespace ApiPlatform\Metadata\Property\Factory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; /** diff --git a/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php b/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php index 36ccc459d06..b29ac8e5b89 100644 --- a/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php +++ b/src/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php @@ -27,8 +27,6 @@ interface PropertyMetadataFactoryInterface * Creates a property metadata. * * @throws PropertyNotFoundException - * - * @return ApiProperty */ public function create(string $resourceClass, string $property, array $options = []): ApiProperty; } diff --git a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php index ffdbac52950..d069141aa43 100644 --- a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php @@ -52,7 +52,7 @@ public function __construct(?ResourceMetadataFactoryInterface $resourceMetadataF /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): ApiProperty { /** @var PropertyMetadata|ApiProperty */ $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 5cc6785cb95..25b59a571ef 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -868,12 +868,16 @@ private function registerLegacyServices(ContainerBuilder $container, array $conf 'api_platform.metadata.property.metadata_factory.default_property' => 'ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory', 'api_platform.metadata.property.metadata_factory.serializer' => 'ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory', 'api_platform.metadata.property.metadata_factory.xml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory', - 'api_platform.metadata.property.metadata_factory.yaml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory' + 'api_platform.metadata.property.metadata_factory.yaml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory', + 'api_platform.metadata.property.metadata_factory.property_info' => 'ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory', + 'api_platform.doctrine.orm.metadata.property.metadata_factory' => 'ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory' ]; - foreach($remapDefinitionClasses as $id => $class) { + foreach ($remapDefinitionClasses as $id => $class) { $container->getDefinition($id)->setClass($class); } + + $container->setAlias('api_platform.metadata.property.metadata_factory', 'api_platform.metadata.property.metadata_factory.legacy'); } private function registerRectorConfiguration(ContainerBuilder $container, XmlFileLoader $loader): void diff --git a/src/Symfony/Bundle/Resources/config/metadata/metadata.xml b/src/Symfony/Bundle/Resources/config/metadata/metadata.xml index e5473365253..894e9db7fc7 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/metadata.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/metadata.xml @@ -47,7 +47,7 @@ - + @@ -59,7 +59,7 @@ - + @@ -85,7 +85,7 @@ - + diff --git a/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php index 2bbf3311bda..4d344171ee6 100644 --- a/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php +++ b/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php @@ -13,8 +13,7 @@ namespace ApiPlatform\Symfony\Validator\Metadata\Property; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use Symfony\Component\Validator\Constraint; @@ -89,18 +88,15 @@ public function __construct(ValidatorMetadataFactoryInterface $validatorMetadata /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): ApiProperty { - /** - * @var PropertyMetadata|ApiProperty - */ $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); $required = $propertyMetadata->isRequired(); - $iri = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getIri() : ($propertyMetadata->getTypes()[0] ?? null); + $types = $propertyMetadata->getTypes(); $schema = $propertyMetadata->getSchema(); - if (null !== $required && $iri && $schema) { + if (null !== $required && $types && $schema) { return $propertyMetadata; } @@ -119,8 +115,10 @@ public function create(string $resourceClass, string $property, array $options = $required = true; } - if (!$iri) { - $iri = self::SCHEMA_MAPPED_CONSTRAINTS[\get_class($constraint)] ?? null; + $type = self::SCHEMA_MAPPED_CONSTRAINTS[\get_class($constraint)] ?? null; + + if (!in_array($type, $types)) { + $types[] = $type; } foreach ($this->restrictionsMetadata as $restrictionMetadata) { @@ -131,12 +129,7 @@ public function create(string $resourceClass, string $property, array $options = } } - if ($iri) { - $propertyMetadata = ( - $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->withIri($iri) : $propertyMetadata->withTypes([$iri]) - ); - } - + $propertyMetadata = $propertyMetadata->withTypes($types); $propertyMetadata = $propertyMetadata->withRequired($required ?? false); if (!empty($restrictions)) { diff --git a/tests/Core/Api/IdentifiersExtractorTest.php b/tests/Core/Api/IdentifiersExtractorTest.php index d7698f44644..301be63ee93 100644 --- a/tests/Core/Api/IdentifiersExtractorTest.php +++ b/tests/Core/Api/IdentifiersExtractorTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IdentifiersExtractor; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; @@ -223,8 +223,8 @@ public function testGetsIdentifiersFromCorrectResourceClass(): void $propertyNameCollectionFactoryProphecy->create(ResourceInterface::class)->willReturn(new PropertyNameCollection(['foo', 'fooz'])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'foo')->willReturn((new ApiProperty())->withIdentifier(true)); - $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'fooz')->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'foo')->willReturn((new PropertyMetadata())->withIdentifier(true)); + $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'fooz')->willReturn(new PropertyMetadata()); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($item)->willReturn(ResourceInterface::class); @@ -247,7 +247,7 @@ public function testNoIdentifiers(): void $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['foo'])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo')->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo')->willReturn(new PropertyMetadata()); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); @@ -284,7 +284,7 @@ private function getMetadataFactoryProphecies($class, $identifiers, array $proph $propertyNameCollectionFactoryProphecy->create($class)->willReturn(new PropertyNameCollection($properties)); foreach ($properties as $prop) { - $metadata = new ApiProperty(); + $metadata = new PropertyMetadata(); $propertyMetadataFactoryProphecy->create($class, $prop)->willReturn($metadata->withIdentifier(\in_array($prop, $identifiers, true))); } @@ -300,7 +300,7 @@ public function testDefaultIdentifierId(): void $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['id'])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn(new PropertyMetadata()); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); diff --git a/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php b/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php index 23061ce3605..84aee338dd3 100644 --- a/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php +++ b/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php @@ -16,13 +16,13 @@ use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidIdentifierException; use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use Doctrine\DBAL\Connection; @@ -161,7 +161,7 @@ private function getMetadataFactories(string $resourceClass, array $identifiers) $nameCollection = ['foobar']; foreach ($identifiers as $identifier) { - $metadata = new ApiProperty(); + $metadata = new PropertyMetadata(); $metadata = $metadata->withIdentifier(true); $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); @@ -169,7 +169,7 @@ private function getMetadataFactories(string $resourceClass, array $identifiers) } //random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); diff --git a/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php index 59b844a8cff..1189c5e568c 100644 --- a/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php +++ b/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\Identifier\IdentifierConverterInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; @@ -26,7 +27,6 @@ use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Platforms\AbstractPlatform; @@ -256,7 +256,7 @@ private function getMetadataFactories(string $resourceClass, array $identifiers) $nameCollection = ['foobar']; foreach ($identifiers as $identifier) { - $metadata = new ApiProperty(); + $metadata = new PropertyMetadata(); $metadata = $metadata->withIdentifier(true); $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); @@ -264,7 +264,7 @@ private function getMetadataFactories(string $resourceClass, array $identifiers) } //random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); diff --git a/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php new file mode 100644 index 00000000000..cb9669e0737 --- /dev/null +++ b/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php @@ -0,0 +1,399 @@ + + * + * 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\Core\Tests\Bridge\Symfony\Validator\Metadata\Property; + +use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; +use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; +use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction; +use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\ValidatorPropertyMetadataFactory; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Tests\Fixtures\DummyAtLeastOneOfValidatedEntity; +use ApiPlatform\Core\Tests\Fixtures\DummyIriWithValidationEntity; +use ApiPlatform\Core\Tests\Fixtures\DummySequentiallyValidatedEntity; +use ApiPlatform\Core\Tests\Fixtures\DummyValidatedEntity; +use ApiPlatform\Core\Tests\ProphecyTrait; +use Doctrine\Common\Annotations\AnnotationReader; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Intl\Countries; +use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\Validator\Constraints\AtLeastOneOf; +use Symfony\Component\Validator\Constraints\Sequentially; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; + +/** + * @author Baptiste Meyer + */ +class ValidatorPropertyMetadataFactoryTest extends TestCase +{ + use ProphecyTrait; + + private $validatorClassMetadata; + + protected function setUp(): void + { + $this->validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($this->validatorClassMetadata); + } + + public function testCreateWithPropertyWithRequiredConstraints() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy', true, true, null, null, null, false); + $expectedPropertyMetadata = $propertyMetadata->withRequired(true); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy'); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithPropertyWithNotRequiredConstraints() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy date', true, true, null, null, null, false); + $expectedPropertyMetadata = $propertyMetadata->withRequired(false); + $expectedPropertyMetadata = $expectedPropertyMetadata->withIri('http://schema.org/Date'); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate', [])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate'); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithPropertyWithoutConstraints() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy id', true, true, null, null, null, true); + $expectedPropertyMetadata = $propertyMetadata->withRequired(false); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyId', [])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyId'); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithPropertyWithRightValidationGroupsAndRequiredConstraints() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); + $expectedPropertyMetadata = $propertyMetadata->withRequired(true); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['dummy']])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['dummy']]); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithPropertyWithBadValidationGroupsAndRequiredConstraints() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); + $expectedPropertyMetadata = $propertyMetadata->withRequired(false); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['ymmud']])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['ymmud']]); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithPropertyWithNonStringValidationGroupsAndRequiredConstraints() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); + $expectedPropertyMetadata = $propertyMetadata->withRequired(false); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]]); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithRequiredByDecorated() + { + $propertyMetadata = new PropertyMetadata(null, 'A dummy date', true, true, null, null, true, false, 'foo:bar'); + $expectedPropertyMetadata = clone $propertyMetadata; + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate', [])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate'); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + + public function testCreateWithPropertyWithValidationConstraints() + { + if (!class_exists(Countries::class)) { + $this->markTestSkipped('symfony/intl not installed'); + } + + $validatorClassMetadata = new ClassMetadata(DummyIriWithValidationEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); + + $types = [ + 'dummyUrl' => 'http://schema.org/url', + 'dummyEmail' => 'http://schema.org/email', + 'dummyUuid' => 'http://schema.org/identifier', + 'dummyCardScheme' => 'http://schema.org/identifier', + 'dummyBic' => 'http://schema.org/identifier', + 'dummyIban' => 'http://schema.org/identifier', + 'dummyDate' => 'http://schema.org/Date', + 'dummyDateTime' => 'http://schema.org/DateTime', + 'dummyTime' => 'http://schema.org/Time', + 'dummyImage' => 'http://schema.org/image', + 'dummyFile' => 'http://schema.org/MediaObject', + 'dummyCurrency' => 'http://schema.org/priceCurrency', + 'dummyIsbn' => 'http://schema.org/isbn', + 'dummyIssn' => 'http://schema.org/issn', + ]; + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + foreach ($types as $property => $iri) { + $decoratedPropertyMetadataFactory->create(DummyIriWithValidationEntity::class, $property, [])->willReturn(new PropertyMetadata())->shouldBeCalled(); + } + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyIriWithValidationEntity::class)->willReturn($validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + + foreach ($types as $property => $iri) { + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyIriWithValidationEntity::class, $property); + $this->assertSame($iri, $resultedPropertyMetadata->getIri()); + } + } + + public function testCreateWithPropertyLengthRestriction(): void + { + $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) + ->willReturn($validatorClassMetadata) + ->shouldBeCalled(); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $property = 'dummy'; + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, $property, [])->willReturn( + new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) + )->shouldBeCalled(); + + $lengthRestrictions = new PropertySchemaLengthRestriction(); + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), [$lengthRestrictions] + ); + + $schema = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema(); + $this->assertNotNull($schema); + $this->assertArrayHasKey('minLength', $schema); + $this->assertArrayHasKey('maxLength', $schema); + } + + public function testCreateWithPropertyRegexRestriction(): void + { + $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) + ->willReturn($validatorClassMetadata) + ->shouldBeCalled(); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn( + new PropertyMetadata() + )->shouldBeCalled(); + + $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), + [new PropertySchemaRegexRestriction()] + ); + + $schema = $validationPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy')->getSchema(); + $this->assertNotNull($schema); + $this->assertArrayHasKey('pattern', $schema); + $this->assertEquals('^(dummy)$', $schema['pattern']); + } + + public function testCreateWithPropertyFormatRestriction(): void + { + $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) + ->willReturn($validatorClassMetadata) + ->shouldBeCalled(); + $formats = [ + 'dummyEmail' => 'email', + 'dummyUuid' => 'uuid', + 'dummyIpv4' => 'ipv4', + 'dummyIpv6' => 'ipv6', + ]; + + foreach ($formats as $property => $format) { + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, $property, [])->willReturn( + new PropertyMetadata() + )->shouldBeCalled(); + $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [new PropertySchemaFormat()] + ); + $schema = $validationPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema(); + $this->assertNotNull($schema); + $this->assertArrayHasKey('format', $schema); + $this->assertEquals($format, $schema['format']); + } + } + + public function testCreateWithSequentiallyConstraint(): void + { + if (!class_exists(Sequentially::class)) { + $this->markTestSkipped(); + } + + $validatorClassMetadata = new ClassMetadata(DummySequentiallyValidatedEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummySequentiallyValidatedEntity::class) + ->willReturn($validatorClassMetadata) + ->shouldBeCalled(); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummySequentiallyValidatedEntity::class, 'dummy', [])->willReturn( + new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) + )->shouldBeCalled(); + $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()] + ); + $schema = $validationPropertyMetadataFactory->create(DummySequentiallyValidatedEntity::class, 'dummy')->getSchema(); + + $this->assertNotNull($schema); + $this->assertArrayHasKey('minLength', $schema); + $this->assertArrayHasKey('maxLength', $schema); + $this->assertArrayHasKey('pattern', $schema); + } + + public function testCreateWithAtLeastOneOfConstraint(): void + { + if (!class_exists(AtLeastOneOf::class)) { + $this->markTestSkipped(); + } + + $validatorClassMetadata = new ClassMetadata(DummyAtLeastOneOfValidatedEntity::class); + (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyAtLeastOneOfValidatedEntity::class) + ->willReturn($validatorClassMetadata) + ->shouldBeCalled(); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyAtLeastOneOfValidatedEntity::class, 'dummy', [])->willReturn( + new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) + )->shouldBeCalled(); + $restrictionsMetadata = [new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()]; + $restrictionsMetadata = [new PropertySchemaOneOfRestriction($restrictionsMetadata), new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()]; + $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + $restrictionsMetadata + ); + $schema = $validationPropertyMetadataFactory->create(DummyAtLeastOneOfValidatedEntity::class, 'dummy')->getSchema(); + + $this->assertNotNull($schema); + $this->assertArrayHasKey('oneOf', $schema); + $this->assertSame([ + ['pattern' => '^(.*#.*)$'], + ['minLength' => 10], + ], $schema['oneOf']); + } +} + diff --git a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php index e96239a9908..6f0d70c7fd8 100644 --- a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; From e8e3f29b1bbdff533cdfb8effd4e3a002170c052 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 11 Jan 2022 16:47:37 +0100 Subject: [PATCH 6/7] temp temp temp --- .../Property/Factory/InheritedPropertyMetadataFactory.php | 6 +++--- .../Bundle/DependencyInjection/ApiPlatformExtension.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php index 699930cedb8..577abbc45d6 100644 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php +++ b/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Metadata\Property\Factory; -use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; /** @@ -35,11 +35,11 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName /** * {@inheritdoc} */ - public function create(string $resourceClass, string $property, array $options = []) + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata { @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - $propertyMetadata = $this->decorated ? $this->decorated->create($resourceClass, $property, $options) : new ApiProperty(); + $propertyMetadata = $this->decorated ? $this->decorated->create($resourceClass, $property, $options) : new PropertyMetadata(); foreach ($this->resourceNameCollectionFactory->create() as $knownResourceClass) { if ($resourceClass === $knownResourceClass) { diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 25b59a571ef..2cd1fb7870e 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -874,9 +874,10 @@ private function registerLegacyServices(ContainerBuilder $container, array $conf ]; foreach ($remapDefinitionClasses as $id => $class) { - $container->getDefinition($id)->setClass($class); + $container->getDefinition($id)->setClass($class)->setDecoratedService('api_platform.metadata.property.metadata_factory.legacy'); } + $container->removeAlias('api_platform.property.metadata_factory'); $container->setAlias('api_platform.metadata.property.metadata_factory', 'api_platform.metadata.property.metadata_factory.legacy'); } From bf513d5021a25ee7c1de83966922948a14f16425 Mon Sep 17 00:00:00 2001 From: Julien LARY <47776596+laryjulien@users.noreply.github.com> Date: Tue, 11 Jan 2022 17:33:31 +0100 Subject: [PATCH 7/7] wip --- .../PropertyInfoPropertyMetadataFactory.php | 89 +++++++++++++++++++ .../PropertyInfoPropertyMetadataFactory.php | 3 +- .../ApiPlatformExtension.php | 4 +- .../config/metadata/resource_collection.xml | 2 +- src/deprecation.php | 6 +- 5 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 src/Core/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php diff --git a/src/Core/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php new file mode 100644 index 00000000000..e6fabf0134a --- /dev/null +++ b/src/Core/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php @@ -0,0 +1,89 @@ + + * + * 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\Core\Metadata\Property\Factory; + +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Exception\PropertyNotFoundException; +use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; + +/** + * PropertyInfo metadata loader decorator. + * + * @author Kévin Dunglas + */ +final class PropertyInfoPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + private $propertyInfo; + private $decorated; + + public function __construct(PropertyInfoExtractorInterface $propertyInfo, PropertyMetadataFactoryInterface $decorated = null) + { + $this->propertyInfo = $propertyInfo; + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata + { + if (null === $this->decorated) { + $propertyMetadata = new PropertyMetadata(); + } else { + try { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + } catch (PropertyNotFoundException $propertyNotFoundException) { + $propertyMetadata = new PropertyMetadata(); + } + } + + if ($propertyMetadata instanceof PropertyMetadata) { + if (!$propertyMetadata->getBuiltinTypes()) { + $propertyMetadata = $propertyMetadata->withBuiltinTypes($this->propertyInfo->getTypes($resourceClass, $property, $options) ?? []); + } + } elseif (null === $propertyMetadata->getType()) { + $propertyMetadata = $propertyMetadata->withType($this->propertyInfo->getTypes($resourceClass, $property, $options)[0] ?? null); + } + + if (null === $propertyMetadata->getDescription() && null !== $description = $this->propertyInfo->getShortDescription($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withDescription($description); + } + + if (null === $propertyMetadata->isReadable() && null !== $readable = $this->propertyInfo->isReadable($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withReadable($readable); + } + + if (null === $propertyMetadata->isWritable() && null !== $writable = $this->propertyInfo->isWritable($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withWritable($writable); + } + + if (method_exists($this->propertyInfo, 'isInitializable')) { + if (null === $propertyMetadata->isInitializable() && null !== $initializable = $this->propertyInfo->isInitializable($resourceClass, $property, $options)) { + $propertyMetadata = $propertyMetadata->withInitializable($initializable); + } + } else { + // BC layer for Symfony < 4.2 + $ref = new \ReflectionClass($resourceClass); + if ($ref->isInstantiable() && $constructor = $ref->getConstructor()) { + foreach ($constructor->getParameters() as $constructorParameter) { + if ($constructorParameter->name === $property && null === $propertyMetadata->isInitializable()) { + $propertyMetadata = $propertyMetadata->withInitializable(true); + } + } + } + } + + return $propertyMetadata; + } +} diff --git a/src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php b/src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php index ae0fcd957ae..970cb0bc5e9 100644 --- a/src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/PropertyInfoPropertyMetadataFactory.php @@ -11,9 +11,8 @@ declare(strict_types=1); -namespace ApiPlatform\Metadata\Property; +namespace ApiPlatform\Metadata\Property\Factory; -use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 2cd1fb7870e..b03cdf80446 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -870,13 +870,15 @@ private function registerLegacyServices(ContainerBuilder $container, array $conf 'api_platform.metadata.property.metadata_factory.xml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory', 'api_platform.metadata.property.metadata_factory.yaml' => 'ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory', 'api_platform.metadata.property.metadata_factory.property_info' => 'ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory', - 'api_platform.doctrine.orm.metadata.property.metadata_factory' => 'ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory' + 'api_platform.doctrine.orm.metadata.property.metadata_factory' => 'ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory', ]; foreach ($remapDefinitionClasses as $id => $class) { $container->getDefinition($id)->setClass($class)->setDecoratedService('api_platform.metadata.property.metadata_factory.legacy'); } + $container->getDefinition('api_platform.metadata.property.metadata_factory.annotation')->setDecoratedService('api_platform.metadata.property.metadata_factory.legacy'); + $container->removeAlias('api_platform.property.metadata_factory'); $container->setAlias('api_platform.metadata.property.metadata_factory', 'api_platform.metadata.property.metadata_factory.legacy'); } diff --git a/src/Symfony/Bundle/Resources/config/metadata/resource_collection.xml b/src/Symfony/Bundle/Resources/config/metadata/resource_collection.xml index ea3cbfe7956..c4b310a9e14 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/resource_collection.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/resource_collection.xml @@ -94,7 +94,7 @@ - + diff --git a/src/deprecation.php b/src/deprecation.php index a3f5fa2d6ce..911be8d5c25 100644 --- a/src/deprecation.php +++ b/src/deprecation.php @@ -247,9 +247,9 @@ ApiPlatform\Core\Bridge\Symfony\Messenger\DataTransformer::class => ApiPlatform\Symfony\Messenger\DataTransformer::class, ApiPlatform\Core\Bridge\Symfony\Messenger\RemoveStamp::class => ApiPlatform\Symfony\Messenger\RemoveStamp::class, - // Bridge\Symfony\PropertyInfo\Metadata\Property => Metadata\Property - ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\PropertyInfoPropertyMetadataFactory::class, - ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class, + // Bridge\Symfony\PropertyInfo\Metadata\Property => Metadata\Property\Factory + ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory::class, + ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory::class, // Bridge\Symfony\Routing ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::class => ApiPlatform\Symfony\Routing\ApiLoader::class,