From 972297ab44e9e6ac76d9468198b3f4dd5854306c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 25 Oct 2017 13:36:10 +0200 Subject: [PATCH] [HttpFoundation][HttpKernel] Move ServiceResetListener logic to RequestStack --- .../Resources/config/services.xml | 6 -- .../ResettableServicePass.php | 15 ++-- .../EventListener/ServiceResetListener.php | 50 ------------ .../HttpKernel/ResettingRequestStack.php | 49 ++++++++++++ .../ResettableServicePassTest.php | 33 ++------ .../ServiceResetListenerTest.php | 77 ------------------- .../Tests/ResettingRequestStackTest.php | 55 +++++++++++++ .../Component/HttpKernel/composer.json | 2 +- 8 files changed, 115 insertions(+), 172 deletions(-) delete mode 100644 src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php create mode 100644 src/Symfony/Component/HttpKernel/ResettingRequestStack.php delete mode 100644 src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/ResettingRequestStackTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 31ca2075e4a98..dea49cbc00538 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -74,11 +74,5 @@ - - - - - - diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php index 56cd059284afe..28212b333ed87 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php @@ -17,7 +17,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\EventListener\ServiceResetListener; +use Symfony\Component\HttpKernel\ResettingRequestStack; /** * @author Alexander M. Turek @@ -39,7 +39,7 @@ public function __construct($tagName = 'kernel.reset') */ public function process(ContainerBuilder $container) { - if (!$container->has(ServiceResetListener::class)) { + if (!$container->has('request_stack')) { return; } @@ -56,14 +56,9 @@ public function process(ContainerBuilder $container) $methods[$id] = $attributes['method']; } - if (empty($services)) { - $container->removeDefinition(ServiceResetListener::class); - - return; + if (!empty($services)) { + $container->register('request_stack', ResettingRequestStack::class) + ->setArguments(array(new IteratorArgument($services), $methods)); } - - $container->findDefinition(ServiceResetListener::class) - ->replaceArgument(0, new IteratorArgument($services)) - ->replaceArgument(1, $methods); } } diff --git a/src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php b/src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php deleted file mode 100644 index cf6d15930315f..0000000000000 --- a/src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Clean up services between requests. - * - * @author Alexander M. Turek - */ -class ServiceResetListener implements EventSubscriberInterface -{ - private $services; - private $resetMethods; - - public function __construct(\Traversable $services, array $resetMethods) - { - $this->services = $services; - $this->resetMethods = $resetMethods; - } - - public function onKernelTerminate() - { - foreach ($this->services as $id => $service) { - $method = $this->resetMethods[$id]; - $service->$method(); - } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() - { - return array( - KernelEvents::TERMINATE => array('onKernelTerminate', -2048), - ); - } -} diff --git a/src/Symfony/Component/HttpKernel/ResettingRequestStack.php b/src/Symfony/Component/HttpKernel/ResettingRequestStack.php new file mode 100644 index 0000000000000..455ae3dec64fe --- /dev/null +++ b/src/Symfony/Component/HttpKernel/ResettingRequestStack.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; + +/** + * Resets services on second master requests. + * + * @author Nicolas Grekas + */ +class ResettingRequestStack extends RequestStack +{ + private $resetNeeded = false; + private $resettableServices; + private $resetMethods; + + public function __construct(\Traversable $resettableServices, array $resetMethods) + { + $this->resettableServices = $resettableServices; + $this->resetMethods = $resetMethods; + } + + /** + * {@inheritdoc} + */ + public function push(Request $request) + { + if ($this->resetNeeded && !$this->getCurrentRequest()) { + foreach ($this->resettableServices as $id => $service) { + $service->{$this->resetMethods[$id]}(); + } + } else { + $this->resetNeeded = true; + } + + parent::push($request); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php index c998ef2eaf086..3d651c8e4ee55 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php @@ -7,8 +7,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; -use Symfony\Component\HttpKernel\EventListener\ServiceResetListener; use Symfony\Component\HttpKernel\Tests\Fixtures\ClearableService; use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService; @@ -24,14 +24,13 @@ public function testCompilerPass() ->setPublic(true) ->addTag('kernel.reset', array('method' => 'clear')); - $container->register(ServiceResetListener::class) - ->setPublic(true) - ->setArguments(array(null, array())); + $container->register('request_stack', RequestStack::class) + ->setPublic(true); $container->addCompilerPass(new ResettableServicePass('kernel.reset')); $container->compile(); - $definition = $container->getDefinition(ServiceResetListener::class); + $definition = $container->getDefinition('request_stack'); $this->assertEquals( array( @@ -57,32 +56,10 @@ public function testMissingMethod() $container = new ContainerBuilder(); $container->register(ResettableService::class) ->addTag('kernel.reset'); - $container->register(ServiceResetListener::class) + $container->register('request_stack', RequestStack::class) ->setArguments(array(null, array())); $container->addCompilerPass(new ResettableServicePass('kernel.reset')); $container->compile(); } - - public function testCompilerPassWithoutResetters() - { - $container = new ContainerBuilder(); - $container->register(ServiceResetListener::class) - ->setArguments(array(null, array())); - $container->addCompilerPass(new ResettableServicePass()); - - $container->compile(); - - $this->assertFalse($container->has(ServiceResetListener::class)); - } - - public function testCompilerPassWithoutListener() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new ResettableServicePass()); - - $container->compile(); - - $this->assertFalse($container->has(ServiceResetListener::class)); - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php deleted file mode 100644 index 603d11b2bf412..0000000000000 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php +++ /dev/null @@ -1,77 +0,0 @@ -buildContainer(); - $container->get('reset_subscriber')->onKernelTerminate(); - - $this->assertEquals(0, ResettableService::$counter); - $this->assertEquals(0, ClearableService::$counter); - } - - public function testResetServicesPartially() - { - $container = $this->buildContainer(); - $container->get('one'); - $container->get('reset_subscriber')->onKernelTerminate(); - - $this->assertEquals(1, ResettableService::$counter); - $this->assertEquals(0, ClearableService::$counter); - } - - public function testResetServicesTwice() - { - $container = $this->buildContainer(); - $container->get('one'); - $container->get('reset_subscriber')->onKernelTerminate(); - $container->get('two'); - $container->get('reset_subscriber')->onKernelTerminate(); - - $this->assertEquals(2, ResettableService::$counter); - $this->assertEquals(1, ClearableService::$counter); - } - - /** - * @return ContainerBuilder - */ - private function buildContainer() - { - $container = new ContainerBuilder(); - $container->register('one', ResettableService::class)->setPublic(true); - $container->register('two', ClearableService::class)->setPublic(true); - - $container->register('reset_subscriber', ServiceResetListener::class) - ->setPublic(true) - ->addArgument(new IteratorArgument(array( - 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), - 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), - ))) - ->addArgument(array( - 'one' => 'reset', - 'two' => 'clear', - )); - - $container->compile(); - - return $container; - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/ResettingRequestStackTest.php b/src/Symfony/Component/HttpKernel/Tests/ResettingRequestStackTest.php new file mode 100644 index 0000000000000..b67409f89dffc --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/ResettingRequestStackTest.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\ResettingRequestStack; +use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService; + +class ResettingRequestStackTest extends TestCase +{ + protected function setUp() + { + ResettableService::$counter = 0; + } + + public function testResetServicesNoOp() + { + $requestStack = new ResettingRequestStack(new \ArrayIterator(array(new ResettableService())), array('reset')); + + $masterRequest = Request::create('/foo'); + + $requestStack->push($masterRequest); + + $this->assertEquals(0, ResettableService::$counter); + } + + public function testResetServices() + { + $requestStack = new ResettingRequestStack(new \ArrayIterator(array(new ResettableService())), array('reset')); + + $masterRequest = Request::create('/foo'); + + $requestStack->push($masterRequest); + $this->assertEquals(0, ResettableService::$counter); + + $requestStack->pop(); + $this->assertEquals(0, ResettableService::$counter); + + $requestStack->push($masterRequest); + $this->assertEquals(1, ResettableService::$counter); + + $requestStack->push($masterRequest); + $this->assertEquals(1, ResettableService::$counter); + } +} diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 2d134e5b14943..63f0222317460 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.3.11|~4.0", + "symfony/http-foundation": "^3.4|~4.0", "symfony/debug": "~2.8|~3.0|~4.0", "psr/log": "~1.0" },