diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 8d5ee9fa14df..22a5f71334ae 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -155,6 +155,7 @@ protected function doDispatch(Event $event) $return = 0; foreach ($listeners as $callable) { if (!is_string($callable) && is_callable($callable)) { + $event = $this->checkListenerExpectedEvent($callable, $event); $return = false === call_user_func($callable, $event) ? 1 : 0; } elseif ($this->isPhpScript($callable)) { $className = substr($callable, 0, strpos($callable, '::')); @@ -200,9 +201,37 @@ protected function doDispatch(Event $event) */ protected function executeEventPhpScript($className, $methodName, Event $event) { + $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event); + return $className::$methodName($event); } + /** + * @param mixed $target + * @param Event $event + * @return Event|CommandEvent + */ + protected function checkListenerExpectedEvent($target, Event $event) + { + if (!$event instanceof Script\Event) { + return $event; + } + + try { + $reflected = new \ReflectionParameter($target, 0); + } catch (\ReflectionException $e) { + return $event; + } + + $expected = $reflected->getClass()->name; + + if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') { + $event = new CommandEvent($event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()); + } + + return $event; + } + /** * Add a listener for a particular event * diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 69e1de290918..f42d4852303f 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -17,6 +17,7 @@ use Composer\Installer\InstallerEvents; use Composer\TestCase; use Composer\Script\ScriptEvents; +use Composer\Script; use Composer\Util\ProcessExecutor; class EventDispatcherTest extends TestCase @@ -38,6 +39,16 @@ public function testListenerExceptionsAreCaught() $dispatcher->dispatchCommandEvent(ScriptEvents::POST_INSTALL_CMD, false); } + public function testDispatcherCanConvertScriptEventToCommandEventForListener() + { + $io = $this->getMock('Composer\IO\IOInterface'); + $dispatcher = $this->getDispatcherStubForListenersTest(array( + "Composer\Test\EventDispatcher\EventDispatcherTest::convertEvent" + ), $io); + + $this->assertEquals(1, $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false)); + } + /** * @dataProvider getValidCommands * @param string $command @@ -205,6 +216,11 @@ public static function call() throw new \RuntimeException(); } + public static function convertEvent(Script\CommandEvent $event) + { + return false; + } + public static function someMethod() { return true;