Skip to content

Commit bf1bed1

Browse files
authored
Merge pull request #3166 from LouisPinsard/allow-api-filter-without-construct
Fix support for custom filters without constructor in ApiFilter annotation
2 parents 7776e9f + 724ac49 commit bf1bed1

File tree

6 files changed

+261
-141
lines changed

6 files changed

+261
-141
lines changed

src/Api/FilterInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface FilterInterface
2727
* - property: the property where the filter is applied
2828
* - type: the type of the filter
2929
* - required: if this filter is required
30-
* - strategy: the used strategy
30+
* - strategy (optional): the used strategy
3131
* - is_collection (optional): is this filter is collection
3232
* - swagger (optional): additional parameters for the path operation,
3333
* e.g. 'swagger' => [

src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler;
1515

16+
use ApiPlatform\Core\Annotation\ApiFilter;
1617
use ApiPlatform\Core\Util\AnnotationFilterExtractorTrait;
1718
use ApiPlatform\Core\Util\ReflectionClassRecursiveIterator;
1819
use Doctrine\Common\Annotations\Reader;
@@ -23,7 +24,7 @@
2324
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
2425

2526
/**
26-
* Injects filters.
27+
* Registers filter services from {@see ApiFilter} annotations.
2728
*
2829
* @internal
2930
*
@@ -43,7 +44,7 @@ final class AnnotationFilterPass implements CompilerPassInterface
4344
/**
4445
* {@inheritdoc}
4546
*/
46-
public function process(ContainerBuilder $container)
47+
public function process(ContainerBuilder $container): void
4748
{
4849
$resourceClassDirectories = $container->getParameter('api_platform.resource_class_directories');
4950

@@ -55,28 +56,41 @@ public function process(ContainerBuilder $container)
5556
/**
5657
* @throws InvalidArgumentException
5758
*/
58-
private function createFilterDefinitions(\ReflectionClass $reflectionClass, ContainerBuilder $container): void
59+
private function createFilterDefinitions(\ReflectionClass $resourceReflectionClass, ContainerBuilder $container): void
5960
{
60-
$reader = $this->reader ?? $this->reader = $container->get('annotation_reader');
61+
$this->reader ?? $this->reader = $container->get('annotation_reader');
6162

62-
foreach ($this->readFilterAnnotations($reflectionClass, $reader) as $id => [$arguments, $filterClass]) {
63+
foreach ($this->readFilterAnnotations($resourceReflectionClass, $this->reader) as $id => [$arguments, $filterClass]) {
6364
if ($container->has($id)) {
6465
continue;
6566
}
6667

67-
if ($container->has($filterClass) && ($definition = $container->findDefinition($filterClass))->isAbstract()) {
68-
$definition = new ChildDefinition($definition->getClass());
69-
} elseif ($reflectionClass = $container->getReflectionClass($filterClass, false)) {
70-
$definition = new Definition($reflectionClass->getName());
71-
$definition->setAutoconfigured(true);
72-
} else {
68+
if (null === $filterReflectionClass = $container->getReflectionClass($filterClass, false)) {
7369
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $filterClass, $id));
7470
}
7571

72+
if ($container->has($filterClass) && ($parentDefinition = $container->findDefinition($filterClass))->isAbstract()) {
73+
$definition = new ChildDefinition($parentDefinition->getClass());
74+
} else {
75+
$definition = new Definition($filterReflectionClass->getName());
76+
$definition->setAutoconfigured(true);
77+
}
78+
7679
$definition->addTag(self::TAG_FILTER_NAME);
7780
$definition->setAutowired(true);
7881

82+
$parameterNames = [];
83+
if (null !== $constructorReflectionMethod = $filterReflectionClass->getConstructor()) {
84+
foreach ($constructorReflectionMethod->getParameters() as $reflectionParameter) {
85+
$parameterNames[$reflectionParameter->name] = true;
86+
}
87+
}
88+
7989
foreach ($arguments as $key => $value) {
90+
if (!isset($parameterNames[$key])) {
91+
throw new InvalidArgumentException(sprintf('Class "%s" does not have argument "$%s".', $filterClass, $key));
92+
}
93+
8094
$definition->setArgument("$$key", $value);
8195
}
8296

0 commit comments

Comments
 (0)