Skip to content

Commit a910f1b

Browse files
author
Louis Pinsard
committed
Add possibility to create filter without constructor
1 parent 4d0b777 commit a910f1b

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ private function createFilterDefinitions(\ReflectionClass $reflectionClass, Cont
6464
continue;
6565
}
6666

67+
$reflectionClass = $container->getReflectionClass($filterClass, false);
6768
if ($container->has($filterClass) && ($definition = $container->findDefinition($filterClass))->isAbstract()) {
6869
$definition = new ChildDefinition($definition->getClass());
69-
} elseif ($reflectionClass = $container->getReflectionClass($filterClass, false)) {
70+
} elseif ($reflectionClass) {
7071
$definition = new Definition($reflectionClass->getName());
7172
$definition->setAutoconfigured(true);
7273
} else {
@@ -76,8 +77,10 @@ private function createFilterDefinitions(\ReflectionClass $reflectionClass, Cont
7677
$definition->addTag(self::TAG_FILTER_NAME);
7778
$definition->setAutowired(true);
7879

79-
foreach ($arguments as $key => $value) {
80-
$definition->setArgument("$$key", $value);
80+
if (null !== $reflectionClass && null !== $reflectionConstructor = $reflectionClass->getConstructor()) {
81+
foreach ($arguments as $key => $value) {
82+
$definition->setArgument("$$key", $value);
83+
}
8184
}
8285

8386
$container->setDefinition($id, $definition);

tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass;
2222
use ApiPlatform\Core\Exception\InvalidArgumentException;
2323
use ApiPlatform\Core\Serializer\Filter\GroupFilter;
24+
use ApiPlatform\Core\Tests\Fixtures\DummyFilterWithoutConstructor;
2425
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\AnotherDummyFilter;
2526
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
2627
use Doctrine\Common\Annotations\Reader;
@@ -53,15 +54,20 @@ public function testProcess()
5354

5455
$reader->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->will(function ($args) {
5556
if (Dummy::class === $args[0]->class && 'dummyDate' === $args[0]->name) {
56-
return [new ApiFilter(['value' => DateFilter::class]), new ApiProperty()];
57+
return [
58+
new ApiFilter(['value' => DateFilter::class]),
59+
new ApiProperty(),
60+
];
5761
}
5862

5963
return [];
6064
});
6165

6266
$reader->getClassAnnotations(Argument::type(\ReflectionClass::class))->will(function ($args) {
6367
if (Dummy::class === $args[0]->name) {
64-
return [new ApiFilter(['value' => SearchFilter::class, 'strategy' => 'exact', 'properties' => ['description', 'relatedDummy.name', 'name']]), new ApiResource([]), new ApiFilter(['value' => GroupFilter::class, 'arguments' => ['parameterName' => 'foobar']])];
68+
return [new ApiFilter(['value' => SearchFilter::class, 'strategy' => 'exact', 'properties' => ['description', 'relatedDummy.name', 'name']]), new ApiResource([]),
69+
new ApiFilter(['value' => GroupFilter::class, 'arguments' => ['parameterName' => 'foobar']]),
70+
];
6571
}
6672

6773
return [];
@@ -81,6 +87,7 @@ public function testProcess()
8187

8288
$containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class))->shouldBeCalled();
8389
$containerBuilderProphecy->getReflectionClass(GroupFilter::class, false)->willReturn(new \ReflectionClass(GroupFilter::class))->shouldBeCalled();
90+
$containerBuilderProphecy->getReflectionClass(DateFilter::class, false)->willReturn(new \ReflectionClass(GroupFilter::class))->shouldBeCalled();
8491

8592
$containerBuilderProphecy->setDefinition('annotated_api_platform_core_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter', Argument::that(function ($def) {
8693
$this->assertInstanceOf(Definition::class, $def);
@@ -207,4 +214,54 @@ public function testProcessInvalidFilterClass()
207214

208215
$annotationFilterPass->process($containerBuilderProphecy->reveal());
209216
}
217+
218+
public function testProcessFilterWithoutConstructor()
219+
{
220+
$annotationFilterPass = new AnnotationFilterPass();
221+
222+
$this->assertInstanceOf(CompilerPassInterface::class, $annotationFilterPass);
223+
224+
$containerBuilderProphecy = $this->prophesize(ContainerBuilder::class);
225+
226+
$containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->shouldBeCalled()->willReturn([
227+
__DIR__.'/../../../../../Fixtures/TestBundle/Entity/',
228+
]);
229+
230+
$reader = $this->prophesize(Reader::class);
231+
232+
$reader->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->will(function ($args) {
233+
if (Dummy::class === $args[0]->class && 'dummyDate' === $args[0]->name) {
234+
return [new ApiProperty(), new ApiFilter(['value' => DummyFilterWithoutConstructor::class])];
235+
}
236+
237+
return [];
238+
});
239+
240+
$reader->getClassAnnotations(Argument::type(\ReflectionClass::class))->will(function ($args) {
241+
if (Dummy::class === $args[0]->name) {
242+
return [new ApiResource([])];
243+
}
244+
245+
return [];
246+
});
247+
248+
$containerBuilderProphecy->get('annotation_reader')->shouldBeCalled()->willReturn($reader->reveal());
249+
250+
$containerBuilderProphecy->has('annotated_api_platform_core_tests_fixtures_test_bundle_entity_dummy_api_platform_core_tests_fixtures_dummy_filter_without_constructor')->shouldBeCalled()->willReturn(false);
251+
252+
$containerBuilderProphecy->has(DummyFilterWithoutConstructor::class)->willReturn(true)->shouldBeCalled();
253+
254+
$containerBuilderProphecy->getReflectionClass(DummyFilterWithoutConstructor::class, false)->willReturn(new \ReflectionClass(DummyFilterWithoutConstructor::class))->shouldBeCalled();
255+
$containerBuilderProphecy->findDefinition(DummyFilterWithoutConstructor::class)->willReturn((new Definition(DummyFilterWithoutConstructor::class))->setAbstract(false))->shouldBeCalled();
256+
257+
$containerBuilderProphecy->setDefinition('annotated_api_platform_core_tests_fixtures_test_bundle_entity_dummy_api_platform_core_tests_fixtures_dummy_filter_without_constructor', Argument::that(function ($def) {
258+
$this->assertInstanceOf(Definition::class, $def);
259+
$this->assertEquals(DummyFilterWithoutConstructor::class, $def->getClass());
260+
$this->assertEquals([], $def->getArguments());
261+
262+
return true;
263+
}))->shouldBeCalled();
264+
265+
$annotationFilterPass->process($containerBuilderProphecy->reveal());
266+
}
210267
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Tests\Fixtures;
15+
16+
use ApiPlatform\Core\Api\FilterInterface;
17+
18+
/**
19+
* @author Kévin Dunglas <dunglas@gmail.com>
20+
*/
21+
class DummyFilterWithoutConstructor implements FilterInterface
22+
{
23+
/**
24+
* @inheritdoc
25+
*/
26+
public function getDescription(string $resourceClass): array
27+
{
28+
return [
29+
'property' => 'foo',
30+
'type' => '',
31+
'required' => false,
32+
'strategy' => '',
33+
];
34+
}
35+
}

0 commit comments

Comments
 (0)