From 205497b0eae2292b6c4f750cbaf0e5dbdbdf75c5 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Sat, 6 Apr 2019 20:05:47 +0200 Subject: [PATCH] [FrameworkBundle][Routing] Add a new tag to be able to use a private service as a service route loader --- UPGRADE-4.3.md | 1 + UPGRADE-5.0.md | 1 + .../Compiler/UnusedTagsPass.php | 1 + .../FrameworkExtension.php | 4 ++ .../Kernel/MicroKernelTrait.php | 13 +++- .../Resources/config/routing.xml | 7 +- .../Tests/Kernel/MicroKernelTraitTest.php | 20 ++++++ src/Symfony/Component/Routing/CHANGELOG.md | 2 +- .../ServiceRouterLoaderContainer.php | 53 +++++++++++++++ .../ServiceRouterLoaderInterface.php | 19 ++++++ .../ServiceRouterLoaderContainerTest.php | 66 +++++++++++++++++++ 11 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php create mode 100644 src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php create mode 100644 src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md index 3f5f22164dfa..60640d5b2168 100644 --- a/UPGRADE-4.3.md +++ b/UPGRADE-4.3.md @@ -123,6 +123,7 @@ Routing options have been deprecated. * Implementing `Serializable` for `Route` and `CompiledRoute` is deprecated; if you serialize them, please ensure your unserialization logic can recover from a failure related to an updated serialization format + * Not tagging the router loader services with `routing.router_loader` has been deprecated. Security -------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index f0ba1c429bdc..adcb91389fc5 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -284,6 +284,7 @@ Routing options have been removed. * `Route` and `CompiledRoute` don't implement `Serializable` anymore; if you serialize them, please ensure your unserialization logic can recover from a failure related to an updated serialization format + * The router loader services must be tagged with `routing.router_loader`. Security -------- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index efeafad5f06e..c90b5215eda3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -49,6 +49,7 @@ class UnusedTagsPass implements CompilerPassInterface 'proxy', 'routing.expression_language_provider', 'routing.loader', + 'routing.router_loader', 'security.expression_language_provider', 'security.remember_me_aware', 'security.voter', diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3413eb2b1331..c81f3465653b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -92,6 +92,7 @@ use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; use Symfony\Component\Routing\Loader\AnnotationFileLoader; +use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderInterface; use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Security\Core\Security; @@ -428,6 +429,9 @@ public function load(array $configs, ContainerBuilder $container) if (!$config['disallow_search_engine_index'] ?? false) { $container->removeDefinition('disallow_search_engine_index_response_listener'); } + + $container->registerForAutoconfiguration(ServiceRouterLoaderInterface::class) + ->addTag('routing.router_loader'); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php index 3919737e44da..5af6053966d4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php @@ -69,14 +69,23 @@ public function registerContainerConfiguration(LoaderInterface $loader) ], ]); - if ($this instanceof EventSubscriberInterface) { + if (!$container->hasDefinition('kernel')) { $container->register('kernel', static::class) ->setSynthetic(true) ->setPublic(true) - ->addTag('kernel.event_subscriber') ; } + $kernelDefinition = $container->getDefinition('kernel'); + + $kernelDefinition->addTag('routing.router_loader', [ + 'service_id' => 'kernel', + ]); + + if ($this instanceof EventSubscriberInterface) { + $kernelDefinition->addTag('kernel.event_subscriber'); + } + $this->configureContainer($container, $loader); $container->addObjectResource($this); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 8c293ebefc39..38af911cdf42 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -40,9 +40,14 @@ + + + + + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php index 539306fcea2b..201316b37256 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php @@ -12,6 +12,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\HttpFoundation\Request; class MicroKernelTraitTest extends TestCase @@ -39,4 +42,21 @@ public function testAsEventSubscriber() $this->assertSame('It\'s dangerous to go alone. Take this ⚔', $response->getContent()); } + + public function testRoutingRouteLoaderTagIsAdded() + { + $frameworkExtension = $this->createMock(ExtensionInterface::class); + $frameworkExtension + ->expects($this->atLeastOnce()) + ->method('getAlias') + ->willReturn('framework'); + + $container = new ContainerBuilder(); + $container->registerExtension($frameworkExtension); + + $kernel = new ConcreteMicroKernel('test', false); + $kernel->registerContainerConfiguration(new ClosureLoader($container)); + + $this->assertTrue($container->getDefinition('kernel')->hasTag('routing.router_loader')); + } } diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index f7439903e04a..fd39033788d5 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -11,7 +11,7 @@ CHANGELOG * deprecated implementing `Serializable` for `Route` and `CompiledRoute`; if you serialize them, please ensure your unserialization logic can recover from a failure related to an updated serialization format * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators - * added support for invokable route loader services + * added support for invokable router loader services 4.2.0 ----- diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php new file mode 100644 index 000000000000..c6ec0eace047 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\DependencyInjection; + +use Psr\Container\ContainerInterface; + +/** + * @internal + * + * @deprecated since Symfony 4.3, to be removed in 5.0 + */ +class ServiceRouterLoaderContainer implements ContainerInterface +{ + private $container; + private $serviceLocator; + + public function __construct(ContainerInterface $container, ContainerInterface $serviceLocator) + { + $this->container = $container; + $this->serviceLocator = $serviceLocator; + } + + /** + * {@inheritdoc} + */ + public function get($id) + { + if ($this->serviceLocator->has($id)) { + return $this->serviceLocator->get($id); + } + + @trigger_error(sprintf('Registering the routing loader "%s" without tagging it with the "routing.router_loader" tag is deprecated since Symfony 4.3 and will be required in Symfony 5.0.', $id), E_USER_DEPRECATED); + + return $this->container->get($id); + } + + /** + * {@inheritdoc} + */ + public function has($id) + { + return $this->serviceLocator->has($id) || $this->container->has($id); + } +} diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php new file mode 100644 index 000000000000..e77d691b6f78 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\DependencyInjection; + +/** + * Marker interface for router loader services. + */ +interface ServiceRouterLoaderInterface +{ +} diff --git a/src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php b/src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php new file mode 100644 index 000000000000..1e97555161ef --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderContainer; + +class ServiceRouterLoaderContainerTest extends TestCase +{ + /** + * @var ContainerInterface + */ + private $container; + + /** + * @var ContainerInterface + */ + private $serviceLocator; + + /** + * @var ServiceRouterLoaderContainer + */ + private $serviceRouterLoaderContainer; + + /** + * {@inheritdoc} + */ + protected function setUp() + { + $this->container = new Container(); + $this->container->set('foo', new \stdClass()); + + $this->serviceLocator = new Container(); + $this->serviceLocator->set('bar', new \stdClass()); + + $this->serviceRouterLoaderContainer = new ServiceRouterLoaderContainer($this->container, $this->serviceLocator); + } + + /** + * @group legacy + * @expectedDeprecation Registering the routing loader "foo" without tagging it with the "routing.router_loader" tag is deprecated since Symfony 4.3 and will be required in Symfony 5.0. + */ + public function testGet() + { + $this->assertSame($this->container->get('foo'), $this->serviceRouterLoaderContainer->get('foo')); + $this->assertSame($this->serviceLocator->get('bar'), $this->serviceRouterLoaderContainer->get('bar')); + } + + public function testHas() + { + $this->assertTrue($this->serviceRouterLoaderContainer->has('foo')); + $this->assertTrue($this->serviceRouterLoaderContainer->has('bar')); + $this->assertFalse($this->serviceRouterLoaderContainer->has('ccc')); + } +}