From 0be9ea8ba1f2bef7bdf6be4b2fe0422dec050195 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 17 Feb 2017 20:46:29 +0100 Subject: [PATCH 1/2] [EventDispatcher] Fix abstract event subscribers registration --- .../RegisterListenersPass.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index ec5e4e8747..431ea21a67 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\ContainerBuilder; 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 @@ class RegisterListenersPass implements CompilerPassInterface } $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 @@ class RegisterListenersPass implements CompilerPassInterface /** * @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(); + } } From 8293b753cfb3ef13159334f001e19d00f4ed273c Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 14 Feb 2017 20:09:41 +0100 Subject: [PATCH 2/2] Replace some container injections by service locators --- UPGRADE-3.3.md | 17 ++++ UPGRADE-4.0.md | 15 ++++ .../Bundle/FrameworkBundle/CHANGELOG.md | 2 + .../EventListener/SessionListener.php | 23 +---- .../EventListener/TestSessionListener.php | 8 +- .../Resources/config/fragment_renderer.xml | 2 +- .../Resources/config/session.xml | 6 +- .../FrameworkBundle/Resources/config/test.xml | 6 +- src/Symfony/Bundle/TwigBundle/CHANGELOG.md | 5 ++ .../ContainerAwareRuntimeLoader.php | 4 + .../Compiler/RuntimeLoaderPass.php | 13 ++- .../TwigBundle/Resources/config/twig.xml | 6 +- .../Tests/ContainerAwareRuntimeLoaderTest.php | 3 + .../DependencyInjection/TwigExtensionTest.php | 2 +- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- src/Symfony/Component/HttpKernel/CHANGELOG.md | 7 ++ .../FragmentRendererPass.php | 13 +-- .../LazyLoadingFragmentHandler.php | 19 ++++- .../EventListener/AbstractSessionListener.php | 53 ++++++++++++ .../AbstractTestSessionListener.php | 83 +++++++++++++++++++ .../EventListener/SessionListener.php | 43 ++++------ .../EventListener/TestSessionListener.php | 73 ++++------------ .../FragmentRendererPassTest.php | 12 +-- .../LazyLoadingFragmentHandlerTest.php | 27 +++++- .../EventListener/TestSessionListenerTest.php | 2 +- 25 files changed, 302 insertions(+), 144 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php create mode 100644 src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index 490415f1a5..28135663fc 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -71,11 +71,22 @@ FrameworkBundle 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` + class 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` + class 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 ------- @@ -127,6 +138,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 ad00aebc78..7dca18843e 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -188,6 +188,13 @@ 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` class instead. + + * The `Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener` class has been + removed. Use the `Symfony\Component\HttpKernel\EventListener\TestSessionListener` + class instead. + HttpFoundation --------------- @@ -229,6 +236,8 @@ 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. Ldap ---- @@ -285,6 +294,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/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 21eeed54ec..ae46d5c3c0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -15,6 +15,8 @@ CHANGELOG * Added configurable paths for validation files * Deprecated `SerializerPass`, use `Symfony\Component\Serializer\DependencyInjection\SerializerPass` instead * Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead + * Deprecated `SessionListener` + * Deprecated `TestSessionListener` 3.2.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php index 6c248d8a42..07bfe7496d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php @@ -12,31 +12,16 @@ namespace Symfony\Bundle\FrameworkBundle\EventListener; 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. Use {@link BaseSessionListener} instead */ class SessionListener extends BaseSessionListener { - /** - * @var ContainerInterface - */ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - protected function getSession() - { - if (!$this->container->has('session')) { - return; - } - - return $this->container->get('session'); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php index b32faa2f05..703be8ff3b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php @@ -11,15 +11,19 @@ namespace Symfony\Bundle\FrameworkBundle\EventListener; -use Symfony\Component\HttpKernel\EventListener\TestSessionListener as BaseTestSessionListener; +@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\TestSessionListener instead.', TestSessionListener::class), E_USER_DEPRECATED); + +use Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener; use Symfony\Component\DependencyInjection\ContainerInterface; /** * TestSessionListener. * * @author Fabien Potencier + * + * @deprecated since version 3.3, to be removed in 4.0. */ -class TestSessionListener extends BaseTestSessionListener +class TestSessionListener extends AbstractTestSessionListener { protected $container; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml index 3f0d319d9d..963179c64e 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 2a4816a2b3..64dc2ef5b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -47,9 +47,11 @@ - + - + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml index ebb311ceb0..580a073f73 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml @@ -20,9 +20,11 @@ - - + + + + diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index 90f7cbd1e0..9f666dbc29 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.3.0 +----- + + * Deprecated `ContainerAwareRuntimeLoader` + 2.7.0 ----- diff --git a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php index 780454aed9..eaa4d698bf 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 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * 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 7d0be74fad..bfefb98e15 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php @@ -11,9 +11,10 @@ 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 +32,13 @@ class RuntimeLoaderPass implements CompilerPassInterface 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)); + continue; } - $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 f247da8b8a..0a6d03dff6 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 1e11e63e48..93202ca987 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php @@ -15,6 +15,9 @@ use Psr\Log\LoggerInterface; 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 4073653c8b..ad54b92767 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -244,7 +244,7 @@ class TwigExtensionTest extends TestCase $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 7e33c18787..2783ffdde0 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/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 0c95ff5640..febe797dc6 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +3.3.0 +----- + + * Deprecated `LazyLoadingFragmentHandler::addRendererService()` + * Added `SessionListener` + * Added `TestSessionListener` + 3.2.0 ----- diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/FragmentRendererPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/FragmentRendererPass.php index 6583d0f7d4..bf4e2a17f4 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,14 +45,11 @@ class FragmentRendererPass implements CompilerPassInterface } $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)); + continue; } $class = $container->getParameterBag()->resolveValue($def->getClass()); @@ -63,8 +62,10 @@ class FragmentRendererPass implements CompilerPassInterface } 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 3559e39e90..d6f4dab141 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 @@ use Symfony\Component\HttpKernel\Fragment\FragmentHandler; 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 @@ class LazyLoadingFragmentHandler extends FragmentHandler * * @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 @@ class LazyLoadingFragmentHandler extends FragmentHandler */ 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/EventListener/AbstractSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php new file mode 100644 index 0000000000..974993c847 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.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\HttpKernel\EventListener; + +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * Sets the session in the request. + * + * @author Johannes M. Schmitt + */ +abstract class AbstractSessionListener implements EventSubscriberInterface +{ + public function onKernelRequest(GetResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $request = $event->getRequest(); + $session = $this->getSession(); + if (null === $session || $request->hasSession()) { + return; + } + + $request->setSession($session); + } + + public static function getSubscribedEvents() + { + return array( + KernelEvents::REQUEST => array('onKernelRequest', 128), + ); + } + + /** + * Gets the session object. + * + * @return SessionInterface|null A SessionInterface instance or null if no session is available + */ + abstract protected function getSession(); +} diff --git a/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php new file mode 100644 index 0000000000..bc1acbd73e --- /dev/null +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * TestSessionListener. + * + * Saves session in test environment. + * + * @author Bulat Shakirzyanov + * @author Fabien Potencier + */ +abstract class AbstractTestSessionListener implements EventSubscriberInterface +{ + public function onKernelRequest(GetResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + // bootstrap the session + $session = $this->getSession(); + if (!$session) { + return; + } + + $cookies = $event->getRequest()->cookies; + + if ($cookies->has($session->getName())) { + $session->setId($cookies->get($session->getName())); + } + } + + /** + * Checks if session was initialized and saves if current request is master + * Runs on 'kernel.response' in test environment. + * + * @param FilterResponseEvent $event + */ + public function onKernelResponse(FilterResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $session = $event->getRequest()->getSession(); + if ($session && $session->isStarted()) { + $session->save(); + $params = session_get_cookie_params(); + $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); + } + } + + public static function getSubscribedEvents() + { + return array( + KernelEvents::REQUEST => array('onKernelRequest', 192), + KernelEvents::RESPONSE => array('onKernelResponse', -128), + ); + } + + /** + * Gets the session object. + * + * @return SessionInterface|null A SessionInterface instance or null if no session is available + */ + abstract protected function getSession(); +} diff --git a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php index ecf065f0e8..39ebfd922f 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php @@ -11,43 +11,30 @@ namespace Symfony\Component\HttpKernel\EventListener; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Psr\Container\ContainerInterface; /** * Sets the session in the request. * - * @author Johannes M. Schmitt + * @author Fabien Potencier + * + * @final since version 3.3 */ -abstract class SessionListener implements EventSubscriberInterface +class SessionListener extends AbstractSessionListener { - public function onKernelRequest(GetResponseEvent $event) + private $container; + + public function __construct(ContainerInterface $container) { - if (!$event->isMasterRequest()) { + $this->container = $container; + } + + protected function getSession() + { + if (!$this->container->has('session')) { return; } - $request = $event->getRequest(); - $session = $this->getSession(); - if (null === $session || $request->hasSession()) { - return; - } - - $request->setSession($session); + return $this->container->get('session'); } - - public static function getSubscribedEvents() - { - return array( - KernelEvents::REQUEST => array('onKernelRequest', 128), - ); - } - - /** - * Gets the session object. - * - * @return SessionInterface|null A SessionInterface instance or null if no session is available - */ - abstract protected function getSession(); } diff --git a/src/Symfony/Component/HttpKernel/EventListener/TestSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/TestSessionListener.php index 8fc8e57579..36abb422f4 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/TestSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/TestSessionListener.php @@ -11,73 +11,30 @@ namespace Symfony\Component\HttpKernel\EventListener; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Psr\Container\ContainerInterface; /** - * TestSessionListener. + * Sets the session in the request. * - * Saves session in test environment. - * - * @author Bulat Shakirzyanov * @author Fabien Potencier + * + * @final since version 3.3 */ -abstract class TestSessionListener implements EventSubscriberInterface +class TestSessionListener extends AbstractTestSessionListener { - public function onKernelRequest(GetResponseEvent $event) + private $container; + + public function __construct(ContainerInterface $container) { - if (!$event->isMasterRequest()) { + $this->container = $container; + } + + protected function getSession() + { + if (!$this->container->has('session')) { return; } - // bootstrap the session - $session = $this->getSession(); - if (!$session) { - return; - } - - $cookies = $event->getRequest()->cookies; - - if ($cookies->has($session->getName())) { - $session->setId($cookies->get($session->getName())); - } + return $this->container->get('session'); } - - /** - * Checks if session was initialized and saves if current request is master - * Runs on 'kernel.response' in test environment. - * - * @param FilterResponseEvent $event - */ - public function onKernelResponse(FilterResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $session = $event->getRequest()->getSession(); - if ($session && $session->isStarted()) { - $session->save(); - $params = session_get_cookie_params(); - $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); - } - } - - public static function getSubscribedEvents() - { - return array( - KernelEvents::REQUEST => array('onKernelRequest', 192), - KernelEvents::RESPONSE => array('onKernelResponse', -128), - ); - } - - /** - * Gets the session object. - * - * @return SessionInterface|null A SessionInterface instance or null if no session is available - */ - abstract protected function getSession(); } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php index 360f806fea..c33db826ef 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 @@ class FragmentRendererPassTest extends TestCase $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 63090d0503..0406345d96 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php @@ -18,7 +18,11 @@ use Symfony\Component\HttpFoundation\Response; 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 @@ class LazyLoadingFragmentHandlerTest extends TestCase // 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'); + } } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php index 52794e0272..2e51d42d15 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php @@ -39,7 +39,7 @@ class TestSessionListenerTest extends TestCase protected function setUp() { - $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\TestSessionListener'); + $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener'); $this->session = $this->getSession(); }