Skip to content

Commit e05abac

Browse files
committed
[FrameworkBundle][Routing] Add a new tag to be able to use a private service as a service route loader
1 parent f551f2d commit e05abac

File tree

9 files changed

+270
-0
lines changed

9 files changed

+270
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
use Symfony\Component\Routing\Generator\UrlGenerator;
9393
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
9494
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
95+
use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderInterface;
9596
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
9697
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
9798
use Symfony\Component\Security\Core\Security;
@@ -421,6 +422,9 @@ public function load(array $configs, ContainerBuilder $container)
421422
if (!$config['disallow_search_engine_index'] ?? false) {
422423
$container->removeDefinition('disallow_search_engine_index_response_listener');
423424
}
425+
426+
$container->registerForAutoconfiguration(ServiceRouterLoaderInterface::class)
427+
->addTag('routing.route_loader');
424428
}
425429

426430
/**

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass;
5050
use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass;
5151
use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass;
52+
use Symfony\Component\Routing\DependencyInjection\ServiceRouterLoaderPass;
5253
use Symfony\Component\Serializer\DependencyInjection\SerializerPass;
5354
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
5455
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
@@ -130,6 +131,7 @@ public function build(ContainerBuilder $container)
130131
$this->addCompilerPassIfExists($container, AddAutoMappingConfigurationPass::class);
131132
$container->addCompilerPass(new RegisterReverseContainerPass(true));
132133
$container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING);
134+
$container->addCompilerPass(new ServiceRouterLoaderPass());
133135

134136
if ($container->getParameter('kernel.debug')) {
135137
$container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);

src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ abstract protected function configureContainer(ContainerBuilder $c, LoaderInterf
6161
*/
6262
public function registerContainerConfiguration(LoaderInterface $loader)
6363
{
64+
6465
$loader->load(function (ContainerBuilder $container) use ($loader) {
6566
$container->loadFromExtension('framework', [
6667
'router' => [
@@ -77,6 +78,11 @@ public function registerContainerConfiguration(LoaderInterface $loader)
7778
;
7879
}
7980

81+
$container
82+
->getDefinition('kernel')
83+
->addTag('routing.route_loader')
84+
;
85+
8086
$this->configureContainer($container, $loader);
8187

8288
$container->addObjectResource($this);

src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
17+
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
1518
use Symfony\Component\HttpFoundation\Request;
1619

1720
class MicroKernelTraitTest extends TestCase
@@ -39,4 +42,21 @@ public function testAsEventSubscriber()
3942

4043
$this->assertSame('It\'s dangerous to go alone. Take this ⚔', $response->getContent());
4144
}
45+
46+
public function testRoutingRouteLoaderTagIsAdded(): void
47+
{
48+
$frameworkExtension = $this->createMock(ExtensionInterface::class);
49+
$frameworkExtension
50+
->expects($this->atLeastOnce())
51+
->method('getAlias')
52+
->willReturn('framework');
53+
54+
$container = new ContainerBuilder();
55+
$container->registerExtension($frameworkExtension);
56+
57+
$kernel = new ConcreteMicroKernel('test', false);
58+
$kernel->registerContainerConfiguration(new ClosureLoader($container));
59+
60+
$this->assertTrue($container->getDefinition('kernel')->hasTag('routing.route_loader'));
61+
}
4262
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
namespace Symfony\Component\Routing\DependencyInjection;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Definition;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderContainer;
20+
21+
class ServiceRouterLoaderPass implements CompilerPassInterface
22+
{
23+
private $loaderServiceServiceId;
24+
private $serviceRouterLoaderTag;
25+
26+
public function __construct(string $loaderServiceServiceId = 'routing.loader.service', string $serviceRouterLoaderTag = 'routing.route_loader')
27+
{
28+
$this->loaderServiceServiceId = $loaderServiceServiceId;
29+
$this->serviceRouterLoaderTag = $serviceRouterLoaderTag;
30+
}
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function process(ContainerBuilder $container): void
36+
{
37+
if (!$container->hasDefinition($this->loaderServiceServiceId)) {
38+
return;
39+
}
40+
41+
$servicesRouterLoaders = [];
42+
foreach ($container->findTaggedServiceIds($this->serviceRouterLoaderTag, true) as $id => $attributes) {
43+
$servicesRouterLoaders[$id] = new Reference($id);
44+
}
45+
46+
$container
47+
->getDefinition($this->loaderServiceServiceId)
48+
->replaceArgument(0, new Definition(ServiceRouterLoaderContainer::class, [
49+
new Reference('service_container'),
50+
ServiceLocatorTagPass::register($container, $servicesRouterLoaders),
51+
$this->serviceRouterLoaderTag,
52+
]));
53+
}
54+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
namespace Symfony\Component\Routing\Loader\DependencyInjection;
13+
14+
use Psr\Container\ContainerInterface;
15+
16+
/**
17+
* @internal
18+
*/
19+
class ServiceRouterLoaderContainer implements ContainerInterface
20+
{
21+
private $container;
22+
private $serviceLocator;
23+
private $serviceRouterLoaderTag;
24+
25+
public function __construct(ContainerInterface $container, ContainerInterface $serviceLocator, string $serviceRouterLoaderTag)
26+
{
27+
$this->container = $container;
28+
$this->serviceLocator = $serviceLocator;
29+
$this->serviceRouterLoaderTag = $serviceRouterLoaderTag;
30+
}
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function get($id)
36+
{
37+
if ($this->serviceLocator->has($id)) {
38+
return $this->serviceLocator->get($id);
39+
}
40+
41+
@trigger_error(sprintf('Not tagging the "%s" service with the "%s" tag is deprecated since Symfony 4.3.', $id, $this->serviceRouterLoaderTag), E_USER_DEPRECATED);
42+
43+
return $this->container->get($id);
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function has($id)
50+
{
51+
return $this->serviceLocator->has($id) || $this->container->has($id);
52+
}
53+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
namespace Symfony\Component\Routing\Loader\DependencyInjection;
13+
14+
interface ServiceRouterLoaderInterface
15+
{
16+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
namespace Symfony\Component\Routing\Tests\DependencyInjection;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Container;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Definition;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
use Symfony\Component\DependencyInjection\ServiceLocator;
20+
use Symfony\Component\Routing\DependencyInjection\ServiceRouterLoaderPass;
21+
use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoader;
22+
use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderContainer;
23+
24+
class ServiceRouterLoaderPassTest extends TestCase
25+
{
26+
public function testProcess(): void
27+
{
28+
$loaderServiceServiceId = 'foo';
29+
$serviceRouterLoaderTag = 'bar';
30+
31+
$container = new ContainerBuilder();
32+
$serviceRouterLoaderDefinition = $container->setDefinition($loaderServiceServiceId, new Definition(ServiceRouterLoader::class, [
33+
new Definition(Container::class),
34+
]));
35+
$container->register('route_service_loader_1')->addTag($serviceRouterLoaderTag);
36+
$container->register('route_service_loader_2')->addTag($serviceRouterLoaderTag);
37+
38+
(new ServiceRouterLoaderPass($loaderServiceServiceId, $serviceRouterLoaderTag))->process($container);
39+
40+
/** @var Definition $serviceRouterLoaderArgument */
41+
$serviceRouterLoaderArgument = $serviceRouterLoaderDefinition->getArgument(0);
42+
$this->assertSame(ServiceRouterLoaderContainer::class, $serviceRouterLoaderArgument->getClass());
43+
$this->assertEquals(new Reference('service_container'), $serviceRouterLoaderArgument->getArgument(0));
44+
/** @var ServiceLocator $serviceLocator */
45+
$serviceLocator = $container->get((string) $serviceRouterLoaderArgument->getArgument(1));
46+
$this->assertTrue($serviceLocator->has('route_service_loader_1'));
47+
$this->assertTrue($serviceLocator->has('route_service_loader_2'));
48+
}
49+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
namespace Symfony\Component\Routing\Tests\Loader;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Psr\Container\ContainerInterface;
16+
use Symfony\Component\DependencyInjection\Container;
17+
use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderContainer;
18+
19+
class ServiceRouterLoaderContainerTest extends TestCase
20+
{
21+
/**
22+
* @var ContainerInterface
23+
*/
24+
private $container;
25+
26+
/**
27+
* @var ContainerInterface
28+
*/
29+
private $serviceLocator;
30+
31+
/**
32+
* @var ServiceRouterLoaderContainer
33+
*/
34+
private $serviceRouterLoaderContainer;
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
protected function setUp(): void
40+
{
41+
$this->container = new Container();
42+
$this->container->set('foo', new \stdClass());
43+
44+
$this->serviceLocator = new Container();
45+
$this->serviceLocator->set('bar', new \stdClass());
46+
47+
$this->serviceRouterLoaderContainer = new ServiceRouterLoaderContainer($this->container, $this->serviceLocator, 'ccc');
48+
}
49+
50+
/**
51+
* @group legacy
52+
* @expectedDeprecation Not tagging the "foo" service with the "ccc" tag is deprecated since Symfony 4.3.
53+
*/
54+
public function testGet(): void
55+
{
56+
$this->assertSame($this->container->get('foo'), $this->serviceRouterLoaderContainer->get('foo'));
57+
$this->assertSame($this->serviceLocator->get('bar'), $this->serviceRouterLoaderContainer->get('bar'));
58+
}
59+
60+
public function testHas(): void
61+
{
62+
$this->assertTrue($this->serviceRouterLoaderContainer->has('foo'));
63+
$this->assertTrue($this->serviceRouterLoaderContainer->has('bar'));
64+
$this->assertFalse($this->serviceRouterLoaderContainer->has('ccc'));
65+
}
66+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy