Skip to content

Commit f937475

Browse files
alanpoulainsoyuka
authored andcommitted
feat(metadata): allow uri variables shortcut syntaxes
1 parent 8e0ba71 commit f937475

File tree

5 files changed

+90
-35
lines changed

5 files changed

+90
-35
lines changed

src/Metadata/ApiResource.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ final class ApiResource
4242
*/
4343
private $outputFormats;
4444
/**
45-
* @var array|UriVariable
45+
* @var array<string, UriVariable>|array<string, array>|string[]|string|null
4646
*/
4747
private $uriVariables;
4848
private $routePrefix;
@@ -405,17 +405,17 @@ public function withOutputFormats($outputFormats): self
405405
}
406406

407407
/**
408-
* @return UriVariable|array
408+
* @return array<string, UriVariable>|array<string, array>|string[]|string|null
409409
*/
410410
public function getUriVariables()
411411
{
412412
return $this->uriVariables;
413413
}
414414

415415
/**
416-
* @param array<string, UriVariable> $uriVariables
416+
* @param array<string, UriVariable>|array<string, array>|string[]|string|null $uriVariables
417417
*/
418-
public function withUriVariables(array $uriVariables): self
418+
public function withUriVariables($uriVariables): self
419419
{
420420
$self = clone $this;
421421
$self->uriVariables = $uriVariables;

src/Metadata/Operation.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Operation
4242
*/
4343
protected $outputFormats;
4444
/**
45-
* @var array|UriVariable|null
45+
* @var array<string, UriVariable>|array<string, array>|string[]|string|null
4646
*/
4747
protected $uriVariables;
4848
protected $routePrefix;
@@ -444,17 +444,17 @@ public function withOutputFormats($outputFormats = null): self
444444
}
445445

446446
/**
447-
* @return UriVariable|array
447+
* @return array<string, UriVariable>|array<string, array>|string[]|string|null
448448
*/
449449
public function getUriVariables()
450450
{
451451
return $this->uriVariables;
452452
}
453453

454454
/**
455-
* @param array<string, UriVariable> $uriVariables
455+
* @param array<string, UriVariable>|array<string, array>|string[]|string|null $uriVariables
456456
*/
457-
public function withUriVariables(array $uriVariables): self
457+
public function withUriVariables($uriVariables): self
458458
{
459459
$self = clone $this;
460460
$self->uriVariables = $uriVariables;

src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,14 @@ public function create(string $resourceClass): ResourceMetadataCollection
8787
}
8888

8989
/**
90-
* Builds resource operations to support:.
91-
*
90+
* Builds resource operations to support:
9291
* Resource
9392
* Get
9493
* Post
9594
* Resource
9695
* Put
9796
* Get
98-
*
99-
* In the future, we will be able to use nested attributes (https://wiki.php.net/rfc/new_in_initializers)
97+
* In the future, we will be able to use nested attributes (https://wiki.php.net/rfc/new_in_initializers).
10098
*
10199
* @return ApiResource[]
102100
*/

src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface;
1717
use ApiPlatform\Metadata\ApiResource;
1818
use ApiPlatform\Metadata\Operation;
19+
use ApiPlatform\Metadata\Operations;
1920
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2021
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2122
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
@@ -58,8 +59,8 @@ public function create(string $resourceClass): ResourceMetadataCollection
5859
$resourceMetadataCollection[$i] = $resource->withExtraProperties($resource->getExtraProperties() + ['user_defined_uri_template' => true]);
5960
}
6061

