diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index 2253bea93b51d..b4ba023169082 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -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 ------- @@ -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 -------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 1335b0e6e04d3..88e7120afafd0 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -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 -------------- @@ -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 ------- @@ -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 ---------- diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php index 6c248d8a42880..cb41856b7055c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php @@ -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 + * + * @deprecated since version 3.3, to be removed in 4.0. */ class SessionListener extends BaseSessionListener { diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php index b32faa2f05668..e6f5e69ba5993 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php @@ -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 + * + * @deprecated since version 3.3, to be removed in 4.0. */ class TestSessionListener extends BaseTestSessionListener { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml index 3f0d319d9de13..963179c64e99e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml @@ -11,7 +11,7 @@ - + %kernel.debug% diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 2a4816a2b3bf1..67b10b374e1d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -47,9 +47,9 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml index ebb311ceb0808..24a3ea37728a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml @@ -20,9 +20,9 @@ - - + + diff --git a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php index 780454aed986e..eaa4d698bf8c4 100644 --- a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php +++ b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php @@ -11,6 +11,8 @@ 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; @@ -18,6 +20,8 @@ * Loads Twig extension runtimes via the service container. * * @author Fabien Potencier + * + * @deprecated since version 3.3, will be removed in 4.0. Use \Twig_ContainerRuntimeLoader instead. */ class ContainerAwareRuntimeLoader implements \Twig_RuntimeLoaderInterface { diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php index 7d0be74fadb78..c7c0bf12a488d 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php @@ -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. @@ -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)); } } diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index f247da8b8aa9f..0a6d03dff68ca 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -138,10 +138,8 @@ - - - - + + diff --git a/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php b/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php index 1e11e63e48687..93202ca987b16 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php @@ -15,6 +15,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Bundle\TwigBundle\ContainerAwareRuntimeLoader; +/** + * @group legacy + */ class ContainerAwareRuntimeLoaderTest extends TestCase { public function testLoad() diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index 4073653c8b571..ad54b9276716c 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -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); diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 7e33c187878fd..2783ffdde0e07 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -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", diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index ec5e4e8747a02..431ea21a6796a 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -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. @@ -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); @@ -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(); + } } diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/FragmentRendererPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/FragmentRendererPass.php index 6583d0f7d40bc..9479d43e765c4 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/FragmentRendererPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/FragmentRendererPass.php @@ -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; /** @@ -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)); @@ -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)); } } diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php b/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php index 3559e39e9001d..d6f4dab1418c0 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php @@ -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; @@ -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. @@ -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; } @@ -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); diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php index 360f806fea6bf..c33db826ef154 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php @@ -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; @@ -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()) diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php index 63090d050340c..0406345d96d68 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php @@ -18,7 +18,11 @@ class LazyLoadingFragmentHandlerTest extends TestCase { - public function test() + /** + * @group legacy + * @expectedDeprecation The Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler::addRendererService() method is deprecated since version 3.3 and will be removed in 4.0. + */ + public function testRenderWithLegacyMapping() { $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); $renderer->expects($this->once())->method('getName')->will($this->returnValue('foo')); @@ -38,4 +42,25 @@ public function test() // second call should not lazy-load anymore (see once() above on the get() method) $handler->render('/foo', 'foo'); } + + public function testRender() + { + $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); + $renderer->expects($this->once())->method('getName')->will($this->returnValue('foo')); + $renderer->expects($this->any())->method('render')->will($this->returnValue(new Response())); + + $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock(); + $requestStack->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/'))); + + $container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock(); + $container->expects($this->once())->method('has')->with('foo')->willReturn(true); + $container->expects($this->once())->method('get')->will($this->returnValue($renderer)); + + $handler = new LazyLoadingFragmentHandler($container, $requestStack, false); + + $handler->render('/foo', 'foo'); + + // second call should not lazy-load anymore (see once() above on the get() method) + $handler->render('/foo', 'foo'); + } }