Skip to content

Commit

Permalink
Merge 2a2ea19 into 0d37caa
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmed-bhs committed Oct 16, 2021
2 parents 0d37caa + 2a2ea19 commit 85a9395
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 10 deletions.
7 changes: 6 additions & 1 deletion src/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Core\Api\FilterCollection;
use ApiPlatform\Core\Api\FilterLocatorTrait;
use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\FilterInterface;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
Expand Down Expand Up @@ -50,7 +51,11 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa
public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = [])
{
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
if (OperationType::SUBRESOURCE === ($context['operation_type'] ?? null)) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}

if (empty($resourceFilters)) {
return;
Expand Down
8 changes: 6 additions & 2 deletions src/Bridge/Doctrine/Orm/Extension/FilterExtension.php
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Core\Api\FilterCollection;
use ApiPlatform\Core\Api\FilterLocatorTrait;
use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\FilterInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
Expand Down Expand Up @@ -55,8 +56,11 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator
}

$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);

if (OperationType::SUBRESOURCE === ($context['operation_type'] ?? null)) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}
if (empty($resourceFilters)) {
return;
}
Expand Down
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension;

use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Psr\Container\ContainerInterface;

Expand Down Expand Up @@ -40,7 +41,12 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa
public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array
{
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);

if (OperationType::SUBRESOURCE === ($context['operation_type'] ?? null)) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}

if (!$resourceFilters) {
return $requestBody;
Expand Down
8 changes: 6 additions & 2 deletions src/EventListener/QueryParameterValidateListener.php
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Core\EventListener;

use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Filter\QueryParameterValidator;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Core\Util\RequestAttributesExtractor;
Expand Down Expand Up @@ -52,8 +53,11 @@ public function onKernelRequest(RequestEvent $event)
$queryParameters = $queryString ? RequestParser::parseRequestParams($queryString) : [];

$resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']);
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);

if (isset($attributes['operation_type']) && OperationType::SUBRESOURCE === $attributes['operation_type']) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}
$this->queryParameterValidator->validateFilters($attributes['resource_class'], $resourceFilters, $queryParameters);
}
}
3 changes: 3 additions & 0 deletions src/Hydra/Serializer/CollectionFiltersNormalizer.php
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Core\Api\FilterCollection;
use ApiPlatform\Core\Api\FilterInterface;
use ApiPlatform\Core\Api\FilterLocatorTrait;
use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Api\ResourceClassResolverInterface;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Psr\Container\ContainerInterface;
Expand Down Expand Up @@ -85,6 +86,8 @@ public function normalize($object, $format = null, array $context = [])
$operationName = $context['collection_operation_name'] ?? null;
if (null === $operationName) {
$resourceFilters = $resourceMetadata->getAttribute('filters', []);
} elseif (OperationType::SUBRESOURCE === ($context['operation_type'] ?? null)) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Hydra/Serializer/CollectionNormalizer.php
Expand Up @@ -79,7 +79,7 @@ public function normalize($object, $format = null, array $context = [])
$context = $this->initContext($resourceClass, $context);
$data = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context);

