Skip to content

[3.4] Deprecations regarding use of service locators/getter injection #21710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions UPGRADE-3.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,21 @@ FrameworkBundle
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass` class has been
deprecated and will be removed in 4.0. Use the `Symfony\Component\Form\DependencyInjection\FormPass`
class instead.

* The `Symfony\Bundle\FrameworkBundle\EventListener\SessionListener` class has been deprecated
and will be removed in 4.0. Use the `Symfony\Component\HttpKernel\EventListener\SessionListener` instead.

* The `Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener` class has been deprecated
and will be removed in 4.0. Use the `Symfony\Component\HttpKernel\EventListener\TestSessionListener` instead.

HttpKernel
-----------

* The `Psr6CacheClearer::addPool()` method has been deprecated. Pass an array of pools indexed
by name to the constructor instead.

* The `LazyLoadingFragmentHandler::addRendererService()` method has been deprecated and
will be removed in 4.0.

Process
-------
Expand Down Expand Up @@ -125,6 +134,12 @@ TwigBridge
* The `TwigRendererEngine::setEnvironment()` method has been deprecated and will be removed
in 4.0. Pass the Twig Environment as second argument of the constructor instead.

TwigBundle
----------

* The `ContainerAwareRuntimeLoader` class has been deprecated and will be removed in 4.0.
Use the Twig `Twig_ContainerRuntimeLoader` class instead.

Workflow
--------

Expand Down
15 changes: 15 additions & 0 deletions UPGRADE-4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ FrameworkBundle

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass` class has been
removed. Use the `Symfony\Component\Form\DependencyInjection\FormPass` class instead.

* The `Symfony\Bundle\FrameworkBundle\EventListener\SessionListener` class has been removed.
Use the `Symfony\Component\HttpKernel\EventListener\SessionListener` instead.

* The `Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener` class has been removed.
Use the `Symfony\Component\HttpKernel\EventListener\TestSessionListener` instead.

SecurityBundle
--------------
Expand Down Expand Up @@ -236,6 +242,9 @@ HttpKernel

