diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 8d5ee9fa1..22a5f7133 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -155,6 +155,7 @@ class EventDispatcher $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 @@ class EventDispatcher */ 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 69e1de290..c90c948ee 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -17,6 +17,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallerEvents; use Composer\TestCase; use Composer\Script\ScriptEvents; +use Composer\Script\CommandEvent; use Composer\Util\ProcessExecutor; class EventDispatcherTest extends TestCase @@ -38,6 +39,16 @@ class EventDispatcherTest extends TestCase $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 @@ class EventDispatcherTest extends TestCase throw new \RuntimeException(); } + public static function convertEvent(CommandEvent $event) + { + return false; + } + public static function someMethod() { return true;