if (isset($context['operation_type']) && OperationType::SUBRESOURCE === $context['operation_type']) {
if (OperationType::SUBRESOURCE === ($context['operation_type'] ?? null)) {
$data['@id'] = $this->iriConverter->getSubresourceIriFromResourceClass($resourceClass, $context);
} else {
$data['@id'] = $this->iriConverter->getIriFromResourceClass($resourceClass);
Expand Down
8 changes: 7 additions & 1 deletion src/OpenApi/Factory/OpenApiFactory.php
Expand Up @@ -403,7 +403,13 @@ private function getLink(string $resourceClass, string $operationId, string $pat
private function getFiltersParameters(ResourceMetadata $resourceMetadata, string $operationName, string $resourceClass): array
{
$parameters = [];
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);

if (isset($resourceMetadata->getSubresourceOperations()[$operationName])) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}

foreach ($resourceFilters as $filterId) {
if (!$filter = $this->getFilter($filterId)) {
continue;
Expand Down
8 changes: 7 additions & 1 deletion src/Swagger/Serializer/DocumentationNormalizer.php
Expand Up @@ -749,7 +749,13 @@ private function getFiltersParameters(bool $v3, string $resourceClass, string $o
}

$parameters = [];
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);

if (isset($resourceMetadata->getSubresourceOperations()[$operationName])) {
$resourceFilters = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'filters', [], true);
} else {
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true);
}

foreach ($resourceFilters as $filterId) {
if (!$filter = $this->getFilter($filterId)) {
continue;
Expand Down
36 changes: 36 additions & 0 deletions tests/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtensionTest.php
Expand Up @@ -68,4 +68,40 @@ public function testApplyToCollectionWithoutFilters()
$orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal());
$orderExtensionTest->applyToCollection($this->prophesize(Builder::class)->reveal(), Dummy::class, 'get');
}

public function testApplyToSubresourceWithValidFilters()
{
$aggregationBuilderProphecy = $this->prophesize(Builder::class);

$dummyMetadata = new ResourceMetadata('subDummy', 'dummy subresource', '#dummy', ['get' => ['method' => 'GET']], [], [], ['parents_dummies_get_subresource' => ['method' => 'GET', 'filters' => ['dummyFilter', 'dummyBadFilter']]]);
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata);

$aggregationBuilder = $aggregationBuilderProphecy->reveal();

$mongoDbOdmFilterProphecy = $this->prophesize(FilterInterface::class);
$mongoDbOdmFilterProphecy->apply($aggregationBuilder, Dummy::class, 'parents_dummies_get_subresource', ['filters' => []])->shouldBeCalled();

$ordinaryFilterProphecy = $this->prophesize(ApiFilterInterface::class);

$filterLocatorProphecy = $this->prophesize(ContainerInterface::class);
$filterLocatorProphecy->has('dummyFilter')->willReturn(true)->shouldBeCalled();
$filterLocatorProphecy->has('dummyBadFilter')->willReturn(true)->shouldBeCalled();
$filterLocatorProphecy->get('dummyFilter')->willReturn($mongoDbOdmFilterProphecy->reveal())->shouldBeCalled();
$filterLocatorProphecy->get('dummyBadFilter')->willReturn($ordinaryFilterProphecy->reveal())->shouldBeCalled();

$orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $filterLocatorProphecy->reveal());
$orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, 'parents_dummies_get_subresource');
}

public function testApplyToSubresourceWithoutFilters()
{
$dummyMetadata = new ResourceMetadata('subDummy', 'dummy subresource', '#dummy', ['get' => ['method' => 'GET']], [], [], ['parents_dummies_get_subresource' => ['method' => 'GET']]);

$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata);

$orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal());
$orderExtensionTest->applyToCollection($this->prophesize(Builder::class)->reveal(), Dummy::class, 'parents_dummies_get_subresource');
}
}
38 changes: 38 additions & 0 deletions tests/Bridge/Doctrine/Orm/Extension/FilterExtensionTest.php
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Core\Api\FilterCollection;
use ApiPlatform\Core\Api\FilterInterface as ApiFilterInterface;
use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\FilterInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
Expand Down Expand Up @@ -101,4 +102,41 @@ public function testApplyToCollectionWithoutFilters()
$orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal());
$orderExtensionTest->applyToCollection($this->prophesize(QueryBuilder::class)->reveal(), new QueryNameGenerator(), Dummy::class, 'get');
}

public function testApplyToSubresourceWithValidFilters()
{
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);

$dummyMetadata = new ResourceMetadata('subDummy', 'dummy subresource', '#dummy', ['get' => ['method' => 'GET']], [], [], ['parents_dummies_get_subresource' => ['method' => 'GET', 'filters' => ['dummyFilter', 'dummyBadFilter']]]);
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata);

