Skip to content

Commit 096ac11

Browse files
authored
fix(metadata): keep configured uri variables (#5217)
fixes #5184
1 parent e9c7e4a commit 096ac11

File tree

9 files changed

+72
-26
lines changed

9 files changed

+72
-26
lines changed

features/main/attribute_resource.feature

+13-18
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
@php8
2+
@v3
3+
@!mysql
4+
@!mongodb
15
Feature: Resource attributes
26
In order to use the Resource attribute
37
As a developer
48
I should be able to fetch data from a state provider
5-
6-
@php8
7-
@v3
8-
@!mysql
9-
@!mongodb
9+
1010
Scenario: Retrieve a Resource collection
1111
When I add "Content-Type" header equal to "application/ld+json"
1212
And I send a "GET" request to "/attribute_resources"
@@ -36,11 +36,7 @@ Feature: Resource attributes
3636
}
3737
"""
3838

39-
@php8
40-
@v3
41-
@!mysql
42-
@!mongodb
43-
Scenario: Retrieve the first resource
39+
Scenario: Retrieve the first resource
4440
When I add "Content-Type" header equal to "application/ld+json"
4541
And I send a "GET" request to "/attribute_resources/1"
4642
Then the response status code should be 200
@@ -57,10 +53,6 @@ Feature: Resource attributes
5753
}
5854
"""
5955

60-
@php8
61-
@v3
62-
@!mysql
63-
@!mongodb
6456
Scenario: Retrieve the aliased resource
6557
When I add "Content-Type" header equal to "application/ld+json"
6658
And I send a "GET" request to "/dummy/1/attribute_resources/2"
@@ -80,10 +72,6 @@ Feature: Resource attributes
8072
}
8173
"""
8274

83-
@php8
84-
@v3
85-
@!mysql
86-
@!mongodb
8775
Scenario: Patch the aliased resource
8876
When I add "Content-Type" header equal to "application/merge-patch+json"
8977
And I send a "PATCH" request to "/dummy/1/attribute_resources/2" with body:
@@ -105,3 +93,10 @@ Feature: Resource attributes
10593
"name": "Patched"
10694
}
10795
"""
96+
97+
Scenario: Uri variables should be configured properly
98+
When I send a "GET" request to "/photos/1/resize/300/100"
99+
Then the response status code should be 400
100+
And the response should be in JSON
101+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
102+
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"'

src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ private function transformUriVariablesToIdentifiers(array $arrayOperation): arra
100100

101101
$arrayOperation['identifiers'] = [];
102102
foreach ($arrayOperation['uri_variables'] as $parameterName => $identifiedBy) {
103+
if ($identifiedBy->getExpandedValue() ?? false) {
104+
continue;
105+
}
106+
103107
if (1 === \count($identifiedBy->getIdentifiers() ?? ['id'])) {
104108
$arrayOperation['identifiers'][$parameterName] = [$identifiedBy->getFromClass(), $identifiedBy->getIdentifiers()[0] ?? ['id']];
105109
continue;

src/Core/Swagger/Serializer/DocumentationNormalizer.php

+4
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ private function addPaths(bool $v3, \ArrayObject $paths, \ArrayObject $definitio
274274
}
275275

276276
foreach ($operations as $operationName => $operation) {
277+
if (false === ($operation['openapi'] ?? null)) {
278+
continue;
279+
}
280+
277281
// Skolem IRI
278282
if ('api_genid' === ($operation['route_name'] ?? null)) {
279283
continue;

src/Doctrine/Odm/State/LinksHandlerTrait.php

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ private function handleLinks(Builder $aggregationBuilder, array $identifiers, ar
3737
return;
3838
}
3939

40+
foreach ($links as $i => $link) {
41+
if (null !== $link->getExpandedValue()) {
42+
unset($links[$i]);
43+
}
44+
}
45+
4046
$executeOptions = $operation->getExtraProperties()['doctrine_mongodb']['execute_options'] ?? [];
4147

4248
$this->buildAggregation($resourceClass, array_reverse($links), array_reverse($identifiers), $context, $executeOptions, $resourceClass, $aggregationBuilder);

src/Doctrine/Orm/State/LinksHandlerTrait.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ private function handleLinks(QueryBuilder $queryBuilder, array $identifiers, Que
4545
$identifiers = array_reverse($identifiers);
4646

4747
foreach (array_reverse($links) as $link) {
48-
if ($link->getExpandedValue() || !$link->getFromClass()) {
48+
if (null !== $link->getExpandedValue() || !$link->getFromClass()) {
4949
continue;
5050
}
5151

src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php

+6
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ private function configureUriVariables($operation)
132132
return $this->normalizeUriVariables($operation);
133133
}
134134

135+
$hasUserConfiguredUriVariables = !($operation->getExtraProperties['is_legacy_resource_metadata'] ?? false);
135136
if (!$operation->getUriVariables()) {
137+
$hasUserConfiguredUriVariables = false;
136138
$operation = $operation->withUriVariables($this->transformLinksToUriVariables($this->linkFactory->createLinksFromIdentifiers($operation)));
137139
}
138140

@@ -157,6 +159,10 @@ private function configureUriVariables($operation)
157159
});
158160

159161
if (\count($variables) !== \count($uriVariables)) {
162+
if ($hasUserConfiguredUriVariables) {
163+
return $operation;
164+
}
165+
160166
$newUriVariables = [];
161167
foreach ($variables as $variable) {
162168
if (isset($uriVariables[$variable])) {

src/OpenApi/Factory/OpenApiFactory.php

+4
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
194194

195195
// Set up parameters
196196
foreach ($uriVariables ?? [] as $parameterName => $uriVariable) {
197+
if ($uriVariable->getExpandedValue() ?? false) {
198+
continue;
199+
}
200+
197201
$parameter = new Model\Parameter($parameterName, 'path', (new \ReflectionClass($uriVariable->getFromClass()))->getShortName().' identifier', true, false, false, ['type' => 'string']);
198202
if ($this->hasParameter($parameter, $parameters)) {
199203
continue;

tests/Fixtures/TestBundle/Entity/Company.php

-7
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@
2828
#[GetCollection]
2929
#[Get]
3030
#[Post]
31-
#[ApiResource(
32-
uriTemplate: '/employees/{employeeId}/rooms/{roomId}/company/{companyId}',
33-
uriVariables: [
34-
'employeeId' => ['from_class' => Employee::class, 'from_property' => 'company'],
35-
],
36-
)]
37-
#[Get]
3831
#[ApiResource(
3932
uriTemplate: '/employees/{employeeId}/company',
4033
uriVariables: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity;
15+
16+
use ApiPlatform\Metadata\Get;
17+
use ApiPlatform\Metadata\Operation;
18+
19+
#[Get(uriTemplate: '/photos/{id}/resize/{width}/{height}', uriVariables: ['id'], provider: [IncompleteUriVariableConfigured::class, 'provide'], openapi: false)]
20+
final class IncompleteUriVariableConfigured
21+
{
22+
public function __construct(public string $id)
23+
{
24+
}
25+
26+
public static function provide(Operation $operation, array $uriVariables = [], array $context = []): self
27+
{
28+
if (isset($uriVariables['width'])) {
29+
throw new \LogicException('URI variable "width" should not exist');
30+
}
31+
32+
return new self($uriVariables['id']);
33+
}
34+
}

0 commit comments

Comments
 (0)