61-
$operations = $resource->getOperations();
62-
foreach ($resource->getOperations() as $key => $operation) {
62+
$operations = new Operations();
63+
foreach ($resource->getOperations() ?? new Operations() as $key => $operation) {
6364
$operation = $this->configureUriVariables($operation);
6465

6566
if ($operation->getUriTemplate()) {
@@ -69,16 +70,14 @@ public function create(string $resourceClass): ResourceMetadataCollection
6970
}
7071

7172
if ($routeName = $operation->getRouteName()) {
72-
$operations->remove($key)->add($routeName, $operation);
73+
$operations->add($routeName, $operation);
7374
continue;
7475
}
7576

7677
$operation = $operation->withUriTemplate($this->generateUriTemplate($operation));
7778
$operationName = $operation->getName() ?: sprintf('_api_%s_%s%s', $operation->getUriTemplate(), strtolower($operation->getMethod() ?? Operation::METHOD_GET), $operation->isCollection() ? '_collection' : '');
7879

79-
// Change the operation key
80-
$operations->remove($key)
81-
->add($operationName, $operation);
80+
$operations->add($operationName, $operation);
8281
}
8382

8483
$resource = $resource->withOperations($operations->sort());
@@ -163,32 +162,38 @@ private function configureUriVariables($operation)
163162
*/
164163
private function normalizeUriVariables($operation)
165164
{
166-
$uriVariables = $operation->getUriVariables() ?? [];
165+
$uriVariables = (array) ($operation->getUriVariables() ?? []);
166+
$normalizedUriVariables = [];
167167
$resourceClass = $operation->getClass();
168168

169169
foreach ($uriVariables as $parameterName => $uriVariable) {
170-
if ($uriVariable instanceof UriVariable) {
171-
continue;
172-
}
170+
$normalizedParameterName = $parameterName;
171+
$normalizedUriVariable = $uriVariable;
173172

174-
if (\is_int($parameterName)) {
175-
$uriVariables[$uriVariable] = (new UriVariable())->withIdentifiers([$uriVariable])->withTargetClass($resourceClass);
176-
} elseif (\is_string($uriVariable)) {
177-
$uriVariables[$parameterName] = (new UriVariable())->withIdentifiers([$uriVariable])->withTargetClass($resourceClass);
178-
} elseif (\is_array($uriVariable) && !isset($uriVariable['class'])) {
179-
$uriVariables[$parameterName] = (new UriVariable())->withIdentifiers($uriVariable)->withTargetClass($resourceClass);
180-
} elseif (\is_array($uriVariable)) {
181-
$uriVariables[$parameterName] = new UriVariable(null, $uriVariable['inverse_property'] ?? null, $uriVariable['property'] ?? null, $uriVariable['class'], $uriVariable['identifiers'] ?? null, $uriVariable['composite_identifier'] ?? null);
182-
} else {
183-
$uriVariables[$parameterName] = $uriVariable;
173+
if (\is_int($normalizedParameterName)) {
174+
$normalizedParameterName = $normalizedUriVariable;
175+
}
176+
if (\is_string($normalizedUriVariable)) {
177+
$normalizedUriVariable = (new UriVariable())->withIdentifiers([$normalizedUriVariable])->withTargetClass($resourceClass);
178+
}
179+
if (\is_array($normalizedUriVariable)) {
180+
if (!isset($normalizedUriVariable['class'])) {
181+
if (2 !== \count($normalizedUriVariable)) {
182+
throw new \LogicException("The uriVariables shortcut syntax needs to be the tuple: 'uriVariable' => [targetClass, targetProperty]");
183+
}
184+
$normalizedUriVariable = (new UriVariable())->withIdentifiers([$normalizedUriVariable[1]])->withTargetClass($normalizedUriVariable[0]);
185+
} else {
186+
$normalizedUriVariable = new UriVariable(null, $normalizedUriVariable['inverse_property'] ?? null, $normalizedUriVariable['property'] ?? null, $normalizedUriVariable['class'], $normalizedUriVariable['identifiers'] ?? null, $normalizedUriVariable['composite_identifier'] ?? null);
187+
}
184188
}
185-
186189
if (null !== ($hasCompositeIdentifier = $operation->getCompositeIdentifier())) {
187-
$uriVariables[$parameterName] = $uriVariables[$parameterName]->withCompositeIdentifier($hasCompositeIdentifier);
190+
$normalizedUriVariable = $normalizedUriVariable->withCompositeIdentifier($hasCompositeIdentifier);
188191
}
192+
193+
$normalizedUriVariables[$normalizedParameterName] = $normalizedUriVariable;
189194
}
190195

191-
return $this->mergeUriVariablesAttributes($operation->withUriVariables($uriVariables));
196+
return $this->mergeUriVariablesAttributes($operation->withUriVariables($normalizedUriVariables));
192197
}
193198

194199
/**

tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,30 @@ class: AttributeResource::class,
7373
),
7474
]
7575
),
76+
new ApiResource(
77+
shortName: 'AttributeResource',
78+
class: AttributeResource::class,
79+
uriTemplate: '/attribute_resources/by_name/{name}',
80+
uriVariables: 'name',
81+
),
82+
new ApiResource(
83+
shortName: 'AttributeResource',
84+
class: AttributeResource::class,
85+
uriTemplate: '/attribute_resources/by_name/{name}',
86+
uriVariables: ['name'],
87+
),
88+
new ApiResource(
89+
shortName: 'AttributeResource',
90+
class: AttributeResource::class,
91+
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
92+
uriVariables: ['dummyId' => [Dummy::class, 'id'], 'id' => [AttributeResource::class, 'id']],
93+
),
94+
new ApiResource(
95+
shortName: 'AttributeResource',
96+
class: AttributeResource::class,
97+
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
98+
uriVariables: ['dummyId' => ['class' => Dummy::class, 'identifiers' => ['id']], 'id' => ['class' => AttributeResource::class, 'identifiers' => ['id']]],
99+
),
76100
]),
77101
);
78102

@@ -106,6 +130,34 @@ class: AttributeResource::class,
106130
),
107131
]
108132
),
133+
new ApiResource(
134+
shortName: 'AttributeResource',
135+
class: AttributeResource::class,
136+
uriTemplate: '/attribute_resources/by_name/{name}',
137+
uriVariables: ['name' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['name'])],
138+
operations: [],
139+
),
140+
new ApiResource(
141+
shortName: 'AttributeResource',
142+
class: AttributeResource::class,
143+
uriTemplate: '/attribute_resources/by_name/{name}',
144+
uriVariables: ['name' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['name'])],
145+
operations: [],
146+
),
147+
new ApiResource(
148+
shortName: 'AttributeResource',
149+
class: AttributeResource::class,
150+
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
151+
uriVariables: ['dummyId' => new UriVariable(targetClass: Dummy::class, identifiers: ['id']), 'id' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['id'])],
152+
operations: [],
153+
),
154+
new ApiResource(
155+
shortName: 'AttributeResource',
156+
class: AttributeResource::class,
157+
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
158+
uriVariables: ['dummyId' => new UriVariable(targetClass: Dummy::class, identifiers: ['id']), 'id' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['id'])],
159+
operations: [],
160+
),
109161
]),
110162
$uriTemplateResourceMetadataCollectionFactory->create(AttributeResource::class)
111163
);

0 commit comments

Comments
 (0)