Add EventDispatcher::removeListener to allow deregistration of listeners

main
Jordi Boggiano 5 years ago
parent 169fb2347a
commit 1b7e957cc1
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC

@ -46,7 +46,7 @@ class EventDispatcher
protected $io;
protected $loader;
protected $process;
protected $listeners;
protected $listeners = array();
private $eventStack;
/**
@ -172,6 +172,9 @@ class EventDispatcher
throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
}
if (is_array($callable) && (is_string($callable[0]) || is_object($callable[0])) && is_string($callable[1])) {
$this->io->writeError(sprintf('> %s: %s', $event->getName(), (is_object($callable[0]) ? get_class($callable[0]) : $callable[0]).'->'.$callable[1] ), true, IOInterface::VERBOSE);
}
$event = $this->checkListenerExpectedEvent($callable, $event);
$return = false === call_user_func($callable, $event) ? 1 : 0;
} elseif ($this->isComposerScript($callable)) {
@ -364,6 +367,22 @@ class EventDispatcher
$this->listeners[$eventName][$priority][] = $listener;
}
/**
* @param callable|object $listener A callable or an object instance for which all listeners should be removed
*/
public function removeListener($listener)
{
foreach ($this->listeners as $eventName => $priorities) {
foreach ($priorities as $priority => $listeners) {
foreach ($listeners as $index => $candidate) {
if ($listener === $candidate || (is_array($candidate) && is_object($listener) && $candidate[0] === $listener)) {
unset($this->listeners[$eventName][$priority][$index]);
}
}
}
}
}
/**
* Adds object methods as listeners for the events in getSubscribedEvents
*

@ -171,6 +171,49 @@ class EventDispatcherTest extends TestCase
return $rm;
}
public function testDispatcherRemoveListener()
{
$composer = $this->createComposerInstance();
$composer->setRepositoryManager($this->getRepositoryManagerMockForDevModePassingTest());
$composer->setInstallationManager($this->getMockBuilder('Composer\Installer\InstallationManager')->disableOriginalConstructor()->getMock());
$dispatcher = new EventDispatcher(
$composer,
$io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE),
$this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock()
);
$listener = array($this, 'someMethod');
$listener2 = array($this, 'someMethod2');
$listener3 = 'Composer\\Test\\EventDispatcher\\EventDispatcherTest::someMethod';
$dispatcher->addListener('ev1', $listener, 0);
$dispatcher->addListener('ev1', $listener, 1);
$dispatcher->addListener('ev1', $listener2, 1);
$dispatcher->addListener('ev1', $listener3);
$dispatcher->addListener('ev2', $listener3);
$dispatcher->addListener('ev2', $listener);
$dispatcher->dispatch('ev1');
$dispatcher->dispatch('ev2');
$expected = '> ev1: Composer\Test\EventDispatcher\EventDispatcherTest->someMethod'.PHP_EOL
.'> ev1: Composer\Test\EventDispatcher\EventDispatcherTest->someMethod2'.PHP_EOL
.'> ev1: Composer\Test\EventDispatcher\EventDispatcherTest->someMethod'.PHP_EOL
.'> ev1: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'.PHP_EOL
.'> ev2: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'.PHP_EOL
.'> ev2: Composer\Test\EventDispatcher\EventDispatcherTest->someMethod'.PHP_EOL;
$this->assertEquals($expected, $io->getOutput());
$dispatcher->removeListener($this);
$dispatcher->dispatch('ev1');
$dispatcher->dispatch('ev2');
$expected .= '> ev1: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'.PHP_EOL
.'> ev2: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'.PHP_EOL;
$this->assertEquals($expected, $io->getOutput());
}
public function testDispatcherCanExecuteCliAndPhpInSameEventScriptStack()
{
$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
@ -446,6 +489,11 @@ class EventDispatcherTest extends TestCase
return true;
}
public static function someMethod2()
{
return true;
}
private function createComposerInstance()
{
$composer = new Composer;

Loading…
Cancel
Save