Skip to content

Commit

Permalink
[FrameworkBundle][Routing] Add a new tag to be able to use a private …
Browse files Browse the repository at this point in the history
…service as a service route loader
  • Loading branch information
fancyweb committed Apr 29, 2019
1 parent b817c6e commit 3a30564
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 3 deletions.
1 change: 1 addition & 0 deletions UPGRADE-4.3.md
Expand Up @@ -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 route loader services with `routing.route_loader` has been deprecated.

Security
--------
Expand Down
1 change: 1 addition & 0 deletions UPGRADE-5.0.md
Expand Up @@ -288,6 +288,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 route loader services must be tagged with `routing.route_loader`.

Security
--------
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -423,6 +424,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.route_loader');
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Expand Up @@ -49,6 +49,7 @@
use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass;
use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass;
use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass;
use Symfony\Component\Routing\DependencyInjection\ServiceRouterLoaderPass;
use Symfony\Component\Serializer\DependencyInjection\SerializerPass;
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
Expand Down
13 changes: 11 additions & 2 deletions src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
Expand Up @@ -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.route_loader', [
'service_id' => 'kernel',
]);

if ($this instanceof EventSubscriberInterface) {
$kernelDefinition->addTag('kernel.event_subscriber');
}

$this->configureContainer($container, $loader);

$container->addObjectResource($this);
Expand Down
Expand Up @@ -40,9 +40,14 @@
<argument type="service" id="file_locator" />
</service>

<service id="routing.loader.service.container" class="Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderContainer">
<argument type="service" id="service_container" />
<argument type="tagged_locator" tag="routing.route_loader" index-by="service_id" />
</service>

<service id="routing.loader.service" class="Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoader">
<tag name="routing.loader" />
<argument type="service" id="service_container" />
<argument type="service" id="routing.loader.service.container" />
</service>

<service id="routing.loader" class="Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader" public="true">
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -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.route_loader'));
}
}
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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.route_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);
}
}
@@ -0,0 +1,19 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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 route loader services.
*/
interface ServiceRouterLoaderInterface
{
}
@@ -0,0 +1,66 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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.route_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'));
}
}

0 comments on commit 3a30564

Please sign in to comment.