Skip to content

Commit

Permalink
feat(metadata): attribute Parameter (#6246)
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Mar 26, 2024
1 parent 3cbef6a commit 3ad3836
Show file tree
Hide file tree
Showing 43 changed files with 1,004 additions and 43 deletions.
2 changes: 2 additions & 0 deletions src/Metadata/ApiFilter.php
Expand Up @@ -26,13 +26,15 @@ final class ApiFilter
{
/**
* @param string|class-string<FilterInterface>|class-string<LegacyFilterInterface> $filterClass
* @param string $alias a filter tag alias to be referenced in a Parameter
*/
public function __construct(
public string $filterClass,
public ?string $id = null,
public ?string $strategy = null,
public array $properties = [],
public array $arguments = [],
public ?string $alias = null,
) {
if (!is_a($this->filterClass, FilterInterface::class, true) && !is_a($this->filterClass, LegacyFilterInterface::class, true)) {
throw new InvalidArgumentException(sprintf('The filter class "%s" does not implement "%s". Did you forget a use statement?', $this->filterClass, FilterInterface::class));
Expand Down
2 changes: 2 additions & 0 deletions src/Metadata/ApiResource.php
Expand Up @@ -960,6 +960,7 @@ public function __construct(
$provider = null,
$processor = null,
protected ?OptionsInterface $stateOptions = null,
protected array|Parameters|null $parameters = null,
protected array $extraProperties = [],
) {
parent::__construct(
Expand Down Expand Up @@ -1000,6 +1001,7 @@ class: $class,
provider: $provider,
processor: $processor,
stateOptions: $stateOptions,
parameters: $parameters,
extraProperties: $extraProperties
);

Expand Down
2 changes: 2 additions & 0 deletions src/Metadata/Delete.php
Expand Up @@ -94,6 +94,7 @@ public function __construct(
$provider = null,
$processor = null,
?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = [],
) {
parent::__construct(
Expand Down Expand Up @@ -170,6 +171,7 @@ class: $class,
processor: $processor,
extraProperties: $extraProperties,
collectDenormalizationErrors: $collectDenormalizationErrors,
parameters: $parameters,
stateOptions: $stateOptions,
);
}
Expand Down
51 changes: 49 additions & 2 deletions src/Metadata/Extractor/XmlResourceExtractor.php
Expand Up @@ -15,11 +15,13 @@

use ApiPlatform\Metadata\Exception\InvalidArgumentException;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\HeaderParameter;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\QueryParameter;
use ApiPlatform\Metadata\Tests\Fixtures\StateOptions;
use ApiPlatform\OpenApi\Model\ExternalDocumentation;
use ApiPlatform\OpenApi\Model\Operation as OpenApiOperation;
use ApiPlatform\OpenApi\Model\Parameter;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use ApiPlatform\OpenApi\Model\RequestBody;
use ApiPlatform\State\OptionsInterface;
use Symfony\Component\Config\Util\XmlUtils;
Expand Down Expand Up @@ -97,6 +99,7 @@ private function buildExtendedBase(\SimpleXMLElement $resource): array
'stateOptions' => $this->buildStateOptions($resource),
'links' => $this->buildLinks($resource),
'headers' => $this->buildHeaders($resource),
'parameters' => $this->buildParameters($resource),
]);
}

Expand Down Expand Up @@ -200,7 +203,7 @@ private function buildOpenapi(\SimpleXMLElement $resource): bool|OpenApiOperatio

if (isset($openapi->parameters->parameter)) {
foreach ($openapi->parameters->parameter as $parameter) {
$data['parameters'][(string) $parameter->attributes()->name] = new Parameter(
$data['parameters'][(string) $parameter->attributes()->name] = new OpenApiParameter(
name: $this->phpize($parameter, 'name', 'string'),
in: $this->phpize($parameter, 'in', 'string'),
description: $this->phpize($parameter, 'description', 'string'),
Expand Down Expand Up @@ -494,4 +497,48 @@ private function buildHeaders(\SimpleXMLElement $resource): ?array

return $headers;
}

/**
* @return array<string, \ApiPlatform\Metadata\Parameter>
*/
private function buildParameters(\SimpleXMLElement $resource): ?array
{
if (!$resource->parameters) {
return null;
}

$parameters = [];
foreach ($resource->parameters->parameter as $parameter) {
$key = (string) $parameter->attributes()->key;
$cl = ('header' === (string) $parameter->attributes()->in) ? HeaderParameter::class : QueryParameter::class;
$parameters[$key] = new $cl(
key: $key,
required: $this->phpize($parameter, 'required', 'bool'),
schema: isset($parameter->schema->values) ? $this->buildValues($parameter->schema->values) : null,
openApi: isset($parameter->openapi) ? new OpenApiParameter(
name: $this->phpize($parameter->openapi, 'name', 'string'),
in: $this->phpize($parameter->openapi, 'in', 'string'),
description: $this->phpize($parameter->openapi, 'description', 'string'),
required: $this->phpize($parameter->openapi, 'required', 'bool'),
deprecated: $this->phpize($parameter->openapi, 'deprecated', 'bool'),
allowEmptyValue: $this->phpize($parameter->openapi, 'allowEmptyValue', 'bool'),
schema: isset($parameter->openapi->schema->values) ? $this->buildValues($parameter->openapi->schema->values) : null,
style: $this->phpize($parameter->openapi, 'style', 'string'),
explode: $this->phpize($parameter->openapi, 'explode', 'bool'),
allowReserved: $this->phpize($parameter->openapi, 'allowReserved', 'bool'),
example: $this->phpize($parameter->openapi, 'example', 'string'),
examples: isset($parameter->openapi->examples->values) ? new \ArrayObject($this->buildValues($parameter->openapi->examples->values)) : null,
content: isset($parameter->openapi->content->values) ? new \ArrayObject($this->buildValues($parameter->openapi->content->values)) : null,
) : null,
provider: $this->phpize($parameter, 'provider', 'string'),
filter: $this->phpize($parameter, 'filter', 'string'),
property: $this->phpize($parameter, 'property', 'string'),
description: $this->phpize($parameter, 'description', 'string'),
priority: $this->phpize($parameter, 'priority', 'integer'),
extraProperties: $this->buildExtraProperties($parameter, 'extraProperties') ?? [],
);
}

return $parameters;
}
}
46 changes: 46 additions & 0 deletions src/Metadata/Extractor/YamlResourceExtractor.php
Expand Up @@ -15,7 +15,9 @@

use ApiPlatform\Metadata\Exception\InvalidArgumentException;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\HeaderParameter;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\QueryParameter;
use ApiPlatform\Metadata\Tests\Fixtures\StateOptions;
use ApiPlatform\OpenApi\Model\ExternalDocumentation;
use ApiPlatform\OpenApi\Model\Operation as OpenApiOperation;
Expand Down Expand Up @@ -124,6 +126,7 @@ private function buildExtendedBase(array $resource): array
'stateOptions' => $this->buildStateOptions($resource),
'links' => $this->buildLinks($resource),
'headers' => $this->buildHeaders($resource),
'parameters' => $this->buildParameters($resource),
]);
}

Expand Down Expand Up @@ -450,4 +453,47 @@ private function buildHeaders(array $resource): ?array

return $headers;
}

