From 92693fa4a7aa3ae74a6c584708b958bf596e111a Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 23 Nov 2022 11:22:40 +0100 Subject: [PATCH] fix(metadata): keep configured uri variables fixes #5184 --- features/main/attribute_resource.feature | 22 ++++++------ ...plateResourceMetadataCollectionFactory.php | 6 ++++ .../IncompleteUriVariableConfigured.php | 34 +++++++++++++++++++ 3 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 tests/Fixtures/TestBundle/Entity/IncompleteUriVariableConfigured.php diff --git a/features/main/attribute_resource.feature b/features/main/attribute_resource.feature index eae47b2689b..60c47cfa97d 100644 --- a/features/main/attribute_resource.feature +++ b/features/main/attribute_resource.feature @@ -1,11 +1,11 @@ +@php8 +@!mysql +@!mongodb Feature: Resource attributes In order to use the Resource attribute As a developer I should be able to fetch data from a state provider - @php8 - @!mysql - @!mongodb Scenario: Retrieve a Resource collection When I add "Content-Type" header equal to "application/ld+json" And I send a "GET" request to "/attribute_resources" @@ -35,9 +35,6 @@ Feature: Resource attributes } """ - @php8 - @!mysql - @!mongodb Scenario: Retrieve the first resource When I add "Content-Type" header equal to "application/ld+json" And I send a "GET" request to "/attribute_resources/1" @@ -55,9 +52,6 @@ Feature: Resource attributes } """ - @php8 - @!mysql - @!mongodb Scenario: Retrieve the aliased resource When I add "Content-Type" header equal to "application/ld+json" And I send a "GET" request to "/dummy/1/attribute_resources/2" @@ -77,9 +71,6 @@ Feature: Resource attributes } """ - @php8 - @!mysql - @!mongodb Scenario: Patch the aliased resource When I add "Content-Type" header equal to "application/merge-patch+json" And I send a "PATCH" request to "/dummy/1/attribute_resources/2" with body: @@ -101,3 +92,10 @@ Feature: Resource attributes "name": "Patched" } """ + + Scenario: Uri variables should be configured properly + When I send a "GET" request to "/photos/1/resize/300/100" + Then the response status code should be 400 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" + And the JSON node "hydra:description" should be equal to 'Unable to generate an IRI for the item of type "ApiPlatform\Tests\Fixtures\TestBundle\Entity\IncompleteUriVariableConfigured"' diff --git a/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php index 3f8cb93688c..051549fd720 100644 --- a/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php @@ -137,7 +137,9 @@ private function configureUriVariables(ApiResource|HttpOperation $operation): Ap return $this->normalizeUriVariables($operation); } + $hasUserConfiguredUriVariables = true; if (!$operation->getUriVariables()) { + $hasUserConfiguredUriVariables = false; $operation = $operation->withUriVariables($this->transformLinksToUriVariables($this->linkFactory->createLinksFromIdentifiers($operation))); } @@ -164,6 +166,10 @@ private function configureUriVariables(ApiResource|HttpOperation $operation): Ap $variables = $route->getPathVariables(); if (\count($variables) !== \count($uriVariables)) { + if ($hasUserConfiguredUriVariables) { + return $operation; + } + $newUriVariables = []; foreach ($variables as $variable) { if (isset($uriVariables[$variable])) { diff --git a/tests/Fixtures/TestBundle/Entity/IncompleteUriVariableConfigured.php b/tests/Fixtures/TestBundle/Entity/IncompleteUriVariableConfigured.php new file mode 100644 index 00000000000..2b1111ecadb --- /dev/null +++ b/tests/Fixtures/TestBundle/Entity/IncompleteUriVariableConfigured.php @@ -0,0 +1,34 @@ + + * + * 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\Tests\Fixtures\TestBundle\Entity; + +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Operation; + +#[ApiResource(uriTemplate: '/photos/{id}/resize/{width}/{height}', uriVariables: ['id'], provider: [IncompleteUriVariableConfigured::class, 'provide'])] +final class IncompleteUriVariableConfigured +{ + public function __construct(public string $id) + { + } + + public static function provide(Operation $operation, array $uriVariables = [], array $context = []): self + { + if (isset($uriVariables['width'])) { + throw new \LogicException('URI variable "width" should not exist'); + } + + return new self($uriVariables['id']); + } +}