From 36fcc117ba891eaeaf753648653d2132c5cd8334 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 29 Aug 2016 13:03:55 -0500 Subject: [PATCH] Use a factory to create the SendResponseListener Reported in: - zendframework/zend-mvc-console#10 - zendframework/zend-mvc-console#11 - zendframework/zend-mvc-console#12 The `SendResponseListener` was lazy-instantiating an event manager on first request to `getEventManager()`. However, because initializers run after delegators, this meant that the EM instance composed did not have a shared EM instance, which triggered the initializer to re-inject, losing any listeners injected by delegators. This patch introduces a factory for the `SendResponseListener`. The factory creates the instance, and then injects it with an EM instance pulled from the container; since these are guaranteed to have a shared EM instance, the initializer will skip injection, keeping any listeners injected by delegators. --- src/Service/SendResponseListenerFactory.php | 25 ++++++++++ src/Service/ServiceListenerFactory.php | 2 +- test/Service/SendResponseFactoryTest.php | 55 +++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/Service/SendResponseListenerFactory.php create mode 100644 test/Service/SendResponseFactoryTest.php diff --git a/src/Service/SendResponseListenerFactory.php b/src/Service/SendResponseListenerFactory.php new file mode 100644 index 000000000..9e7cf90fb --- /dev/null +++ b/src/Service/SendResponseListenerFactory.php @@ -0,0 +1,25 @@ +setEventManager($container->get('EventManager')); + return $listener; + } +} diff --git a/src/Service/ServiceListenerFactory.php b/src/Service/ServiceListenerFactory.php index 758e62c40..788c91ffc 100644 --- a/src/Service/ServiceListenerFactory.php +++ b/src/Service/ServiceListenerFactory.php @@ -86,7 +86,7 @@ class ServiceListenerFactory implements FactoryInterface 'ViewPrefixPathStackResolver' => 'Zend\Mvc\Service\ViewPrefixPathStackResolverFactory', 'Zend\Mvc\MiddlewareListener' => InvokableFactory::class, 'Zend\Mvc\RouteListener' => InvokableFactory::class, - 'Zend\Mvc\SendResponseListener' => InvokableFactory::class, + 'Zend\Mvc\SendResponseListener' => SendResponseListenerFactory::class, 'Zend\View\Renderer\FeedRenderer' => InvokableFactory::class, 'Zend\View\Renderer\JsonRenderer' => InvokableFactory::class, 'Zend\View\Renderer\PhpRenderer' => ViewPhpRendererFactory::class, diff --git a/test/Service/SendResponseFactoryTest.php b/test/Service/SendResponseFactoryTest.php new file mode 100644 index 000000000..e4ea9143b --- /dev/null +++ b/test/Service/SendResponseFactoryTest.php @@ -0,0 +1,55 @@ +prophesize(SharedEventManagerInterface::class); + $events = $this->prophesize(EventManagerInterface::class); + $events->getSharedManager()->will([$sharedEvents, 'reveal']); + + $events->setIdentifiers([SendResponseListener::class, SendResponseListener::class])->shouldBeCalled(); + $events->attach( + SendResponseEvent::EVENT_SEND_RESPONSE, + Argument::type(PhpEnvironmentResponseSender::class), + -1000 + )->shouldBeCalled(); + $events->attach( + SendResponseEvent::EVENT_SEND_RESPONSE, + Argument::type(SimpleStreamResponseSender::class), + -3000 + )->shouldBeCalled(); + $events->attach( + SendResponseEvent::EVENT_SEND_RESPONSE, + Argument::type(HttpResponseSender::class), + -4000 + )->shouldBeCalled(); + + $container = $this->prophesize(ContainerInterface::class); + $container->get('EventManager')->will([$events, 'reveal']); + + $factory = new SendResponseListenerFactory(); + $listener = $factory($container->reveal()); + $this->assertInstanceOf(SendResponseListener::class, $listener); + $this->assertSame($events->reveal(), $listener->getEventManager()); + } +}