Skip to content

Commit

Permalink
chore: deprecate ApiPlatform\Api\FilterInterface (#6315)
Browse files Browse the repository at this point in the history
* chore: deprecate ApiPlatform\Api\FilterInterface

* filter description optional

* remove property array key in description filter when is set to null

* property is not mandatory

---------

Co-authored-by: soyuka <soyuka@users.noreply.github.com>
  • Loading branch information
louismariegaborit and soyuka committed Apr 18, 2024
1 parent b77e7ab commit 61bc8b6
Show file tree
Hide file tree
Showing 15 changed files with 120 additions and 177 deletions.
90 changes: 52 additions & 38 deletions src/Api/FilterInterface.php
Expand Up @@ -13,46 +13,60 @@

namespace ApiPlatform\Api;

/**
* Filters applicable on a resource.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*
* @deprecated
*/
interface FilterInterface
{
if (interface_exists(\ApiPlatform\Metadata\FilterInterface::class)) {
trigger_deprecation('api-platform', '3.3', sprintf('%s is deprecated in favor of %s. This class will be removed in 4.0.', FilterInterface::class, \ApiPlatform\Metadata\FilterInterface::class));
class_alias(
\ApiPlatform\Metadata\FilterInterface::class,
__NAMESPACE__.'\FilterInterface'
);

if (false) { // @phpstan-ignore-line
interface FilterInterface extends \ApiPlatform\Metadata\FilterInterface
{
}
}
} else {
/**
* Gets the description of this filter for the given resource.
* Filters applicable on a resource.
*
* Returns an array with the filter parameter names as keys and array with the following data as values:
* - property: the property where the filter is applied
* - type: the type of the filter
* - required: if this filter is required
* - strategy (optional): the used strategy
* - is_collection (optional): if this filter is for collection
* - swagger (optional): additional parameters for the path operation,
* e.g. 'swagger' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'type' => 'integer',
* ]
* - openapi (optional): additional parameters for the path operation in the version 3 spec,
* e.g. 'openapi' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'schema' => [
* 'type' => 'integer',
* ]
* ]
* - schema (optional): schema definition,
* e.g. 'schema' => [
* 'type' => 'string',
* 'enum' => ['value_1', 'value_2'],
* ]
* The description can contain additional data specific to a filter.
* @author Kévin Dunglas <dunglas@gmail.com>
*
* @see \ApiPlatform\OpenApi\Factory\OpenApiFactory::getFiltersParameters
* @deprecated
*/
public function getDescription(string $resourceClass): array;
interface FilterInterface
{
/**
* Gets the description of this filter for the given resource.
*
* Returns an array with the filter parameter names as keys and array with the following data as values:
* - property: the property where the filter is applied
* - type: the type of the filter
* - required: if this filter is required
* - strategy (optional): the used strategy
* - is_collection (optional): if this filter is for collection
* - swagger (optional): additional parameters for the path operation,
* e.g. 'swagger' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'type' => 'integer',
* ]
* - openapi (optional): additional parameters for the path operation in the version 3 spec,
* e.g. 'openapi' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'schema' => [
* 'type' => 'integer',
* ]
* ]
* - schema (optional): schema definition,
* e.g. 'schema' => [
* 'type' => 'string',
* 'enum' => ['value_1', 'value_2'],
* ]
* The description can contain additional data specific to a filter.
*
* @see \ApiPlatform\OpenApi\Factory\OpenApiFactory::getFiltersParameters
*/
public function getDescription(string $resourceClass): array;
}
}
3 changes: 1 addition & 2 deletions src/Api/FilterLocatorTrait.php
Expand Up @@ -14,7 +14,6 @@
namespace ApiPlatform\Api;

use ApiPlatform\Exception\InvalidArgumentException;
use ApiPlatform\Metadata\FilterInterface as MetadataFilterInterface;
use Psr\Container\ContainerInterface;

/**
Expand Down Expand Up @@ -45,7 +44,7 @@ private function setFilterLocator(?ContainerInterface $filterLocator, bool $allo
/**
* Gets a filter with a backward compatibility.
*/
private function getFilter(string $filterId): FilterInterface|MetadataFilterInterface|null
private function getFilter(string $filterId): ?FilterInterface
{
if ($this->filterLocator && $this->filterLocator->has($filterId)) {
return $this->filterLocator->get($filterId);
Expand Down
9 changes: 4 additions & 5 deletions src/Hydra/Serializer/CollectionFiltersNormalizer.php
Expand Up @@ -13,7 +13,6 @@

namespace ApiPlatform\Hydra\Serializer;

use ApiPlatform\Api\FilterInterface as LegacyFilterInterface;
use ApiPlatform\Api\ResourceClassResolverInterface as LegacyResourceClassResolverInterface;
use ApiPlatform\Doctrine\Odm\State\Options as ODMOptions;
use ApiPlatform\Doctrine\Orm\State\Options;
Expand Down Expand Up @@ -148,8 +147,8 @@ public function setNormalizer(NormalizerInterface $normalizer): void
/**
* Returns the content of the Hydra search property.
*
* @param LegacyFilterInterface[]|FilterInterface[] $filters
* @param array<string, Parameter> $parameters
* @param FilterInterface[] $filters
* @param array<string, Parameter> $parameters
*/
private function getSearch(string $resourceClass, array $parts, array $filters, array|Parameters|null $parameters): array
{
Expand All @@ -158,7 +157,7 @@ private function getSearch(string $resourceClass, array $parts, array $filters,
foreach ($filters as $filter) {
foreach ($filter->getDescription($resourceClass) as $variable => $data) {
$variables[] = $variable;
$mapping[] = ['@type' => 'IriTemplateMapping', 'variable' => $variable, 'property' => $data['property'], 'required' => $data['required']];
$mapping[] = ['@type' => 'IriTemplateMapping', 'variable' => $variable, 'property' => $data['property'] ?? null, 'required' => $data['required'] ?? false];
}
}

Expand Down Expand Up @@ -207,7 +206,7 @@ private function getSearch(string $resourceClass, array $parts, array $filters,
/**
* Gets a filter with a backward compatibility.
*/
private function getFilter(string $filterId): LegacyFilterInterface|FilterInterface|null
private function getFilter(string $filterId): ?FilterInterface
{
if ($this->filterLocator && $this->filterLocator->has($filterId)) {
return $this->filterLocator->get($filterId);
Expand Down
7 changes: 3 additions & 4 deletions src/Metadata/ApiFilter.php
Expand Up @@ -13,7 +13,6 @@

namespace ApiPlatform\Metadata;

use ApiPlatform\Api\FilterInterface as LegacyFilterInterface;
use ApiPlatform\Metadata\Exception\InvalidArgumentException;

/**
Expand All @@ -25,8 +24,8 @@
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
* @param string|class-string<FilterInterface> $filterClass
* @param string $alias a filter tag alias to be referenced in a Parameter
*/
public function __construct(
public string $filterClass,
Expand All @@ -36,7 +35,7 @@ public function __construct(
public array $arguments = [],
public ?string $alias = null,
) {
if (!is_a($this->filterClass, FilterInterface::class, true) && !is_a($this->filterClass, LegacyFilterInterface::class, true)) {
if (!is_a($this->filterClass, FilterInterface::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
92 changes: 40 additions & 52 deletions src/Metadata/FilterInterface.php
Expand Up @@ -13,59 +13,47 @@

namespace ApiPlatform\Metadata;

if (interface_exists(\ApiPlatform\Api\FilterInterface::class)) {
class_alias(
\ApiPlatform\Api\FilterInterface::class,
__NAMESPACE__.'\FilterInterface'
);

if (false) { // @phpstan-ignore-line
interface FilterInterface extends \ApiPlatform\Api\FilterInterface
{
}
}
} else {
/**
* Filters applicable on a resource.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
interface FilterInterface
{
/**
* Filters applicable on a resource.
* Gets the description of this filter for the given resource.
*
* Returns an array with the filter parameter names as keys and array with the following data as values:
* - property: the property where the filter is applied
* - type: the type of the filter
* - required: if this filter is required
* - description : the description of the filter
* - strategy: the used strategy
* - is_collection: if this filter is for collection
* - swagger: additional parameters for the path operation,
* e.g. 'swagger' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'type' => 'integer',
* ]
* - openapi: additional parameters for the path operation in the version 3 spec,
* e.g. 'openapi' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'schema' => [
* 'type' => 'integer',
* ]
* ]
* - schema: schema definition,
* e.g. 'schema' => [
* 'type' => 'string',
* 'enum' => ['value_1', 'value_2'],
* ]
* The description can contain additional data specific to a filter.
*
* @see \ApiPlatform\OpenApi\Factory\OpenApiFactory::getFiltersParameters
*
* @author Kévin Dunglas <dunglas@gmail.com>
* @return array<string, array{property?: string, type?: string, required?: bool, description?: string, strategy?: string, is_collection?: bool, swagger?: array<string, mixed>, openapi?: array<string, mixed>|\ApiPlatform\OpenApi\Model\Parameter, schema?: array<string, mixed>}>
*/
interface FilterInterface
{
/**
* Gets the description of this filter for the given resource.
*
* Returns an array with the filter parameter names as keys and array with the following data as values:
* - property: the property where the filter is applied
* - type: the type of the filter
* - required: if this filter is required
* - strategy (optional): the used strategy
* - is_collection (optional): if this filter is for collection
* - swagger (optional): additional parameters for the path operation,
* e.g. 'swagger' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'type' => 'integer',
* ]
* - openapi (optional): additional parameters for the path operation in the version 3 spec,
* e.g. 'openapi' => [
* 'description' => 'My Description',
* 'name' => 'My Name',
* 'schema' => [
* 'type' => 'integer',
* ]
* ]
* - schema (optional): schema definition,
* e.g. 'schema' => [
* 'type' => 'string',
* 'enum' => ['value_1', 'value_2'],
* ]
* 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;
}
public function getDescription(string $resourceClass): array;
}
Expand Up @@ -32,8 +32,18 @@ public function testParameterFactory(): void
public function getDescription(string $resourceClass): array
{
return [
'hydra' => ['schema' => ['type' => 'foo'], 'openapi' => new Parameter('test', 'query')],
'everywhere' => ['openapi' => ['allowEmptyValue' => true]],
'hydra' => [
'property' => 'hydra',
'type' => 'string',
'required' => false,
'schema' => ['type' => 'foo'],
'openapi' => new Parameter('test', 'query'),
],
'everywhere' => [
'property' => 'everywhere',
'type' => 'string',
'required' => false,
'openapi' => ['allowEmptyValue' => true]],
];
}
});
Expand Down
5 changes: 2 additions & 3 deletions src/ParameterValidator/FilterLocatorTrait.php
Expand Up @@ -13,9 +13,8 @@

namespace ApiPlatform\ParameterValidator;

use ApiPlatform\Api\FilterInterface;
use ApiPlatform\Exception\InvalidArgumentException;
use ApiPlatform\Metadata\FilterInterface as MetadataFilterInterface;
use ApiPlatform\Metadata\FilterInterface;
use Psr\Container\ContainerInterface;

/**
Expand Down Expand Up @@ -46,7 +45,7 @@ private function setFilterLocator(?ContainerInterface $filterLocator, bool $allo
/**
* Gets a filter with a backward compatibility.
*/
private function getFilter(string $filterId): FilterInterface|MetadataFilterInterface|null
private function getFilter(string $filterId): ?FilterInterface
{
if ($this->filterLocator && $this->filterLocator->has($filterId)) {
return $this->filterLocator->get($filterId);
Expand Down
1 change: 0 additions & 1 deletion src/Serializer/Filter/GroupFilter.php
Expand Up @@ -148,7 +148,6 @@ public function apply(Request $request, bool $normalization, array $attributes,
public function getDescription(string $resourceClass): array
{
$description = [
'property' => null,
'type' => 'string',
'is_collection' => true,
'required' => false,
Expand Down
1 change: 0 additions & 1 deletion src/Serializer/Filter/PropertyFilter.php
Expand Up @@ -163,7 +163,6 @@ public function getDescription(string $resourceClass): array

return [
"$this->parameterName[]" => [
'property' => null,
'type' => 'string',
'is_collection' => true,
'required' => false,
Expand Down
2 changes: 0 additions & 2 deletions src/Serializer/Tests/Filter/GroupFilterTest.php
Expand Up @@ -116,7 +116,6 @@ public function testGetDescription(): void
$groupFilter = new GroupFilter('custom_groups');
$expectedDescription = [
'custom_groups[]' => [
'property' => null,
'type' => 'string',
'is_collection' => true,
'required' => false,
Expand All @@ -131,7 +130,6 @@ public function testGetDescriptionWithWhitelist(): void
$groupFilter = new GroupFilter('custom_groups', false, ['default_group', 'another_default_group']);
$expectedDescription = [
'custom_groups[]' => [
'property' => null,
'type' => 'string',
'is_collection' => true,
'required' => false,
Expand Down
1 change: 0 additions & 1 deletion src/Serializer/Tests/Filter/PropertyFilterTest.php
Expand Up @@ -214,7 +214,6 @@ public function testGetDescription(): void
$propertyFilter = new PropertyFilter('custom_properties');
$expectedDescription = [
'custom_properties[]' => [
'property' => null,
'type' => 'string',
'is_collection' => true,
'required' => false,
Expand Down
3 changes: 3 additions & 0 deletions tests/.ignored-deprecations
Expand Up @@ -7,3 +7,6 @@
# Fixed in DoctrineMongoDBBundle 4.6
%Accessing Doctrine\\Common\\Lexer\\Token properties via ArrayAccess is deprecated, use the value, type or position property instead%
%Do the same.*Doctrine\\Bundle\\MongoDBBundle%

# Fixed when ApiPlatform\Api\FilterLocatorTrait will we deleted
%ApiPlatform\\Api\\FilterInterface is deprecated in favor of ApiPlatform\\Metadata\\FilterInterface%
3 changes: 3 additions & 0 deletions tests/.ignored-deprecations-legacy-events
Expand Up @@ -20,3 +20,6 @@
%Since api-platform/core 3.3: Use a "ApiPlatform\\State\\ProviderInterface" as first argument in "ApiPlatform\\Symfony\\EventListener\\AddFormatListener" instead of "Negotiation\\Negotiator".%

%Since api-platform/core 3.3: Use a "ApiPlatform\\Metadata\\Resource\\Factory\\ResourceMetadataCollectionFactoryInterface" as second argument in "ApiPlatform\\Symfony\\EventListener\\DeserializeListener" instead of "ApiPlatform\\Serializer\\SerializerContextBuilderInterface".%

# Fixed when ApiPlatform\Api\FilterLocatorTrait will we deleted
%ApiPlatform\\Api\\FilterInterface is deprecated in favor of ApiPlatform\\Metadata\\FilterInterface%

0 comments on commit 61bc8b6

Please sign in to comment.