Skip to content

Commit

Permalink
feat(metadata): allow uri variables shortcut syntaxes
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain authored and soyuka committed Oct 22, 2021
1 parent 8e0ba71 commit f937475
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 35 deletions.
8 changes: 4 additions & 4 deletions src/Metadata/ApiResource.php
Expand Up @@ -42,7 +42,7 @@ final class ApiResource
*/
private $outputFormats;
/**
* @var array|UriVariable
* @var array<string, UriVariable>|array<string, array>|string[]|string|null
*/
private $uriVariables;
private $routePrefix;
Expand Down Expand Up @@ -405,17 +405,17 @@ public function withOutputFormats($outputFormats): self
}

/**
* @return UriVariable|array
* @return array<string, UriVariable>|array<string, array>|string[]|string|null
*/
public function getUriVariables()
{
return $this->uriVariables;
}

/**
* @param array<string, UriVariable> $uriVariables
* @param array<string, UriVariable>|array<string, array>|string[]|string|null $uriVariables
*/
public function withUriVariables(array $uriVariables): self
public function withUriVariables($uriVariables): self
{
$self = clone $this;
$self->uriVariables = $uriVariables;
Expand Down
8 changes: 4 additions & 4 deletions src/Metadata/Operation.php
Expand Up @@ -42,7 +42,7 @@ class Operation
*/
protected $outputFormats;
/**
* @var array|UriVariable|null
* @var array<string, UriVariable>|array<string, array>|string[]|string|null
*/
protected $uriVariables;
protected $routePrefix;
Expand Down Expand Up @@ -444,17 +444,17 @@ public function withOutputFormats($outputFormats = null): self
}

/**
* @return UriVariable|array
* @return array<string, UriVariable>|array<string, array>|string[]|string|null
*/
public function getUriVariables()
{
return $this->uriVariables;
}

/**
* @param array<string, UriVariable> $uriVariables
* @param array<string, UriVariable>|array<string, array>|string[]|string|null $uriVariables
*/
public function withUriVariables(array $uriVariables): self
public function withUriVariables($uriVariables): self
{
$self = clone $this;
$self->uriVariables = $uriVariables;
Expand Down
Expand Up @@ -87,16 +87,14 @@ public function create(string $resourceClass): ResourceMetadataCollection
}

/**
* Builds resource operations to support:.
*
* Builds resource operations to support:
* Resource
* Get
* Post
* Resource
* Put
* Get
*
* In the future, we will be able to use nested attributes (https://wiki.php.net/rfc/new_in_initializers)
* In the future, we will be able to use nested attributes (https://wiki.php.net/rfc/new_in_initializers).
*
* @return ApiResource[]
*/
Expand Down
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Operations;
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
Expand Down Expand Up @@ -58,8 +59,8 @@ public function create(string $resourceClass): ResourceMetadataCollection
$resourceMetadataCollection[$i] = $resource->withExtraProperties($resource->getExtraProperties() + ['user_defined_uri_template' => true]);
}