$queryBuilder = $queryBuilderProphecy->reveal();

$ormFilterProphecy = $this->prophesize(FilterInterface::class);
$ormFilterProphecy->apply($queryBuilder, new QueryNameGenerator(), Dummy::class, 'parents_dummies_get_subresource', ['filters' => [], 'operation_type' => OperationType::SUBRESOURCE])->shouldBeCalled();

$ordinaryFilterProphecy = $this->prophesize(ApiFilterInterface::class);

$filterLocatorProphecy = $this->prophesize(ContainerInterface::class);
$filterLocatorProphecy->has('dummyFilter')->willReturn(true)->shouldBeCalled();
$filterLocatorProphecy->has('dummyBadFilter')->willReturn(true)->shouldBeCalled();
$filterLocatorProphecy->get('dummyFilter')->willReturn($ormFilterProphecy->reveal())->shouldBeCalled();
$filterLocatorProphecy->get('dummyBadFilter')->willReturn($ordinaryFilterProphecy->reveal())->shouldBeCalled();

$orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $filterLocatorProphecy->reveal());

$orderExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, 'parents_dummies_get_subresource', ['operation_type' => OperationType::SUBRESOURCE]);
}

public function testApplyToSubresourceWithoutFilters()
{
$dummyMetadata = new ResourceMetadata('subDummy', 'dummy subresource', '#dummy', ['get' => ['method' => 'GET']], [], [], ['parents_dummies_get_subresource' => ['method' => 'GET']]);

$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata);

$orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal());
$orderExtensionTest->applyToCollection($this->prophesize(QueryBuilder::class)->reveal(), new QueryNameGenerator(), Dummy::class, 'parents_dummies_get_subresource');
}
}
41 changes: 40 additions & 1 deletion tests/OpenApi/Factory/OpenApiFactoryTest.php
Expand Up @@ -696,7 +696,7 @@ public function testSubresourceDocumentation()
[],
['get' => ['method' => 'GET'] + self::OPERATION_FORMATS],
[],
['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]]
['get' => ['method' => 'GET', 'filters' => ['subf1', 'subf2', 'subf3', 'subf4', 'subf5'], 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]]
);
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$resourceMetadataFactoryProphecy->create(Question::class)->shouldBeCalled()->willReturn($questionMetadata);
Expand Down Expand Up @@ -734,7 +734,46 @@ public function testSubresourceDocumentation()
$typeFactory = new TypeFactory();
$schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$typeFactory->setSchemaFactory($schemaFactory);

$filterLocatorProphecy = $this->prophesize(ContainerInterface::class);
$filters = [
'subf1' => new DummyFilter(['name' => [
'property' => 'name',
'type' => 'string',
'required' => true,
'strategy' => 'exact',
'openapi' => ['example' => 'bar', 'deprecated' => true, 'allowEmptyValue' => true, 'allowReserved' => true, 'explode' => true],
]]),
'subf2' => new DummyFilter(['ha' => [
'property' => 'foo',
'type' => 'int',
'required' => false,
'strategy' => 'partial',
]]),
'subf3' => new DummyFilter(['toto' => [
'property' => 'name',
'type' => 'array',
'is_collection' => true,
'required' => true,
'strategy' => 'exact',
]]),
'subf4' => new DummyFilter(['order[name]' => [
'property' => 'name',
'type' => 'string',
'required' => false,
'schema' => [
'type' => 'string',
'enum' => ['asc', 'desc'],
],
]]),
];

foreach ($filters as $filterId => $filter) {
$filterLocatorProphecy->has($filterId)->willReturn(true)->shouldBeCalled();
$filterLocatorProphecy->get($filterId)->willReturn($filter)->shouldBeCalled();
}

$filterLocatorProphecy->has('subf5')->willReturn(false)->shouldBeCalled();

$factory = new OpenApiFactory(
$resourceNameCollectionFactoryProphecy->reveal(),
Expand Down

0 comments on commit 85a9395

Please sign in to comment.