/**
* @return array<string, \ApiPlatform\Metadata\Parameter>
*/
private function buildParameters(array $resource): ?array
{
if (!isset($resource['parameters']) || !\is_array($resource['parameters'])) {
return null;
}

$parameters = [];
foreach ($resource['parameters'] as $key => $parameter) {
$cl = ($parameter['in'] ?? 'query') === 'header' ? HeaderParameter::class : QueryParameter::class;
$parameters[$key] = new $cl(
key: $key,
required: $this->phpize($parameter, 'required', 'bool'),
schema: $parameter['schema'],
openApi: ($parameter['openapi'] ?? null) ? new Parameter(
name: $parameter['openapi']['name'],
in: $parameter['in'] ?? 'query',
description: $parameter['openapi']['description'] ?? '',
required: $parameter['openapi']['required'] ?? $parameter['required'] ?? false,
deprecated: $parameter['openapi']['deprecated'] ?? false,
allowEmptyValue: $parameter['openapi']['allowEmptyValue'] ?? false,
schema: $parameter['openapi']['schema'] ?? $parameter['schema'] ?? [],
style: $parameter['openapi']['style'] ?? null,
explode: $parameter['openapi']['explode'] ?? false,
allowReserved: $parameter['openapi']['allowReserved '] ?? false,
example: $parameter['openapi']['example'] ?? null,
examples: isset($parameter['openapi']['examples']) ? new \ArrayObject($parameter['openapi']['examples']) : null,
content: isset($parameter['openapi']['content']) ? new \ArrayObject($parameter['openapi']['content']) : null
) : null,
provider: $this->phpize($parameter, 'provider', 'string'),
filter: $this->phpize($parameter, 'filter', 'string'),
property: $this->phpize($parameter, 'property', 'string'),
description: $this->phpize($parameter, 'description', 'string'),
priority: $this->phpize($parameter, 'priority', 'integer'),
extraProperties: $this->buildArrayValue($parameter, 'extraProperties') ?? [],
);
}

return $parameters;
}
}
24 changes: 24 additions & 0 deletions src/Metadata/Extractor/schema/resources.xsd
Expand Up @@ -433,6 +433,29 @@
</xsd:sequence>
</xsd:group>

