Эх сурвалжийг харах

Merge pull request #3544 from alcohol/match-event-to-listener-expectation

fix for composer/composer#3382
Jordi Boggiano 10 жил өмнө
parent
commit
76c666e210

+ 29 - 0
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
      *

+ 16 - 0
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;