* The `Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
by name to the constructor instead.

* The `LazyLoadingFragmentHandler::addRendererService()` method has been removed.


Process
-------
Expand Down Expand Up @@ -276,6 +285,12 @@ Translation

* Removed the backup feature from the file dumper classes.

TwigBundle
----------

* The `ContainerAwareRuntimeLoader` class has been removed. Use the
Twig `Twig_ContainerRuntimeLoader` class instead.

TwigBridge
----------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
use Symfony\Component\HttpKernel\EventListener\SessionListener as BaseSessionListener;
use Symfony\Component\DependencyInjection\ContainerInterface;

@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', SessionListener::class, BaseSessionListener::class), E_USER_DEPRECATED);

/**
* Sets the session in the request.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since version 3.3, to be removed in 4.0.
*/
class SessionListener extends BaseSessionListener
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
use Symfony\Component\HttpKernel\EventListener\TestSessionListener as BaseTestSessionListener;
use Symfony\Component\DependencyInjection\ContainerInterface;

@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', TestSessionListener::class, BaseTestSessionListener::class), E_USER_DEPRECATED);

/**
* TestSessionListener.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since version 3.3, to be removed in 4.0.
*/
class TestSessionListener extends BaseTestSessionListener
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<services>
<service id="fragment.handler" class="Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler">
<argument type="service" id="service_container" />
<argument /> <!-- fragment renderer locator -->
<argument type="service" id="request_stack" />
<argument>%kernel.debug%</argument>
</service>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@

<service id="session.handler.write_check" class="Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler" public="false" />

<service id="session_listener" class="Symfony\Bundle\FrameworkBundle\EventListener\SessionListener">
<service id="session_listener" class="Symfony\Component\HttpKernel\EventListener\SessionListener">
<tag name="kernel.event_subscriber" />
<argument type="service" id="service_container" />
<getter name="getSession" type="service" id="session" on-invalid="null" />
</service>

<service id="session.save_listener" class="Symfony\Component\HttpKernel\EventListener\SaveSessionListener">
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

<service id="test.client.cookiejar" class="Symfony\Component\BrowserKit\CookieJar" shared="false" />

<service id="test.session.listener" class="Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener">
<argument type="service" id="service_container" />
<service id="test.session.listener" class="Symfony\Component\HttpKernel\EventListener\TestSessionListener">
<tag name="kernel.event_subscriber" />
<getter name="getSession" type="service" id="session" on-invalid="null" />
</service>
</services>
</container>
4 changes: 4 additions & 0 deletions src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@

namespace Symfony\Bundle\TwigBundle;

@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use the Twig_ContainerRuntimeLoader class instead.'), ContainerAwareRuntimeLoader::class);

use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Loads Twig extension runtimes via the service container.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since version 3.3, will be removed in 4.0. Use \Twig_ContainerRuntimeLoader instead.
*/
class ContainerAwareRuntimeLoader implements \Twig_RuntimeLoaderInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;

/**
* Registers Twig runtime services.
Expand All @@ -31,17 +33,13 @@ public function process(ContainerBuilder $container)
foreach ($container->findTaggedServiceIds('twig.runtime') as $id => $attributes) {
$def = $container->getDefinition($id);

if (!$def->isPublic()) {
throw new InvalidArgumentException(sprintf('The service "%s" must be public as it can be lazy-loaded.', $id));
}

if ($def->isAbstract()) {
throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as it can be lazy-loaded.', $id));
}

$mapping[$def->getClass()] = $id;
$mapping[$def->getClass()] = new Reference($id);
}

$definition->replaceArgument(1, $mapping);
$definition->replaceArgument(0, new ServiceLocatorArgument($mapping));
}
}
6 changes: 2 additions & 4 deletions src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,8 @@
<argument /> <!-- thousands separator, set in TwigExtension -->
</service>

<service id="twig.runtime_loader" class="Symfony\Bundle\TwigBundle\ContainerAwareRuntimeLoader" public="false">
<argument type="service" id="service_container" />
<argument type="collection" /> <!-- the mapping between class names and service names -->
<argument type="service" id="logger" on-invalid="null" />
<service id="twig.runtime_loader" class="Twig_ContainerRuntimeLoader" public="false">
<argument /> <!-- runtime locator -->
</service>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\TwigBundle\ContainerAwareRuntimeLoader;

/**
* @group legacy
*/
class ContainerAwareRuntimeLoaderTest extends TestCase
{
public function testLoad()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public function testRuntimeLoader()
$container->compile();

$loader = $container->getDefinition('twig.runtime_loader');
$args = $loader->getArgument(1);
$args = $loader->getArgument(0)->getValues();
$this->assertArrayHasKey('Symfony\Bridge\Twig\Form\TwigRenderer', $args);
$this->assertArrayHasKey('FooClass', $args);
$this->assertContains('twig.form.renderer', $args);
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/TwigBundle/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"symfony/twig-bridge": "^3.2.1",
"symfony/http-foundation": "~2.8|~3.0",
"symfony/http-kernel": "~2.8.16|~3.1.9|^3.2.2",
"twig/twig": "~1.28|~2.0"
"twig/twig": "^1.32|^2.2"
},
"require-dev": {
"symfony/asset": "~2.8|~3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Compiler pass to register tagged services for an event dispatcher.
Expand Down Expand Up @@ -105,8 +106,8 @@ public function process(ContainerBuilder $container)
}
$container->addObjectResource($class);

$r = new \ReflectionClass($class);
$extractingDispatcher->addSubscriber($r->newInstanceWithoutConstructor());
ExtractingEventDispatcher::$subscriber = $class;
$extractingDispatcher->addSubscriber($extractingDispatcher);
foreach ($extractingDispatcher->listeners as $args) {
$args[1] = new ClosureProxyArgument($id, $args[1]);
$definition->addMethodCall('addListener', $args);
Expand All @@ -119,12 +120,21 @@ public function process(ContainerBuilder $container)
/**
* @internal
*/
class ExtractingEventDispatcher extends EventDispatcher
class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface
{
public $listeners = array();

public static $subscriber;

public function addListener($eventName, $listener, $priority = 0)
{
$this->listeners[] = array($eventName, $listener[1], $priority);
}

public static function getSubscribedEvents()
{
$callback = array(self::$subscriber, 'getSubscribedEvents');

return $callback();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;

/**
Expand Down Expand Up @@ -43,11 +45,9 @@ public function process(ContainerBuilder $container)
}

$definition = $container->getDefinition($this->handlerService);
$renderers = array();
foreach ($container->findTaggedServiceIds($this->rendererTag) as $id => $tags) {
$def = $container->getDefinition($id);
if (!$def->isPublic()) {
throw new InvalidArgumentException(sprintf('The service "%s" must be public as fragment renderer are lazy-loaded.', $id));
}

if ($def->isAbstract()) {
throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as fragment renderer are lazy-loaded.', $id));
Expand All @@ -63,8 +63,10 @@ public function process(ContainerBuilder $container)
}

foreach ($tags as $tag) {
$definition->addMethodCall('addRendererService', array($tag['alias'], $id));
$renderers[$tag['alias']] = new Reference($id);
}
}

$definition->replaceArgument(0, new ServiceLocatorArgument($renderers));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Symfony\Component\HttpKernel\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;

Expand All @@ -23,7 +23,11 @@
class LazyLoadingFragmentHandler extends FragmentHandler
{
private $container;
/**
* @deprecated since version 3.3, to be removed in 4.0
*/
private $rendererIds = array();
private $initialized = array();

/**
* Constructor.
Expand All @@ -44,9 +48,13 @@ public function __construct(ContainerInterface $container, RequestStack $request
*
* @param string $name The service name
* @param string $renderer The render service id
*
* @deprecated since version 3.3, to be removed in 4.0
*/
public function addRendererService($name, $renderer)
{
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);

$this->rendererIds[$name] = $renderer;
}

Expand All @@ -55,10 +63,17 @@ public function addRendererService($name, $renderer)
*/
public function render($uri, $renderer = 'inline', array $options = array())
{
// BC 3.x, to be removed in 4.0
if (isset($this->rendererIds[$renderer])) {
$this->addRenderer($this->container->get($this->rendererIds[$renderer]));

unset($this->rendererIds[$renderer]);

return parent::render($uri, $renderer, $options);
}

if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) {
$this->addRenderer($this->container->get($renderer));
$this->initialized[$renderer] = true;
}

return parent::render($uri, $renderer, $options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
namespace Symfony\Component\HttpKernel\Tests\DependencyInjection;

use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass;
use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
Expand Down Expand Up @@ -60,19 +62,13 @@ public function testValidContentRenderer()
$renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
$renderer
->expects($this->once())
->method('addMethodCall')
->with('addRendererService', array('foo', 'my_content_renderer'))
;
->method('replaceArgument')
->with(0, $this->equalTo(new ServiceLocatorArgument(array('foo' => new Reference('my_content_renderer')))));

$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
$definition->expects($this->atLeastOnce())
->method('getClass')
->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService'));
$definition
->expects($this->once())
->method('isPublic')
->will($this->returnValue(true))
;

$builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'getReflectionClass'))->getMock();
$builder->expects($this->any())
Expand Down
Loading