From abd28eebb452cd03e6066d8d0df42803c8029563 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 25 Oct 2017 11:05:04 +0200 Subject: [PATCH] Prototype: Service reset as middleware. --- .../Resources/config/services.xml | 14 ++-- .../Functional/DebugAutowiringCommandTest.php | 4 +- .../ResettableServicePass.php | 16 ++--- .../EventListener/ServiceResetListener.php | 50 -------------- .../Middleware/ServiceResetMiddleware.php | 66 +++++++++++++++++++ .../ResettableServicePassTest.php | 38 +++++------ .../ServiceResetMiddlewareTest.php} | 40 ++++++++--- 7 files changed, 131 insertions(+), 97 deletions(-) delete mode 100644 src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php create mode 100644 src/Symfony/Component/HttpKernel/Middleware/ServiceResetMiddleware.php rename src/Symfony/Component/HttpKernel/Tests/{EventListener/ServiceResetListenerTest.php => Middleware/ServiceResetMiddlewareTest.php} (58%) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 31ca2075e4a98..590c2ce995091 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -12,12 +12,18 @@ - + + + + + + + @@ -74,11 +80,5 @@ - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php index 0b7f9290a50bb..3e5a266df6370 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php @@ -29,8 +29,8 @@ public function testBasicFunctionality() $tester = new ApplicationTester($application); $tester->run(array('command' => 'debug:autowiring')); - $this->assertContains('Symfony\Component\HttpKernel\HttpKernelInterface', $tester->getDisplay()); - $this->assertContains('alias to http_kernel', $tester->getDisplay()); + $this->assertContains('Symfony\Component\DependencyInjection\ContainerInterface', $tester->getDisplay()); + $this->assertContains('alias to service_container', $tester->getDisplay()); } public function testSearchArgument() diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php index 56cd059284afe..2e33faa43907b 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\Middleware\ServiceResetMiddleware; /** * @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(ServiceResetMiddleware::class)) { return; } @@ -56,14 +56,8 @@ public function process(ContainerBuilder $container) $methods[$id] = $attributes['method']; } - if (empty($services)) { - $container->removeDefinition(ServiceResetListener::class); - - return; - } - - $container->findDefinition(ServiceResetListener::class) - ->replaceArgument(0, new IteratorArgument($services)) - ->replaceArgument(1, $methods); + $container->findDefinition(ServiceResetMiddleware::class) + ->replaceArgument('$services', new IteratorArgument($services)) + ->replaceArgument('$resetMethods', $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/Middleware/ServiceResetMiddleware.php b/src/Symfony/Component/HttpKernel/Middleware/ServiceResetMiddleware.php new file mode 100644 index 0000000000000..6bfcde36a0b97 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Middleware/ServiceResetMiddleware.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Middleware; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\TerminableInterface; + +/** + * Clean up services between requests. + * + * @author Alexander M. Turek + */ +class ServiceResetMiddleware implements HttpKernelInterface, TerminableInterface +{ + private $httpKernel; + private $services; + private $resetMethods; + + public function __construct(HttpKernelInterface $httpKernel, \Traversable $services, array $resetMethods) + { + $this->services = $services; + $this->resetMethods = $resetMethods; + $this->httpKernel = $httpKernel; + } + + /** + * {@inheritdoc} + */ + public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) + { + if (self::MASTER_REQUEST === $type) { + $this->resetServices(); + } + + return $this->httpKernel->handle($request); + } + + /** + * {@inheritdoc} + */ + public function terminate(Request $request, Response $response) + { + if ($this->httpKernel instanceof TerminableInterface) { + $this->httpKernel->terminate($request, $response); + } + } + + private function resetServices() + { + foreach ($this->services as $id => $service) { + $method = $this->resetMethods[$id]; + $service->$method(); + } + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php index c998ef2eaf086..938c3278b9587 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php @@ -8,7 +8,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; -use Symfony\Component\HttpKernel\EventListener\ServiceResetListener; +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\Middleware\ServiceResetMiddleware; use Symfony\Component\HttpKernel\Tests\Fixtures\ClearableService; use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService; @@ -17,6 +18,7 @@ class ResettableServicePassTest extends TestCase public function testCompilerPass() { $container = new ContainerBuilder(); + $container->register(HttpKernel::class)->setSynthetic(true); $container->register('one', ResettableService::class) ->setPublic(true) ->addTag('kernel.reset', array('method' => 'reset')); @@ -24,17 +26,22 @@ public function testCompilerPass() ->setPublic(true) ->addTag('kernel.reset', array('method' => 'clear')); - $container->register(ServiceResetListener::class) + $container->register(ServiceResetMiddleware::class) ->setPublic(true) - ->setArguments(array(null, array())); + ->setArguments(array( + '$httpKernel' => new Reference(HttpKernel::class), + '$services' => null, + '$resetMethods' => array() + )); $container->addCompilerPass(new ResettableServicePass('kernel.reset')); $container->compile(); - $definition = $container->getDefinition(ServiceResetListener::class); + $definition = $container->getDefinition(ServiceResetMiddleware::class); $this->assertEquals( array( + new Reference(HttpKernel::class), new IteratorArgument(array( 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), @@ -55,27 +62,20 @@ public function testCompilerPass() public function testMissingMethod() { $container = new ContainerBuilder(); + $container->register(HttpKernel::class)->setSynthetic(true); $container->register(ResettableService::class) ->addTag('kernel.reset'); - $container->register(ServiceResetListener::class) - ->setArguments(array(null, array())); + $container->register(ServiceResetMiddleware::class) + ->setArguments(array( + '$httpKernel' => new Reference(HttpKernel::class), + '$services' => null, + '$resetMethods' => 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(); @@ -83,6 +83,6 @@ public function testCompilerPassWithoutListener() $container->compile(); - $this->assertFalse($container->has(ServiceResetListener::class)); + $this->assertFalse($container->has(ServiceResetMiddleware::class)); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/Middleware/ServiceResetMiddlewareTest.php similarity index 58% rename from src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php rename to src/Symfony/Component/HttpKernel/Tests/Middleware/ServiceResetMiddlewareTest.php index 603d11b2bf412..9ce869f225922 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Middleware/ServiceResetMiddlewareTest.php @@ -1,17 +1,21 @@ buildContainer(); - $container->get('reset_subscriber')->onKernelTerminate(); + $container->get('reset_middleware')->handle(new Request()); + + $this->assertEquals(0, ResettableService::$counter); + $this->assertEquals(0, ClearableService::$counter); + } + + public function testNoResetOnSubRequests() + { + $container = $this->buildContainer(); + $container->get('one'); + $container->get('reset_middleware')->handle(new Request(), HttpKernelInterface::SUB_REQUEST); $this->assertEquals(0, ResettableService::$counter); $this->assertEquals(0, ClearableService::$counter); @@ -32,7 +46,7 @@ public function testResetServicesPartially() { $container = $this->buildContainer(); $container->get('one'); - $container->get('reset_subscriber')->onKernelTerminate(); + $container->get('reset_middleware')->handle(new Request()); $this->assertEquals(1, ResettableService::$counter); $this->assertEquals(0, ClearableService::$counter); @@ -42,9 +56,9 @@ public function testResetServicesTwice() { $container = $this->buildContainer(); $container->get('one'); - $container->get('reset_subscriber')->onKernelTerminate(); + $container->get('reset_middleware')->handle(new Request()); $container->get('two'); - $container->get('reset_subscriber')->onKernelTerminate(); + $container->get('reset_middleware')->handle(new Request()); $this->assertEquals(2, ResettableService::$counter); $this->assertEquals(1, ClearableService::$counter); @@ -58,9 +72,12 @@ private function buildContainer() $container = new ContainerBuilder(); $container->register('one', ResettableService::class)->setPublic(true); $container->register('two', ClearableService::class)->setPublic(true); + $container->register(HttpKernel::class, HttpKernelInterface::class) + ->setSynthetic(true); - $container->register('reset_subscriber', ServiceResetListener::class) + $container->register('reset_middleware', ServiceResetMiddleware::class) ->setPublic(true) + ->addArgument(new Reference(HttpKernel::class)) ->addArgument(new IteratorArgument(array( 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), @@ -72,6 +89,13 @@ private function buildContainer() $container->compile(); + $kernelMock = $this->createMock(HttpKernelInterface::class); + $kernelMock->expects($this->any()) + ->method('handle') + ->willReturn(new Response()); + + $container->set(HttpKernel::class, $kernelMock); + return $container; } }