From b91c76f2869e19dcd6985979ce81f7337f79af62 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 11 Nov 2013 07:43:49 -0600 Subject: [PATCH 1/5] [#5432] Test if callback is an array prior to accessing as array - Callbacks can be strings, objects (functors), or closures, too. - Allow testing against functor callbacks --- library/Zend/Mvc/Controller/Plugin/Forward.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Forward.php b/library/Zend/Mvc/Controller/Plugin/Forward.php index 4f48cf2c77a..b86e3353778 100644 --- a/library/Zend/Mvc/Controller/Plugin/Forward.php +++ b/library/Zend/Mvc/Controller/Plugin/Forward.php @@ -176,11 +176,22 @@ protected function detachProblemListeners(SharedEvents $sharedEvents) $events = $sharedEvents->getListeners($id, $eventName); foreach ($events as $currentEvent) { $currentCallback = $currentEvent->getCallback(); - if (!isset($currentCallback[0])) { + + // Testing against object callbacks + if (!is_object($currentCallback) + || !is_array($currentCallback) + || !isset($currentCallback[0]) + ) { continue; } + + // If we have an array, grab the object + if (is_array($currentCallback)) { + $currentCallback = $currentCallback[0]; + } + foreach ($classArray as $class) { - if (is_a($currentCallback[0], $class)) { + if (is_a($currentCallback, $class)) { $sharedEvents->detach($id, $currentEvent); $results[$id][$eventName][] = $currentEvent; } From e5fd6bf333a024ef0ee1fa629ef061ef906535e4 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 11 Nov 2013 08:07:16 -0600 Subject: [PATCH 2/5] [#5432] Added test - Finally determined a way to add a test for this. --- .../Mvc/Controller/Plugin/ForwardTest.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/ZendTest/Mvc/Controller/Plugin/ForwardTest.php b/tests/ZendTest/Mvc/Controller/Plugin/ForwardTest.php index 4debb6e9dcf..f87a662980f 100644 --- a/tests/ZendTest/Mvc/Controller/Plugin/ForwardTest.php +++ b/tests/ZendTest/Mvc/Controller/Plugin/ForwardTest.php @@ -19,6 +19,7 @@ use Zend\Mvc\Controller\Plugin\Forward as ForwardPlugin; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\RouteMatch; +use Zend\Stdlib\CallbackHandler; use ZendTest\Mvc\Controller\TestAsset\ForwardController; use ZendTest\Mvc\Controller\TestAsset\SampleController; use ZendTest\Mvc\Controller\TestAsset\UneventfulController; @@ -128,6 +129,29 @@ public function testPluginDispatchsRequestedControllerWhenFound() $this->assertEquals(array('content' => 'ZendTest\Mvc\Controller\TestAsset\ForwardController::testAction'), $result); } + /** + * @group 5432 + */ + public function testNonArrayListenerDoesNotRaiseErrorWhenPluginDispatchsRequestedController() + { + $services = $this->plugins->getServiceLocator(); + $events = $services->get('EventManager'); + $sharedEvents = $this->getMock('Zend\EventManager\SharedEventManagerInterface'); + $sharedEvents->expects($this->any())->method('getListeners')->will($this->returnValue(array( + new CallbackHandler(function ($e) {}) + ))); + $events = $this->getMock('Zend\EventManager\EventManagerInterface'); + $events->expects($this->any())->method('getSharedManager')->will($this->returnValue($sharedEvents)); + $application = $this->getMock('Zend\Mvc\ApplicationInterface'); + $application->expects($this->any())->method('getEventManager')->will($this->returnValue($events)); + $event = $this->controller->getEvent(); + $event->setApplication($application); + + $result = $this->plugin->dispatch('forward'); + $this->assertInternalType('array', $result); + $this->assertEquals(array('content' => 'ZendTest\Mvc\Controller\TestAsset\ForwardController::testAction'), $result); + } + public function testDispatchWillSeedRouteMatchWithPassedParameters() { $result = $this->plugin->dispatch('forward', array( From 9c5ba9b89cfbbf9fbdcba173639f82084fb05a2f Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 11 Nov 2013 08:07:34 -0600 Subject: [PATCH 3/5] [#5432] CS fixes - Trailing whitespace --- library/Zend/Mvc/Controller/Plugin/Forward.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Forward.php b/library/Zend/Mvc/Controller/Plugin/Forward.php index b86e3353778..6e005ead131 100644 --- a/library/Zend/Mvc/Controller/Plugin/Forward.php +++ b/library/Zend/Mvc/Controller/Plugin/Forward.php @@ -178,8 +178,8 @@ protected function detachProblemListeners(SharedEvents $sharedEvents) $currentCallback = $currentEvent->getCallback(); // Testing against object callbacks - if (!is_object($currentCallback) - || !is_array($currentCallback) + if (!is_object($currentCallback) + || !is_array($currentCallback) || !isset($currentCallback[0]) ) { continue; From 8bf43108e64fd9abedef04bbe14648afe2a8e989 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 12 Nov 2013 09:21:02 -0600 Subject: [PATCH 4/5] [#5432] Incorporate feedback - Simplify logic when introspecting callback --- library/Zend/Mvc/Controller/Plugin/Forward.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Forward.php b/library/Zend/Mvc/Controller/Plugin/Forward.php index 6e005ead131..c03bface974 100644 --- a/library/Zend/Mvc/Controller/Plugin/Forward.php +++ b/library/Zend/Mvc/Controller/Plugin/Forward.php @@ -177,19 +177,16 @@ protected function detachProblemListeners(SharedEvents $sharedEvents) foreach ($events as $currentEvent) { $currentCallback = $currentEvent->getCallback(); - // Testing against object callbacks - if (!is_object($currentCallback) - || !is_array($currentCallback) - || !isset($currentCallback[0]) - ) { - continue; - } - // If we have an array, grab the object if (is_array($currentCallback)) { $currentCallback = $currentCallback[0]; } + // This routine is only valid for object callbacks + if (!is_object($currentCallback)) { + continue; + } + foreach ($classArray as $class) { if (is_a($currentCallback, $class)) { $sharedEvents->detach($id, $currentEvent); From 2c20e80b57a81582927a35ac442bf4f59516a19f Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 12 Nov 2013 09:27:28 -0600 Subject: [PATCH 5/5] [#5432] Use array_shift instead of specific index access - per @Maks3w --- library/Zend/Mvc/Controller/Plugin/Forward.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Forward.php b/library/Zend/Mvc/Controller/Plugin/Forward.php index c03bface974..78dc1b6791b 100644 --- a/library/Zend/Mvc/Controller/Plugin/Forward.php +++ b/library/Zend/Mvc/Controller/Plugin/Forward.php @@ -179,7 +179,7 @@ protected function detachProblemListeners(SharedEvents $sharedEvents) // If we have an array, grab the object if (is_array($currentCallback)) { - $currentCallback = $currentCallback[0]; + $currentCallback = array_shift($currentCallback); } // This routine is only valid for object callbacks