$operations = $resource->getOperations();
foreach ($resource->getOperations() as $key => $operation) {
$operations = new Operations();
foreach ($resource->getOperations() ?? new Operations() as $key => $operation) {
$operation = $this->configureUriVariables($operation);

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

if ($routeName = $operation->getRouteName()) {
$operations->remove($key)->add($routeName, $operation);
$operations->add($routeName, $operation);
continue;
}

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

// Change the operation key
$operations->remove($key)
->add($operationName, $operation);
$operations->add($operationName, $operation);
}

$resource = $resource->withOperations($operations->sort());
Expand Down Expand Up @@ -163,32 +162,38 @@ private function configureUriVariables($operation)
*/
private function normalizeUriVariables($operation)
{
$uriVariables = $operation->getUriVariables() ?? [];
$uriVariables = (array) ($operation->getUriVariables() ?? []);
$normalizedUriVariables = [];
$resourceClass = $operation->getClass();

foreach ($uriVariables as $parameterName => $uriVariable) {
if ($uriVariable instanceof UriVariable) {
continue;
}
$normalizedParameterName = $parameterName;
$normalizedUriVariable = $uriVariable;

if (\is_int($parameterName)) {
$uriVariables[$uriVariable] = (new UriVariable())->withIdentifiers([$uriVariable])->withTargetClass($resourceClass);
} elseif (\is_string($uriVariable)) {
$uriVariables[$parameterName] = (new UriVariable())->withIdentifiers([$uriVariable])->withTargetClass($resourceClass);
} elseif (\is_array($uriVariable) && !isset($uriVariable['class'])) {
$uriVariables[$parameterName] = (new UriVariable())->withIdentifiers($uriVariable)->withTargetClass($resourceClass);
} elseif (\is_array($uriVariable)) {
$uriVariables[$parameterName] = new UriVariable(null, $uriVariable['inverse_property'] ?? null, $uriVariable['property'] ?? null, $uriVariable['class'], $uriVariable['identifiers'] ?? null, $uriVariable['composite_identifier'] ?? null);
} else {
$uriVariables[$parameterName] = $uriVariable;
if (\is_int($normalizedParameterName)) {
$normalizedParameterName = $normalizedUriVariable;
}
if (\is_string($normalizedUriVariable)) {
$normalizedUriVariable = (new UriVariable())->withIdentifiers([$normalizedUriVariable])->withTargetClass($resourceClass);
}
if (\is_array($normalizedUriVariable)) {
if (!isset($normalizedUriVariable['class'])) {
if (2 !== \count($normalizedUriVariable)) {
throw new \LogicException("The uriVariables shortcut syntax needs to be the tuple: 'uriVariable' => [targetClass, targetProperty]");
}
$normalizedUriVariable = (new UriVariable())->withIdentifiers([$normalizedUriVariable[1]])->withTargetClass($normalizedUriVariable[0]);
} else {
$normalizedUriVariable = new UriVariable(null, $normalizedUriVariable['inverse_property'] ?? null, $normalizedUriVariable['property'] ?? null, $normalizedUriVariable['class'], $normalizedUriVariable['identifiers'] ?? null, $normalizedUriVariable['composite_identifier'] ?? null);
}
}

if (null !== ($hasCompositeIdentifier = $operation->getCompositeIdentifier())) {
$uriVariables[$parameterName] = $uriVariables[$parameterName]->withCompositeIdentifier($hasCompositeIdentifier);
$normalizedUriVariable = $normalizedUriVariable->withCompositeIdentifier($hasCompositeIdentifier);
}

$normalizedUriVariables[$normalizedParameterName] = $normalizedUriVariable;
}

return $this->mergeUriVariablesAttributes($operation->withUriVariables($uriVariables));
return $this->mergeUriVariablesAttributes($operation->withUriVariables($normalizedUriVariables));
}

/**
Expand Down
Expand Up @@ -73,6 +73,30 @@ class: AttributeResource::class,
),
]
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/attribute_resources/by_name/{name}',
uriVariables: 'name',
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/attribute_resources/by_name/{name}',
uriVariables: ['name'],
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
uriVariables: ['dummyId' => [Dummy::class, 'id'], 'id' => [AttributeResource::class, 'id']],
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
uriVariables: ['dummyId' => ['class' => Dummy::class, 'identifiers' => ['id']], 'id' => ['class' => AttributeResource::class, 'identifiers' => ['id']]],
),
]),
);

Expand Down Expand Up @@ -106,6 +130,34 @@ class: AttributeResource::class,
),
]
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/attribute_resources/by_name/{name}',
uriVariables: ['name' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['name'])],
operations: [],
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/attribute_resources/by_name/{name}',
uriVariables: ['name' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['name'])],
operations: [],
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
uriVariables: ['dummyId' => new UriVariable(targetClass: Dummy::class, identifiers: ['id']), 'id' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['id'])],
operations: [],
),
new ApiResource(
shortName: 'AttributeResource',
class: AttributeResource::class,
uriTemplate: '/dummy/{dummyId}/attribute_resources/{id}',
uriVariables: ['dummyId' => new UriVariable(targetClass: Dummy::class, identifiers: ['id']), 'id' => new UriVariable(targetClass: AttributeResource::class, identifiers: ['id'])],
operations: [],
),
]),
$uriTemplateResourceMetadataCollectionFactory->create(AttributeResource::class)
);
Expand Down

0 comments on commit f937475

Please sign in to comment.