Skip to content

Commit 24c6b04

Browse files
committedFeb 5, 2025
Autoconfigure resource dirs using ApiResource attribute
1 parent 562ddd3 commit 24c6b04

File tree

4 files changed

+57
-0
lines changed

4 files changed

+57
-0
lines changed
 

‎src/Symfony/Bundle/ApiPlatformBundle.php

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace ApiPlatform\Symfony\Bundle;
1515

1616
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AttributeFilterPass;
17+
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AttributeResourcePass;
1718
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass;
1819
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass;
1920
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass;
@@ -47,6 +48,7 @@ public function build(ContainerBuilder $container): void
4748
$container->addCompilerPass(new DataProviderPass());
4849
// Run the compiler pass before the {@see ResolveInstanceofConditionalsPass} to allow autoconfiguration of generated filter definitions.
4950
$container->addCompilerPass(new AttributeFilterPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 101);
51+
$container->addCompilerPass(new AttributeResourcePass());
5052
$container->addCompilerPass(new FilterPass());
5153
$container->addCompilerPass(new ElasticsearchClientPass());
5254
$container->addCompilerPass(new GraphQlTypePass());

‎src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php

+5
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
use Ramsey\Uuid\Uuid;
4949
use Symfony\Component\Config\FileLocator;
5050
use Symfony\Component\Config\Resource\DirectoryResource;
51+
use Symfony\Component\DependencyInjection\ChildDefinition;
5152
use Symfony\Component\DependencyInjection\ContainerBuilder;
5253
use Symfony\Component\DependencyInjection\Definition;
5354
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -168,6 +169,10 @@ public function load(array $configs, ContainerBuilder $container): void
168169
->addTag('api_platform.uri_variables.transformer');
169170
$container->registerForAutoconfiguration(ParameterProviderInterface::class)
170171
->addTag('api_platform.parameter_provider');
172+
$container->registerAttributeForAutoconfiguration(ApiResource::class, static function(ChildDefinition $definition): void {
173+
$definition->addTag('api_platform.resource');
174+
$definition->addTag('container.excluded', ['source' => __FILE__]);
175+
});
171176

172177
if (!$container->has('api_platform.state.item_provider')) {
173178
$container->setAlias('api_platform.state.item_provider', 'api_platform.state_provider.object');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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\Symfony\Bundle\DependencyInjection\Compiler;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
18+
use Symfony\Component\DependencyInjection\ContainerBuilder;
19+
20+
/**
21+
* Registers resource classes from {@see ApiResource} attribute.
22+
*
23+
* @internal
24+
*
25+
* @author Jérôme Tamarelle <jerome@tamarelle.net>
26+
*/
27+
final class AttributeResourcePass implements CompilerPassInterface
28+
{
29+
/**
30+
* {@inheritdoc}
31+
*/
32+
public function process(ContainerBuilder $container): void
33+
{
34+
$resourceClassDirectories = $container->getParameter('api_platform.resource_class_directories');
35+
36+
// findTaggedServiceIds cannot be used, as the services are excluded
37+
foreach ($container->getDefinitions() as $id => $definition) {
38+
if ($definition->hasTag('api_platform.resource')) {
39+
$r = new \ReflectionClass($definition->getClass());
40+
if ($r->getFileName()) {
41+
$resourceClassDirectories[] = dirname($r->getFileName());
42+
}
43+
}
44+
}
45+
$resourceClassDirectories = array_unique($resourceClassDirectories);
46+
$container->setParameter('api_platform.resource_class_directories', $resourceClassDirectories);
47+
}
48+
}

‎tests/Symfony/Bundle/ApiPlatformBundleTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use ApiPlatform\Symfony\Bundle\ApiPlatformBundle;
1717
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AttributeFilterPass;
18+
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AttributeResourcePass;
1819
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass;
1920
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass;
2021
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass;
@@ -45,6 +46,7 @@ public function testBuild(): void
4546
$containerProphecy = $this->prophesize(ContainerBuilder::class);
4647
$containerProphecy->addCompilerPass(Argument::type(DataProviderPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled();
4748
$containerProphecy->addCompilerPass(Argument::type(AttributeFilterPass::class), PassConfig::TYPE_BEFORE_OPTIMIZATION, 101)->willReturn($containerProphecy->reveal())->shouldBeCalled();
49+
$containerProphecy->addCompilerPass(Argument::type(AttributeResourcePass::class))->shouldBeCalled()->willReturn($containerProphecy->reveal())->shouldBeCalled();
4850
$containerProphecy->addCompilerPass(Argument::type(FilterPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled();
4951
$containerProphecy->addCompilerPass(Argument::type(ElasticsearchClientPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled();
5052
$containerProphecy->addCompilerPass(Argument::type(GraphQlTypePass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled();

0 commit comments

Comments
 (0)
Failed to load comments.