diff --git a/src/Annotation/ApiResource.php b/src/Annotation/ApiResource.php index b7102812d7b..a73c978ed57 100644 --- a/src/Annotation/ApiResource.php +++ b/src/Annotation/ApiResource.php @@ -63,6 +63,7 @@ * @Attribute("securityMessage", type="string"), * @Attribute("securityPostDenormalize", type="string"), * @Attribute("securityPostDenormalizeMessage", type="string"), + * @Attribute("path", type="string"), * @Attribute("shortName", type="string"), * @Attribute("stateless", type="bool"), * @Attribute("subresourceOperations", type="array"), @@ -159,6 +160,11 @@ final class ApiResource */ public $itemOperations; + /** + * @var string + */ + public $path; + /** * @var string */ diff --git a/src/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php b/src/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php index d7cf855da08..77d744fa04b 100644 --- a/src/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php +++ b/src/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php @@ -39,12 +39,14 @@ public function create(string $resourceClass): ResourceMetadata { $resourceMetadata = $this->decorated->create($resourceClass); - if (null === $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations(['get' => ['method' => 'GET']]); - } - - if (null === $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations(['get' => ['method' => 'GET']]); + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + if (null === $operationCollectionMetadata->getCollectionOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withCollectionOperations(['get' => ['method' => 'GET']]); + } + + if (null === $operationCollectionMetadata->getItemOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withItemOperations(['get' => ['method' => 'GET']]); + } } return $resourceMetadata; diff --git a/src/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php b/src/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php index c095cccb7c3..e07c942141c 100644 --- a/src/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php +++ b/src/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php @@ -20,7 +20,7 @@ use ApiPlatform\Core\Documentation\Documentation; 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\OperationCollectionMetadata; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; use Psr\Container\ContainerInterface; @@ -81,23 +81,23 @@ public function getAnnotations(): array $annotations = []; foreach ($resourceNameCollection as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $prefixedShortName = ($iri = $resourceMetadata->getIri()) ? $iri : '#'.$resourceMetadata->getShortName(); - $resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName); - if (null === $resourceHydraDoc) { - continue; - } + foreach ($this->resourceMetadataFactory->create($resourceClass) as $resourceMetadata) { + $prefixedShortName = ($iri = $resourceMetadata->getIri()) ? $iri : '#'.$resourceMetadata->getShortName(); + $resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName); + if (null === $resourceHydraDoc) { + continue; + } - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - foreach ($collectionOperations as $operationName => $operation) { - $annotations[] = $this->getApiDoc(true, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc, $entrypointHydraDoc); + if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { + foreach ($collectionOperations as $operationName => $operation) { + $annotations[] = $this->getApiDoc(true, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc, $entrypointHydraDoc); + } } - } - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - foreach ($itemOperations as $operationName => $operation) { - $annotations[] = $this->getApiDoc(false, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc); + if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { + foreach ($itemOperations as $operationName => $operation) { + $annotations[] = $this->getApiDoc(false, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc); + } } } } @@ -108,7 +108,7 @@ public function getAnnotations(): array /** * Builds ApiDoc annotation from ApiPlatform data. */ - private function getApiDoc(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, string $operationName, array $resourceHydraDoc, array $entrypointHydraDoc = []): ApiDoc + private function getApiDoc(bool $collection, string $resourceClass, OperationCollectionMetadata $resourceMetadata, string $operationName, array $resourceHydraDoc, array $entrypointHydraDoc = []): ApiDoc { if ($collection) { $method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); diff --git a/src/Bridge/Symfony/Routing/ApiLoader.php b/src/Bridge/Symfony/Routing/ApiLoader.php index 17b886ac4c0..aa3c1297f22 100644 --- a/src/Bridge/Symfony/Routing/ApiLoader.php +++ b/src/Bridge/Symfony/Routing/ApiLoader.php @@ -19,7 +19,7 @@ use ApiPlatform\Core\Exception\RuntimeException; 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\OperationCollectionMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\PathResolver\OperationPathResolverInterface; use Symfony\Component\Config\FileLocator; @@ -92,63 +92,64 @@ public function load($data, $type = null): RouteCollection $this->loadExternalFiles($routeCollection); foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceMetadata = $resourceMetadata->withAttributes(($resourceMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]); - $resourceShortName = $resourceMetadata->getShortName(); + foreach ($this->resourceMetadataFactory->create($resourceClass) as $operationCollectionMetadata) { + $operationCollectionMetadata = $operationCollectionMetadata->withAttributes(($operationCollectionMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]); + $resourceShortName = $operationCollectionMetadata->getShortName(); - if (null === $resourceShortName) { - throw new InvalidResourceException(sprintf('Resource %s has no short name defined.', $resourceClass)); - } + if (null === $resourceShortName) { + throw new InvalidResourceException(sprintf('Resource %s has no short name defined.', $resourceClass)); + } - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - foreach ($collectionOperations as $operationName => $operation) { - $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::COLLECTION); + if (null !== $collectionOperations = $operationCollectionMetadata->getCollectionOperations()) { + foreach ($collectionOperations as $operationName => $operation) { + $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $operationCollectionMetadata, OperationType::COLLECTION); + } } - } - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - foreach ($itemOperations as $operationName => $operation) { - $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::ITEM); + if (null !== $itemOperations = $operationCollectionMetadata->getItemOperations()) { + foreach ($itemOperations as $operationName => $operation) { + $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $operationCollectionMetadata, OperationType::ITEM); + } } - } - if (null === $this->subresourceOperationFactory) { - continue; - } + if (null === $this->subresourceOperationFactory) { + continue; + } - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { - if (null === $controller = $operation['controller'] ?? null) { - $controller = self::DEFAULT_ACTION_PATTERN.'get_subresource'; + foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { + if (null === $controller = $operation['controller'] ?? null) { + $controller = self::DEFAULT_ACTION_PATTERN.'get_subresource'; - if (!$this->container->has($controller)) { - throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', OperationType::SUBRESOURCE, 'GET')); + if (!$this->container->has($controller)) { + throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', OperationType::SUBRESOURCE, 'GET')); + } } - } - $routeCollection->add($operation['route_name'], new Route( - $operation['path'], - [ - '_controller' => $controller, - '_format' => null, - '_stateless' => $operation['stateless'] ?? $resourceMetadata->getAttribute('stateless'), - '_api_resource_class' => $operation['resource_class'], - '_api_identified_by' => $operation['identified_by'], - '_api_has_composite_identifier' => false, - '_api_subresource_operation_name' => $operation['route_name'], - '_api_subresource_context' => [ - 'property' => $operation['property'], - 'identifiers' => $operation['identifiers'], - 'collection' => $operation['collection'], - 'operationId' => $operationId, - ], - ] + ($operation['defaults'] ?? []), - $operation['requirements'] ?? [], - $operation['options'] ?? [], - $operation['host'] ?? '', - $operation['schemes'] ?? [], - ['GET'], - $operation['condition'] ?? '' - )); + $routeCollection->add($operation['route_name'], new Route( + $operation['path'], + [ + '_controller' => $controller, + '_format' => null, + '_stateless' => $operation['stateless'] ?? $operationCollectionMetadata->getAttribute('stateless'), + '_api_resource_class' => $operation['resource_class'], + '_api_identified_by' => $operation['identified_by'], + '_api_has_composite_identifier' => false, + '_api_subresource_operation_name' => $operation['route_name'], + '_api_subresource_context' => [ + 'property' => $operation['property'], + 'identifiers' => $operation['identifiers'], + 'collection' => $operation['collection'], + 'operationId' => $operationId, + ], + ] + ($operation['defaults'] ?? []), + $operation['requirements'] ?? [], + $operation['options'] ?? [], + $operation['host'] ?? '', + $operation['schemes'] ?? [], + ['GET'], + $operation['condition'] ?? '' + )); + } } } @@ -204,9 +205,9 @@ private function loadExternalFiles(RouteCollection $routeCollection): void * * @throws RuntimeException */ - private function addRoute(RouteCollection $routeCollection, string $resourceClass, string $operationName, array $operation, ResourceMetadata $resourceMetadata, string $operationType): void + private function addRoute(RouteCollection $routeCollection, string $resourceClass, string $operationName, array $operation, OperationCollectionMetadata $operationCollectionMetadata, string $operationType): void { - $resourceShortName = $resourceMetadata->getShortName(); + $resourceShortName = $operationCollectionMetadata->getShortName(); if (isset($operation['route_name'])) { if (!isset($operation['method'])) { @@ -228,10 +229,10 @@ private function addRoute(RouteCollection $routeCollection, string $resourceClas } } - $operation['identified_by'] = (array) ($operation['identified_by'] ?? $resourceMetadata->getAttribute('identified_by')); - $operation['has_composite_identifier'] = \count($operation['identified_by']) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false; + $operation['identified_by'] = (array) ($operation['identified_by'] ?? $operationCollectionMetadata->getAttribute('identified_by')); + $operation['has_composite_identifier'] = \count($operation['identified_by']) > 1 ? $operationCollectionMetadata->getAttribute('composite_identifier', true) : false; - $path = trim(trim($resourceMetadata->getAttribute('route_prefix', '')), '/'); + $path = trim(trim($operationCollectionMetadata->getAttribute('route_prefix', '')), '/'); $path .= $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); $route = new Route( diff --git a/src/Metadata/Extractor/XmlExtractor.php b/src/Metadata/Extractor/XmlExtractor.php index 3de449b43c4..9bae2e33ccb 100644 --- a/src/Metadata/Extractor/XmlExtractor.php +++ b/src/Metadata/Extractor/XmlExtractor.php @@ -42,7 +42,8 @@ protected function extractPath(string $path) foreach ($xml->resource as $resource) { $resourceClass = $this->resolve((string) $resource['class']); - $this->resources[$resourceClass] = [ + $this->resources[$resourceClass][] = [ + 'path' => $this->phpize($resource, 'path', 'string'), 'shortName' => $this->phpize($resource, 'shortName', 'string'), 'description' => $this->phpize($resource, 'description', 'string'), 'iri' => $this->phpize($resource, 'iri', 'string'), diff --git a/src/Metadata/Extractor/YamlExtractor.php b/src/Metadata/Extractor/YamlExtractor.php index c3cefd33234..618d5d960bd 100644 --- a/src/Metadata/Extractor/YamlExtractor.php +++ b/src/Metadata/Extractor/YamlExtractor.php @@ -53,6 +53,12 @@ protected function extractPath(string $path) private function extractResources(array $resourcesYaml, string $path): void { foreach ($resourcesYaml as $resourceName => $resourceYaml) { + if (is_numeric($resourceName)) { + // Multi ApiResource declared + $resourceName = array_key_first($resourceYaml); + $resourceYaml = $resourceYaml[$resourceName]; + } + $resourceName = $this->resolve($resourceName); if (null === $resourceYaml) { @@ -63,7 +69,8 @@ private function extractResources(array $resourcesYaml, string $path): void throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $resourceName, \gettype($resourceYaml), $path)); } - $this->resources[$resourceName] = [ + $resource = [ + 'path' => $this->phpize($resourceYaml, 'path', 'string'), 'shortName' => $this->phpize($resourceYaml, 'shortName', 'string'), 'description' => $this->phpize($resourceYaml, 'description', 'string'), 'iri' => $this->phpize($resourceYaml, 'iri', 'string'), @@ -75,7 +82,8 @@ private function extractResources(array $resourcesYaml, string $path): void ]; if (!isset($resourceYaml['properties'])) { - $this->resources[$resourceName]['properties'] = null; + $resource['properties'] = null; + $this->resources[$resourceName][] = $resource; continue; } @@ -84,15 +92,17 @@ private function extractResources(array $resourcesYaml, string $path): void throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path)); } - $this->extractProperties($resourceYaml, $resourceName, $path); + $this->extractProperties($resourceYaml, $resource, $path); + + $this->resources[$resourceName][] = $resource; } } - private function extractProperties(array $resourceYaml, string $resourceName, string $path): void + private function extractProperties(array $resourceYaml, array $resource, string $path): void { foreach ($resourceYaml['properties'] as $propertyName => $propertyValues) { if (null === $propertyValues) { - $this->resources[$resourceName]['properties'][$propertyName] = null; + $resource['properties'][$propertyName] = null; continue; } @@ -104,7 +114,7 @@ private function extractProperties(array $resourceYaml, string $resourceName, st $propertyValues['subresource']['resourceClass'] = $this->resolve($propertyValues['subresource']['resourceClass']); } - $this->resources[$resourceName]['properties'][$propertyName] = [ + $resource['properties'][$propertyName] = [ 'description' => $this->phpize($propertyValues, 'description', 'string'), 'readable' => $this->phpize($propertyValues, 'readable', 'bool'), 'writable' => $this->phpize($propertyValues, 'writable', 'bool'), diff --git a/src/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php b/src/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php index 3fe7dcf95bb..ec25aa1b8d2 100644 --- a/src/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php +++ b/src/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php @@ -42,44 +42,48 @@ public function __construct(Reader $reader, ResourceMetadataFactoryInterface $de */ public function create(string $resourceClass): ResourceMetadata { - $parentResourceMetadata = null; + $resourceMetadata = null; if ($this->decorated) { try { - $parentResourceMetadata = $this->decorated->create($resourceClass); + $resourceMetadata = $this->decorated->create($resourceClass); } catch (ResourceClassNotFoundException $resourceNotFoundException) { // Ignore not found exception from decorated factories } } - if (null === $parentResourceMetadata) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); + if (null === $resourceMetadata) { + return $this->handleNotFound($resourceMetadata, $resourceClass); } try { $reflectionClass = new \ReflectionClass($resourceClass); } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); + return $this->handleNotFound($resourceMetadata, $resourceClass); } $filters = array_keys($this->readFilterAnnotations($reflectionClass, $this->reader)); if (!$filters) { - return $parentResourceMetadata; + return $resourceMetadata; } - $parentFilters = $parentResourceMetadata->getAttribute('filters', []); + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + $parentFilters = $operationCollectionMetadata->getAttribute('filters', []); - if ($parentFilters) { - $filters = array_merge($parentFilters, $filters); - } + if ($parentFilters) { + $filters = array_merge($parentFilters, $filters); + } - $attributes = $parentResourceMetadata->getAttributes(); + $attributes = $operationCollectionMetadata->getAttributes(); + + if (!$attributes) { + $attributes = []; + } - if (!$attributes) { - $attributes = []; + $resourceMetadata[$path] = $operationCollectionMetadata->withAttributes(array_merge($attributes, ['filters' => $filters])); } - return $parentResourceMetadata->withAttributes(array_merge($attributes, ['filters' => $filters])); + return $resourceMetadata; } /** diff --git a/src/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php b/src/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php index e55a024519d..c8f3ad8086b 100644 --- a/src/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Exception\ResourceClassNotFoundException; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use Doctrine\Common\Annotations\Reader; @@ -41,10 +42,10 @@ public function __construct(Reader $reader, ResourceMetadataFactoryInterface $de */ public function create(string $resourceClass): ResourceMetadata { - $parentResourceMetadata = null; + $resourceMetadata = null; if ($this->decorated) { try { - $parentResourceMetadata = $this->decorated->create($resourceClass); + $resourceMetadata = $this->decorated->create($resourceClass); } catch (ResourceClassNotFoundException $resourceNotFoundException) { // Ignore not found exception from decorated factories } @@ -53,15 +54,28 @@ public function create(string $resourceClass): ResourceMetadata try { $reflectionClass = new \ReflectionClass($resourceClass); } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); + return $this->handleNotFound($resourceMetadata, $resourceClass); } - $resourceAnnotation = $this->reader->getClassAnnotation($reflectionClass, ApiResource::class); - if (!$resourceAnnotation instanceof ApiResource) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); + if (!$resourceMetadata) { + $resourceMetadata = new ResourceMetadata([]); } - return $this->createMetadata($resourceAnnotation, $parentResourceMetadata); + foreach ($this->reader->getClassAnnotations($reflectionClass) as $resourceAnnotation) { + if ($resourceAnnotation instanceof ApiResource) { + $resourceMetadata[$resourceAnnotation->path] = $this->createMetadata( + $resourceAnnotation, + $resourceMetadata[$resourceAnnotation->path] ?? null + ); + } + } + + // todo Does empty work with ArrayAccess and IteratorAggregate? + if (empty($resourceMetadata)) { + return $this->handleNotFound($resourceMetadata, $resourceClass); + } + + return $resourceMetadata; } /** @@ -78,12 +92,13 @@ private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, strin throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); } - private function createMetadata(ApiResource $annotation, ResourceMetadata $parentResourceMetadata = null): ResourceMetadata + private function createMetadata(ApiResource $annotation, OperationCollectionMetadata $operationCollectionMetadata = null): OperationCollectionMetadata { $attributes = (null === $annotation->attributes && [] === $this->defaults['attributes']) ? null : (array) $annotation->attributes + $this->defaults['attributes']; - if (!$parentResourceMetadata) { - return new ResourceMetadata( + if (!$operationCollectionMetadata) { + return new OperationCollectionMetadata( + $annotation->path, $annotation->shortName, $annotation->description ?? $this->defaults['description'] ?? null, $annotation->iri ?? $this->defaults['iri'] ?? null, @@ -95,18 +110,17 @@ private function createMetadata(ApiResource $annotation, ResourceMetadata $paren ); } - $resourceMetadata = $parentResourceMetadata; - foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - $resourceMetadata = $this->createWith($resourceMetadata, $property, $annotation->{$property}); + foreach (['path', 'shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { + $operationCollectionMetadata = $this->createWith($operationCollectionMetadata, $property, $annotation->{$property}); } - return $resourceMetadata; + return $operationCollectionMetadata; } /** * Creates a new instance of metadata if the property is not already set. */ - private function createWith(ResourceMetadata $resourceMetadata, string $property, $value): ResourceMetadata + private function createWith(OperationCollectionMetadata $resourceMetadata, string $property, $value): OperationCollectionMetadata { $upperProperty = ucfirst($property); $getter = "get$upperProperty"; diff --git a/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php b/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php index fee663cf97c..5b8b7fef30f 100644 --- a/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Exception\ResourceClassNotFoundException; use ApiPlatform\Core\Metadata\Extractor\ExtractorInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; /** @@ -61,7 +62,7 @@ public function create(string $resourceClass): ResourceMetadata $resource['graphql'] = $resource['graphql'] ?? $this->defaults['graphql'] ?? null; $resource['attributes'] = (null === $resource['attributes'] && [] === $this->defaults['attributes']) ? null : (array) $resource['attributes'] + $this->defaults['attributes']; - return $this->update($parentResourceMetadata ?: new ResourceMetadata(), $resource); + return $this->update($parentResourceMetadata ?: new ResourceMetadata([]), $resource); } /** @@ -83,12 +84,13 @@ private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, strin */ private function update(ResourceMetadata $resourceMetadata, array $metadata): ResourceMetadata { - foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - if (null === $metadata[$property] || null !== $resourceMetadata->{'get'.ucfirst($property)}()) { + $operationCollectionMetadata = $resourceMetadata[$metadata['path']] ?: new OperationCollectionMetadata(); + foreach (['path', 'shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { + if (null === $metadata[$property] || null !== $operationCollectionMetadata->{'get'.ucfirst($property)}()) { continue; } - $resourceMetadata = $resourceMetadata->{'with'.ucfirst($property)}($metadata[$property]); + $resourceMetadata[$metadata['path']] = $operationCollectionMetadata->{'with'.ucfirst($property)}($metadata[$property]); } return $resourceMetadata; diff --git a/src/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php b/src/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php index 24cca24c2b3..ba7e63e3671 100644 --- a/src/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php @@ -51,25 +51,28 @@ public function __construct(ResourceMetadataFactoryInterface $decorated, array $ public function create(string $resourceClass): ResourceMetadata { $resourceMetadata = $this->decorated->create($resourceClass); - $rawResourceFormats = $resourceMetadata->getAttribute('formats'); - $resourceFormats = null === $rawResourceFormats ? $this->formats : $this->normalizeFormats($rawResourceFormats); - $rawResourceInputFormats = $resourceMetadata->getAttribute('input_formats'); - $rawResourceOutputFormats = $resourceMetadata->getAttribute('output_formats'); + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + $rawResourceFormats = $operationCollectionMetadata->getAttribute('formats'); + $resourceFormats = null === $rawResourceFormats ? $this->formats : $this->normalizeFormats($rawResourceFormats); - $resourceInputFormats = $rawResourceInputFormats ? $this->normalizeFormats($rawResourceInputFormats) : $resourceFormats; - $resourceOutputFormats = $rawResourceOutputFormats ? $this->normalizeFormats($rawResourceOutputFormats) : $resourceFormats; + $rawResourceInputFormats = $operationCollectionMetadata->getAttribute('input_formats'); + $rawResourceOutputFormats = $operationCollectionMetadata->getAttribute('output_formats'); - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $collectionOperations)); - } + $resourceInputFormats = $rawResourceInputFormats ? $this->normalizeFormats($rawResourceInputFormats) : $resourceFormats; + $resourceOutputFormats = $rawResourceOutputFormats ? $this->normalizeFormats($rawResourceOutputFormats) : $resourceFormats; - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $itemOperations)); - } + if (null !== $collectionOperations = $operationCollectionMetadata->getCollectionOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withCollectionOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $collectionOperations)); + } - if (null !== $subresourceOperations = $resourceMetadata->getSubresourceOperations()) { - $resourceMetadata = $resourceMetadata->withSubresourceOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $subresourceOperations)); + if (null !== $itemOperations = $operationCollectionMetadata->getItemOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withItemOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $itemOperations)); + } + + if (null !== $subresourceOperations = $operationCollectionMetadata->getSubresourceOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withSubresourceOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $subresourceOperations)); + } } return $resourceMetadata; diff --git a/src/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php b/src/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php index 24e7b997d72..82fbc0ba9ac 100644 --- a/src/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php @@ -36,23 +36,27 @@ public function create(string $resourceClass): ResourceMetadata { $resourceMetadata = $this->decorated->create($resourceClass); - $attributes = $resourceMetadata->getAttributes() ?: []; - $attributes['input'] = isset($attributes['input']) ? $this->transformInputOutput($attributes['input']) : null; - $attributes['output'] = isset($attributes['output']) ? $this->transformInputOutput($attributes['output']) : null; + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + $attributes = $operationCollectionMetadata->getAttributes() ?: []; + $attributes['input'] = isset($attributes['input']) ? $this->transformInputOutput($attributes['input']) : null; + $attributes['output'] = isset($attributes['output']) ? $this->transformInputOutput($attributes['output']) : null; - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->getTransformedOperations($collectionOperations, $attributes)); - } + if (null !== $collectionOperations = $operationCollectionMetadata->getCollectionOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withCollectionOperations($this->getTransformedOperations($collectionOperations, $attributes)); + } - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations($this->getTransformedOperations($itemOperations, $attributes)); - } + if (null !== $itemOperations = $operationCollectionMetadata->getItemOperations()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withItemOperations($this->getTransformedOperations($itemOperations, $attributes)); + } + + if (null !== $graphQlAttributes = $operationCollectionMetadata->getGraphql()) { + $resourceMetadata[$path] = $operationCollectionMetadata->withGraphql($this->getTransformedOperations($graphQlAttributes, $attributes)); + } - if (null !== $graphQlAttributes = $resourceMetadata->getGraphql()) { - $resourceMetadata = $resourceMetadata->withGraphql($this->getTransformedOperations($graphQlAttributes, $attributes)); + $resourceMetadata[$path] = $operationCollectionMetadata->withAttributes($attributes); } - return $resourceMetadata->withAttributes($attributes); + return $resourceMetadata; } private function getTransformedOperations(array $operations, array $resourceAttributes): array diff --git a/src/Metadata/Resource/Factory/OperationResourceMetadataFactory.php b/src/Metadata/Resource/Factory/OperationResourceMetadataFactory.php index 931f99ef311..27d2271b938 100644 --- a/src/Metadata/Resource/Factory/OperationResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/OperationResourceMetadataFactory.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Metadata\Resource\Factory; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; /** @@ -57,51 +58,53 @@ public function create(string $resourceClass): ResourceMetadata $resourceMetadata = $this->decorated->create($resourceClass); $isAbstract = (new \ReflectionClass($resourceClass))->isAbstract(); - $collectionOperations = $resourceMetadata->getCollectionOperations(); - if (null === $collectionOperations) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->createOperations($isAbstract ? ['GET'] : ['GET', 'POST'], $resourceMetadata)); - } else { - $resourceMetadata = $this->normalize(true, $resourceClass, $resourceMetadata, $collectionOperations); - } + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + $collectionOperations = $operationCollectionMetadata->getCollectionOperations(); + if (null === $collectionOperations) { + $resourceMetadata[$path] = $operationCollectionMetadata->withCollectionOperations($this->createOperations($isAbstract ? ['GET'] : ['GET', 'POST'], $operationCollectionMetadata)); + } else { + $resourceMetadata[$path] = $this->normalize(true, $resourceClass, $operationCollectionMetadata, $collectionOperations); + } - $itemOperations = $resourceMetadata->getItemOperations(); - if (null === $itemOperations) { - $methods = ['GET', 'DELETE']; + $itemOperations = $operationCollectionMetadata->getItemOperations(); + if (null === $itemOperations) { + $methods = ['GET', 'DELETE']; - if (!$isAbstract) { - $methods[] = 'PUT'; + if (!$isAbstract) { + $methods[] = 'PUT'; - if ($this->patchFormats) { - $methods[] = 'PATCH'; + if ($this->patchFormats) { + $methods[] = 'PATCH'; + } } - } - $resourceMetadata = $resourceMetadata->withItemOperations($this->createOperations($methods, $resourceMetadata)); - } else { - $resourceMetadata = $this->normalize(false, $resourceClass, $resourceMetadata, $itemOperations); - } + $resourceMetadata[$path] = $operationCollectionMetadata->withItemOperations($this->createOperations($methods, $operationCollectionMetadata)); + } else { + $resourceMetadata[$path] = $this->normalize(false, $resourceClass, $operationCollectionMetadata, $itemOperations); + } - $graphql = $resourceMetadata->getGraphql(); - if (null === $graphql) { - $resourceMetadata = $resourceMetadata->withGraphql(['item_query' => [], 'collection_query' => [], 'delete' => [], 'update' => [], 'create' => []]); - } else { - $resourceMetadata = $this->normalizeGraphQl($resourceMetadata, $graphql); + $graphql = $operationCollectionMetadata->getGraphql(); + if (null === $graphql) { + $resourceMetadata[$path] = $operationCollectionMetadata->withGraphql(['item_query' => [], 'collection_query' => [], 'delete' => [], 'update' => [], 'create' => []]); + } else { + $resourceMetadata[$path] = $this->normalizeGraphQl($operationCollectionMetadata, $graphql); + } } return $resourceMetadata; } - private function createOperations(array $methods, ResourceMetadata $resourceMetadata): array + private function createOperations(array $methods, OperationCollectionMetadata $operationCollectionMetadata): array { $operations = []; foreach ($methods as $method) { - $operations[strtolower($method)] = ['method' => $method, 'stateless' => $resourceMetadata->getAttribute('stateless')]; + $operations[strtolower($method)] = ['method' => $method, 'stateless' => $operationCollectionMetadata->getAttribute('stateless')]; } return $operations; } - private function normalize(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata + private function normalize(bool $collection, string $resourceClass, OperationCollectionMetadata $operationCollectionMetadata, array $operations): OperationCollectionMetadata { $newOperations = []; foreach ($operations as $operationName => $operation) { @@ -131,15 +134,15 @@ private function normalize(bool $collection, string $resourceClass, ResourceMeta $operation['method'] = strtoupper($operation['method']); } - $operation['stateless'] = $operation['stateless'] ?? $resourceMetadata->getAttribute('stateless'); + $operation['stateless'] = $operation['stateless'] ?? $operationCollectionMetadata->getAttribute('stateless'); $newOperations[$operationName] = $operation; } - return $collection ? $resourceMetadata->withCollectionOperations($newOperations) : $resourceMetadata->withItemOperations($newOperations); + return $collection ? $operationCollectionMetadata->withCollectionOperations($newOperations) : $operationCollectionMetadata->withItemOperations($newOperations); } - private function normalizeGraphQl(ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata + private function normalizeGraphQl(OperationCollectionMetadata $operationCollectionMetadata, array $operations): OperationCollectionMetadata { foreach ($operations as $operationName => $operation) { if (\is_int($operationName) && \is_string($operation)) { @@ -148,6 +151,6 @@ private function normalizeGraphQl(ResourceMetadata $resourceMetadata, array $ope } } - return $resourceMetadata->withGraphql($operations); + return $operationCollectionMetadata->withGraphql($operations); } } diff --git a/src/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php b/src/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php index f2257d24efd..faf352e9397 100644 --- a/src/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php @@ -43,17 +43,19 @@ public function create(string $resourceClass): ResourceMetadata { $resourceMetadata = $this->decorated->create($resourceClass); - if (null !== $resourceMetadata->getDescription()) { - return $resourceMetadata; - } - - $reflectionClass = new \ReflectionClass($resourceClass); - - try { - $docBlock = $this->docBlockFactory->create($reflectionClass, $this->contextFactory->createFromReflector($reflectionClass)); - $resourceMetadata = $resourceMetadata->withDescription($docBlock->getSummary()); - } catch (\InvalidArgumentException $e) { - // Ignore empty DocBlocks + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + if (null !== $operationCollectionMetadata->getDescription()) { + continue; + } + + $reflectionClass = new \ReflectionClass($resourceClass); + + try { + $docBlock = $this->docBlockFactory->create($reflectionClass, $this->contextFactory->createFromReflector($reflectionClass)); + $resourceMetadata[$path] = $operationCollectionMetadata->withDescription($docBlock->getSummary()); + } catch (\InvalidArgumentException $e) { + // Ignore empty DocBlocks + } } return $resourceMetadata; diff --git a/src/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php b/src/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php index c7f9e898f63..834d00b50e3 100644 --- a/src/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php @@ -36,14 +36,20 @@ public function create(string $resourceClass): ResourceMetadata { $resourceMetadata = $this->decorated->create($resourceClass); - if (null !== $resourceMetadata->getShortName()) { - return $resourceMetadata; - } + foreach ($resourceMetadata as $path => $operationCollectionMetadata) { + if (null !== $operationCollectionMetadata->getShortName()) { + continue; + } + + if (false !== $pos = strrpos($resourceClass, '\\')) { + $resourceMetadata[$path] = $operationCollectionMetadata->withShortName(substr($resourceClass, $pos + 1)); + + continue; + } - if (false !== $pos = strrpos($resourceClass, '\\')) { - return $resourceMetadata->withShortName(substr($resourceClass, $pos + 1)); + $resourceMetadata[$path] = $operationCollectionMetadata->withShortName($resourceClass); } - return $resourceMetadata->withShortName($resourceClass); + return $resourceMetadata; } } diff --git a/src/Metadata/Resource/OperationCollectionMetadata.php b/src/Metadata/Resource/OperationCollectionMetadata.php new file mode 100644 index 00000000000..76d23810958 --- /dev/null +++ b/src/Metadata/Resource/OperationCollectionMetadata.php @@ -0,0 +1,375 @@ + + * + * 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\Resource; + +use ApiPlatform\Core\Api\OperationType; + +/** + * Operation collection metadata. + * + * @author Kévin Dunglas + * @author Vincent Chalamon + */ +final class OperationCollectionMetadata +{ + private $path; + private $shortName; + private $description; + private $iri; + private $itemOperations; + private $collectionOperations; + private $subresourceOperations; + private $graphql; + private $attributes; + private $parent; + private $property; + + public function __construct(string $path = null, string $shortName = null, string $description = null, string $iri = null, array $itemOperations = null, array $collectionOperations = null, array $attributes = null, array $subresourceOperations = null, array $graphql = null, string $parent = null, string $property = null) + { + $this->path = $path; + $this->shortName = $shortName; + $this->description = $description; + $this->iri = $iri; + $this->itemOperations = $itemOperations; + $this->collectionOperations = $collectionOperations; + $this->subresourceOperations = $subresourceOperations; + $this->graphql = $graphql; + $this->attributes = $attributes; + $this->parent = $parent; + $this->property = $property; + } + + /** + * Gets the path. + */ + public function getPath(): ?string + { + return $this->path; + } + + /** + * Returns a new instance with the given path. + */ + public function withPath(string $path): self + { + $metadata = clone $this; + $metadata->path = $path; + + return $metadata; + } + + /** + * Gets the short name. + */ + public function getShortName(): ?string + { + return $this->shortName; + } + + /** + * Returns a new instance with the given short name. + */ + public function withShortName(string $shortName): self + { + $metadata = clone $this; + $metadata->shortName = $shortName; + + return $metadata; + } + + /** + * Gets the description. + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * Returns a new instance with the given description. + */ + public function withDescription(string $description): self + { + $metadata = clone $this; + $metadata->description = $description; + + return $metadata; + } + + /** + * Gets the associated IRI. + */ + public function getIri(): ?string + { + return $this->iri; + } + + /** + * Returns a new instance with the given IRI. + */ + public function withIri(string $iri): self + { + $metadata = clone $this; + $metadata->iri = $iri; + + return $metadata; + } + + /** + * Gets item operations. + */ + public function getItemOperations(): ?array + { + return $this->itemOperations; + } + + /** + * Returns a new instance with the given item operations. + */ + public function withItemOperations(array $itemOperations): self + { + $metadata = clone $this; + $metadata->itemOperations = $itemOperations; + + return $metadata; + } + + /** + * Gets collection operations. + */ + public function getCollectionOperations(): ?array + { + return $this->collectionOperations; + } + + /** + * Returns a new instance with the given collection operations. + */ + public function withCollectionOperations(array $collectionOperations): self + { + $metadata = clone $this; + $metadata->collectionOperations = $collectionOperations; + + return $metadata; + } + + /** + * Gets subresource operations. + */ + public function getSubresourceOperations(): ?array + { + return $this->subresourceOperations; + } + + /** + * Returns a new instance with the given subresource operations. + */ + public function withSubresourceOperations(array $subresourceOperations): self + { + $metadata = clone $this; + $metadata->subresourceOperations = $subresourceOperations; + + return $metadata; + } + + /** + * Gets a collection operation attribute, optionally fallback to a resource attribute. + * + * @param mixed|null $defaultValue + */ + public function getCollectionOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) + { + return $this->findOperationAttribute($this->collectionOperations, $operationName, $key, $defaultValue, $resourceFallback); + } + + /** + * Gets an item operation attribute, optionally fallback to a resource attribute. + * + * @param mixed|null $defaultValue + */ + public function getItemOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) + { + return $this->findOperationAttribute($this->itemOperations, $operationName, $key, $defaultValue, $resourceFallback); + } + + /** + * Gets a subresource operation attribute, optionally fallback to a resource attribute. + * + * @param mixed|null $defaultValue + */ + public function getSubresourceOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) + { + return $this->findOperationAttribute($this->subresourceOperations, $operationName, $key, $defaultValue, $resourceFallback); + } + + public function getGraphqlAttribute(string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) + { + if (isset($this->graphql[$operationName][$key])) { + return $this->graphql[$operationName][$key]; + } + + if ($resourceFallback && isset($this->attributes[$key])) { + return $this->attributes[$key]; + } + + return $defaultValue; + } + + /** + * Gets the first available operation attribute according to the following order: collection, item, subresource, optionally fallback to a default value. + * + * @param mixed|null $defaultValue + */ + public function getOperationAttribute(array $attributes, string $key, $defaultValue = null, bool $resourceFallback = false) + { + if (isset($attributes['collection_operation_name'])) { + return $this->getCollectionOperationAttribute($attributes['collection_operation_name'], $key, $defaultValue, $resourceFallback); + } + + if (isset($attributes['item_operation_name'])) { + return $this->getItemOperationAttribute($attributes['item_operation_name'], $key, $defaultValue, $resourceFallback); + } + + if (isset($attributes['subresource_operation_name'])) { + return $this->getSubresourceOperationAttribute($attributes['subresource_operation_name'], $key, $defaultValue, $resourceFallback); + } + + if ($resourceFallback && isset($this->attributes[$key])) { + return $this->attributes[$key]; + } + + return $defaultValue; + } + + /** + * Gets an attribute for a given operation type and operation name. + * + * @param mixed|null $defaultValue + */ + public function getTypedOperationAttribute(string $operationType, string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) + { + switch ($operationType) { + case OperationType::COLLECTION: + return $this->getCollectionOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); + case OperationType::ITEM: + return $this->getItemOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); + default: + return $this->getSubresourceOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); + } + } + + /** + * Gets attributes. + */ + public function getAttributes(): ?array + { + return $this->attributes; + } + + /** + * Gets an attribute. + * + * @param mixed|null $defaultValue + */ + public function getAttribute(string $key, $defaultValue = null) + { + return $this->attributes[$key] ?? $defaultValue; + } + + /** + * Returns a new instance with the given attribute. + */ + public function withAttributes(array $attributes): self + { + $metadata = clone $this; + $metadata->attributes = $attributes; + + return $metadata; + } + + /** + * Gets options of for the GraphQL query. + */ + public function getGraphql(): ?array + { + return $this->graphql; + } + + /** + * Returns a new instance with the given GraphQL options. + */ + public function withGraphql(array $graphql): self + { + $metadata = clone $this; + $metadata->graphql = $graphql; + + return $metadata; + } + + /** + * Gets the parent name. + */ + public function getParent(): ?string + { + return $this->parent; + } + + /** + * Returns a new instance with the given parent. + */ + public function withParent(string $parent): self + { + $metadata = clone $this; + $metadata->parent = $parent; + + return $metadata; + } + + /** + * Gets the property name. + */ + public function getProperty(): ?string + { + return $this->property; + } + + /** + * Returns a new instance with the given property. + */ + public function withProperty(string $property): self + { + $metadata = clone $this; + $metadata->property = $property; + + return $metadata; + } + + /** + * Gets an operation attribute, optionally fallback to a resource attribute. + * + * @param mixed|null $defaultValue + */ + private function findOperationAttribute(?array $operations, ?string $operationName, string $key, $defaultValue, bool $resourceFallback) + { + if (null !== $operationName && isset($operations[$operationName][$key])) { + return $operations[$operationName][$key]; + } + + if ($resourceFallback && isset($this->attributes[$key])) { + return $this->attributes[$key]; + } + + return $defaultValue; + } +} diff --git a/src/Metadata/Resource/ResourceMetadata.php b/src/Metadata/Resource/ResourceMetadata.php index cc226f6c201..a4a275718a5 100644 --- a/src/Metadata/Resource/ResourceMetadata.php +++ b/src/Metadata/Resource/ResourceMetadata.php @@ -13,34 +13,82 @@ namespace ApiPlatform\Core\Metadata\Resource; -use ApiPlatform\Core\Api\OperationType; - /** * Resource metadata. * * @author Kévin Dunglas + * @author Vincent Chalamon */ -final class ResourceMetadata +final class ResourceMetadata implements \IteratorAggregate, \ArrayAccess { - private $shortName; - private $description; - private $iri; - private $itemOperations; - private $collectionOperations; - private $subresourceOperations; - private $graphql; - private $attributes; - - public function __construct(string $shortName = null, string $description = null, string $iri = null, array $itemOperations = null, array $collectionOperations = null, array $attributes = null, array $subresourceOperations = null, array $graphql = null) - { - $this->shortName = $shortName; - $this->description = $description; - $this->iri = $iri; - $this->itemOperations = $itemOperations; - $this->collectionOperations = $collectionOperations; - $this->subresourceOperations = $subresourceOperations; - $this->graphql = $graphql; - $this->attributes = $attributes; + /** + * @var OperationCollectionMetadata[] + */ + private $operations; + + public function __construct(array $operations) + { + $this->operations = $operations; + } + + /** + * {@inheritdoc} + */ + public function getIterator(): \Traversable + { + return new \ArrayIterator($this->operations); + } + + /** + * {@inheritdoc} + */ + public function offsetExists($offset): bool + { + return \array_key_exists($offset, $this->operations); + } + + /** + * {@inheritdoc} + */ + public function offsetGet($offset): OperationCollectionMetadata + { + return $this->operations[$offset]; + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value): void + { + $this->operations[$offset] = $value; + } + + /** + * {@inheritdoc} + */ + public function offsetUnset($offset): void + { + unset($this->operations[$offset]); + } + + /** + * Gets the path. + */ + public function getPath(): ?string + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getPath(); + } + + /** + * Returns a new instance with the given path. + */ + public function withPath(string $path): OperationCollectionMetadata + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->withPath($path); } /** @@ -48,18 +96,19 @@ public function __construct(string $shortName = null, string $description = null */ public function getShortName(): ?string { - return $this->shortName; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getShortName(); } /** * Returns a new instance with the given short name. */ - public function withShortName(string $shortName): self + public function withShortName(string $shortName): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->shortName = $shortName; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withShortName($shortName); } /** @@ -67,18 +116,19 @@ public function withShortName(string $shortName): self */ public function getDescription(): ?string { - return $this->description; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getDescription(); } /** * Returns a new instance with the given description. */ - public function withDescription(string $description): self + public function withDescription(string $description): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->description = $description; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withDescription($description); } /** @@ -86,18 +136,19 @@ public function withDescription(string $description): self */ public function getIri(): ?string { - return $this->iri; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getIri(); } /** * Returns a new instance with the given IRI. */ - public function withIri(string $iri): self + public function withIri(string $iri): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->iri = $iri; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withIri($iri); } /** @@ -105,18 +156,19 @@ public function withIri(string $iri): self */ public function getItemOperations(): ?array { - return $this->itemOperations; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getItemOperations(); } /** * Returns a new instance with the given item operations. */ - public function withItemOperations(array $itemOperations): self + public function withItemOperations(array $itemOperations): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->itemOperations = $itemOperations; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withItemOperations($itemOperations); } /** @@ -124,18 +176,19 @@ public function withItemOperations(array $itemOperations): self */ public function getCollectionOperations(): ?array { - return $this->collectionOperations; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getCollectionOperations(); } /** * Returns a new instance with the given collection operations. */ - public function withCollectionOperations(array $collectionOperations): self + public function withCollectionOperations(array $collectionOperations): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->collectionOperations = $collectionOperations; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withCollectionOperations($collectionOperations); } /** @@ -143,18 +196,19 @@ public function withCollectionOperations(array $collectionOperations): self */ public function getSubresourceOperations(): ?array { - return $this->subresourceOperations; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getSubresourceOperations(); } /** * Returns a new instance with the given subresource operations. */ - public function withSubresourceOperations(array $subresourceOperations): self + public function withSubresourceOperations(array $subresourceOperations): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->subresourceOperations = $subresourceOperations; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withSubresourceOperations($subresourceOperations); } /** @@ -164,7 +218,9 @@ public function withSubresourceOperations(array $subresourceOperations): self */ public function getCollectionOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) { - return $this->findOperationAttribute($this->collectionOperations, $operationName, $key, $defaultValue, $resourceFallback); + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getCollectionOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); } /** @@ -174,7 +230,9 @@ public function getCollectionOperationAttribute(?string $operationName, string $ */ public function getItemOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) { - return $this->findOperationAttribute($this->itemOperations, $operationName, $key, $defaultValue, $resourceFallback); + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getItemOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); } /** @@ -184,20 +242,16 @@ public function getItemOperationAttribute(?string $operationName, string $key, $ */ public function getSubresourceOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) { - return $this->findOperationAttribute($this->subresourceOperations, $operationName, $key, $defaultValue, $resourceFallback); + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getSubresourceOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); } public function getGraphqlAttribute(string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) { - if (isset($this->graphql[$operationName][$key])) { - return $this->graphql[$operationName][$key]; - } + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; + return $this->getFirstOperation()->getGraphqlAttribute($operationName, $key, $defaultValue, $resourceFallback); } /** @@ -207,23 +261,9 @@ public function getGraphqlAttribute(string $operationName, string $key, $default */ public function getOperationAttribute(array $attributes, string $key, $defaultValue = null, bool $resourceFallback = false) { - if (isset($attributes['collection_operation_name'])) { - return $this->getCollectionOperationAttribute($attributes['collection_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if (isset($attributes['item_operation_name'])) { - return $this->getItemOperationAttribute($attributes['item_operation_name'], $key, $defaultValue, $resourceFallback); - } + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - if (isset($attributes['subresource_operation_name'])) { - return $this->getSubresourceOperationAttribute($attributes['subresource_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; + return $this->getFirstOperation()->getOperationAttribute($attributes, $key, $defaultValue, $resourceFallback); } /** @@ -233,14 +273,9 @@ public function getOperationAttribute(array $attributes, string $key, $defaultVa */ public function getTypedOperationAttribute(string $operationType, string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) { - switch ($operationType) { - case OperationType::COLLECTION: - return $this->getCollectionOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - case OperationType::ITEM: - return $this->getItemOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - default: - return $this->getSubresourceOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - } + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getTypedOperationAttribute($operationType, $operationName, $key, $defaultValue, $resourceFallback); } /** @@ -248,7 +283,9 @@ public function getTypedOperationAttribute(string $operationType, string $operat */ public function getAttributes(): ?array { - return $this->attributes; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getAttributes(); } /** @@ -258,18 +295,19 @@ public function getAttributes(): ?array */ public function getAttribute(string $key, $defaultValue = null) { - return $this->attributes[$key] ?? $defaultValue; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getAttribute($key, $defaultValue); } /** * Returns a new instance with the given attribute. */ - public function withAttributes(array $attributes): self + public function withAttributes(array $attributes): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->attributes = $attributes; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withAttributes($attributes); } /** @@ -277,35 +315,23 @@ public function withAttributes(array $attributes): self */ public function getGraphql(): ?array { - return $this->graphql; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); + + return $this->getFirstOperation()->getGraphql(); } /** * Returns a new instance with the given GraphQL options. */ - public function withGraphql(array $graphql): self + public function withGraphql(array $graphql): OperationCollectionMetadata { - $metadata = clone $this; - $metadata->graphql = $graphql; + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0, prefer parsing '.__CLASS__.' collection of OperationCollectionMetadata objects.', E_USER_DEPRECATED); - return $metadata; + return $this->getFirstOperation()->withGraphql($graphql); } - /** - * Gets an operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - private function findOperationAttribute(?array $operations, ?string $operationName, string $key, $defaultValue, bool $resourceFallback) + private function getFirstOperation(): ?OperationCollectionMetadata { - if (null !== $operationName && isset($operations[$operationName][$key])) { - return $operations[$operationName][$key]; - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; + return reset($this->operations) ?: null; } } diff --git a/src/Metadata/schema/metadata.xsd b/src/Metadata/schema/metadata.xsd index e61ad5658f4..bf347f46e17 100644 --- a/src/Metadata/schema/metadata.xsd +++ b/src/Metadata/schema/metadata.xsd @@ -27,6 +27,7 @@ + diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index 69238100fb1..db60a9e1b23 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -24,7 +24,7 @@ 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\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\OpenApi\Model; use ApiPlatform\Core\OpenApi\Model\ExternalDocumentation; use ApiPlatform\Core\OpenApi\OpenApi; @@ -86,17 +86,18 @@ public function __invoke(array $context = []): OpenApi $schemas = []; foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceMetadata = $resourceMetadata->withAttributes(($resourceMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]); - $resourceShortName = $resourceMetadata->getShortName(); + foreach ($this->resourceMetadataFactory->create($resourceClass) as $operationCollectionMetadata) { + $operationCollectionMetadata = $operationCollectionMetadata->withAttributes(($operationCollectionMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]); + $resourceShortName = $operationCollectionMetadata->getShortName(); - // Items needs to be parsed first to be able to reference the lines from the collection operation - list($itemOperationLinks, $itemOperationSchemas) = $this->collectPaths($resourceMetadata, $resourceClass, OperationType::ITEM, $context, $paths, $links, $schemas); - $schemas += $itemOperationSchemas; - list($collectionOperationLinks, $collectionOperationSchemas) = $this->collectPaths($resourceMetadata, $resourceClass, OperationType::COLLECTION, $context, $paths, $links, $schemas); + // Items needs to be parsed first to be able to reference the lines from the collection operation + list($itemOperationLinks, $itemOperationSchemas) = $this->collectPaths($operationCollectionMetadata, $resourceClass, OperationType::ITEM, $context, $paths, $links, $schemas); + $schemas += $itemOperationSchemas; + list($collectionOperationLinks, $collectionOperationSchemas) = $this->collectPaths($operationCollectionMetadata, $resourceClass, OperationType::COLLECTION, $context, $paths, $links, $schemas); - list($subresourceOperationLinks, $subresourceOperationSchemas) = $this->collectPaths($resourceMetadata, $resourceClass, OperationType::SUBRESOURCE, $context, $paths, $links, $schemas); - $schemas += $collectionOperationSchemas; + list($subresourceOperationLinks, $subresourceOperationSchemas) = $this->collectPaths($operationCollectionMetadata, $resourceClass, OperationType::SUBRESOURCE, $context, $paths, $links, $schemas); + $schemas += $collectionOperationSchemas; + } } $securitySchemes = $this->getSecuritySchemes(); @@ -112,25 +113,25 @@ public function __invoke(array $context = []): OpenApi /** * @return array | array */ - private function collectPaths(ResourceMetadata $resourceMetadata, string $resourceClass, string $operationType, array $context, Model\Paths $paths, array &$links, array $schemas = []): array + private function collectPaths(OperationCollectionMetadata $operationCollectionMetadata, string $resourceClass, string $operationType, array $context, Model\Paths $paths, array &$links, array $schemas = []): array { - $resourceShortName = $resourceMetadata->getShortName(); - $operations = OperationType::COLLECTION === $operationType ? $resourceMetadata->getCollectionOperations() : (OperationType::ITEM === $operationType ? $resourceMetadata->getItemOperations() : $this->subresourceOperationFactory->create($resourceClass)); + $resourceShortName = $operationCollectionMetadata->getShortName(); + $operations = OperationType::COLLECTION === $operationType ? $operationCollectionMetadata->getCollectionOperations() : (OperationType::ITEM === $operationType ? $operationCollectionMetadata->getItemOperations() : $this->subresourceOperationFactory->create($resourceClass)); if (!$operations) { return [$links, $schemas]; } foreach ($operations as $operationName => $operation) { - $identifiers = (array) ($operation['identified_by'] ?? $resourceMetadata->getAttribute('identified_by')); - $hasCompositeIdentifiers = \count($identifiers) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false; + $identifiers = (array) ($operation['identified_by'] ?? $operationCollectionMetadata->getAttribute('identified_by')); + $hasCompositeIdentifiers = \count($identifiers) > 1 ? $operationCollectionMetadata->getAttribute('composite_identifier', true) : false; if ($hasCompositeIdentifiers) { $identifiers = ['id']; } $path = $this->getPath($resourceShortName, $operationName, $operation, $operationType); - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - list($requestMimeTypes, $responseMimeTypes) = $this->getMimeTypes($resourceClass, $operationName, $operationType, $resourceMetadata); + $method = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); + list($requestMimeTypes, $responseMimeTypes) = $this->getMimeTypes($resourceClass, $operationName, $operationType, $operationCollectionMetadata); $operationId = $operation['openapi_context']['operationId'] ?? lcfirst($operationName).ucfirst($resourceShortName).ucfirst($operationType); $linkedOperationId = 'get'.ucfirst($resourceShortName).ucfirst(OperationType::ITEM); $pathItem = $paths->getPath($path) ?: new Model\PathItem(); @@ -153,7 +154,7 @@ private function collectPaths(ResourceMetadata $resourceMetadata, string $resour $links[$operationId] = $this->getLink($resourceClass, $operationId, $path); } elseif (OperationType::COLLECTION === $operationType && 'GET' === $method) { - $parameters = array_merge($parameters, $this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($resourceMetadata, $operationName, $resourceClass)); + $parameters = array_merge($parameters, $this->getPaginationParameters($operationCollectionMetadata, $operationName), $this->getFiltersParameters($operationCollectionMetadata, $operationName, $resourceClass)); } elseif (OperationType::SUBRESOURCE === $operationType) { // FIXME: In SubresourceOperationFactory identifiers may happen twice $added = []; @@ -167,34 +168,34 @@ private function collectPaths(ResourceMetadata $resourceMetadata, string $resour } if ($operation['collection']) { - $parameters = array_merge($parameters, $this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($resourceMetadata, $operationName, $resourceClass)); + $parameters = array_merge($parameters, $this->getPaginationParameters($operationCollectionMetadata, $operationName), $this->getFiltersParameters($operationCollectionMetadata, $operationName, $resourceClass)); } } // Create responses switch ($method) { case 'GET': - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); + $successStatus = (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); $responses[$successStatus] = new Model\Response(sprintf('%s %s', $resourceShortName, OperationType::COLLECTION === $operationType ? 'collection' : 'resource'), $responseContent); break; case 'POST': $responseLinks = new \ArrayObject(isset($links[$linkedOperationId]) ? [ucfirst($linkedOperationId) => $links[$linkedOperationId]] : []); $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201'); + $successStatus = (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201'); $responses[$successStatus] = new Model\Response(sprintf('%s resource created', $resourceShortName), $responseContent, null, $responseLinks); $responses['400'] = new Model\Response('Invalid input'); break; case 'PATCH': case 'PUT': $responseLinks = new \ArrayObject(isset($links[$linkedOperationId]) ? [ucfirst($linkedOperationId) => $links[$linkedOperationId]] : []); - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); + $successStatus = (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); $responses[$successStatus] = new Model\Response(sprintf('%s resource updated', $resourceShortName), $responseContent, null, $responseLinks); $responses['400'] = new Model\Response('Invalid input'); break; case 'DELETE': - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204'); + $successStatus = (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204'); $responses[$successStatus] = new Model\Response(sprintf('%s resource deleted', $resourceShortName)); break; } @@ -229,7 +230,7 @@ private function collectPaths(ResourceMetadata $resourceMetadata, string $resour $parameters, $requestBody, isset($operation['openapi_context']['callbacks']) ? new \ArrayObject($operation['openapi_context']['callbacks']) : null, - $operation['openapi_context']['deprecated'] ?? (bool) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', false, true), + $operation['openapi_context']['deprecated'] ?? (bool) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', false, true), $operation['openapi_context']['security'] ?? [], $operation['openapi_context']['servers'] ?? [] )); @@ -251,10 +252,10 @@ private function buildContent(array $responseMimeTypes, array $operationSchemas) return $content; } - private function getMimeTypes(string $resourceClass, string $operationName, string $operationType, ResourceMetadata $resourceMetadata = null): array + private function getMimeTypes(string $resourceClass, string $operationName, string $operationType, OperationCollectionMetadata $operationCollectionMetadata = null): array { - $requestFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', $this->formats, true); - $responseFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', $this->formats, true); + $requestFormats = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', $this->formats, true); + $responseFormats = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', $this->formats, true); $requestMimeTypes = $this->flattenMimeTypes($requestFormats); $responseMimeTypes = $this->flattenMimeTypes($responseFormats); @@ -347,10 +348,10 @@ private function getLink(string $resourceClass, string $operationId, string $pat /** * Gets parameters corresponding to enabled filters. */ - private function getFiltersParameters(ResourceMetadata $resourceMetadata, string $operationName, string $resourceClass): array + private function getFiltersParameters(OperationCollectionMetadata $operationCollectionMetadata, string $operationName, string $resourceClass): array { $parameters = []; - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); + $resourceFilters = $operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); foreach ($resourceFilters as $filterId) { if (!$filter = $this->getFilter($filterId)) { continue; @@ -380,7 +381,7 @@ private function getFiltersParameters(ResourceMetadata $resourceMetadata, string return $parameters; } - private function getPaginationParameters(ResourceMetadata $resourceMetadata, string $operationName): array + private function getPaginationParameters(OperationCollectionMetadata $operationCollectionMetadata, string $operationName): array { if (!$this->paginationOptions->isPaginationEnabled()) { return []; @@ -388,17 +389,17 @@ private function getPaginationParameters(ResourceMetadata $resourceMetadata, str $parameters = []; - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_enabled', true, true)) { + if ($operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'pagination_enabled', true, true)) { $parameters[] = new Model\Parameter($this->paginationOptions->getPaginationPageParameterName(), 'query', 'The collection page number', false, false, true, ['type' => 'integer', 'default' => 1]); - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->paginationOptions->getClientItemsPerPage(), true)) { + if ($operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->paginationOptions->getClientItemsPerPage(), true)) { $schema = [ 'type' => 'integer', - 'default' => $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', 30, true), + 'default' => $operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', 30, true), 'minimum' => 0, ]; - if (null !== $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', null, true)) { + if (null !== $maxItemsPerPage = $operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', null, true)) { $schema['maximum'] = $maxItemsPerPage; } @@ -406,7 +407,7 @@ private function getPaginationParameters(ResourceMetadata $resourceMetadata, str } } - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_enabled', $this->paginationOptions->getPaginationClientEnabled(), true)) { + if ($operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_enabled', $this->paginationOptions->getPaginationClientEnabled(), true)) { $parameters[] = new Model\Parameter($this->paginationOptions->getPaginationClientEnabledParameterName(), 'query', 'Enable or disable pagination', false, false, true, ['type' => 'boolean']); } diff --git a/src/Swagger/Serializer/DocumentationNormalizer.php b/src/Swagger/Serializer/DocumentationNormalizer.php index 11a3be3ecd5..ab0b61dad4f 100644 --- a/src/Swagger/Serializer/DocumentationNormalizer.php +++ b/src/Swagger/Serializer/DocumentationNormalizer.php @@ -32,7 +32,7 @@ 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\ResourceMetadata; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\PathResolver\OperationPathResolverInterface; use Psr\Container\ContainerInterface; @@ -184,23 +184,24 @@ public function normalize($object, $format = null, array $context = []) $links = new \ArrayObject(); foreach ($object->getResourceNameCollection() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceShortName = $resourceMetadata->getShortName(); - if ($this->identifiersExtractor) { - $resourceMetadata = $resourceMetadata->withAttributes(($resourceMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]); - } + foreach ($this->resourceMetadataFactory->create($resourceClass) as $operationCollectionMetadata) { + $resourceShortName = $operationCollectionMetadata->getShortName(); + if ($this->identifiersExtractor) { + $operationCollectionMetadata = $operationCollectionMetadata->withAttributes(($operationCollectionMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]); + } - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $resourceMetadata, OperationType::ITEM, $links); - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $resourceMetadata, OperationType::COLLECTION, $links); + // Items needs to be parsed first to be able to reference the lines from the collection operation + $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $operationCollectionMetadata, OperationType::ITEM, $links); + $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $operationCollectionMetadata, OperationType::COLLECTION, $links); - if (null === $this->subresourceOperationFactory) { - continue; - } + if (null === $this->subresourceOperationFactory) { + continue; + } - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $subresourceOperation) { - $method = $resourceMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, $subresourceOperation['operation_name'], 'method', 'GET'); - $paths[$this->getPath($subresourceOperation['shortNames'][0], $subresourceOperation['route_name'], $subresourceOperation, OperationType::SUBRESOURCE)][strtolower($method)] = $this->addSubresourceOperation($v3, $subresourceOperation, $definitions, $operationId, $resourceMetadata); + foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $subresourceOperation) { + $method = $operationCollectionMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, $subresourceOperation['operation_name'], 'method', 'GET'); + $paths[$this->getPath($subresourceOperation['shortNames'][0], $subresourceOperation['route_name'], $subresourceOperation, OperationType::SUBRESOURCE)][strtolower($method)] = $this->addSubresourceOperation($v3, $subresourceOperation, $definitions, $operationId, $operationCollectionMetadata); + } } } @@ -213,9 +214,9 @@ public function normalize($object, $format = null, array $context = []) /** * Updates the list of entries in the paths collection. */ - private function addPaths(bool $v3, \ArrayObject $paths, \ArrayObject $definitions, string $resourceClass, string $resourceShortName, ResourceMetadata $resourceMetadata, string $operationType, \ArrayObject $links) + private function addPaths(bool $v3, \ArrayObject $paths, \ArrayObject $definitions, string $resourceClass, string $resourceShortName, OperationCollectionMetadata $operationCollectionMetadata, string $operationType, \ArrayObject $links) { - if (null === $operations = OperationType::COLLECTION === $operationType ? $resourceMetadata->getCollectionOperations() : $resourceMetadata->getItemOperations()) { + if (null === $operations = OperationType::COLLECTION === $operationType ? $operationCollectionMetadata->getCollectionOperations() : $operationCollectionMetadata->getItemOperations()) { return; } @@ -224,10 +225,10 @@ private function addPaths(bool $v3, \ArrayObject $paths, \ArrayObject $definitio if ($this->operationMethodResolver) { $method = OperationType::ITEM === $operationType ? $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName) : $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); } else { - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); + $method = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); } - $paths[$path][strtolower($method)] = $this->getPathOperation($v3, $operationName, $operation, $method, $operationType, $resourceClass, $resourceMetadata, $definitions, $links); + $paths[$path][strtolower($method)] = $this->getPathOperation($v3, $operationName, $operation, $method, $operationType, $resourceClass, $operationCollectionMetadata, $definitions, $links); } } @@ -254,22 +255,22 @@ private function getPath(string $resourceShortName, string $operationName, array * * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object */ - private function getPathOperation(bool $v3, string $operationName, array $operation, string $method, string $operationType, string $resourceClass, ResourceMetadata $resourceMetadata, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject + private function getPathOperation(bool $v3, string $operationName, array $operation, string $method, string $operationType, string $resourceClass, OperationCollectionMetadata $operationCollectionMetadata, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject { $pathOperation = new \ArrayObject($operation[$v3 ? 'openapi_context' : 'swagger_context'] ?? []); - $resourceShortName = $resourceMetadata->getShortName(); + $resourceShortName = $operationCollectionMetadata->getShortName(); $pathOperation['tags'] ?? $pathOperation['tags'] = [$resourceShortName]; $pathOperation['operationId'] ?? $pathOperation['operationId'] = lcfirst($operationName).ucfirst($resourceShortName).ucfirst($operationType); if ($v3 && 'GET' === $method && OperationType::ITEM === $operationType && $link = $this->getLinkObject($resourceClass, $pathOperation['operationId'], $this->getPath($resourceShortName, $operationName, $operation, $operationType))) { $links[$pathOperation['operationId']] = $link; } - if ($resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { + if ($operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { $pathOperation['deprecated'] = true; } if (null === $this->formatsProvider) { - $requestFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', [], true); - $responseFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', [], true); + $requestFormats = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', [], true); + $responseFormats = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', [], true); } else { $requestFormats = $responseFormats = $this->formatsProvider->getFormatsFromOperation($resourceClass, $operationName, $operationType); } @@ -278,16 +279,16 @@ private function getPathOperation(bool $v3, string $operationName, array $operat $responseMimeTypes = $this->flattenMimeTypes($responseFormats); switch ($method) { case 'GET': - return $this->updateGetOperation($v3, $pathOperation, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); + return $this->updateGetOperation($v3, $pathOperation, $responseMimeTypes, $operationType, $operationCollectionMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); case 'POST': - return $this->updatePostOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions, $links); + return $this->updatePostOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $operationCollectionMetadata, $resourceClass, $resourceShortName, $operationName, $definitions, $links); case 'PATCH': $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Updates the %s resource.', $resourceShortName); // no break case 'PUT': - return $this->updatePutOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); + return $this->updatePutOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $operationCollectionMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); case 'DELETE': - return $this->updateDeleteOperation($v3, $pathOperation, $resourceShortName, $operationType, $operationName, $resourceMetadata); + return $this->updateDeleteOperation($v3, $pathOperation, $resourceShortName, $operationType, $operationName, $operationCollectionMetadata); } return $pathOperation; @@ -321,9 +322,9 @@ private function addSchemas(bool $v3, array $message, \ArrayObject $definitions, return [$message, true]; } - private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array $mimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject + private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array $mimeTypes, string $operationType, OperationCollectionMetadata $operationCollectionMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject { - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); + $successStatus = (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); if (!$v3) { $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($mimeTypes); @@ -336,16 +337,16 @@ private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $mimeTypes); $pathOperation['responses'] ?? $pathOperation['responses'] = [$successStatus => $successResponse]; - $pathOperation['parameters'] ?? $pathOperation['parameters'] = $this->getFiltersParameters($v3, $resourceClass, $operationName, $resourceMetadata); + $pathOperation['parameters'] ?? $pathOperation['parameters'] = $this->getFiltersParameters($v3, $resourceClass, $operationName, $operationCollectionMetadata); - $this->addPaginationParameters($v3, $resourceMetadata, OperationType::COLLECTION, $operationName, $pathOperation); + $this->addPaginationParameters($v3, $operationCollectionMetadata, OperationType::COLLECTION, $operationName, $pathOperation); return $pathOperation; } $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Retrieves a %s resource.', $resourceShortName); - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata); + $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $operationCollectionMetadata); $successResponse = ['description' => sprintf('%s resource response', $resourceShortName)]; [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $mimeTypes); @@ -358,9 +359,9 @@ private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array return $pathOperation; } - private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMetadata, string $operationType, string $operationName, \ArrayObject $pathOperation) + private function addPaginationParameters(bool $v3, OperationCollectionMetadata $operationCollectionMetadata, string $operationType, string $operationName, \ArrayObject $pathOperation) { - if ($this->paginationEnabled && $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_enabled', true, true)) { + if ($this->paginationEnabled && $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_enabled', true, true)) { $paginationParameter = [ 'name' => $this->paginationPageParameterName, 'in' => 'query', @@ -373,7 +374,7 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet ] : $paginationParameter['type'] = 'integer'; $pathOperation['parameters'][] = $paginationParameter; - if ($resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { + if ($operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { $itemPerPageParameter = [ 'name' => $this->itemsPerPageParameterName, 'in' => 'query', @@ -383,15 +384,15 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet if ($v3) { $itemPerPageParameter['schema'] = [ 'type' => 'integer', - 'default' => $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_items_per_page', 30, true), + 'default' => $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_items_per_page', 30, true), 'minimum' => 0, ]; - $maxItemsPerPage = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'maximum_items_per_page', null, true); + $maxItemsPerPage = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'maximum_items_per_page', null, true); if (null !== $maxItemsPerPage) { @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', E_USER_DEPRECATED); } - $maxItemsPerPage = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage, true); + $maxItemsPerPage = $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage, true); if (null !== $maxItemsPerPage) { $itemPerPageParameter['schema']['maximum'] = $maxItemsPerPage; @@ -404,7 +405,7 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet } } - if ($this->paginationEnabled && $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_enabled', $this->paginationClientEnabled, true)) { + if ($this->paginationEnabled && $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_enabled', $this->paginationClientEnabled, true)) { $paginationEnabledParameter = [ 'name' => $this->paginationClientEnabledParameterName, 'in' => 'query', @@ -419,7 +420,7 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet /** * @throws ResourceClassNotFoundException */ - private function addSubresourceOperation(bool $v3, array $subresourceOperation, \ArrayObject $definitions, string $operationId, ResourceMetadata $resourceMetadata): \ArrayObject + private function addSubresourceOperation(bool $v3, array $subresourceOperation, \ArrayObject $definitions, string $operationId, OperationCollectionMetadata $operationCollectionMetadata): \ArrayObject { $operationName = 'get'; // TODO: we might want to extract that at some point to also support other subresource operations $collection = $subresourceOperation['collection'] ?? false; @@ -481,7 +482,7 @@ private function addSubresourceOperation(bool $v3, array $subresourceOperation, return $pathOperation; } - private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject + private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, OperationCollectionMetadata $operationCollectionMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject { if (!$v3) { $pathOperation['consumes'] ?? $pathOperation['consumes'] = array_keys($requestMimeTypes); @@ -491,7 +492,7 @@ private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, arra $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Creates a %s resource.', $resourceShortName); if (OperationType::ITEM === $operationType) { - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata); + $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $operationCollectionMetadata); } $successResponse = ['description' => sprintf('%s resource created', $resourceShortName)]; @@ -502,7 +503,7 @@ private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, arra } $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201') => $successResponse, + (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201') => $successResponse, '400' => ['description' => 'Invalid input'], '404' => ['description' => 'Resource not found'], ]; @@ -510,7 +511,7 @@ private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, arra return $this->addRequestBody($v3, $pathOperation, $definitions, $resourceClass, $resourceShortName, $operationType, $operationName, $requestMimeTypes); } - private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject + private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, OperationCollectionMetadata $operationCollectionMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject { if (!$v3) { $pathOperation['consumes'] ?? $pathOperation['consumes'] = array_keys($requestMimeTypes); @@ -519,13 +520,13 @@ private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Replaces the %s resource.', $resourceShortName); - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata); + $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $operationCollectionMetadata); $successResponse = ['description' => sprintf('%s resource updated', $resourceShortName)]; [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $responseMimeTypes); $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200') => $successResponse, + (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200') => $successResponse, '400' => ['description' => 'Invalid input'], '404' => ['description' => 'Resource not found'], ]; @@ -573,22 +574,22 @@ private function hasBodyParameter(array $parameters): bool return false; } - private function updateDeleteOperation(bool $v3, \ArrayObject $pathOperation, string $resourceShortName, string $operationType, string $operationName, ResourceMetadata $resourceMetadata): \ArrayObject + private function updateDeleteOperation(bool $v3, \ArrayObject $pathOperation, string $resourceShortName, string $operationType, string $operationName, OperationCollectionMetadata $operationCollectionMetadata): \ArrayObject { $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Removes the %s resource.', $resourceShortName); $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204') => ['description' => sprintf('%s resource deleted', $resourceShortName)], + (string) $operationCollectionMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204') => ['description' => sprintf('%s resource deleted', $resourceShortName)], '404' => ['description' => 'Resource not found'], ]; - return $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata); + return $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $operationCollectionMetadata); } - private function addItemOperationParameters(bool $v3, \ArrayObject $pathOperation, string $operationType, string $operationName, ResourceMetadata $resourceMetadata): \ArrayObject + private function addItemOperationParameters(bool $v3, \ArrayObject $pathOperation, string $operationType, string $operationName, OperationCollectionMetadata $operationCollectionMetadata): \ArrayObject { - $identifiers = (array) $resourceMetadata + $identifiers = (array) $operationCollectionMetadata ->getTypedOperationAttribute(OperationType::ITEM, $operationName, 'identified_by', ['id'], true); - $hasCompositeIdentifiers = \count($identifiers) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false; + $hasCompositeIdentifiers = \count($identifiers) > 1 ? $operationCollectionMetadata->getAttribute('composite_identifier', true) : false; if ($hasCompositeIdentifiers) { $identifiers = ['id']; @@ -722,14 +723,14 @@ private function computeDoc(bool $v3, Documentation $documentation, \ArrayObject /** * Gets parameters corresponding to enabled filters. */ - private function getFiltersParameters(bool $v3, string $resourceClass, string $operationName, ResourceMetadata $resourceMetadata): array + private function getFiltersParameters(bool $v3, string $resourceClass, string $operationName, OperationCollectionMetadata $operationCollectionMetadata): array { if (null === $this->filterLocator) { return []; } $parameters = []; - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); + $resourceFilters = $operationCollectionMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); foreach ($resourceFilters as $filterId) { if (!$filter = $this->getFilter($filterId)) { continue; diff --git a/tests/Api/FormatsProviderTest.php b/tests/Api/FormatsProviderTest.php index e9bc6c79713..f8f2bca9ac0 100644 --- a/tests/Api/FormatsProviderTest.php +++ b/tests/Api/FormatsProviderTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Api\FormatsProvider; use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -42,7 +43,7 @@ public function testNoResourceClass() public function testResourceClassWithoutFormatsAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); @@ -52,7 +53,7 @@ public function testResourceClassWithoutFormatsAttributes() public function testResourceClassWithFormatsAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld']]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => ['jsonld']])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -63,7 +64,7 @@ public function testResourceClassWithFormatsAttributes() public function testResourceClassWithFormatsAttributesOverRiddingMimeTypes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -77,7 +78,7 @@ public function testBadFormatsShortDeclaration() $this->expectExceptionMessage('You either need to add the format \'foo\' to your project configuration or declare a mime type for it in your annotation.'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['foo']]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => ['foo']])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); @@ -91,7 +92,7 @@ public function testInvalidFormatsShortDeclaration() $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, array given.'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => [['badFormat']]]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => [['badFormat']]])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -105,7 +106,7 @@ public function testInvalidFormatsDeclaration() $this->expectExceptionMessage('The \'formats\' attributes must be an array, string given for resource class \'Foo\'.'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => 'badFormat']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => 'badFormat'])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -116,7 +117,7 @@ public function testInvalidFormatsDeclaration() public function testResourceClassWithoutFormatsAttributesFromOperation() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); @@ -126,7 +127,7 @@ public function testResourceClassWithoutFormatsAttributesFromOperation() public function testResourceClassWithFormatsAttributesFromOperation() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld']]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => ['jsonld']])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -137,7 +138,7 @@ public function testResourceClassWithFormatsAttributesFromOperation() public function testResourceClassWithFormatsAttributesOverRiddingMimeTypesFromOperation() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -151,7 +152,7 @@ public function testBadFormatsShortDeclarationFromOperation() $this->expectExceptionMessage('You either need to add the format \'foo\' to your project configuration or declare a mime type for it in your annotation.'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['foo']]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => ['foo']])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); @@ -165,7 +166,7 @@ public function testInvalidFormatsShortDeclarationFromOperation() $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, array given.'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => [['badFormat']]]); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => [['badFormat']]])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); @@ -179,7 +180,7 @@ public function testInvalidFormatsDeclarationFromOperation() $this->expectExceptionMessage('The \'formats\' attributes must be an array, string given for resource class \'Foo\'.'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => 'badFormat']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata(null, null, null, null, null, null, ['formats' => 'badFormat'])]); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); diff --git a/tests/Bridge/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php b/tests/Bridge/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php index f0dba0efee9..625bb59df53 100644 --- a/tests/Bridge/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php +++ b/tests/Bridge/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php @@ -21,6 +21,7 @@ use ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface; use ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface as GraphQlSubscriptionManagerInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\NotAResource; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -79,9 +80,9 @@ public function testLegacyPublishUpdate(): void $iriConverterProphecy->getIriFromItem($toDeleteExpressionLanguage, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummy_friends/4')->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true, 'normalization_context' => ['groups' => ['foo', 'bar']]])); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyFriend::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => "['foo', 'bar']"])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => true, 'normalization_context' => ['groups' => ['foo', 'bar']]])])); + $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(DummyFriend::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => "['foo', 'bar']"])])); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->serialize($toInsert, 'jsonld', ['groups' => ['foo', 'bar']])->willReturn('1'); @@ -161,9 +162,9 @@ public function testPublishUpdate(): void $iriConverterProphecy->getIriFromItem($toDeleteExpressionLanguage, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummy_friends/4')->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true, 'normalization_context' => ['groups' => ['foo', 'bar']]])); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyFriend::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => ['private' => true, 'retry' => 10]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => true, 'normalization_context' => ['groups' => ['foo', 'bar']]])])); + $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(DummyFriend::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => ['private' => true, 'retry' => 10]])])); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->serialize($toInsert, 'jsonld', ['groups' => ['foo', 'bar']])->willReturn('1'); @@ -226,7 +227,7 @@ public function testPublishGraphQlUpdates(): void $iriConverterProphecy->getIriFromItem($toUpdate, UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/2'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true, 'normalization_context' => ['groups' => ['foo', 'bar']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => true, 'normalization_context' => ['groups' => ['foo', 'bar']]])])); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->serialize($toUpdate, 'jsonld', ['groups' => ['foo', 'bar']])->willReturn('2'); @@ -314,7 +315,7 @@ public function testInvalidMercureAttribute(): void $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => 1])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => 1])])); $serializerProphecy = $this->prophesize(SerializerInterface::class); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php index 532f19b1bf6..68d2a639a9b 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultCollectionExtensionInterface; use ApiPlatform\Core\Exception\RuntimeException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -69,7 +70,7 @@ public function testGetCollection() $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtensionTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtensionTest.php index 462a31bc4df..699776dd4fb 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtensionTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtensionTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\FilterExtension; use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\FilterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -37,7 +38,7 @@ public function testApplyToCollectionWithValidFilters() { $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET', 'filters' => ['dummyFilter', 'dummyBadFilter']], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET', 'filters' => ['dummyFilter', 'dummyBadFilter']], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], [])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); @@ -60,7 +61,7 @@ public function testApplyToCollectionWithValidFilters() public function testApplyToCollectionWithoutFilters() { - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']]); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtensionTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtensionTest.php index ac38a38c335..9d94bc09fd2 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtensionTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtensionTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\OrderExtension; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -84,7 +85,7 @@ public function testApplyToCollectionWithOrderOverridden() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['foo' => 'DESC']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['foo' => 'DESC']])])); $objectManagerProphecy = $this->prophesize(DocumentManager::class); $objectManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -108,7 +109,7 @@ public function testApplyToCollectionWithOrderOverriddenWithNoDirection() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['foo', 'bar' => 'DESC']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['foo', 'bar' => 'DESC']])])); $objectManagerProphecy = $this->prophesize(DocumentManager::class); $objectManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -142,7 +143,7 @@ public function testApplyToCollectionWithOrderOverriddenWithAssociation() $classMetadataProphecy->hasReference('author')->shouldBeCalled()->willReturn(true); $classMetadataProphecy->getFieldMapping('author')->shouldBeCalled()->willReturn(['isOwningSide' => true, 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_ID]); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['author.name']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['author.name']])])); $objectManagerProphecy = $this->prophesize(DocumentManager::class); $objectManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php index 59b7c75ad2e..976c7c74448 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php @@ -20,6 +20,7 @@ use ApiPlatform\Core\DataProvider\PartialPaginatorInterface; use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Test\DoctrineMongoDbOdmSetup; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; @@ -65,7 +66,7 @@ public function testApplyToCollection() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 40, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -91,7 +92,7 @@ public function testApplyToCollectionWithItemPerPageZero() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 0, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -121,7 +122,7 @@ public function testApplyToCollectionWithItemPerPageZeroAndPage2() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 0, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -152,7 +153,7 @@ public function testApplyToCollectionWithItemPerPageLessThan0() 'pagination_client_enabled' => true, 'pagination_items_per_page' => -20, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -180,7 +181,7 @@ public function testApplyToCollectionWithItemPerPageTooHigh() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => true, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -207,7 +208,7 @@ public function testApplyToCollectionWithGraphql() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => 20, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -231,7 +232,7 @@ public function testApplyToCollectionWithGraphqlAndCountContext() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => 20, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -259,7 +260,7 @@ public function testApplyToCollectionWithGraphqlAndCountContext() public function testApplyToCollectionNoFilters() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -278,7 +279,7 @@ public function testApplyToCollectionNoFilters() public function testApplyToCollectionPaginationDisabled() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -300,7 +301,7 @@ public function testApplyToCollectionPaginationDisabled() public function testApplyToCollectionGraphQlPaginationDisabled() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [], [ @@ -327,7 +328,7 @@ public function testApplyToCollectionWithMaximumItemsPerPage() 'pagination_client_enabled' => true, 'pagination_maximum_items_per_page' => 80, ]; - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -350,7 +351,7 @@ public function testApplyToCollectionWithMaximumItemsPerPage() public function testSupportsResult() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -365,7 +366,7 @@ public function testSupportsResult() public function testSupportsResultClientNotAllowedToPaginate() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -383,7 +384,7 @@ public function testSupportsResultClientNotAllowedToPaginate() public function testSupportsResultPaginationDisabled() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -400,7 +401,7 @@ public function testSupportsResultPaginationDisabled() public function testSupportsResultGraphQlPaginationDisabled() { - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [], [ @@ -427,7 +428,7 @@ public function testGetResult() $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($documentManager); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $iteratorProphecy = $this->prophesize(Iterator::class); $iteratorProphecy->toArray()->willReturn([ diff --git a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php index 2153c347fc6..cf518bfd51d 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php @@ -23,6 +23,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -81,7 +82,7 @@ public function testGetItemSingleIdentifier() ]); $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); @@ -153,7 +154,7 @@ public function testGetItemDoubleIdentifier() ]); $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $context = []; $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php index e19c8f225bf..6f78d6ca41d 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php @@ -22,6 +22,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\RelatedDummy; @@ -160,7 +161,7 @@ public function testGetSubresource() $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => ['id']]); @@ -249,7 +250,7 @@ public function testGetSubSubresourceItem() $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $this->resourceMetadataFactoryProphecy->create(ThirdLevel::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(ThirdLevel::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); @@ -398,7 +399,7 @@ public function testGetSubresourceOneToOneOwningRelation() $managerRegistryProphecy->getManagerForClass(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $this->resourceMetadataFactoryProphecy->create(RelatedOwningDummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(RelatedOwningDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); @@ -446,7 +447,7 @@ public function testAggregationResultExtension() $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); @@ -532,7 +533,7 @@ public function testGetSubresourceCollectionItem() $rDummyManagerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); diff --git a/tests/Bridge/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php b/tests/Bridge/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php index ea95a402b83..def4d36407f 100644 --- a/tests/Bridge/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php +++ b/tests/Bridge/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php @@ -23,6 +23,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\AbstractDummy; @@ -58,7 +59,7 @@ public function testApplyToCollection() $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -136,7 +137,7 @@ public function testApplyToItem() $callContext = ['serializer_groups' => ['foo']]; $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -240,7 +241,7 @@ public function testApplyToItem() public function testCreateItemWithOperationName() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -264,7 +265,7 @@ public function testCreateItemWithOperationName() public function testCreateCollectionWithOperationName() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -289,7 +290,7 @@ public function testDenormalizeItemWithCorrectResourceClass() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); //Dummy is the correct class for the denormalization context serialization groups, and we're fetching RelatedDummy - $resourceMetadata = (new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]]); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['normalization_context' => ['groups' => ['foo']]])]); $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($resourceMetadata)->shouldBeCalled(); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata)->shouldBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -312,7 +313,7 @@ public function testDenormalizeItemWithExistingGroups() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); //groups exist from the context, we don't need to compute them again - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -336,7 +337,7 @@ public function testMaxJoinsReached() $this->expectExceptionMessage('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary with the "api_platform.eager_loading.max_joins" configuration key (https://api-platform.com/docs/core/performance/#eager-loading), or limit the maximum serialization depth using the "enable_max_depth" option of the Symfony serializer (https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth).'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -385,8 +386,9 @@ public function testMaxJoinsReached() public function testMaxDepth() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => ['enable_max_depth' => 'true', 'groups' => ['foo']]]); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['normalization_context' => ['enable_max_depth' => 'true', 'groups' => ['foo']]]), + ]); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); @@ -452,8 +454,9 @@ public function testMaxDepth() public function testForceEager() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]), + ]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); @@ -496,8 +499,9 @@ public function testForceEager() public function testExtraLazy() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]), + ]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); @@ -533,7 +537,9 @@ public function testExtraLazy() public function testResourceClassNotFoundException() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['normalization_context' => ['groups' => ['foo']]]), + ]))); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -557,7 +563,9 @@ public function testResourceClassNotFoundException() public function testPropertyNotFoundException() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['normalization_context' => ['groups' => ['foo']]]), + ]))); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -581,7 +589,9 @@ public function testPropertyNotFoundException() public function testResourceClassNotFoundExceptionPropertyNameCollection() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['normalization_context' => ['groups' => ['foo']]]), + ]))); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willThrow(new ResourceClassNotFoundException()); @@ -610,7 +620,7 @@ public function testResourceClassNotFoundExceptionPropertyNameCollection() public function testApplyToCollectionWithSerializerContextBuilder() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -674,7 +684,7 @@ public function testApplyToCollectionWithSerializerContextBuilder() public function testAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -738,7 +748,7 @@ public function testAttributes() public function testNotInAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -779,7 +789,7 @@ public function testNotInAttributes() public function testOnlyOneRelationNotInAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -845,7 +855,7 @@ public function testOnlyOneRelationNotInAttributes() public function testApplyToCollectionNoPartial() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['normalization_context' => ['groups' => ['foo']]])]))); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -899,7 +909,7 @@ public function testLegacyApplyToCollectionWithANonReadableButFetchEagerProperty private function doTestApplyToCollectionWithANonReadableButFetchEagerProperty(bool $legacy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['normalization_context' => ['groups' => ['foo']]])]))); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -955,7 +965,7 @@ public function testLegacyApplyToCollectionWithAReadableButNotFetchEagerProperty private function doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(bool $legacy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['normalization_context' => ['groups' => ['foo']]])]))); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); diff --git a/tests/Bridge/Doctrine/Orm/Extension/FilterExtensionTest.php b/tests/Bridge/Doctrine/Orm/Extension/FilterExtensionTest.php index abdd3b6e0b6..bc5b55b2934 100644 --- a/tests/Bridge/Doctrine/Orm/Extension/FilterExtensionTest.php +++ b/tests/Bridge/Doctrine/Orm/Extension/FilterExtensionTest.php @@ -20,6 +20,7 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -38,7 +39,7 @@ public function testApplyToCollectionWithValidFilters() { $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET', 'filters' => ['dummyFilter', 'dummyBadFilter']], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET', 'filters' => ['dummyFilter', 'dummyBadFilter']], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], [])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); @@ -67,7 +68,7 @@ public function testApplyToCollectionWithValidFiltersAndDeprecatedFilterCollecti { $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET', 'filters' => ['dummyFilter']], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET', 'filters' => ['dummyFilter']], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], [])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); @@ -93,7 +94,7 @@ public function testConstructWithInvalidFilterLocator() public function testApplyToCollectionWithoutFilters() { - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']]); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); diff --git a/tests/Bridge/Doctrine/Orm/Extension/OrderExtensionTest.php b/tests/Bridge/Doctrine/Orm/Extension/OrderExtensionTest.php index 8b938800cfb..3bada7e6811 100644 --- a/tests/Bridge/Doctrine/Orm/Extension/OrderExtensionTest.php +++ b/tests/Bridge/Doctrine/Orm/Extension/OrderExtensionTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\OrderExtension; use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\EmbeddedDummy; @@ -82,7 +83,7 @@ public function testApplyToCollectionWithOrderOverridden() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['foo' => 'DESC']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['foo' => 'DESC']])])); $emProphecy = $this->prophesize(EntityManager::class); $emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -106,7 +107,7 @@ public function testApplyToCollectionWithOrderOverriddenWithNoDirection() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['foo', 'bar' => 'DESC']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['foo', 'bar' => 'DESC']])])); $emProphecy = $this->prophesize(EntityManager::class); $emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -131,7 +132,7 @@ public function testApplyToCollectionWithOrderOverriddenWithAssociation() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['author.name']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['author.name']])])); $emProphecy = $this->prophesize(EntityManager::class); $emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -155,7 +156,7 @@ public function testApplyToCollectionWithOrderOverriddenWithEmbeddedAssociation( $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['id']); $classMetadataProphecy->embeddedClasses = ['embeddedDummy' => []]; - $resourceMetadataFactoryProphecy->create(EmbeddedDummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['embeddedDummy.dummyName' => 'DESC']])); + $resourceMetadataFactoryProphecy->create(EmbeddedDummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['embeddedDummy.dummyName' => 'DESC']])])); $emProphecy = $this->prophesize(EntityManager::class); $emProphecy->getClassMetadata(EmbeddedDummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); diff --git a/tests/Bridge/Doctrine/Orm/Extension/PaginationExtensionTest.php b/tests/Bridge/Doctrine/Orm/Extension/PaginationExtensionTest.php index cddca47dc65..0239b3f0150 100644 --- a/tests/Bridge/Doctrine/Orm/Extension/PaginationExtensionTest.php +++ b/tests/Bridge/Doctrine/Orm/Extension/PaginationExtensionTest.php @@ -22,6 +22,7 @@ use ApiPlatform\Core\DataProvider\PartialPaginatorInterface; use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -127,7 +128,7 @@ public function testApplyToCollection() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 40, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -164,7 +165,7 @@ public function testLegacyApplyToCollection() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 40, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -193,7 +194,7 @@ public function testApplyToCollectionWithItemPerPageZero() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 0, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -231,7 +232,7 @@ public function testLegacyApplyToCollectionWithItemPerPageZero() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 0, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -263,7 +264,7 @@ public function testApplyToCollectionWithItemPerPageZeroAndPage2() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 0, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -304,7 +305,7 @@ public function testLegacyApplyToCollectionWithItemPerPageZeroAndPage2() 'pagination_client_enabled' => true, 'pagination_items_per_page' => 0, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -336,7 +337,7 @@ public function testApplyToCollectionWithItemPerPageLessThan0() 'pagination_client_enabled' => true, 'pagination_items_per_page' => -20, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -377,7 +378,7 @@ public function testLegacyApplyToCollectionWithItemPerPageLessThen0() 'pagination_client_enabled' => true, 'pagination_items_per_page' => -20, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -406,7 +407,7 @@ public function testApplyToCollectionWithItemPerPageTooHigh() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => true, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -444,7 +445,7 @@ public function testLegacyApplyToCollectionWithItemPerPageTooHigh() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => true, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -476,7 +477,7 @@ public function testApplyToCollectionWithGraphql() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => 20, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -514,7 +515,7 @@ public function testLegacyApplyToCollectionWithGraphql() 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => 20, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -537,7 +538,7 @@ public function testLegacyApplyToCollectionWithGraphql() public function testApplyToCollectionNofilters() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -586,7 +587,7 @@ public function testLegacyApplyToCollectionEmptyRequest() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -605,7 +606,7 @@ public function testLegacyApplyToCollectionEmptyRequest() public function testApplyToCollectionPaginationDisabled() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -637,7 +638,7 @@ public function testLegacyApplyToCollectionPaginationDisabled() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -657,7 +658,7 @@ public function testLegacyApplyToCollectionPaginationDisabled() public function testApplyToCollectionGraphQlPaginationDisabled() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [], [ @@ -685,7 +686,7 @@ public function testApplyToCollectionWithMaximumItemsPerPage() 'pagination_client_enabled' => true, 'pagination_maximum_items_per_page' => 80, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes)); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -725,7 +726,7 @@ public function testLegacyApplyToCollectionWithMaximumItemsPerPage() 'pagination_client_enabled' => true, 'maximum_items_per_page' => 80, ]; - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], $attributes))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], $attributes)]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -752,7 +753,7 @@ public function testLegacyApplyToCollectionWithMaximumItemsPerPage() public function testSupportsResult() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory); @@ -776,7 +777,7 @@ public function testLegacySupportsResult() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $extension = new PaginationExtension( @@ -813,7 +814,7 @@ public function testLegacySupportsResultEmptyRequest() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $extension = new PaginationExtension( @@ -827,7 +828,7 @@ public function testLegacySupportsResultEmptyRequest() public function testSupportsResultClientNotAllowedToPaginate() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -855,7 +856,7 @@ public function testLegacySupportsResultClientNotAllowedToPaginate() $requestStack->push(new Request(['pagination' => true])); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $extension = new PaginationExtension( @@ -871,7 +872,7 @@ public function testLegacySupportsResultClientNotAllowedToPaginate() public function testSupportsResultPaginationDisabled() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [ @@ -898,7 +899,7 @@ public function testLegacySupportsResultPaginationDisabled() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $extension = new PaginationExtension( @@ -913,7 +914,7 @@ public function testLegacySupportsResultPaginationDisabled() public function testSupportsResultGraphQlPaginationDisabled() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [])])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $pagination = new Pagination($resourceMetadataFactory, [], [ @@ -949,7 +950,7 @@ public function testGetResult() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy')])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -984,7 +985,7 @@ public function testGetResultWithoutDistinct() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy')])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1029,7 +1030,7 @@ public function testLegacyGetResult() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy')])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1064,7 +1065,7 @@ public function testGetResultWithFetchJoinCollectionDisabled() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, null, ['pagination_fetch_join_collection' => false])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, null, ['pagination_fetch_join_collection' => false])])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1113,7 +1114,7 @@ public function testLegacyGetResultWithFetchJoinCollectionDisabled() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, null, ['pagination_fetch_join_collection' => false])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, null, ['pagination_fetch_join_collection' => false])])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1154,7 +1155,7 @@ public function testGetResultWithUseOutputWalkersDisabled() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, null, ['pagination_use_output_walkers' => false])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, null, ['pagination_use_output_walkers' => false])])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1203,7 +1204,7 @@ public function testLegacyGetResultWithUseOutputWalkersDisabled() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, null, ['pagination_use_output_walkers' => false])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, null, ['pagination_use_output_walkers' => false])])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1244,7 +1245,7 @@ public function testGetResultWithPartial() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, null, ['pagination_partial' => true])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, null, ['pagination_partial' => true])])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), @@ -1287,7 +1288,7 @@ public function testLegacyGetResultWithPartial() $requestStack->push(new Request()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, null, ['pagination_partial' => true])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, null, ['pagination_partial' => true])])); $paginationExtension = new PaginationExtension( $managerRegistryProphecy->reveal(), diff --git a/tests/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php b/tests/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php index 5a8322d865b..60e581a5b6a 100644 --- a/tests/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php +++ b/tests/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php @@ -25,6 +25,7 @@ use ApiPlatform\Core\DataProvider\Pagination; use ApiPlatform\Core\Exception\ResourceClassNotFoundException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -68,10 +69,10 @@ public function testSupports() $identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false])); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['elasticsearch' => false])]))); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException()); $collectionDataProvider = new CollectionDataProvider( @@ -96,7 +97,7 @@ public function testGetCollection() $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $documents = [ 'took' => 15, diff --git a/tests/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtensionTest.php b/tests/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtensionTest.php index ce3a86062a3..dc0ad14ea1a 100644 --- a/tests/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtensionTest.php +++ b/tests/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtensionTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\ConstantScoreFilterInterface; use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\SortFilterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -42,7 +43,7 @@ public function testConstruct() public function testApplyToCollection() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata(null, null, null, null, ['get' => ['filters' => ['filter.term']]]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, ['get' => ['filters' => ['filter.term']]])]))->shouldBeCalled(); $constantScoreFilterProphecy = $this->prophesize(ConstantScoreFilterInterface::class); $constantScoreFilterProphecy->apply([], Foo::class, 'get', ['filters' => ['name' => ['Kilian', 'Xavier', 'François']]])->willReturn(['bool' => ['must' => [['terms' => ['name' => ['Kilian', 'Xavier', 'François']]]]]])->shouldBeCalled(); @@ -59,7 +60,7 @@ public function testApplyToCollection() public function testApplyToCollectionWithNoFilters() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $constantScoreFilterExtension = new ConstantScoreFilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal()); @@ -69,7 +70,7 @@ public function testApplyToCollectionWithNoFilters() public function testApplyToCollectionWithNoConstantScoreFilters() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata(null, null, null, null, ['get' => ['filters' => ['filter.order']]]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, ['get' => ['filters' => ['filter.order']]])]))->shouldBeCalled(); $containerProphecy = $this->prophesize(ContainerInterface::class); $containerProphecy->has('filter.order')->willReturn(true)->shouldBeCalled(); diff --git a/tests/Bridge/Elasticsearch/DataProvider/Extension/SortExtensionTest.php b/tests/Bridge/Elasticsearch/DataProvider/Extension/SortExtensionTest.php index caa8b3feaa1..ef7fbd6a734 100644 --- a/tests/Bridge/Elasticsearch/DataProvider/Extension/SortExtensionTest.php +++ b/tests/Bridge/Elasticsearch/DataProvider/Extension/SortExtensionTest.php @@ -20,6 +20,7 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -49,7 +50,7 @@ public function testConstruct() public function testApplyToCollection() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['name', 'bar' => 'desc']]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['name', 'bar' => 'desc']])]))->shouldBeCalled(); $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); $nameConverterProphecy->normalize('name', Foo::class)->willReturn('name')->shouldBeCalled(); @@ -63,7 +64,7 @@ public function testApplyToCollection() public function testApplyToCollectionWithNestedProperty() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['order' => ['foo.bar' => 'desc']]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['order' => ['foo.bar' => 'desc']])]))->shouldBeCalled(); $fooType = new Type(Type::BUILTIN_TYPE_ARRAY, false, Foo::class, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, Foo::class)); @@ -85,7 +86,7 @@ public function testApplyToCollectionWithNestedProperty() public function testApplyToCollectionWithDefaultDirection() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); @@ -101,7 +102,7 @@ public function testApplyToCollectionWithDefaultDirection() public function testApplyToCollectionWithNoOrdering() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $sortExtension = new SortExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(IdentifierExtractorInterface::class)->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal()); diff --git a/tests/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtensionTest.php b/tests/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtensionTest.php index 319ead908de..2691daafca3 100644 --- a/tests/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtensionTest.php +++ b/tests/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtensionTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\ConstantScoreFilterInterface; use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\SortFilterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -42,7 +43,7 @@ public function testConstruct() public function testApplyToCollection() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata(null, null, null, null, ['get' => ['filters' => ['filter.order']]]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, ['get' => ['filters' => ['filter.order']]])]))->shouldBeCalled(); $sortFilterProphecy = $this->prophesize(SortFilterInterface::class); $sortFilterProphecy->apply([], Foo::class, 'get', ['filters' => ['order' => ['id' => 'desc']]])->willReturn([['id' => ['order' => 'desc']]])->shouldBeCalled(); @@ -59,7 +60,7 @@ public function testApplyToCollection() public function testApplyToCollectionWithNoFilters() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $sortFilterExtension = new SortFilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal()); @@ -69,7 +70,7 @@ public function testApplyToCollectionWithNoFilters() public function testApplyToCollectionWithNoSortFilters() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata(null, null, null, null, ['get' => ['filters' => ['filter.term']]]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, ['get' => ['filters' => ['filter.term']]])]))->shouldBeCalled(); $containerProphecy = $this->prophesize(ContainerInterface::class); $containerProphecy->has('filter.term')->willReturn(true)->shouldBeCalled(); diff --git a/tests/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php b/tests/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php index a89545551da..80b10dc91f9 100644 --- a/tests/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php +++ b/tests/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php @@ -23,6 +23,7 @@ use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\Exception\ResourceClassNotFoundException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -66,10 +67,10 @@ public function testSupports() $identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false])); + $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); + $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['elasticsearch' => false])]))); $resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException()); $itemDataProvider = new ItemDataProvider( diff --git a/tests/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php b/tests/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php index c21a5ba30aa..a1580934ecf 100644 --- a/tests/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php +++ b/tests/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory; use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -45,8 +46,9 @@ public function testCreate() $decoratedProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); $decoratedProphecy->create(Foo::class)->willReturn($originalDocumentMetadata)->shouldBeCalled(); - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['elasticsearch_index' => 'foo', 'elasticsearch_type' => 'bar']); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withAttributes(['elasticsearch_index' => 'foo', 'elasticsearch_type' => 'bar']), + ]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn($resourceMetadata)->shouldBeCalled(); @@ -67,7 +69,7 @@ public function testCreateWithNoParentDocumentMetadataAndNoAttributes() $decoratedProphecy->create(Foo::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); (new AttributeDocumentMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $decoratedProphecy->reveal()))->create(Foo::class); } diff --git a/tests/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php b/tests/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php index 6c1b03a3c92..da5467d41a7 100644 --- a/tests/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php +++ b/tests/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory; use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -48,7 +49,7 @@ public function testCreate() $decoratedProphecy->create(Foo::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadata('Foo'))->shouldBeCalled(); + $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Foo')]))->shouldBeCalled(); $catNamespaceProphecy = $this->prophesize(CatNamespace::class); $catNamespaceProphecy->indices(['index' => 'foo']) @@ -97,7 +98,7 @@ public function testCreateWithNoResourceShortName() $decoratedProphecy->create(Foo::class)->willReturn($originalDocumentMetadata)->shouldBeCalled(); $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $documentMetadata = (new CatDocumentMetadataFactory($this->prophesize(Client::class)->reveal(), $resourceMetadataFactory->reveal(), $decoratedProphecy->reveal()))->create(Foo::class); @@ -115,7 +116,7 @@ public function testCreateWithIndexNotFound() $decoratedProphecy->create(Foo::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadata('Foo'))->shouldBeCalled(); + $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Foo')]))->shouldBeCalled(); $catNamespaceProphecy = $this->prophesize(CatNamespace::class); $catNamespaceProphecy->indices(['index' => 'foo'])->willThrow(new Missing404Exception())->shouldBeCalled(); diff --git a/tests/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php b/tests/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php index bc77eca98e3..23594744874 100644 --- a/tests/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php +++ b/tests/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Resource\Factory\ElasticsearchOperationResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -35,7 +36,7 @@ public function testConstruct() public function testCreate() { $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $decoratedProphecy->create(Foo::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $resourceMetadata = (new ElasticsearchOperationResourceMetadataFactory($decoratedProphecy->reveal()))->create(Foo::class); @@ -45,9 +46,10 @@ public function testCreate() public function testCreateWithExistingOperations() { - $originalResourceMetadata = new ResourceMetadata(); - $originalResourceMetadata = $originalResourceMetadata->withItemOperations(['foo' => ['method' => 'GET']]); - $originalResourceMetadata = $originalResourceMetadata->withCollectionOperations(['bar' => ['method' => 'GET']]); + $originalResourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withItemOperations(['foo' => ['method' => 'GET']]) + ->withCollectionOperations(['bar' => ['method' => 'GET']]), + ]); $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedProphecy->create(Foo::class)->willReturn($originalResourceMetadata)->shouldBeCalled(); diff --git a/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php b/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php index e27c1c3b712..89510240cb8 100644 --- a/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php +++ b/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php @@ -21,6 +21,7 @@ use ApiPlatform\Core\Documentation\Documentation; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -126,7 +127,7 @@ private function extractAnnotations($filterLocator) $apiDocumentationBuilderProphecy = $this->prophesize(NormalizerInterface::class); $apiDocumentationBuilderProphecy->normalize(new Documentation($resourceNameCollection))->willReturn($this->getHydraDoc())->shouldBeCalled(); - $dummyResourceMetadata = (new ResourceMetadata()) + $dummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) ->withShortName('Dummy') ->withItemOperations([ 'get' => [ @@ -149,10 +150,9 @@ private function extractAnnotations($filterLocator) 'post' => [ 'method' => 'POST', ], - ]); + ]), ])); - $relatedDummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('RelatedDummy'); + $relatedDummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withShortName('RelatedDummy')])); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); @@ -396,13 +396,13 @@ public function testGetAnnotationsWithInvalidHydraSupportedOperation() $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - $dummyResourceMetadata = (new ResourceMetadata()) + $dummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) ->withShortName('Dummy') ->withItemOperations([ 'get' => [ 'method' => 'GET', ], - ]); + ]), ])); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); @@ -440,13 +440,13 @@ public function testGetAnnotationsWithEmptyHydraSupportedOperation() $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - $dummyResourceMetadata = (new ResourceMetadata()) + $dummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) ->withShortName('Dummy') ->withItemOperations([ 'get' => [ 'method' => 'GET', ], - ]); + ]), ])); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); @@ -484,13 +484,13 @@ public function testGetAnnotationsWithInvalidHydraSupportedProperty() $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - $dummyResourceMetadata = (new ResourceMetadata()) + $dummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) ->withShortName('Dummy') ->withCollectionOperations([ 'get' => [ 'method' => 'GET', ], - ]); + ]), ])); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); @@ -528,13 +528,13 @@ public function testGetAnnotationsWithEmptyHydraSupportedProperty() $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - $dummyResourceMetadata = (new ResourceMetadata()) + $dummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) ->withShortName('Dummy') ->withCollectionOperations([ 'get' => [ 'method' => 'GET', ], - ]); + ]), ])); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); diff --git a/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php b/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php index 3e041c8678e..696699dd653 100644 --- a/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php +++ b/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php @@ -20,6 +20,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy; @@ -68,7 +69,7 @@ public function testConstruct() public function testSupports() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -90,7 +91,7 @@ public function testSupports() public function testNoOnDataFirstArray() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -112,11 +113,11 @@ public function testNoOnDataFirstArray() public function testSupportsAttributeNormalization() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Acme\CustomAttributeDummy')->willReturn(new ResourceMetadata('dummy', 'dummy', null, [ + $resourceMetadataFactoryProphecy->create('Acme\CustomAttributeDummy')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', null, [ 'get' => ['method' => 'GET', 'normalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_get']]], 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], 'delete' => ['method' => 'DELETE'], - ], []))->shouldBeCalled(); + ], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -216,12 +217,12 @@ public function testSupportsUnsupportedClassFormat() public function testParse() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [ + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', null, [ 'get' => ['method' => 'GET', 'normalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_get']]], 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], 'gerard' => ['method' => 'get', 'path' => '/gerard', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], 'delete' => ['method' => 'DELETE'], - ], []))->shouldBeCalled(); + ], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -290,7 +291,7 @@ public function testParse() public function testParseDateTime() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -332,8 +333,8 @@ public function testParseDateTime() public function testParseRelation() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', null, [], [])]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -423,7 +424,7 @@ public function testParseRelation() public function testParseWithNameConverter() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', null, [], [])]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -468,8 +469,8 @@ public function testParseWithNameConverter() public function testParseRecursive() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', null, [], [])]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); diff --git a/tests/Bridge/Symfony/Bundle/Action/SwaggerUiActionTest.php b/tests/Bridge/Symfony/Bundle/Action/SwaggerUiActionTest.php index 73ad02d47c2..db396cf5f88 100644 --- a/tests/Bridge/Symfony/Bundle/Action/SwaggerUiActionTest.php +++ b/tests/Bridge/Symfony/Bundle/Action/SwaggerUiActionTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\Documentation\Documentation; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -54,7 +55,7 @@ public function testInvoke(Request $request, $twigProphecy) $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['Foo', 'Bar']))->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata('F'))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'F')]))->shouldBeCalled(); $normalizerProphecy = $this->prophesize(NormalizerInterface::class); $normalizerProphecy->normalize(Argument::type(Documentation::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); @@ -158,7 +159,7 @@ public function testDoNotRunCurrentRequest(Request $request) $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['Foo', 'Bar']))->shouldBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $normalizerProphecy = $this->prophesize(NormalizerInterface::class); $normalizerProphecy->normalize(Argument::type(Documentation::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); diff --git a/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php b/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php index 90e31dffbb5..a54dae17bbd 100644 --- a/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php +++ b/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php @@ -27,6 +27,7 @@ use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyEntity; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -253,7 +254,7 @@ private function apiResourceClassWillReturn($data, $context = []) ->create($data) ->shouldBeCalled() ->willReturn( - new ResourceMetadata(null, null, null, [], [], ['filters' => ['foo', 'a_filter']]) + new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], [], ['filters' => ['foo', 'a_filter']])]) ); } } diff --git a/tests/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php b/tests/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php index 1a231b883c7..86db79778c3 100644 --- a/tests/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php +++ b/tests/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiContext; use ApiPlatform\Core\Documentation\DocumentationInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\Core\OpenApi\Model\Info; @@ -48,7 +49,7 @@ class SwaggerUiActionTest extends TestCase public function testInvoke(Request $request, $twigProphecy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata('F'))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'F')]))->shouldBeCalled(); $normalizerProphecy = $this->prophesize(NormalizerInterface::class); $normalizerProphecy->normalize(Argument::type(DocumentationInterface::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); @@ -153,7 +154,7 @@ public function getInvokeParameters() public function testDoNotRunCurrentRequest(Request $request) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $normalizerProphecy = $this->prophesize(NormalizerInterface::class); $normalizerProphecy->normalize(Argument::type(DocumentationInterface::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); diff --git a/tests/Bridge/Symfony/Messenger/DataPersisterTest.php b/tests/Bridge/Symfony/Messenger/DataPersisterTest.php index 30b9a9110d0..4ba6e3591cc 100644 --- a/tests/Bridge/Symfony/Messenger/DataPersisterTest.php +++ b/tests/Bridge/Symfony/Messenger/DataPersisterTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; use ApiPlatform\Core\Exception\ResourceClassNotFoundException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar; @@ -38,7 +39,7 @@ class DataPersisterTest extends TestCase public function testSupport() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => true])])); $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal(), $this->prophesize(ContextAwareDataPersisterInterface::class)->reveal()); $this->assertTrue($dataPersister->supports(new Dummy())); @@ -47,7 +48,7 @@ public function testSupport() public function testSupportWithContext() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => true])])); $metadataFactoryProphecy->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal(), $this->prophesize(ContextAwareDataPersisterInterface::class)->reveal()); @@ -58,7 +59,7 @@ public function testSupportWithContext() public function testSupportWithContextAndMessengerDispatched() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => true])])); $metadataFactoryProphecy->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal(), $this->prophesize(ContextAwareDataPersisterInterface::class)->reveal()); @@ -70,8 +71,8 @@ public function testPersist() $dummy = new Dummy(); $metadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => true])])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'input'])])); $metadataFactory->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); $chainDataPersister = $this->prophesize(ContextAwareDataPersisterInterface::class); @@ -91,8 +92,8 @@ public function testRemove() $dummy = new Dummy(); $metadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => true])])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'input'])])); $metadataFactory->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); $chainDataPersister = $this->prophesize(ContextAwareDataPersisterInterface::class); @@ -112,8 +113,8 @@ public function testPersistWithHandOver() $dummy = new Dummy(); $metadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'persist'])); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => ['persist', 'input']])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'persist'])])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => ['persist', 'input']])])); $metadataFactory->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); $chainDataPersister = $this->prophesize(ContextAwareDataPersisterInterface::class); @@ -154,8 +155,8 @@ public function testRemoveWithHandOver() $dummy = new Dummy(); $metadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'persist'])); - $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => ['persist', 'input']])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'persist'])])); + $metadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => ['persist', 'input']])])); $metadataFactory->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); $chainDataPersister = $this->prophesize(ContextAwareDataPersisterInterface::class); @@ -173,7 +174,7 @@ public function testRemoveWithHandOver() public function testSupportWithGraphqlContext() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata(null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies', null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])]))); $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal(), $this->prophesize(ContextAwareDataPersisterInterface::class)->reveal()); $this->assertTrue($dataPersister->supports(new DummyCar(), ['resource_class' => Dummy::class, 'graphql_operation_name' => 'create'])); diff --git a/tests/Bridge/Symfony/Messenger/DataTransformerTest.php b/tests/Bridge/Symfony/Messenger/DataTransformerTest.php index 82b529d9188..e19dc9087b5 100644 --- a/tests/Bridge/Symfony/Messenger/DataTransformerTest.php +++ b/tests/Bridge/Symfony/Messenger/DataTransformerTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Bridge\Symfony\Messenger\DataTransformer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -34,7 +35,7 @@ class DataTransformerTest extends TestCase public function testSupport() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'input'])])); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth']])); @@ -46,7 +47,7 @@ public function testSupport() public function testSupportWithinRequest() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['foo' => ['messenger' => 'input']], null, [])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['foo' => ['messenger' => 'input']], null, [])])); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'operation_type' => OperationType::ITEM, 'item_operation_name' => 'foo'])); @@ -55,7 +56,7 @@ public function testSupportWithinRequest() public function testNoSupport() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => true])])); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth']])); @@ -64,7 +65,7 @@ public function testNoSupport() public function testNoSupportWithinRequest() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['foo' => ['messenger' => true]], null, [])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['foo' => ['messenger' => true]], null, [])])); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'operation_type' => OperationType::ITEM, 'item_operation_name' => 'foo'])); @@ -76,7 +77,7 @@ public function testNoSupportWithinRequest() public function testNoSupportWithoutInput() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'input'])])); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, [])); @@ -88,7 +89,7 @@ public function testNoSupportWithoutInput() public function testNoSupportWithObject() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['messenger' => 'input'])])); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertFalse($dataTransformer->supportsTransformation(new Dummy(), Dummy::class, [])); @@ -108,7 +109,7 @@ public function testTransform() public function testSupportWithGraphqlContext() { $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata(null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])); + $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies', null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])]))); $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'graphql_operation_name' => 'create'])); } diff --git a/tests/Bridge/Symfony/Routing/ApiLoaderTest.php b/tests/Bridge/Symfony/Routing/ApiLoaderTest.php index 1570e7e27fe..50e2b21a8dd 100644 --- a/tests/Bridge/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Bridge/Symfony/Routing/ApiLoaderTest.php @@ -23,6 +23,7 @@ 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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; @@ -49,24 +50,25 @@ class ApiLoaderTest extends TestCase public function testApiLoader() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withAttributes(['identified_by' => 'id']); - //default operation based on OperationResourceMetadataFactory - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - //custom operations - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'requirements' => ['_format' => 'a valid format'], 'defaults' => ['my_default' => 'default_value'], 'condition' => "request.headers.get('User-Agent') matches '/firefox/i'", 'stateless' => null], //with controller - 'my_second_op' => ['method' => 'POST', 'options' => ['option' => 'option_value'], 'host' => '{subdomain}.api-platform.com', 'schemes' => ['https'], 'stateless' => null], //without controller, takes the default one - 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], //custom path - 'my_stateless_op' => ['method' => 'GET', 'stateless' => true], - ]); - $resourceMetadata = $resourceMetadata->withSubresourceOperations([ - 'subresources_get_subresource' => ['stateless' => true], + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withShortName('dummy') + ->withAttributes(['identified_by' => 'id']) + //default operation based on OperationResourceMetadataFactory + ->withItemOperations([ + 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], + 'put' => ['method' => 'PUT', 'stateless' => null], + 'delete' => ['method' => 'DELETE', 'stateless' => null], + ]) + //custom operations + ->withCollectionOperations([ + 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'requirements' => ['_format' => 'a valid format'], 'defaults' => ['my_default' => 'default_value'], 'condition' => "request.headers.get('User-Agent') matches '/firefox/i'", 'stateless' => null], //with controller + 'my_second_op' => ['method' => 'POST', 'options' => ['option' => 'option_value'], 'host' => '{subdomain}.api-platform.com', 'schemes' => ['https'], 'stateless' => null], //without controller, takes the default one + 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], //custom path + 'my_stateless_op' => ['method' => 'GET', 'stateless' => true], + ]) + ->withSubresourceOperations([ + 'subresources_get_subresource' => ['stateless' => true], + ]), ]); $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); @@ -114,14 +116,15 @@ public function testApiLoader() public function testApiLoaderWithPrefix() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withShortName('dummy') + ->withItemOperations([ + 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], + 'put' => ['method' => 'PUT', 'stateless' => null], + 'delete' => ['method' => 'DELETE', 'stateless' => null], + ]) + ->withAttributes(['route_prefix' => '/foobar-prefix', 'identified_by' => 'id']), ]); - $resourceMetadata = $resourceMetadata->withAttributes(['route_prefix' => '/foobar-prefix', 'identified_by' => 'id']); $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); @@ -145,15 +148,14 @@ public function testNoMethodApiLoader() { $this->expectException(\RuntimeException::class); - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => [], - ]); - - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withShortName('dummy') + ->withItemOperations([ + 'get' => [], + ]) + ->withCollectionOperations([ + 'get' => ['method' => 'GET', 'stateless' => null], + ]), ]); $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); @@ -163,15 +165,14 @@ public function testWrongMethodApiLoader() { $this->expectException(\RuntimeException::class); - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'post' => ['method' => 'POST', 'stateless' => null], - ]); - - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withShortName('dummy') + ->withItemOperations([ + 'post' => ['method' => 'POST', 'stateless' => null], + ]) + ->withCollectionOperations([ + 'get' => ['method' => 'GET', 'stateless' => null], + ]), ]); $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); @@ -181,22 +182,23 @@ public function testNoShortNameApiLoader() { $this->expectException(InvalidResourceException::class); - $this->getApiLoaderWithResourceMetadata(new ResourceMetadata())->load(null); + $this->getApiLoaderWithResourceMetadata(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->load(null); } public function testRecursiveSubresource() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'stateless' => null], //with controller - 'my_second_op' => ['method' => 'POST', 'stateless' => null], //without controller, takes the default one - 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], //custom path + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withShortName('dummy') + ->withItemOperations([ + 'get' => ['method' => 'GET', 'stateless' => null], + 'put' => ['method' => 'PUT', 'stateless' => null], + 'delete' => ['method' => 'DELETE', 'stateless' => null], + ]) + ->withCollectionOperations([ + 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'stateless' => null], //with controller + 'my_second_op' => ['method' => 'POST', 'stateless' => null], //without controller, takes the default one + 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], //custom path + ]), ]); $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata, true)->load(null); @@ -257,11 +259,11 @@ private function getApiLoaderWithResourceMetadata(ResourceMetadata $resourceMeta $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata); - $relatedDummyEntityMetadata = (new ResourceMetadata())->withShortName('related_dummies')->withSubresourceOperations([ + $relatedDummyEntityMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withShortName('related_dummies')->withSubresourceOperations([ 'recursivesubresource_get_subresource' => [ 'controller' => 'dummy_controller', ], - ]); + ])])); $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->willReturn($relatedDummyEntityMetadata); diff --git a/tests/Bridge/Symfony/Routing/IriConverterTest.php b/tests/Bridge/Symfony/Routing/IriConverterTest.php index 96cf660e91f..ccc436cdf81 100644 --- a/tests/Bridge/Symfony/Routing/IriConverterTest.php +++ b/tests/Bridge/Symfony/Routing/IriConverterTest.php @@ -28,6 +28,7 @@ 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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy; @@ -163,7 +164,7 @@ public function testGetIriFromResourceClassAbsoluteUrl() $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', '', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])])); $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); $this->assertEquals($converter->getIriFromResourceClass(Dummy::class), 'http://example.com/dummies'); @@ -220,7 +221,7 @@ public function testGetItemIriFromResourceClass() $routerProphecy->generate('api_dummies_get_item', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies/1'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['composite_identifier' => true])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['composite_identifier' => true])]))); $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); $this->assertEquals($converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]), '/dummies/1'); @@ -235,7 +236,7 @@ public function testGetItemIriFromResourceClassAbsoluteUrl() $routerProphecy->generate('api_dummies_get_item', ['id' => 1], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/1'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', '', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])])); $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); $this->assertEquals($converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]), 'http://example.com/dummies/1'); @@ -253,7 +254,7 @@ public function testNotAbleToGenerateGetItemIriFromResourceClass() $routerProphecy->generate('dummies', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['composite_identifier' => true])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['composite_identifier' => true])]))); $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); $converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]); diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php index 8e79a7abf56..e5c5fa84d92 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidateListener; use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyEntity; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -178,9 +179,9 @@ public function testThrowsValidationExceptionWithViolationsFound() private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array { - $resourceMetadata = new ResourceMetadata(null, null, null, [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [ 'create' => ['validation_groups' => $expectedValidationGroups], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); if ($receive) { diff --git a/tests/EventListener/DeserializeListenerTest.php b/tests/EventListener/DeserializeListenerTest.php index 602ed2ee4eb..7c977cf092f 100644 --- a/tests/EventListener/DeserializeListenerTest.php +++ b/tests/EventListener/DeserializeListenerTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\EventListener\DeserializeListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -106,11 +107,11 @@ public function testDoNotDeserializeWhenDisabledInOperationAttribute(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, [], [ 'post' => [ 'deserialize' => false, ], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); @@ -339,7 +340,7 @@ public function testNoContentType(): void $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->willReturn(['input' => ['class' => 'Foo'], 'output' => ['class' => 'Foo']]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]])); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['formats' => ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]])])); $listener = new DeserializeListener( $serializerProphecy->reveal(), diff --git a/tests/EventListener/QueryParameterValidateListenerTest.php b/tests/EventListener/QueryParameterValidateListenerTest.php index c77773bcb3d..31ae56536a7 100644 --- a/tests/EventListener/QueryParameterValidateListenerTest.php +++ b/tests/EventListener/QueryParameterValidateListenerTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\Exception\FilterValidationException; use ApiPlatform\Core\Filter\QueryParameterValidator; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -125,12 +126,7 @@ private function setUpWithFilters(array $filters = []) $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy ->create(Dummy::class) - ->willReturn( - (new ResourceMetadata('dummy')) - ->withAttributes([ - 'filters' => $filters, - ]) - ); + ->willReturn(new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'dummy'))->withAttributes(['filters' => $filters])])); $this->queryParameterValidor = $this->prophesize(QueryParameterValidator::class); diff --git a/tests/EventListener/ReadListenerTest.php b/tests/EventListener/ReadListenerTest.php index b07245d74e6..1a0cc21add3 100644 --- a/tests/EventListener/ReadListenerTest.php +++ b/tests/EventListener/ReadListenerTest.php @@ -21,6 +21,7 @@ use ApiPlatform\Core\Exception\RuntimeException; use ApiPlatform\Core\Identifier\IdentifierDenormalizerInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -114,11 +115,11 @@ public function testDoNotReadWhenDisabledInOperationAttribute() $identifierConverter = $this->prophesize(IdentifierDenormalizerInterface::class); - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, [ 'put' => [ 'read' => false, ], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); diff --git a/tests/EventListener/RespondListenerTest.php b/tests/EventListener/RespondListenerTest.php index fd397873464..9e8f635c033 100644 --- a/tests/EventListener/RespondListenerTest.php +++ b/tests/EventListener/RespondListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\EventListener\RespondListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -97,7 +98,7 @@ public function testPost200WithoutLocation() 'bar' ); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_OK]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['get' => ['status' => Response::HTTP_OK]])])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -121,7 +122,7 @@ public function testPost301WithLocation() 'bar' ); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_MOVED_PERMANENTLY]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['get' => ['status' => Response::HTTP_MOVED_PERMANENTLY]])])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -202,7 +203,7 @@ public function testSetSunsetHeader() 'bar' ); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['sunset' => 'tomorrow']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['get' => ['sunset' => 'tomorrow']])])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -226,7 +227,7 @@ public function testSetCustomStatus() 'bar' ); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_ACCEPTED]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['get' => ['status' => Response::HTTP_ACCEPTED]])])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); diff --git a/tests/EventListener/SerializeListenerTest.php b/tests/EventListener/SerializeListenerTest.php index 05cb16f14aa..8036e41cb0c 100644 --- a/tests/EventListener/SerializeListenerTest.php +++ b/tests/EventListener/SerializeListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\EventListener\SerializeListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Serializer\ResourceList; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; @@ -81,11 +82,11 @@ public function testDoNotSerializeWhenDisabledInOperationAttribute() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, [], [ 'post' => [ 'serialize' => false, ], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); diff --git a/tests/EventListener/WriteListenerTest.php b/tests/EventListener/WriteListenerTest.php index 7517a2eefbf..e356ae9a46c 100644 --- a/tests/EventListener/WriteListenerTest.php +++ b/tests/EventListener/WriteListenerTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\DataPersister\DataPersisterInterface; use ApiPlatform\Core\EventListener\WriteListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ConcreteDummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -151,7 +152,7 @@ public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() $iriConverterProphecy->getIriFromItem($dummy)->shouldNotBeCalled(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['output' => ['class' => null]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['output' => ['class' => null]])])); $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); @@ -281,11 +282,11 @@ public function testDoNotWriteWhenDisabledInOperationAttribute() $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, [], [ 'post' => [ 'write' => false, ], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); diff --git a/tests/Fixtures/FileConfigurations/multiple_resources.yml b/tests/Fixtures/FileConfigurations/multiple_resources.yml new file mode 100644 index 00000000000..7875322a073 --- /dev/null +++ b/tests/Fixtures/FileConfigurations/multiple_resources.yml @@ -0,0 +1,17 @@ +resources: + - 'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface': + path: /dummy-resources + properties: + something: + identifier: true + somethingElse: + writable: false + readable: true + - 'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface': + path: /dummy-resources-subresource + properties: + something: + identifier: true + somethingElse: + writable: false + readable: true diff --git a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php index a4d464f6770..76939ab5a49 100644 --- a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; @@ -89,7 +90,7 @@ public function testResolve(): void $readStageCollection = [new \stdClass()]; $this->readStageProphecy->__invoke($resourceClass, $rootClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($readStageCollection); - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->securityStageProphecy->__invoke($resourceClass, $operationName, $resolverContext + [ 'extra_variables' => [ @@ -166,7 +167,7 @@ public function testResolveCustom(): void $this->readStageProphecy->__invoke($resourceClass, $rootClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($readStageCollection); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata())->withGraphql([$operationName => ['collection_query' => 'query_resolver_id']]) + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([$operationName => ['collection_query' => 'query_resolver_id']])])) ); $customCollection = [new \stdClass()]; diff --git a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php index 4b16857a4cf..ba6895a21ab 100644 --- a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php @@ -22,6 +22,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStageInterface; use ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStageInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -94,7 +95,7 @@ public function testResolve(): void $deserializeStageItem->field = 'deserialize'; $this->deserializeStageProphecy->__invoke($readStageItem, $resourceClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($deserializeStageItem); - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->securityStageProphecy->__invoke($resourceClass, $operationName, $resolverContext + [ 'extra_variables' => [ @@ -180,7 +181,7 @@ public function testResolveNullDeserializeStageItem(): void $deserializeStageItem = null; $this->deserializeStageProphecy->__invoke($readStageItem, $resourceClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($deserializeStageItem); - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->securityStageProphecy->__invoke($resourceClass, $operationName, $resolverContext + [ 'extra_variables' => [ @@ -263,7 +264,7 @@ public function testResolveCustom(): void $this->deserializeStageProphecy->__invoke($readStageItem, $resourceClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($deserializeStageItem); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata())->withGraphql([$operationName => ['mutation' => 'query_resolver_id']]) + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([$operationName => ['mutation' => 'query_resolver_id']])])) ); $customItem = new \stdClass(); @@ -315,7 +316,7 @@ public function testResolveCustomBadItem(): void $this->deserializeStageProphecy->__invoke($readStageItem, $resourceClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($deserializeStageItem); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata('shortName'))->withGraphql([$operationName => ['mutation' => 'query_resolver_id']]) + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName'))->withGraphql([$operationName => ['mutation' => 'query_resolver_id']])])) ); $customItem = new Dummy(); diff --git a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php index 69cc1b31576..d791b2096c7 100644 --- a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -80,7 +81,7 @@ public function testResolve(?string $resourceClass, string $determinedResourceCl $this->readStageProphecy->__invoke($resourceClass, $rootClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($readStageItem); - $this->resourceMetadataFactoryProphecy->create($determinedResourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($determinedResourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->securityStageProphecy->__invoke($determinedResourceClass, $operationName, $resolverContext + [ 'extra_variables' => [ @@ -189,7 +190,7 @@ public function testResolveCustom(): void $this->readStageProphecy->__invoke($resourceClass, $rootClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($readStageItem); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata())->withGraphql([$operationName => ['item_query' => 'query_resolver_id']]) + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([$operationName => ['item_query' => 'query_resolver_id']])])) ); $customItem = new \stdClass(); @@ -230,7 +231,7 @@ public function testResolveCustomBadItem(): void $this->readStageProphecy->__invoke($resourceClass, $rootClass, $operationName, $resolverContext)->shouldBeCalled()->willReturn($readStageItem); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata())->withGraphql([$operationName => ['item_query' => 'query_resolver_id']]) + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([$operationName => ['item_query' => 'query_resolver_id']])])) ); $customItem = new Dummy(); diff --git a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php index 2d6240366a3..d33f0cab68a 100644 --- a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php @@ -20,6 +20,7 @@ use ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface; use ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; @@ -85,7 +86,7 @@ public function testResolve(): void $subscriptionId = 'subscriptionId'; $this->subscriptionManagerProphecy->retrieveSubscriptionId($resolverContext, $serializeStageData)->shouldBeCalled()->willReturn($subscriptionId); - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn((new ResourceMetadata())->withAttributes(['mercure' => true])); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['mercure' => true])]))); $mercureUrl = 'mercure-url'; $this->mercureSubscriptionIriGeneratorProphecy->generateMercureUrl($subscriptionId)->shouldBeCalled()->willReturn($mercureUrl); @@ -154,7 +155,7 @@ public function testResolveNoSubscriptionId(): void $this->subscriptionManagerProphecy->retrieveSubscriptionId($resolverContext, $serializeStageData)->willReturn(null); - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn((new ResourceMetadata())->withAttributes(['mercure' => true])); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['mercure' => true])]))); $this->mercureSubscriptionIriGeneratorProphecy->generateMercureUrl(Argument::any())->shouldNotBeCalled(); @@ -180,7 +181,7 @@ public function testResolveNoMercureSubscriptionIriGenerator(): void $subscriptionId = 'subscriptionId'; $this->subscriptionManagerProphecy->retrieveSubscriptionId($resolverContext, $serializeStageData)->willReturn($subscriptionId); - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn((new ResourceMetadata())->withAttributes(['mercure' => true])); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withAttributes(['mercure' => true])]))); $this->expectException(\LogicException::class); $this->expectExceptionMessage('Cannot use Mercure for subscriptions when MercureBundle is not installed. Try running "composer require mercure".'); diff --git a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php index 641ab7aa45d..a7ba0b6d3a7 100644 --- a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -60,9 +61,11 @@ public function testApplyDisabled($objectToPopulate): void { $operationName = 'item_query'; $resourceClass = 'myResource'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ - $operationName => ['deserialize' => false], - ]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withGraphql([ + $operationName => ['deserialize' => false], + ]), + ])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $result = ($this->deserializeStage)($objectToPopulate, $resourceClass, $operationName, []); @@ -80,7 +83,7 @@ public function testApply($objectToPopulate, array $denormalizationContext): voi $operationName = 'item_query'; $resourceClass = 'myResource'; $context = ['args' => ['input' => 'myInput']]; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, false)->shouldBeCalled()->willReturn($denormalizationContext); diff --git a/tests/GraphQl/Resolver/Stage/ReadStageTest.php b/tests/GraphQl/Resolver/Stage/ReadStageTest.php index 447622dc2b9..2f81e3433d3 100644 --- a/tests/GraphQl/Resolver/Stage/ReadStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ReadStageTest.php @@ -21,6 +21,7 @@ use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; @@ -72,9 +73,11 @@ public function testApplyDisabled(array $context, $expectedResult): void { $operationName = 'item_query'; $resourceClass = 'myResource'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ - $operationName => ['read' => false], - ]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withGraphql([ + $operationName => ['read' => false], + ]), + ])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $result = ($this->readStage)($resourceClass, null, $operationName, $context); @@ -108,7 +111,7 @@ public function testApplyItem(?string $identifier, $item, bool $throwNotFound, $ 'args' => ['id' => $identifier], 'info' => $info, ]; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $normalizationContext = ['normalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); @@ -152,7 +155,7 @@ public function testApplyMutationOrSubscription(bool $isMutation, bool $isSubscr 'args' => ['input' => ['id' => $identifier]], 'info' => $info, ]; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('shortName')); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName')])); $normalizationContext = ['normalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); @@ -205,7 +208,7 @@ public function testApplyCollection(array $args, ?string $rootClass, ?array $sou 'info' => $info, 'source' => $source, ]; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $normalizationContext = ['normalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php index 32fcdf211c2..670ec9afd98 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -53,7 +54,7 @@ protected function setUp(): void public function testNoSecurity(): void { $resourceClass = 'myResource'; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->resourceAccessCheckerProphecy->isGranted(Argument::cetera())->shouldNotBeCalled(); @@ -66,9 +67,9 @@ public function testGranted(): void $resourceClass = 'myResource'; $isGranted = 'not_granted'; $extraVariables = ['extra' => false]; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['security_post_denormalize' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted($resourceClass, $isGranted, $extraVariables)->shouldBeCalled()->willReturn(true); @@ -85,9 +86,9 @@ public function testGrantedLegacy(): void $resourceClass = 'myResource'; $isGranted = 'not_granted'; $extraVariables = ['extra' => false]; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['access_control' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted($resourceClass, $isGranted, $extraVariables)->shouldBeCalled()->willReturn(true); @@ -101,9 +102,9 @@ public function testNotGranted(): void $resourceClass = 'myResource'; $isGranted = 'not_granted'; $extraVariables = ['extra' => false]; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['security_post_denormalize' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted($resourceClass, $isGranted, $extraVariables)->shouldBeCalled()->willReturn(false); @@ -126,9 +127,9 @@ public function testNoSecurityBundleInstalled(): void $operationName = 'item_query'; $resourceClass = 'myResource'; $isGranted = 'not_granted'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['security_post_denormalize' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->expectException(\LogicException::class); @@ -141,7 +142,7 @@ public function testNoSecurityBundleInstalledNoExpression(): void $this->securityPostDenormalizeStage = new SecurityPostDenormalizeStage($this->resourceMetadataFactoryProphecy->reveal(), null); $resourceClass = 'myResource'; - $resourceMetadata = new ResourceMetadata(); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted(Argument::any())->shouldNotBeCalled(); diff --git a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php index bc15b7203f7..22ec5059c34 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStage; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -53,7 +54,7 @@ protected function setUp(): void public function testNoSecurity(): void { $resourceClass = 'myResource'; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $this->resourceAccessCheckerProphecy->isGranted(Argument::cetera())->shouldNotBeCalled(); @@ -66,9 +67,9 @@ public function testGranted(): void $resourceClass = 'myResource'; $isGranted = 'not_granted'; $extraVariables = ['extra' => false]; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['security' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted($resourceClass, $isGranted, $extraVariables)->shouldBeCalled()->willReturn(true); @@ -82,9 +83,9 @@ public function testNotGranted(): void $resourceClass = 'myResource'; $isGranted = 'not_granted'; $extraVariables = ['extra' => false]; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['security' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted($resourceClass, $isGranted, $extraVariables)->shouldBeCalled()->willReturn(false); @@ -107,9 +108,9 @@ public function testNoSecurityBundleInstalled(): void $operationName = 'item_query'; $resourceClass = 'myResource'; $isGranted = 'not_granted'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['security' => $isGranted], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->expectException(\LogicException::class); @@ -122,7 +123,7 @@ public function testNoSecurityBundleInstalledNoExpression(): void $this->securityStage = new SecurityStage($this->resourceMetadataFactoryProphecy->reveal(), null); $resourceClass = 'myResource'; - $resourceMetadata = new ResourceMetadata(); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->resourceAccessCheckerProphecy->isGranted(Argument::any())->shouldNotBeCalled(); diff --git a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php index baf6e3b0836..c3d4b68db4a 100644 --- a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; @@ -54,9 +55,9 @@ public function testApplyDisabled(array $context, bool $paginationEnabled, ?arra { $operationName = 'item_query'; $resourceClass = 'myResource'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['serialize' => false], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $result = ($this->createSerializeStage($paginationEnabled))(null, $resourceClass, $operationName, $context); @@ -83,7 +84,7 @@ public function applyDisabledProvider(): array public function testApply($itemOrCollection, string $operationName, array $context, bool $paginationEnabled, ?array $expectedResult): void { $resourceClass = 'myResource'; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('shortName')); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName')])); $normalizationContext = ['normalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); @@ -125,7 +126,7 @@ public function testApplyCollectionWithPagination(iterable $collection, array $a 'args' => $args, 'info' => $this->prophesize(ResolveInfo::class)->reveal(), ]; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('shortName')); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName')])); $normalizationContext = ['normalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); @@ -163,7 +164,7 @@ public function testApplyBadNormalizedData(): void $operationName = 'item_query'; $resourceClass = 'myResource'; $context = ['is_collection' => false, 'is_mutation' => false, 'is_subscription' => false, 'args' => [], 'info' => $this->prophesize(ResolveInfo::class)->reveal()]; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $normalizationContext = ['normalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); diff --git a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php index 3aa9c3ea987..e1af7039959 100644 --- a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStage; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Core\Validator\Exception\ValidationException; @@ -53,9 +54,9 @@ public function testApplyDisabled(): void { $operationName = 'item_query'; $resourceClass = 'myResource'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['validate' => false], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $this->validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); @@ -68,9 +69,9 @@ public function testApply(): void $operationName = 'item_query'; $resourceClass = 'myResource'; $validationGroups = ['group']; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['validation_groups' => $validationGroups], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $object = new \stdClass(); @@ -84,9 +85,9 @@ public function testApplyNotValidated(): void $operationName = 'item_query'; $resourceClass = 'myResource'; $validationGroups = ['group']; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['validation_groups' => $validationGroups], - ]); + ])])); $info = $this->prophesize(ResolveInfo::class)->reveal(); $context = ['info' => $info]; $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); diff --git a/tests/GraphQl/Resolver/Stage/WriteStageTest.php b/tests/GraphQl/Resolver/Stage/WriteStageTest.php index 20b276eb806..fa3f0a26b62 100644 --- a/tests/GraphQl/Resolver/Stage/WriteStageTest.php +++ b/tests/GraphQl/Resolver/Stage/WriteStageTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStage; use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -54,7 +55,7 @@ protected function setUp(): void public function testNoData(): void { $resourceClass = 'myResource'; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $result = ($this->writeStage)(null, $resourceClass, 'item_query', []); @@ -65,9 +66,9 @@ public function testApplyDisabled(): void { $operationName = 'item_query'; $resourceClass = 'myResource'; - $resourceMetadata = (new ResourceMetadata())->withGraphql([ + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ $operationName => ['write' => false], - ]); + ])])); $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata); $data = new \stdClass(); @@ -81,7 +82,7 @@ public function testApplyDelete(): void $operationName = 'delete'; $resourceClass = 'myResource'; $context = []; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $denormalizationContext = ['denormalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, false)->willReturn($denormalizationContext); @@ -100,7 +101,7 @@ public function testApply(): void $operationName = 'create'; $resourceClass = 'myResource'; $context = []; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $denormalizationContext = ['denormalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, false)->willReturn($denormalizationContext); @@ -124,7 +125,7 @@ public function testLegacyApply(): void $operationName = 'create'; $resourceClass = 'myResource'; $context = []; - $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $denormalizationContext = ['denormalization' => true]; $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, false)->willReturn($denormalizationContext); diff --git a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php index 5dd421f6688..70b2e79a969 100644 --- a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php +++ b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilder; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -68,15 +69,14 @@ public function testCreateNormalizationContext(?string $resourceClass, string $o } $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata('shortName')) - ->withGraphql([ - $operationName => [ - 'input' => ['class' => 'inputClass'], - 'output' => ['class' => 'outputClass'], - 'normalization_context' => ['groups' => ['normalization_group']], - ], - ]) - ); + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName'))->withGraphql([ + $operationName => [ + 'input' => ['class' => 'inputClass'], + 'output' => ['class' => 'outputClass'], + 'normalization_context' => ['groups' => ['normalization_group']], + ], + ]), + ]))); if ($expectedExceptionClass) { $this->expectException($expectedExceptionClass); @@ -231,15 +231,14 @@ public function createNormalizationContextProvider(): array public function testCreateDenormalizationContext(?string $resourceClass, string $operationName, array $expectedContext): void { $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn( - (new ResourceMetadata()) - ->withGraphql([ - $operationName => [ - 'input' => ['class' => 'inputClass'], - 'output' => ['class' => 'outputClass'], - 'denormalization_context' => ['groups' => ['denormalization_group']], - ], - ]) - ); + (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql([ + $operationName => [ + 'input' => ['class' => 'inputClass'], + 'output' => ['class' => 'outputClass'], + 'denormalization_context' => ['groups' => ['denormalization_group']], + ], + ]), + ]))); $context = $this->serializerContextBuilder->create($resourceClass, $operationName, [], false); diff --git a/tests/GraphQl/Type/FieldsBuilderTest.php b/tests/GraphQl/Type/FieldsBuilderTest.php index 6fe5922e969..26ed944a12a 100644 --- a/tests/GraphQl/Type/FieldsBuilderTest.php +++ b/tests/GraphQl/Type/FieldsBuilderTest.php @@ -26,6 +26,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -151,8 +152,8 @@ public function testGetItemQueryFields(string $resourceClass, ResourceMetadata $ public function itemQueryFieldsProvider(): array { return [ - 'no resource field configuration' => ['resourceClass', new ResourceMetadata(), 'action', [], null, null, []], - 'nominal standard type case with deprecation reason and description' => ['resourceClass', (new ResourceMetadata('ShortName'))->withGraphql(['action' => ['deprecation_reason' => 'not useful', 'description' => 'Custom description.']]), 'action', [], GraphQLType::string(), null, + 'no resource field configuration' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), 'action', [], null, null, []], + 'nominal standard type case with deprecation reason and description' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withGraphql(['action' => ['deprecation_reason' => 'not useful', 'description' => 'Custom description.']])])), 'action', [], GraphQLType::string(), null, [ 'actionShortName' => [ 'type' => GraphQLType::string(), @@ -165,7 +166,7 @@ public function itemQueryFieldsProvider(): array ], ], ], - 'nominal item case' => ['resourceClass', new ResourceMetadata('ShortName'), 'action', [], $graphqlType = new ObjectType(['name' => 'item']), $resolver = function () { + 'nominal item case' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'ShortName')]), 'action', [], $graphqlType = new ObjectType(['name' => 'item']), $resolver = function () { }, [ 'actionShortName' => [ @@ -180,7 +181,7 @@ public function itemQueryFieldsProvider(): array ], ], 'empty overridden args and add fields' => [ - 'resourceClass', new ResourceMetadata('ShortName'), 'item_query', ['args' => [], 'name' => 'customActionName'], GraphQLType::string(), null, + 'resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'ShortName')]), 'item_query', ['args' => [], 'name' => 'customActionName'], GraphQLType::string(), null, [ 'shortName' => [ 'type' => GraphQLType::string(), @@ -193,7 +194,7 @@ public function itemQueryFieldsProvider(): array ], ], 'override args with custom ones' => [ - 'resourceClass', new ResourceMetadata('ShortName'), 'item_query', ['args' => ['customArg' => ['type' => 'a type']]], GraphQLType::string(), null, + 'resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'ShortName')]), 'item_query', ['args' => ['customArg' => ['type' => 'a type']]], GraphQLType::string(), null, [ 'shortName' => [ 'type' => GraphQLType::string(), @@ -244,8 +245,8 @@ public function testGetCollectionQueryFields(string $resourceClass, ResourceMeta public function collectionQueryFieldsProvider(): array { return [ - 'no resource field configuration' => ['resourceClass', new ResourceMetadata(), 'action', [], null, null, []], - 'nominal collection case with deprecation reason and description' => ['resourceClass', (new ResourceMetadata('ShortName'))->withGraphql(['action' => ['deprecation_reason' => 'not useful', 'description' => 'Custom description.']]), 'action', [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { + 'no resource field configuration' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), 'action', [], null, null, []], + 'nominal collection case with deprecation reason and description' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withGraphql(['action' => ['deprecation_reason' => 'not useful', 'description' => 'Custom description.']])])), 'action', [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { }, [ 'actionShortNames' => [ @@ -274,7 +275,7 @@ public function collectionQueryFieldsProvider(): array ], ], ], - 'collection with filters' => ['resourceClass', (new ResourceMetadata('ShortName'))->withGraphql(['action' => ['filters' => ['my_filter']]]), 'action', [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { + 'collection with filters' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withGraphql(['action' => ['filters' => ['my_filter']]])])), 'action', [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { }, [ 'actionShortNames' => [ @@ -308,7 +309,7 @@ public function collectionQueryFieldsProvider(): array ], ], 'collection empty overridden args and add fields' => [ - 'resourceClass', new ResourceMetadata('ShortName'), 'action', ['args' => [], 'name' => 'customActionName'], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { + 'resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'ShortName')]), 'action', ['args' => [], 'name' => 'customActionName'], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { }, [ 'actionShortNames' => [ @@ -322,7 +323,7 @@ public function collectionQueryFieldsProvider(): array ], ], 'collection override args with custom ones' => [ - 'resourceClass', new ResourceMetadata('ShortName'), 'action', ['args' => ['customArg' => ['type' => 'a type']]], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { + 'resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'ShortName')]), 'action', ['args' => ['customArg' => ['type' => 'a type']]], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { }, [ 'actionShortNames' => [ @@ -338,7 +339,7 @@ public function collectionQueryFieldsProvider(): array ], ], ], - 'collection with page-based pagination enabled' => ['resourceClass', (new ResourceMetadata('ShortName', null, null, null, null, ['pagination_type' => 'page']))->withGraphql(['action' => ['filters' => ['my_filter']]]), 'action', [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { + 'collection with page-based pagination enabled' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName', null, null, null, null, ['pagination_type' => 'page']))->withGraphql(['action' => ['filters' => ['my_filter']]])])), 'action', [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function () { }, [ 'actionShortNames' => [ @@ -382,7 +383,7 @@ public function testGetMutationFields(string $resourceClass, ResourceMetadata $r public function mutationFieldsProvider(): array { return [ - 'nominal case with deprecation reason' => ['resourceClass', (new ResourceMetadata('ShortName'))->withGraphql(['action' => ['deprecation_reason' => 'not useful']]), 'action', $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function () { + 'nominal case with deprecation reason' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withGraphql(['action' => ['deprecation_reason' => 'not useful']])])), 'action', $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function () { }, [ 'actionShortName' => [ @@ -402,7 +403,7 @@ public function mutationFieldsProvider(): array ], ], ], - 'custom description' => ['resourceClass', (new ResourceMetadata('ShortName'))->withGraphql(['action' => ['description' => 'Custom description.']]), 'action', $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function () { + 'custom description' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withGraphql(['action' => ['description' => 'Custom description.']])])), 'action', $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function () { }, [ 'actionShortName' => [ @@ -445,9 +446,9 @@ public function testGetSubscriptionFields(string $resourceClass, ResourceMetadat public function subscriptionFieldsProvider(): array { return [ - 'mercure not enabled' => ['resourceClass', new ResourceMetadata('ShortName'), 'action', new ObjectType(['name' => 'subscription']), new ObjectType(['name' => 'input']), null, [], + 'mercure not enabled' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'ShortName')]), 'action', new ObjectType(['name' => 'subscription']), new ObjectType(['name' => 'input']), null, [], ], - 'nominal case with deprecation reason' => ['resourceClass', (new ResourceMetadata('ShortName'))->withAttributes(['mercure' => true])->withGraphql(['action' => ['deprecation_reason' => 'not useful']]), 'action', $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function () { + 'nominal case with deprecation reason' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withAttributes(['mercure' => true])->withGraphql(['action' => ['deprecation_reason' => 'not useful']])])), 'action', $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function () { }, [ 'actionShortNameSubscribe' => [ @@ -467,7 +468,7 @@ public function subscriptionFieldsProvider(): array ], ], ], - 'custom description' => ['resourceClass', (new ResourceMetadata('ShortName'))->withAttributes(['mercure' => true])->withGraphql(['action' => ['description' => 'Custom description.']]), 'action', $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function () { + 'custom description' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'ShortName'))->withAttributes(['mercure' => true])->withGraphql(['action' => ['description' => 'Custom description.']])])), 'action', $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function () { }, [ 'actionShortNameSubscribe' => [ @@ -508,7 +509,7 @@ public function testGetResourceObjectTypeFields(string $resourceClass, ResourceM $this->typesContainerProphecy->has('NotRegisteredType')->willReturn(false); $this->typesContainerProphecy->all()->willReturn([]); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(false); - $this->resourceMetadataFactoryProphecy->create('subresourceClass')->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create('subresourceClass')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $fieldsBuilder = $this->fieldsBuilder; if ($advancedNameConverter) { @@ -525,7 +526,7 @@ public function resourceObjectTypeFieldsProvider(): array $advancedNameConverter->normalize('field', 'resourceClass')->willReturn('normalizedField'); return [ - 'query' => ['resourceClass', new ResourceMetadata(), + 'query' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'property' => new PropertyMetadata(), 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, true, false), @@ -553,7 +554,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'query with advanced name converter' => ['resourceClass', new ResourceMetadata(), + 'query with advanced name converter' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'field' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true, false), ], @@ -572,7 +573,7 @@ public function resourceObjectTypeFieldsProvider(): array ], $advancedNameConverter->reveal(), ], - 'query input' => ['resourceClass', new ResourceMetadata(), + 'query input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'property' => new PropertyMetadata(), 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, false), @@ -591,7 +592,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'mutation non input' => ['resourceClass', new ResourceMetadata(), + 'mutation non input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'property' => new PropertyMetadata(), 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), @@ -611,7 +612,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'mutation input' => ['resourceClass', new ResourceMetadata(), + 'mutation input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'property' => new PropertyMetadata(), 'propertyBool' => (new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), 'propertyBool description', false, true))->withAttributes(['deprecation_reason' => 'not useful']), @@ -647,7 +648,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'delete mutation input' => ['resourceClass', new ResourceMetadata(), + 'delete mutation input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), ], @@ -659,7 +660,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'create mutation input' => ['resourceClass', new ResourceMetadata(), + 'create mutation input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), ], @@ -675,7 +676,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'update mutation input' => ['resourceClass', new ResourceMetadata(), + 'update mutation input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), ], @@ -694,7 +695,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'subscription non input' => ['resourceClass', new ResourceMetadata(), + 'subscription non input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'property' => new PropertyMetadata(), 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), @@ -714,7 +715,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'subscription input' => ['resourceClass', new ResourceMetadata(), + 'subscription input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'property' => new PropertyMetadata(), 'propertyBool' => (new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), 'propertyBool description', false, true))->withAttributes(['deprecation_reason' => 'not useful']), @@ -729,13 +730,13 @@ public function resourceObjectTypeFieldsProvider(): array 'clientSubscriptionId' => GraphQLType::string(), ], ], - 'null io metadata non input' => ['resourceClass', new ResourceMetadata(), + 'null io metadata non input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), ], false, null, 'update', null, ['class' => null], [], ], - 'null io metadata input' => ['resourceClass', new ResourceMetadata(), + 'null io metadata input' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'propertyBool' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_BOOL), null, false, true), ], @@ -744,7 +745,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'invalid types' => ['resourceClass', new ResourceMetadata(), + 'invalid types' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), [ 'propertyInvalidType' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_NULL), null, true, false), 'propertyNotRegisteredType' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_CALLABLE), null, true, false), diff --git a/tests/GraphQl/Type/SchemaBuilderTest.php b/tests/GraphQl/Type/SchemaBuilderTest.php index f61d556b7e3..00ddb22b128 100644 --- a/tests/GraphQl/Type/SchemaBuilderTest.php +++ b/tests/GraphQl/Type/SchemaBuilderTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\GraphQl\Type\TypesFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -101,7 +102,7 @@ public function testGetSchema(string $resourceClass, ResourceMetadata $resourceM public function schemaProvider(): array { return [ - 'no graphql configuration' => ['resourceClass', new ResourceMetadata(), + 'no graphql configuration' => ['resourceClass', new ResourceMetadata([new OperationCollectionMetadata('/dummies')]), new ObjectType([ 'name' => 'Query', 'fields' => [ @@ -109,7 +110,7 @@ public function schemaProvider(): array ], ]), null, null, ], - 'item query' => ['resourceClass', (new ResourceMetadata())->withGraphql(['item_query' => []]), + 'item query' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['item_query' => []])])), new ObjectType([ 'name' => 'Query', 'fields' => [ @@ -118,7 +119,7 @@ public function schemaProvider(): array ], ]), null, null, ], - 'collection query' => ['resourceClass', (new ResourceMetadata())->withGraphql(['collection_query' => []]), + 'collection query' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['collection_query' => []])])), new ObjectType([ 'name' => 'Query', 'fields' => [ @@ -127,7 +128,7 @@ public function schemaProvider(): array ], ]), null, null, ], - 'custom item query' => ['resourceClass', (new ResourceMetadata())->withGraphql(['custom_item_query' => ['item_query' => 'item_query_resolver']]), + 'custom item query' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['custom_item_query' => ['item_query' => 'item_query_resolver']])])), new ObjectType([ 'name' => 'Query', 'fields' => [ @@ -136,7 +137,7 @@ public function schemaProvider(): array ], ]), null, null, ], - 'custom collection query' => ['resourceClass', (new ResourceMetadata())->withGraphql(['custom_collection_query' => ['collection_query' => 'collection_query_resolver']]), + 'custom collection query' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['custom_collection_query' => ['collection_query' => 'collection_query_resolver']])])), new ObjectType([ 'name' => 'Query', 'fields' => [ @@ -145,7 +146,7 @@ public function schemaProvider(): array ], ]), null, null, ], - 'mutation' => ['resourceClass', (new ResourceMetadata())->withGraphql(['mutation' => []]), + 'mutation' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['mutation' => []])])), new ObjectType([ 'name' => 'Query', 'fields' => [ @@ -160,7 +161,7 @@ public function schemaProvider(): array ]), null, ], - 'subscription' => ['resourceClass', (new ResourceMetadata())->withGraphql(['update' => []]), + 'subscription' => ['resourceClass', (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['update' => []])])), new ObjectType([ 'name' => 'Query', 'fields' => [ diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index b6d50e25af3..e4bf697c692 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\GraphQl\Type\TypeBuilder; use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -77,7 +78,7 @@ protected function setUp(): void public function testGetResourceObjectType(): void { - $resourceMetadata = new ResourceMetadata('shortName', 'description'); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName', 'description')]); $this->typesContainerProphecy->has('shortName')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('shortName', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -99,8 +100,9 @@ public function testGetResourceObjectType(): void public function testGetResourceObjectTypeOutputClass(): void { - $resourceMetadata = (new ResourceMetadata('shortName', 'description')) - ->withGraphql(['item_query' => ['output' => ['class' => 'outputClass']]]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description')) + ->withGraphql(['item_query' => ['output' => ['class' => 'outputClass']]]), + ])); $this->typesContainerProphecy->has('shortName')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('shortName', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -125,11 +127,12 @@ public function testGetResourceObjectTypeOutputClass(): void */ public function testGetResourceObjectTypeQuerySerializationGroups(string $itemSerializationGroup, string $collectionSerializationGroup, string $shortName, string $queryName) { - $resourceMetadata = (new ResourceMetadata('shortName', 'description')) + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description')) ->withGraphql([ 'item_query' => ['normalization_context' => ['groups' => [$itemSerializationGroup]]], 'collection_query' => ['normalization_context' => ['groups' => [$collectionSerializationGroup]]], - ]); + ]), + ])); $this->typesContainerProphecy->has($shortName)->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set($shortName, Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -166,7 +169,7 @@ public function resourceObjectTypeQuerySerializationGroupsProvider(): array public function testGetResourceObjectTypeInput(): void { - $resourceMetadata = new ResourceMetadata('shortName', 'description'); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName', 'description')]); $this->typesContainerProphecy->has('customShortNameInput')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('customShortNameInput', Argument::type(NonNull::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -190,8 +193,7 @@ public function testGetResourceObjectTypeInput(): void public function testGetResourceObjectTypeCustomMutationInputArgs(): void { - $resourceMetadata = (new ResourceMetadata('shortName', 'description')) - ->withGraphql(['custom' => ['args' => []]]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description'))->withGraphql(['custom' => ['args' => []]])])); $this->typesContainerProphecy->has('customShortNameInput')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('customShortNameInput', Argument::type(NonNull::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -217,7 +219,7 @@ public function testGetResourceObjectTypeCustomMutationInputArgs(): void public function testGetResourceObjectTypeMutation(): void { - $resourceMetadata = new ResourceMetadata('shortName', 'description'); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName', 'description')]); $this->typesContainerProphecy->has('createShortNamePayload')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('createShortNamePayload', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -244,11 +246,10 @@ public function testGetResourceObjectTypeMutation(): void public function testGetResourceObjectTypeMutationWrappedType(): void { - $resourceMetadata = (new ResourceMetadata('shortName', 'description')) - ->withGraphql([ - 'item_query' => ['normalization_context' => ['groups' => ['item_query']]], - 'create' => ['normalization_context' => ['groups' => ['create']]], - ]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description'))->withGraphql([ + 'item_query' => ['normalization_context' => ['groups' => ['item_query']]], + 'create' => ['normalization_context' => ['groups' => ['create']]], + ])])); $this->typesContainerProphecy->has('createShortNamePayload')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('createShortNamePayload', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -288,7 +289,7 @@ public function testGetResourceObjectTypeMutationWrappedType(): void public function testGetResourceObjectTypeMutationNested(): void { - $resourceMetadata = new ResourceMetadata('shortName', 'description'); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName', 'description')]); $this->typesContainerProphecy->has('createShortNameNestedPayload')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('createShortNameNestedPayload', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -310,7 +311,7 @@ public function testGetResourceObjectTypeMutationNested(): void public function testGetResourceObjectTypeSubscription(): void { - $resourceMetadata = (new ResourceMetadata('shortName', 'description'))->withAttributes(['mercure' => true]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description'))->withAttributes(['mercure' => true])])); $this->typesContainerProphecy->has('updateShortNameSubscriptionPayload')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('updateShortNameSubscriptionPayload', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -339,11 +340,12 @@ public function testGetResourceObjectTypeSubscription(): void public function testGetResourceObjectTypeSubscriptionWrappedType(): void { - $resourceMetadata = (new ResourceMetadata('shortName', 'description')) + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description')) ->withGraphql([ 'item_query' => ['normalization_context' => ['groups' => ['item_query']]], 'update' => ['normalization_context' => ['groups' => ['update']]], - ]); + ]), + ])); $this->typesContainerProphecy->has('updateShortNameSubscriptionPayload')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('updateShortNameSubscriptionPayload', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); @@ -384,7 +386,7 @@ public function testGetResourceObjectTypeSubscriptionWrappedType(): void public function testGetResourceObjectTypeSubscriptionNested(): void { - $resourceMetadata = (new ResourceMetadata('shortName', 'description'))->withAttributes(['mercure' => true]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'shortName', 'description'))->withAttributes(['mercure' => true])])); $this->typesContainerProphecy->has('updateShortNameSubscriptionNestedPayload')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('updateShortNameSubscriptionNestedPayload', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); diff --git a/tests/GraphQl/Type/TypeConverterTest.php b/tests/GraphQl/Type/TypeConverterTest.php index d9548b79cd7..a681b0ba0ac 100644 --- a/tests/GraphQl/Type/TypeConverterTest.php +++ b/tests/GraphQl/Type/TypeConverterTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\GraphQl\Type\TypeConverter; use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\GraphQl\Type\Definition\DateTimeType; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -93,7 +94,7 @@ public function testConvertTypeNoGraphQlResourceMetadata(): void $type = new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy'); $this->typeBuilderProphecy->isCollection($type)->shouldBeCalled()->willReturn(false); - $this->resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn(new ResourceMetadata()); + $this->resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $graphqlType = $this->typeConverter->convertType($type, false, null, null, null, 'resourceClass', 'rootClass', null, 0); $this->assertNull($graphqlType); @@ -104,7 +105,7 @@ public function testConvertTypeNodeResource(): void $type = new Type(Type::BUILTIN_TYPE_OBJECT, false, 'node'); $this->typeBuilderProphecy->isCollection($type)->shouldBeCalled()->willReturn(false); - $this->resourceMetadataFactoryProphecy->create('node')->shouldBeCalled()->willReturn((new ResourceMetadata('Node'))->withGraphql(['test'])); + $this->resourceMetadataFactoryProphecy->create('node')->shouldBeCalled()->willReturn((new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'Node'))->withGraphql(['test'])]))); $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage('A "Node" resource cannot be used with GraphQL because the type is already used by the Relay specification.'); @@ -128,7 +129,7 @@ public function testConvertTypeResourceClassNotFound(): void */ public function testConvertTypeResource(Type $type, ObjectType $expectedGraphqlType): void { - $graphqlResourceMetadata = (new ResourceMetadata())->withGraphql(['test']); + $graphqlResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withGraphql(['test'])])); $this->typeBuilderProphecy->isCollection($type)->shouldBeCalled()->willReturn(true); $this->resourceMetadataFactoryProphecy->create('dummyValue')->shouldBeCalled()->willReturn($graphqlResourceMetadata); diff --git a/tests/Hal/Serializer/CollectionNormalizerTest.php b/tests/Hal/Serializer/CollectionNormalizerTest.php index 78727046afc..d25ac78d280 100644 --- a/tests/Hal/Serializer/CollectionNormalizerTest.php +++ b/tests/Hal/Serializer/CollectionNormalizerTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\DataProvider\PartialPaginatorInterface; use ApiPlatform\Core\Hal\Serializer\CollectionNormalizer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -142,7 +143,7 @@ private function normalizePaginator($partial = false) $resourceClassResolverProphecy->getResourceClass($paginatorProphecy, 'Foo')->willReturn('Foo'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index 8fa3efc45cd..72b5c32d6df 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Api\UrlGeneratorInterface; use ApiPlatform\Core\Hal\Serializer\EntrypointNormalizer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -53,7 +54,7 @@ public function testNormalize() $collection = new ResourceNameCollection([Dummy::class]); $entrypoint = new Entrypoint($collection); $factoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, ['get']))->shouldBeCalled(); + $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, ['get'])]))->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/api/dummies')->shouldBeCalled(); diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index 9cc93119d29..f1af93ab3f7 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\HttpCache\EventListener\AddHeadersListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -103,7 +104,7 @@ public function testAddHeaders() $event->getResponse()->willReturn($response)->shouldBeCalled(); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $factory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); $listener->onKernelResponse($event->reveal()); @@ -127,7 +128,7 @@ public function testDoNotSetHeaderWhenAlreadySet() $event->getResponse()->willReturn($response)->shouldBeCalled(); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $factory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); $listener->onKernelResponse($event->reveal()); @@ -146,7 +147,7 @@ public function testSetHeadersFromResourceMetadata() $event->getRequest()->willReturn($request)->shouldBeCalled(); $event->getResponse()->willReturn($response)->shouldBeCalled(); - $metadata = new ResourceMetadata(null, null, null, null, null, ['cache_headers' => ['max_age' => 123, 'shared_max_age' => 456, 'stale_while_revalidate' => 928, 'stale_if_error' => 70, 'vary' => ['Vary-1', 'Vary-2']]]); + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['cache_headers' => ['max_age' => 123, 'shared_max_age' => 456, 'stale_while_revalidate' => 928, 'stale_if_error' => 70, 'vary' => ['Vary-1', 'Vary-2']]])]); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); @@ -166,13 +167,13 @@ public function testSetHeadersFromResourceMetadataMarkedAsPrivate() $event->getRequest()->willReturn($request)->shouldBeCalled(); $event->getResponse()->willReturn($response)->shouldBeCalled(); - $metadata = new ResourceMetadata(null, null, null, null, null, [ + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, [ 'cache_headers' => [ 'max_age' => 123, 'public' => false, 'shared_max_age' => 456, ], - ]); + ])]); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); @@ -194,13 +195,13 @@ public function testSetHeadersFromResourceMetadataMarkedAsPublic() $event->getRequest()->willReturn($request)->shouldBeCalled(); $event->getResponse()->willReturn($response)->shouldBeCalled(); - $metadata = new ResourceMetadata(null, null, null, null, null, [ + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, [ 'cache_headers' => [ 'max_age' => 123, 'public' => true, 'shared_max_age' => 456, ], - ]); + ])]); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); @@ -219,12 +220,12 @@ public function testSetHeadersFromResourceMetadataWithNoPrivacy() $event->getRequest()->willReturn($request)->shouldBeCalled(); $event->getResponse()->willReturn($response)->shouldBeCalled(); - $metadata = new ResourceMetadata(null, null, null, null, null, [ + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, [ 'cache_headers' => [ 'max_age' => 123, 'shared_max_age' => 456, ], - ]); + ])]); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); @@ -243,12 +244,12 @@ public function testSetHeadersFromResourceMetadataWithNoPrivacyDefaultsPrivate() $event->getRequest()->willReturn($request)->shouldBeCalled(); $event->getResponse()->willReturn($response)->shouldBeCalled(); - $metadata = new ResourceMetadata(null, null, null, null, null, [ + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, [ 'cache_headers' => [ 'max_age' => 123, 'shared_max_age' => 456, ], - ]); + ])]); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); diff --git a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php index 84f30befed1..ddf4b344f50 100644 --- a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php @@ -21,6 +21,7 @@ use ApiPlatform\Core\Hydra\Serializer\CollectionFiltersNormalizer; use ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\Foo; use ApiPlatform\Core\Tests\Fixtures\NotAResource; @@ -205,7 +206,7 @@ public function testDoNothingIfNoFilter() ])->willReturn(['name' => 'foo']); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('foo', '', null, [], ['get' => []])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'foo', '', null, [], ['get' => []])])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); @@ -233,7 +234,7 @@ public function testDoNothingIfNoRequestUri() ])->willReturn(['name' => 'foo']); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('foo', '', null, [], [], ['filters' => ['foo']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'foo', '', null, [], [], ['filters' => ['foo']])])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); @@ -301,7 +302,7 @@ private function normalize($filterLocator) ])->willReturn(['name' => 'foo']); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('foo', '', null, [], [], ['filters' => ['foo']])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'foo', '', null, [], [], ['filters' => ['foo']])])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index b0ca173a402..b309ea45376 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -24,6 +24,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; @@ -66,10 +67,10 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create('dummy', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['name', 'description', 'nameConverted', 'relatedDummy'])); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], [])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); + $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummy')])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $propertyMetadataFactoryProphecy->create('dummy', 'name')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name', true, true, true, true, false, false, null, null, [])); diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 4465dc3b63c..9b860578c8e 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Api\UrlGeneratorInterface; use ApiPlatform\Core\Hydra\Serializer\EntrypointNormalizer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -55,8 +56,8 @@ public function testNormalize() $entrypoint = new Entrypoint($collection); $factoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, ['get']))->shouldBeCalled(); - $factoryProphecy->create(FooDummy::class)->willReturn(new ResourceMetadata('FooDummy', null, null, null, ['get']))->shouldBeCalled(); + $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, ['get'])]))->shouldBeCalled(); + $factoryProphecy->create(FooDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'FooDummy', null, null, null, ['get'])]))->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/api/dummies')->shouldBeCalled(); diff --git a/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php b/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php index cecc2b391ae..8bff40610fd 100644 --- a/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php +++ b/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -31,7 +32,7 @@ class TransformFieldsetsParametersListenerTest extends TestCase protected function setUp(): void { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy')); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy')])); $this->listener = new TransformFieldsetsParametersListener($resourceMetadataFactoryProphecy->reveal()); } diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index c68118ffe1d..c6655d4db75 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\DataProvider\PartialPaginatorInterface; use ApiPlatform\Core\JsonApi\Serializer\CollectionNormalizer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -63,7 +64,7 @@ public function testNormalizePaginator() $resourceClassResolverProphecy->getResourceClass($paginator, 'Foo')->willReturn('Foo'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ @@ -134,7 +135,7 @@ public function testNormalizePartialPaginator() $resourceClassResolverProphecy->getResourceClass($paginator, 'Foo')->willReturn('Foo'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ @@ -192,7 +193,7 @@ public function testNormalizeArray() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($data, 'Foo')->willReturn('Foo'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', @@ -243,7 +244,7 @@ public function testNormalizeIncludedData() $resourceClassResolverProphecy->getResourceClass($data, 'Foo')->willReturn('Foo'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ @@ -318,7 +319,7 @@ public function testNormalizeWithoutDataKey() $resourceClassResolverProphecy->getResourceClass($data, 'Foo')->willReturn('Foo'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ diff --git a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php index f2f6fa9e1f1..09acc7ab12d 100644 --- a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php +++ b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php @@ -19,6 +19,7 @@ use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\JsonApi\Serializer\EntrypointNormalizer; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -56,9 +57,9 @@ public function testNormalize() $collection = new ResourceNameCollection([Dummy::class, RelatedDummy::class, DummyCar::class]); $entrypoint = new Entrypoint($collection); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, ['get']))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata('RelatedDummy', null, null, ['get'], null))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata('DummyCar', null, null, null, ['post']))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', null, null, null, ['get'])]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'RelatedDummy', null, null, ['get'], null)]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyCar', null, null, null, ['post'])]))->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResourceClass(Dummy::class, UrlGeneratorInterface::ABS_URL)->willReturn('http://localhost/api/dummies')->shouldBeCalled(); diff --git a/tests/JsonApi/Serializer/ItemNormalizerTest.php b/tests/JsonApi/Serializer/ItemNormalizerTest.php index e56812ccd8f..9a37420edb9 100644 --- a/tests/JsonApi/Serializer/ItemNormalizerTest.php +++ b/tests/JsonApi/Serializer/ItemNormalizerTest.php @@ -24,6 +24,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CircularReference; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -124,7 +125,7 @@ public function testNormalize(): void $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('hello'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', 'A dummy', '/dummy', null, null, ['id', 'name'])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', 'A dummy', '/dummy', null, null, ['id', 'name'])])); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(NormalizerInterface::class); @@ -191,7 +192,7 @@ public function testNormalizeChildInheritedProperty(): void $propertyAccessorProphecy->getValue($dummy, 'inherited')->willThrow(new NoSuchPropertyException()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', 'A dummy', '/dummy', null, null, ['id', 'name'])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', 'A dummy', '/dummy', null, null, ['id', 'name'])])); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(NormalizerInterface::class); @@ -242,7 +243,7 @@ public function testNormalizeCircularReference() $resourceClassResolverProphecy->getResourceClass($circularReferenceEntity, CircularReference::class)->willReturn(CircularReference::class); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(CircularReference::class)->willReturn(new ResourceMetadata('CircularReference')); + $resourceMetadataFactoryProphecy->create(CircularReference::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'CircularReference')])); $normalizer = new ItemNormalizer( $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), @@ -301,7 +302,7 @@ public function testNormalizeNonExistentProperty() $propertyAccessorProphecy->getValue($dummy, 'bar')->willThrow(new NoSuchPropertyException()); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy')])); $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), diff --git a/tests/JsonLd/Action/ContextActionTest.php b/tests/JsonLd/Action/ContextActionTest.php index fed7e6940f9..0cf175ffc7b 100644 --- a/tests/JsonLd/Action/ContextActionTest.php +++ b/tests/JsonLd/Action/ContextActionTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\JsonLd\ContextBuilderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -62,7 +63,7 @@ public function testContextActionWithResourceClass() $contextBuilderProphecy->getResourceContext('dummy')->willReturn(['/dummies']); $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn( - new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []) + new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], [])]) ); $this->assertEquals(['@context' => ['/dummies']], $contextAction('dummy')); } @@ -78,7 +79,7 @@ public function testContextActionWithThrown() $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); $resourceMetadataFactoryProphecy->create('gerard')->shouldBeCalled()->willReturn( - new ResourceMetadata('gerard', 'gerard', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []) + new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'gerard', 'gerard', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], [])]) ); $contextAction('dummy'); } diff --git a/tests/JsonLd/ContextBuilderTest.php b/tests/JsonLd/ContextBuilderTest.php index eaff17b716d..1cdab08fad8 100644 --- a/tests/JsonLd/ContextBuilderTest.php +++ b/tests/JsonLd/ContextBuilderTest.php @@ -21,6 +21,7 @@ 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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Dto\OutputDto; @@ -55,7 +56,7 @@ protected function setUp(): void public function testResourceContext() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyEntity')])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA')->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'Dummy property A', true, true, true, true, false, false, null, null, [])); @@ -72,7 +73,7 @@ public function testResourceContext() public function testResourceContextWithJsonldContext() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyEntity')])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA')->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'Dummy property A', true, true, true, true, false, false, null, null, ['jsonld_context' => ['@type' => '@id', '@id' => 'customId', 'foo' => 'bar']])); @@ -93,7 +94,7 @@ public function testResourceContextWithJsonldContext() public function testGetEntryPointContext() { - $this->resourceMetadataFactoryProphecy->create('dummyPropertyA')->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataFactoryProphecy->create('dummyPropertyA')->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyEntity')])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA')->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'Dummy property A', true, true, true, true, false, false, null, null, ['jsonld_context' => ['@type' => '@id', '@id' => 'customId', 'foo' => 'bar']])); @@ -114,7 +115,7 @@ public function testGetEntryPointContext() public function testResourceContextWithReverse() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyEntity')])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA')->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'Dummy property A', true, true, true, true, false, false, null, null, ['jsonld_context' => ['@reverse' => 'parent']])); @@ -181,7 +182,7 @@ public function testAnonymousResourceContextWithApiResource() $this->propertyNameCollectionFactoryProphecy->create(OutputDto::class)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create(OutputDto::class, 'dummyPropertyA')->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'Dummy property A', true, true, true, true, false, false, null, null, [])); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy')])); $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); diff --git a/tests/JsonLd/Serializer/ItemNormalizerTest.php b/tests/JsonLd/Serializer/ItemNormalizerTest.php index 657925f7710..29eaf8e2c81 100644 --- a/tests/JsonLd/Serializer/ItemNormalizerTest.php +++ b/tests/JsonLd/Serializer/ItemNormalizerTest.php @@ -22,6 +22,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -97,7 +98,7 @@ public function testNormalize() $dummy->setName('hello'); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy')])); $propertyNameCollection = new PropertyNameCollection(['name']); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection); diff --git a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php index 7392b1f5666..0d420db85d4 100644 --- a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -38,7 +39,7 @@ class AddLinkHeaderListenerTest extends TestCase public function testAddLinkHeader(string $expected, Request $request) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['mercure' => true])])); $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); @@ -64,7 +65,7 @@ public function addProvider(): array public function testDoNotAddHeader(Request $request) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); diff --git a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php index 0d571730e1f..911d47585fc 100644 --- a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; @@ -57,7 +58,7 @@ public function testConstruct() public function testCreate($readGroups, $writeGroups) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $dummyResourceMetadata = (new ResourceMetadata()) + $dummyResourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) ->withAttributes([ 'normalization_context' => [ AbstractNormalizer::GROUPS => $readGroups, @@ -65,7 +66,8 @@ public function testCreate($readGroups, $writeGroups) 'denormalization_context' => [ AbstractNormalizer::GROUPS => $writeGroups, ], - ]); + ]), + ])); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata); $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); @@ -143,7 +145,7 @@ public function groupsProvider(): array public function testCreateInherited(): void { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyTableInheritanceChild::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy->create(DummyTableInheritanceChild::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')])); $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); $dummySerializerClassMetadata = new SerializerClassMetadata(DummyTableInheritanceChild::class); diff --git a/tests/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php index 75384f367c0..189f58fdce6 100644 --- a/tests/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceFilterMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\DummyFilter; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -34,7 +35,7 @@ class AnnotationResourceFilterMetadataFactoryTest extends TestCase public function testCreate() { $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(Dummy::class)->willReturn(new ResourceMetadata('hello', 'blabla'))->shouldBeCalled(); + $decorated->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'hello', 'blabla')]))->shouldBeCalled(); $reader = $this->prophesize(Reader::class); $reader->getClassAnnotations(Argument::type(\ReflectionClass::class))->shouldBeCalled()->willReturn([ diff --git a/tests/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php index 6e974afc1bd..9bdabd3359e 100644 --- a/tests/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\Exception\ResourceClassNotFoundException; use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -71,7 +72,7 @@ public function testCreateWithDefaults() ], ]); $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotation)->shouldBeCalled(); + $reader->getClassAnnotations(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn([$annotation])->shouldBeCalled(); $factory = new AnnotationResourceMetadataFactory($reader->reveal(), null, $defaults); $metadata = $factory->create(Dummy::class); @@ -89,7 +90,7 @@ public function testCreateWithoutAttributes() { $annotation = new ApiResource([]); $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotation)->shouldBeCalled(); + $reader->getClassAnnotations(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn([$annotation])->shouldBeCalled(); $factory = new AnnotationResourceMetadataFactory($reader->reveal(), null); $metadata = $factory->create(Dummy::class); @@ -112,22 +113,22 @@ public function getCreateDependencies() $annotationFull = new ApiResource($resourceData); $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotationFull)->shouldBeCalled(); + $reader->getClassAnnotations(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn([$annotationFull])->shouldBeCalled(); $decoratedThrow = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedThrow->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); $decoratedReturn = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedReturn->create(Dummy::class)->willReturn(new ResourceMetadata('hello', 'blabla'))->shouldBeCalled(); + $decoratedReturn->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'hello', 'blabla')]))->shouldBeCalled(); $resourceData['description'] = null; $annotationWithNull = new ApiResource($resourceData); $decoratedReturnWithNull = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedReturnWithNull->create(Dummy::class)->willReturn(new ResourceMetadata('hello'))->shouldBeCalled(); + $decoratedReturnWithNull->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'hello')]))->shouldBeCalled(); $readerWithNull = $this->prophesize(Reader::class); - $readerWithNull->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotationWithNull)->shouldBeCalled(); + $readerWithNull->getClassAnnotations(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn([$annotationWithNull])->shouldBeCalled(); return [ [$reader, $decoratedThrow, 'shortName', 'description'], diff --git a/tests/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php index f5a8a354dfa..c3da1cb5f0e 100644 --- a/tests/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\CachedResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -34,7 +35,7 @@ public function testCreateWithItemHit() { $cacheItem = $this->prophesize(CacheItemInterface::class); $cacheItem->isHit()->willReturn(true)->shouldBeCalled(); - $cacheItem->get()->willReturn(new ResourceMetadata(null, 'Dummy.'))->shouldBeCalled(); + $cacheItem->get()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'Dummy.')]))->shouldBeCalled(); $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalled(); @@ -44,12 +45,12 @@ public function testCreateWithItemHit() $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - $this->assertEquals(new ResourceMetadata(null, 'Dummy.'), $resultedResourceMetadata); + $this->assertEquals(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'Dummy.')]), $resultedResourceMetadata); } public function testCreateWithItemNotHit() { - $propertyMetadata = new ResourceMetadata(null, 'Dummy.'); + $propertyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'Dummy.')]); $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn($propertyMetadata)->shouldBeCalled(); @@ -65,7 +66,7 @@ public function testCreateWithItemNotHit() $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - $expectedResult = new ResourceMetadata(null, 'Dummy.'); + $expectedResult = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'Dummy.')]); $this->assertEquals($expectedResult, $resultedResourceMetadata); $this->assertEquals($expectedResult, $cachedResourceMetadataFactory->create(Dummy::class), 'Trigger the local cache'); } @@ -73,7 +74,7 @@ public function testCreateWithItemNotHit() public function testCreateWithGetCacheItemThrowsCacheException() { $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, 'Dummy.'))->shouldBeCalled(); + $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'Dummy.')]))->shouldBeCalled(); $cacheException = $this->prophesize(\Exception::class); $cacheException->willImplement(CacheException::class); @@ -84,7 +85,7 @@ public function testCreateWithGetCacheItemThrowsCacheException() $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - $expectedResult = new ResourceMetadata(null, 'Dummy.'); + $expectedResult = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'Dummy.')]); $this->assertEquals($expectedResult, $resultedResourceMetadata); $this->assertEquals($expectedResult, $cachedResourceMetadataFactory->create(Dummy::class), 'Trigger the local cache'); } diff --git a/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php index a5d1dbc552e..e08aa242fed 100644 --- a/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php @@ -22,6 +22,7 @@ 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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -136,12 +137,12 @@ public function testXmlParentResourceMetadataFactory(ResourceMetadata $expectedR $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcesoptional.xml'; $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata(null, 'test'))->shouldBeCalled(); + $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'test')]))->shouldBeCalled(); $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - $expectedResourceMetadata = $expectedResourceMetadata->withDescription('test'); + $expectedResourceMetadata['/dummies'] = $expectedResourceMetadata['/dummies']->withDescription('test'); $this->assertEquals($expectedResourceMetadata, $resourceMetadata); } @@ -224,12 +225,12 @@ public function testYamlParentResourceMetadataFactory(ResourceMetadata $expected $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcesoptional.yml'; $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata(null, 'test'))->shouldBeCalled(); + $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'test')]))->shouldBeCalled(); $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - $expectedResourceMetadata = $expectedResourceMetadata->withDescription('test'); + $expectedResourceMetadata['/dummies'] = $expectedResourceMetadata['/dummies']->withDescription('test'); $this->assertEquals($expectedResourceMetadata, $resourceMetadata); } @@ -292,6 +293,17 @@ public function testItSupportsInterfaceAsAResource() $this->assertSame('DummyResourceInterface', $resourceMetadata->getShortName()); } + public function testItSupportsMultipleApiResource() + { + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/multiple_resources.yml'; + + $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); + $shortNameResourceMetadataFactory = new ShortNameResourceMetadataFactory($resourceMetadataFactory); + + $resourceMetadata = $shortNameResourceMetadataFactory->create(DummyResourceInterface::class); + $this->assertSame('DummyResourceInterface', $resourceMetadata->getShortName()); + } + public function testItFallbacksToDefaultConfiguration() { $defaults = [ @@ -307,13 +319,16 @@ public function testItFallbacksToDefaultConfiguration() ]; $resourceConfiguration = [ Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'subresourceOperations' => null, - 'itemOperations' => ['get', 'delete'], - 'attributes' => [ - 'pagination_maximum_items_per_page' => 10, - 'stateless' => false, + [ + 'path' => '/dummies', + 'shortName' => null, + 'description' => null, + 'subresourceOperations' => null, + 'itemOperations' => ['get', 'delete'], + 'attributes' => [ + 'pagination_maximum_items_per_page' => 10, + 'stateless' => false, + ], ], ], ]; @@ -332,8 +347,10 @@ public function getResources(): array } }; $factory = new ExtractorResourceMetadataFactory($extractor, null, $defaults); - $metadata = $factory->create(Dummy::class); + $resourceMetadata = $factory->create(Dummy::class); + $metadata = $resourceMetadata['/dummies']; + $this->assertEquals('/dummies', $metadata->getPath()); $this->assertNull($metadata->getShortName()); $this->assertEquals('CHANGEME!', $metadata->getDescription()); $this->assertEquals(['get'], $metadata->getCollectionOperations()); diff --git a/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php b/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php index 39c81511c39..0a621925033 100644 --- a/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php +++ b/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; @@ -26,7 +27,7 @@ abstract class FileConfigurationMetadataFactoryProvider extends TestCase { public function resourceMetadataProvider() { - $resourceMetadata = new ResourceMetadata(); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $metadata = [ 'shortName' => 'thedummyshortname', @@ -74,39 +75,39 @@ public function resourceMetadataProvider() public function optionalResourceMetadataProvider() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations(['my_op_name' => ['method' => 'POST']]); - - return [[$resourceMetadata]]; + return [[new ResourceMetadata([(new OperationCollectionMetadata('/dummies'))->withItemOperations(['my_op_name' => ['method' => 'POST']])])]]; } public function noCollectionOperationsResourceMetadataProvider() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations(['my_op_name' => ['method' => 'POST']]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([]); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withItemOperations(['my_op_name' => ['method' => 'POST']]) + ->withCollectionOperations([]), + ]); return [[$resourceMetadata]]; } public function noItemOperationsResourceMetadataProvider() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withCollectionOperations(['my_op_name' => ['method' => 'POST']]); - $resourceMetadata = $resourceMetadata->withItemOperations([]); + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withCollectionOperations(['my_op_name' => ['method' => 'POST']]) + ->withItemOperations([]), + ]); return [[$resourceMetadata]]; } public function legacyOperationsResourceMetadataProvider() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'my_op_name' => ['method' => 'POST'], - 'my_other_op_name' => ['method' => 'GET'], - ]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op_name' => ['method' => 'POST'], + $resourceMetadata = new ResourceMetadata([(new OperationCollectionMetadata('/dummies')) + ->withItemOperations([ + 'my_op_name' => ['method' => 'POST'], + 'my_other_op_name' => ['method' => 'GET'], + ]) + ->withCollectionOperations([ + 'my_op_name' => ['method' => 'POST'], + ]), ]); return [[$resourceMetadata]]; diff --git a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php index a3381deab22..4a99e4746c3 100644 --- a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\InputOutputResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyEntity; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -29,7 +30,7 @@ class InputOutputResourceMetadataFactoryTest extends TestCase */ public function testInputOutputMetadata($attributes, $expected) { - $resourceMetadata = (new ResourceMetadata(null))->withAttributes($attributes); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', null))->withAttributes($attributes)])); $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $decorated = $decoratedProphecy->reveal(); @@ -43,7 +44,7 @@ public function testInputOutputMetadata($attributes, $expected) */ public function testInputOutputViaGraphQlMetadata($attributes, $expected) { - $resourceMetadata = (new ResourceMetadata(null))->withGraphQl(['create' => $attributes]); + $resourceMetadata = (new ResourceMetadata([(new OperationCollectionMetadata('/dummies', null))->withGraphQl(['create' => $attributes])])); $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $decorated = $decoratedProphecy->reveal(); diff --git a/tests/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php index f2b79dd84d7..b249ca159f4 100644 --- a/tests/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\OperationResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -43,27 +44,27 @@ public function getMetadata(): iterable $jsonapi = ['jsonapi' => ['application/vnd.api+json']]; // Item operations - yield [new ResourceMetadata(null, null, null, null, [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get', 'put', 'delete']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, null, [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get', 'put', 'patch', 'delete']), [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['get'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['put'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['put']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['delete'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['delete']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], []), new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], []), new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['untouched' => ['method' => 'GET']], [], null, [], []), new ResourceMetadata(null, null, null, ['untouched' => ['method' => 'GET', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['untouched_custom' => ['route_name' => 'custom_route']], [], null, [], []), new ResourceMetadata(null, null, null, ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), new ResourceMetadata(null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['statefull_attribute' => ['method' => 'GET']], [], ['stateless' => false], [], []), new ResourceMetadata(null, null, null, ['statefull_attribute' => ['method' => 'GET', 'stateless' => false]], [], ['stateless' => false], [], []), $jsonapi]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, $this->getOperations(['get', 'put', 'delete']), [], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, $this->getOperations(['get', 'put', 'patch', 'delete']), [], null, [], []), $jsonapi])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['get'], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, $this->getOperations(['get']), [], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['put'], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, $this->getOperations(['put']), [], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['delete'], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, $this->getOperations(['delete']), [], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], []), $jsonapi])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['untouched' => ['method' => 'GET']], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['untouched' => ['method' => 'GET', 'stateless' => null]], [], null, [], []), $jsonapi])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['untouched_custom' => ['route_name' => 'custom_route']], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], [], null, [], []), $jsonapi])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), $jsonapi])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['statefull_attribute' => ['method' => 'GET']], [], ['stateless' => false], [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, ['statefull_attribute' => ['method' => 'GET', 'stateless' => false]], [], ['stateless' => false], [], []), $jsonapi])]; // Collection operations - yield [new ResourceMetadata(null, null, null, [], null, null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['get', 'post']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['get'], null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['get']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['post'], null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['post']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['options' => ['method' => 'OPTIONS', 'route_name' => 'options']], null, [], []), new ResourceMetadata(null, null, null, [], ['options' => ['route_name' => 'options', 'method' => 'OPTIONS', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['untouched' => ['method' => 'GET']], null, [], []), new ResourceMetadata(null, null, null, [], ['untouched' => ['method' => 'GET', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route']], null, [], []), new ResourceMetadata(null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), new ResourceMetadata(null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, [], ['stateless_attribute' => ['method' => 'GET']], ['stateless' => true], null, []), new ResourceMetadata(null, null, null, [], ['stateless_attribute' => ['method' => 'GET', 'stateless' => true]], ['stateless' => true], null, []), $jsonapi]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], null, null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], $this->getOperations(['get', 'post']), null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['get'], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], $this->getOperations(['get']), null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['post'], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], $this->getOperations(['post']), null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['options' => ['method' => 'OPTIONS', 'route_name' => 'options']], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['options' => ['route_name' => 'options', 'method' => 'OPTIONS', 'stateless' => null]], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['untouched' => ['method' => 'GET']], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['untouched' => ['method' => 'GET', 'stateless' => null]], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route']], null, [], [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], null, [], [])])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), $jsonapi])]; + yield [new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['stateless_attribute' => ['method' => 'GET']], ['stateless' => true], null, [])]), new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [], ['stateless_attribute' => ['method' => 'GET', 'stateless' => true]], ['stateless' => true], null, []), $jsonapi])]; } private function getOperations(array $names): array diff --git a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php index cd22507b294..5fe03d6179c 100644 --- a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\PhpDocResourceMetadataFactory; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\ClassWithNoDocBlock; use ApiPlatform\Core\Tests\Fixtures\DummyEntity; @@ -27,7 +28,7 @@ class PhpDocResourceMetadataFactoryTest extends TestCase public function testExistingDescription() { - $resourceMetadata = new ResourceMetadata(null, 'My desc'); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, 'My desc')]); $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $decorated = $decoratedProphecy->reveal(); @@ -38,7 +39,7 @@ public function testExistingDescription() public function testNoDocBlock() { - $resourceMetadata = new ResourceMetadata(); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $decoratedProphecy->create(ClassWithNoDocBlock::class)->willReturn($resourceMetadata)->shouldBeCalled(); $decorated = $decoratedProphecy->reveal(); @@ -50,7 +51,7 @@ public function testNoDocBlock() public function testExtractDescription() { $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(DummyEntity::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $decoratedProphecy->create(DummyEntity::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies')]))->shouldBeCalled(); $decorated = $decoratedProphecy->reveal(); $factory = new PhpDocResourceMetadataFactory($decorated); diff --git a/tests/Metadata/Resource/ResourceMetadataTest.php b/tests/Metadata/Resource/ResourceMetadataTest.php index 33f9cd12b45..34d0b502d03 100644 --- a/tests/Metadata/Resource/ResourceMetadataTest.php +++ b/tests/Metadata/Resource/ResourceMetadataTest.php @@ -14,60 +14,66 @@ namespace ApiPlatform\Core\Tests\Metadata\Resource; use ApiPlatform\Core\Api\OperationType; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use PHPUnit\Framework\TestCase; /** * @author Kévin Dunglas + * @author Vincent Chalamon + * + * todo Update this test + * todo Add OperationCollectionMetadataTest */ class ResourceMetadataTest extends TestCase { public function testValueObject() { - $metadata = new ResourceMetadata('shortName', 'desc', 'http://example.com/foo', ['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], ['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], ['baz' => 'bar'], ['sop1' => ['sub' => 'bus']], ['query' => ['foo' => 'graphql']]); - $this->assertSame('shortName', $metadata->getShortName()); - $this->assertSame('desc', $metadata->getDescription()); - $this->assertSame('http://example.com/foo', $metadata->getIri()); - $this->assertSame(['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], $metadata->getItemOperations()); - $this->assertSame('a', $metadata->getItemOperationAttribute('iop1', 'foo', 'z')); - $this->assertSame('a', $metadata->getTypedOperationAttribute(OperationType::ITEM, 'iop1', 'foo', 'z')); - $this->assertSame('bar', $metadata->getItemOperationAttribute('iop1', 'baz', 'z', true)); - $this->assertSame('bar', $metadata->getItemOperationAttribute(null, 'baz', 'z', true)); - $this->assertSame('z', $metadata->getItemOperationAttribute('iop1', 'notExist', 'z', true)); - $this->assertSame('z', $metadata->getItemOperationAttribute('notExist', 'notExist', 'z', true)); - $this->assertSame(['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], $metadata->getCollectionOperations()); - $this->assertSame('c', $metadata->getCollectionOperationAttribute('cop1', 'foo', 'z')); - $this->assertSame('c', $metadata->getTypedOperationAttribute(OperationType::COLLECTION, 'cop1', 'foo', 'z')); - $this->assertSame('bar', $metadata->getCollectionOperationAttribute('cop1', 'baz', 'z', true)); - $this->assertSame('bar', $metadata->getCollectionOperationAttribute(null, 'baz', 'z', true)); - $this->assertSame('z', $metadata->getCollectionOperationAttribute('cop1', 'notExist', 'z', true)); - $this->assertSame('z', $metadata->getCollectionOperationAttribute('notExist', 'notExist', 'z', true)); - $this->assertSame(['baz' => 'bar'], $metadata->getAttributes()); - $this->assertSame('bar', $metadata->getAttribute('baz')); - $this->assertSame('z', $metadata->getAttribute('notExist', 'z')); - $this->assertSame(['sop1' => ['sub' => 'bus']], $metadata->getSubresourceOperations()); - $this->assertSame('bus', $metadata->getSubresourceOperationAttribute('sop1', 'sub')); - $this->assertSame('bus', $metadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, 'sop1', 'sub')); - $this->assertSame('sub', $metadata->getSubresourceOperationAttribute('sop1', 'bus', 'sub')); - $this->assertSame('bar', $metadata->getSubresourceOperationAttribute('sop1', 'baz', 'sub', true)); - $this->assertSame('graphql', $metadata->getGraphqlAttribute('query', 'foo')); - $this->assertSame('bar', $metadata->getGraphqlAttribute('query', 'baz', null, true)); - $this->assertSame('hey', $metadata->getGraphqlAttribute('query', 'notExist', 'hey', true)); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'shortName', 'desc', 'http://example.com/foo', ['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], ['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], ['baz' => 'bar'], ['sop1' => ['sub' => 'bus']], ['query' => ['foo' => 'graphql']])]); + $operationCollectionMetadata = $resourceMetadata['/dummies']; + $this->assertSame('shortName', $operationCollectionMetadata->getShortName()); + $this->assertSame('desc', $operationCollectionMetadata->getDescription()); + $this->assertSame('http://example.com/foo', $operationCollectionMetadata->getIri()); + $this->assertSame(['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], $operationCollectionMetadata->getItemOperations()); + $this->assertSame('a', $operationCollectionMetadata->getItemOperationAttribute('iop1', 'foo', 'z')); + $this->assertSame('a', $operationCollectionMetadata->getTypedOperationAttribute(OperationType::ITEM, 'iop1', 'foo', 'z')); + $this->assertSame('bar', $operationCollectionMetadata->getItemOperationAttribute('iop1', 'baz', 'z', true)); + $this->assertSame('bar', $operationCollectionMetadata->getItemOperationAttribute(null, 'baz', 'z', true)); + $this->assertSame('z', $operationCollectionMetadata->getItemOperationAttribute('iop1', 'notExist', 'z', true)); + $this->assertSame('z', $operationCollectionMetadata->getItemOperationAttribute('notExist', 'notExist', 'z', true)); + $this->assertSame(['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], $operationCollectionMetadata->getCollectionOperations()); + $this->assertSame('c', $operationCollectionMetadata->getCollectionOperationAttribute('cop1', 'foo', 'z')); + $this->assertSame('c', $operationCollectionMetadata->getTypedOperationAttribute(OperationType::COLLECTION, 'cop1', 'foo', 'z')); + $this->assertSame('bar', $operationCollectionMetadata->getCollectionOperationAttribute('cop1', 'baz', 'z', true)); + $this->assertSame('bar', $operationCollectionMetadata->getCollectionOperationAttribute(null, 'baz', 'z', true)); + $this->assertSame('z', $operationCollectionMetadata->getCollectionOperationAttribute('cop1', 'notExist', 'z', true)); + $this->assertSame('z', $operationCollectionMetadata->getCollectionOperationAttribute('notExist', 'notExist', 'z', true)); + $this->assertSame(['baz' => 'bar'], $operationCollectionMetadata->getAttributes()); + $this->assertSame('bar', $operationCollectionMetadata->getAttribute('baz')); + $this->assertSame('z', $operationCollectionMetadata->getAttribute('notExist', 'z')); + $this->assertSame(['sop1' => ['sub' => 'bus']], $operationCollectionMetadata->getSubresourceOperations()); + $this->assertSame('bus', $operationCollectionMetadata->getSubresourceOperationAttribute('sop1', 'sub')); + $this->assertSame('bus', $operationCollectionMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, 'sop1', 'sub')); + $this->assertSame('sub', $operationCollectionMetadata->getSubresourceOperationAttribute('sop1', 'bus', 'sub')); + $this->assertSame('bar', $operationCollectionMetadata->getSubresourceOperationAttribute('sop1', 'baz', 'sub', true)); + $this->assertSame('graphql', $operationCollectionMetadata->getGraphqlAttribute('query', 'foo')); + $this->assertSame('bar', $operationCollectionMetadata->getGraphqlAttribute('query', 'baz', null, true)); + $this->assertSame('hey', $operationCollectionMetadata->getGraphqlAttribute('query', 'notExist', 'hey', true)); - $newMetadata = $metadata->withShortName('name'); - $this->assertNotSame($metadata, $newMetadata); + $newMetadata = $operationCollectionMetadata->withShortName('name'); + $this->assertNotSame($operationCollectionMetadata, $newMetadata); $this->assertSame('name', $newMetadata->getShortName()); - $newMetadata = $metadata->withDescription('description'); - $this->assertNotSame($metadata, $newMetadata); + $newMetadata = $operationCollectionMetadata->withDescription('description'); + $this->assertNotSame($operationCollectionMetadata, $newMetadata); $this->assertSame('description', $newMetadata->getDescription()); - $newMetadata = $metadata->withIri('foo:bar'); - $this->assertNotSame($metadata, $newMetadata); + $newMetadata = $operationCollectionMetadata->withIri('foo:bar'); + $this->assertNotSame($operationCollectionMetadata, $newMetadata); $this->assertSame('foo:bar', $newMetadata->getIri()); - $newMetadata = $metadata->withItemOperations(['a' => ['b' => 'c']]); - $this->assertNotSame($metadata, $newMetadata); + $newMetadata = $operationCollectionMetadata->withItemOperations(['a' => ['b' => 'c']]); + $this->assertNotSame($operationCollectionMetadata, $newMetadata); $this->assertSame(['a' => ['b' => 'c']], $newMetadata->getItemOperations()); } @@ -76,7 +82,7 @@ public function testValueObject() */ public function testWithMethods(string $name, $value) { - $metadata = new ResourceMetadata(); + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $newMetadata = $metadata->{"with$name"}($value); $this->assertNotSame($metadata, $newMetadata); $this->assertSame($value, $newMetadata->{"get$name"}()); @@ -84,13 +90,13 @@ public function testWithMethods(string $name, $value) public function testGetOperationAttributeFallback() { - $metadata = new ResourceMetadata(); + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $this->assertSame('okay', $metadata->getOperationAttribute([], 'doh', 'okay')); } public function testGetOperationAttributeFallbackToResourceAttribute() { - $metadata = new ResourceMetadata(null, null, null, null, null, ['doh' => 'nuts']); + $metadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['doh' => 'nuts'])]); $this->assertSame('nuts', $metadata->getOperationAttribute([], 'doh', 'okay', true)); } diff --git a/tests/Operation/Factory/SubresourceOperationFactoryTest.php b/tests/Operation/Factory/SubresourceOperationFactoryTest.php index 8b53f873c4f..fd058c80cec 100644 --- a/tests/Operation/Factory/SubresourceOperationFactoryTest.php +++ b/tests/Operation/Factory/SubresourceOperationFactoryTest.php @@ -20,6 +20,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface; @@ -40,8 +41,8 @@ class SubresourceOperationFactoryTest extends TestCase public function testCreate() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo', 'subresource', 'subcollection'])); @@ -160,15 +161,15 @@ public function testCreate() public function testCreateByOverriding() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn((new ResourceMetadata('dummyEntity'))->withSubresourceOperations([ + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([(new OperationCollectionMetadata('/dummies', 'dummyEntity'))->withSubresourceOperations([ 'subcollections_get_subresource' => [ 'path' => '/dummy_entities/{id}/foobars', ], 'subcollections_another_subresource_get_subresource' => [ 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar.{_format}', ], - ])); + ])])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo', 'subresource', 'subcollection'])); @@ -287,8 +288,8 @@ public function testCreateByOverriding() public function testCreateWithMaxDepth() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); @@ -344,9 +345,9 @@ public function testCreateWithMaxDepthMultipleSubresources() * DummyEntity -secondSubresource-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity. */ $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyValidatedEntity')); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyValidatedEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); @@ -436,9 +437,9 @@ public function testCreateWithMaxDepthMultipleSubresourcesSameMaxDepth() * DummyEntity -secondSubresource (maxDepth=1)-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity. */ $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyValidatedEntity')); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyValidatedEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); @@ -509,7 +510,7 @@ public function testCreateSelfReferencingSubresources() * DummyEntity -subresource-> DummyEntity --> DummyEntity ... */ $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); @@ -563,7 +564,7 @@ public function testCreateWithDifferentMaxDepthSelfReferencingSubresources() * DummyEntity -secondSubresource-> DummyEntity !!!-subresource-> DummyEntity ... */ $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); @@ -638,8 +639,8 @@ public function testCreateWithDifferentMaxDepthSelfReferencingSubresources() public function testCreateWithEnd() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); @@ -702,8 +703,8 @@ public function testCreateWithEnd() public function testCreateWithEndButNoCollection() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); @@ -752,8 +753,8 @@ public function testCreateWithEndButNoCollection() public function testCreateWithRootResourcePrefix() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity', null, null, null, null, ['route_prefix' => 'root_resource_prefix'])); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity', null, null, null, null, ['route_prefix' => 'root_resource_prefix'])])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); @@ -806,8 +807,8 @@ public function testCreateSelfReferencingSubresourcesWithSubresources() * DummyEntity -subresource (maxDepth=1) -> DummyEntity -otherSubresource-> RelatedDummyEntity. */ $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); + $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummyEntity')])); + $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'relatedDummyEntity')])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'otherSubresource'])); diff --git a/tests/Security/EventListener/DenyAccessListenerTest.php b/tests/Security/EventListener/DenyAccessListenerTest.php index bdc4b4d9265..09a5e994629 100644 --- a/tests/Security/EventListener/DenyAccessListenerTest.php +++ b/tests/Security/EventListener/DenyAccessListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\Security\EventListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Security\EventListener\DenyAccessListener; use ApiPlatform\Core\Security\ExpressionLanguage; @@ -63,7 +64,7 @@ public function testNoIsGrantedAttribute() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies')]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -81,7 +82,7 @@ public function testIsGranted() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -105,7 +106,7 @@ public function testAccessControl() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['access_control' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -127,7 +128,7 @@ public function testIsNotGranted() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -150,7 +151,7 @@ public function testSecurityMessage() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")', 'security_message' => 'You are not admin.']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")', 'security_message' => 'You are not admin.'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -174,7 +175,7 @@ public function testIsGrantedLegacy() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -199,7 +200,7 @@ public function testIsNotGrantedLegacy() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -224,7 +225,7 @@ public function testSecurityComponentNotAvailable() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -246,7 +247,7 @@ public function testExpressionLanguageNotInstalled() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); @@ -272,7 +273,7 @@ public function testNotBehindAFirewall() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")'])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); diff --git a/tests/Serializer/AbstractItemNormalizerTest.php b/tests/Serializer/AbstractItemNormalizerTest.php index d9309862707..242b8953075 100644 --- a/tests/Serializer/AbstractItemNormalizerTest.php +++ b/tests/Serializer/AbstractItemNormalizerTest.php @@ -25,6 +25,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; use ApiPlatform\Core\Serializer\AbstractItemNormalizer; @@ -1151,7 +1152,7 @@ public function testNormalizationWithDataTransformer() $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', '', '', null, null, ['input' => ['class' => InputDto::class]])); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'dummy', '', '', null, null, ['input' => ['class' => InputDto::class]])])); $dataTransformerProphecy = $this->prophesize(DataTransformerInterface::class); $dataTransformerProphecy->supportsTransformation($jsonInput, Dummy::class, $context)->willReturn(true); diff --git a/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php b/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php index 6106b145e07..357943196ea 100644 --- a/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php +++ b/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php @@ -31,6 +31,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\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; @@ -375,7 +376,7 @@ private function doTestNormalizeWithNameConverter(bool $legacy = false): void $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name', 'nameConverted'])); - $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS]); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); @@ -499,7 +500,7 @@ public function testNormalizeWithApiKeysEnabled(): void $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS]); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); @@ -2948,7 +2949,7 @@ public function testNormalizeWithDefaultProperty($expectedDefault, $expectedExam $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(DummyPropertyWithDefaultValue::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo'])); - $dummyMetadata = new ResourceMetadata('DummyPropertyWithDefaultValue', null, null, ['get' => ['method' => 'GET']]); + $dummyMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyPropertyWithDefaultValue', null, null, ['get' => ['method' => 'GET']])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class)->shouldBeCalled()->willReturn($dummyMetadata); diff --git a/tests/Validator/EventListener/ValidateListenerTest.php b/tests/Validator/EventListener/ValidateListenerTest.php index f34ce95abbc..c87507a358c 100644 --- a/tests/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Validator/EventListener/ValidateListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\Validator\EventListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyEntity; use ApiPlatform\Core\Tests\ProphecyTrait; @@ -117,11 +118,11 @@ public function testDoNotValidateWhenDisabledInOperationAttribute() $validatorProphecy = $this->prophesize(ValidatorInterface::class); $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - $resourceMetadata = new ResourceMetadata('DummyEntity', null, null, [], [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', 'DummyEntity', null, null, [], [ 'post' => [ 'validate' => false, ], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata); @@ -158,9 +159,9 @@ public function testThrowsValidationExceptionWithViolationsFound() private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array { - $resourceMetadata = new ResourceMetadata(null, null, null, [ + $resourceMetadata = new ResourceMetadata([new OperationCollectionMetadata('/dummies', null, null, null, [ 'create' => ['validation_groups' => $expectedValidationGroups], - ]); + ])]); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); if ($receive) {