Add EventDispatcher::removeListener to allow deregistration of listeners
parent
169fb2347a
commit
1b7e957cc1
|
@ -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…
Reference in New Issue