diff --git a/CHANGELOG.md b/CHANGELOG.md index 79b5f89fa..cf038ef58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,9 @@ All notable changes to this project will be documented in this file, in reverse ### Fixed -- Nothing. +- [#247](https://github.com/zendframework/zend-mvc/pull/247) fixes bug in + controller plugin Forward, introduced in 2.1.0, where problem listeners were + not detached for forwarded controller dispatch ## 3.1.0 - 2017-05-01 diff --git a/src/Controller/Plugin/Forward.php b/src/Controller/Plugin/Forward.php index d6dbdfbba..4410aaea5 100644 --- a/src/Controller/Plugin/Forward.php +++ b/src/Controller/Plugin/Forward.php @@ -194,6 +194,13 @@ protected function detachProblemListeners(SharedEvents $sharedEvents) if (! is_object($currentCallback)) { continue; } + + foreach ($classArray as $class) { + if ($currentCallback instanceof $class) { + $this->detachSharedListener($id, $currentEvent, $sharedEvents); + $results[$id][$eventName][$priority] = $currentEvent; + } + } } } } diff --git a/test/Controller/Plugin/ForwardTest.php b/test/Controller/Plugin/ForwardTest.php index a604944f6..7554d0cf4 100644 --- a/test/Controller/Plugin/ForwardTest.php +++ b/test/Controller/Plugin/ForwardTest.php @@ -33,6 +33,7 @@ use ZendTest\Mvc\Controller\TestAsset\ForwardController; use ZendTest\Mvc\Controller\TestAsset\SampleController; use ZendTest\Mvc\Controller\TestAsset\UneventfulController; +use ZendTest\Mvc\Controller\Plugin\TestAsset\ListenerStub; class ForwardTest extends TestCase { @@ -237,6 +238,64 @@ function ($e) {} $this->assertEquals(['content' => 'ZendTest\Mvc\Controller\TestAsset\ForwardController::testAction'], $result); } + public function testProblemListenersAreDetachedAndReattachedWhenPluginDispatchesRequestedController() + { + $services = $this->services; + $events = $services->get('EventManager'); + + $myCallback = [new ListenerStub(),'myCallback']; + $sharedEvents = $this->createMock(SharedEventManagerInterface::class); + $sharedEvents->expects($this->once())->method('detach')->with($myCallback, 'Zend\Stdlib\DispatchableInterface'); + $sharedEvents + ->expects($this->once()) + ->method('attach') + ->with('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, $myCallback, -50); + $sharedEvents->expects($this->any())->method('getListeners')->will($this->returnValue([-50 => [$myCallback]])); + $events = $this->createEventManager($sharedEvents); + + $application = $this->createMock(ApplicationInterface::class); + $application->expects($this->any())->method('getEventManager')->will($this->returnValue($events)); + $event = $this->controller->getEvent(); + $event->setApplication($application); + + $this->plugin->setListenersToDetach([[ + 'id' => 'Zend\Stdlib\DispatchableInterface', + 'event' => MvcEvent::EVENT_DISPATCH, + 'class' => 'ZendTest\Mvc\Controller\Plugin\TestAsset\ListenerStub', + ]]); + + $result = $this->plugin->dispatch('forward'); + } + + public function testInvokableProblemListenersAreDetachedAndReattachedWhenPluginDispatchesRequestedController() + { + $services = $this->services; + $events = $services->get('EventManager'); + + $myCallback = new ListenerStub(); + $sharedEvents = $this->createMock(SharedEventManagerInterface::class); + $sharedEvents->expects($this->once())->method('detach')->with($myCallback, 'Zend\Stdlib\DispatchableInterface'); + $sharedEvents + ->expects($this->once()) + ->method('attach') + ->with('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, $myCallback, -50); + $sharedEvents->expects($this->any())->method('getListeners')->will($this->returnValue([-50 => [$myCallback]])); + $events = $this->createEventManager($sharedEvents); + + $application = $this->createMock(ApplicationInterface::class); + $application->expects($this->any())->method('getEventManager')->will($this->returnValue($events)); + $event = $this->controller->getEvent(); + $event->setApplication($application); + + $this->plugin->setListenersToDetach([[ + 'id' => 'Zend\Stdlib\DispatchableInterface', + 'event' => MvcEvent::EVENT_DISPATCH, + 'class' => 'ZendTest\Mvc\Controller\Plugin\TestAsset\ListenerStub', + ]]); + + $result = $this->plugin->dispatch('forward'); + } + public function testDispatchWillSeedRouteMatchWithPassedParameters() { $result = $this->plugin->dispatch('forward', [ diff --git a/test/Controller/Plugin/TestAsset/ListenerStub.php b/test/Controller/Plugin/TestAsset/ListenerStub.php new file mode 100644 index 000000000..689657d72 --- /dev/null +++ b/test/Controller/Plugin/TestAsset/ListenerStub.php @@ -0,0 +1,13 @@ +