<xsd:element name="parameter">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="openApi" minOccurs="0" type="openApiOperation"/>
<xsd:element name="schema" minOccurs="0" type="sequenceWithValues"/>
<xsd:element name="extraProperties" minOccurs="0" type="sequenceWithValues"/>
</xsd:sequence>
<xsd:attribute type="xsd:string" name="key" use="required"/>
<xsd:attribute type="xsd:string" name="in"/>
<xsd:attribute type="xsd:string" name="provider"/>
<xsd:attribute type="xsd:string" name="filter"/>
<xsd:attribute type="xsd:string" name="property"/>
<xsd:attribute type="xsd:string" name="description"/>
<xsd:attribute type="xsd:boolean" name="required"/>
</xsd:complexType>
</xsd:element>

<xsd:complexType name="parameters">
<xsd:sequence maxOccurs="unbounded">
<xsd:element ref="parameter"/>
</xsd:sequence>
</xsd:complexType>

<xsd:group name="extendedBase">
<xsd:sequence>
<xsd:group ref="base"/>
Expand All @@ -444,6 +467,7 @@
<xsd:element name="inputFormats" minOccurs="0" type="formats"/>
<xsd:element name="openapiContext" minOccurs="0" type="sequenceWithValues"/> <!-- TODO Remove in 4.0 -->
<xsd:element name="openapi" minOccurs="0" type="openApiOperation"/>
<xsd:element name="parameters" minOccurs="0" type="parameters"/>
<xsd:element name="options" minOccurs="0" type="sequenceWithValues"/>
<xsd:element name="outputFormats" minOccurs="0" type="formats"/>
<xsd:element name="paginationViaCursor" minOccurs="0" type="paginationViaCursor"/>
Expand Down
2 changes: 2 additions & 0 deletions src/Metadata/FilterInterface.php
Expand Up @@ -63,6 +63,8 @@ interface FilterInterface
* The description can contain additional data specific to a filter.
*
* @see \ApiPlatform\OpenApi\Factory\OpenApiFactory::getFiltersParameters
*
* @return array<string, array{property: string, type: string, required: bool, strategy: string, is_collection: bool, openapi: array<string, mixed>, schema: array<string, mixed>}>
*/
public function getDescription(string $resourceClass): array;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Metadata/Get.php
Expand Up @@ -94,6 +94,7 @@ public function __construct(
$provider = null,
$processor = null,
?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = [],
) {
parent::__construct(
Expand Down Expand Up @@ -169,6 +170,7 @@ class: $class,
provider: $provider,
processor: $processor,
stateOptions: $stateOptions,
parameters: $parameters,
extraProperties: $extraProperties,
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/Metadata/GetCollection.php
Expand Up @@ -94,6 +94,7 @@ public function __construct(
$provider = null,
$processor = null,
?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = [],
private ?string $itemUriTemplate = null,
) {
Expand Down Expand Up @@ -169,6 +170,7 @@ class: $class,
name: $name,
provider: $provider,
processor: $processor,
parameters: $parameters,
extraProperties: $extraProperties,
stateOptions: $stateOptions,
);
Expand Down
3 changes: 3 additions & 0 deletions src/Metadata/GraphQl/Operation.php
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Metadata\Link;
use ApiPlatform\Metadata\Operation as AbstractOperation;
use ApiPlatform\Metadata\Parameters;
use ApiPlatform\State\OptionsInterface;

class Operation extends AbstractOperation
Expand Down Expand Up @@ -84,6 +85,7 @@ public function __construct(
$provider = null,
$processor = null,
?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = []
) {
parent::__construct(
Expand Down Expand Up @@ -131,6 +133,7 @@ class: $class,
provider: $provider,
processor: $processor,
stateOptions: $stateOptions,
parameters: $parameters,
extraProperties: $extraProperties
);
}
Expand Down
3 changes: 3 additions & 0 deletions src/Metadata/GraphQl/Query.php
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Metadata\GraphQl;

use ApiPlatform\Metadata\Parameters;
use ApiPlatform\State\OptionsInterface;

#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
Expand Down Expand Up @@ -68,6 +69,7 @@ public function __construct(
$provider = null,
$processor = null,
?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = [],

protected ?bool $nested = null,
Expand Down Expand Up @@ -121,6 +123,7 @@ class: $class,
provider: $provider,
processor: $processor,
stateOptions: $stateOptions,
parameters: $parameters,
extraProperties: $extraProperties
);
}
Expand Down
3 changes: 3 additions & 0 deletions src/Metadata/GraphQl/QueryCollection.php
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\Metadata\GraphQl;

use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\Parameters;
use ApiPlatform\State\OptionsInterface;

#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
Expand Down Expand Up @@ -69,6 +70,7 @@ public function __construct(
$provider = null,
$processor = null,
protected ?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = [],

?bool $nested = null,
Expand Down Expand Up @@ -121,6 +123,7 @@ class: $class,
name: $name ?: 'collection_query',
provider: $provider,
processor: $processor,
parameters: $parameters,
extraProperties: $extraProperties,
nested: $nested,
);
Expand Down
3 changes: 3 additions & 0 deletions src/Metadata/GraphQl/Subscription.php
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Metadata\GraphQl;

use ApiPlatform\Metadata\Parameters;
use ApiPlatform\State\OptionsInterface;

#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
Expand Down Expand Up @@ -68,6 +69,7 @@ public function __construct(
$provider = null,
$processor = null,
?OptionsInterface $stateOptions = null,
array|Parameters|null $parameters = null,
array $extraProperties = [],
) {
parent::__construct(
Expand Down Expand Up @@ -119,6 +121,7 @@ class: $class,
provider: $provider,
processor: $processor,
stateOptions: $stateOptions,
parameters: $parameters,
extraProperties: $extraProperties,
);
}
Expand Down
22 changes: 22 additions & 0 deletions src/Metadata/HeaderParameter.php
@@ -0,0 +1,22 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* 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\Metadata;

/**
* @experimental
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class HeaderParameter extends Parameter implements HeaderParameterInterface
{
}

0 comments on commit 3ad3836

Please sign in to comment.