[EventDispatcher] Revers event tracing order

This commit is contained in:
Roland Franssen 2018-12-01 18:19:47 +01:00
parent 68b823f243
commit 2570d6f877
2 changed files with 36 additions and 24 deletions

View File

@ -29,7 +29,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
protected $logger;
protected $stopwatch;
private $called;
private $callStack;
private $dispatcher;
private $wrappedListeners;
@ -38,7 +38,6 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
$this->dispatcher = $dispatcher;
$this->stopwatch = $stopwatch;
$this->logger = $logger;
$this->called = array();
$this->wrappedListeners = array();
}
@ -123,6 +122,10 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
*/
public function dispatch($eventName, Event $event = null)
{
if (null === $this->callStack) {
$this->callStack = new \SplObjectStorage();
}
if (null === $event) {
$event = new Event();
}
@ -158,11 +161,15 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
*/
public function getCalledListeners()
{
if (null === $this->callStack) {
return array();
}
$called = array();
foreach ($this->called as $eventName => $listeners) {
foreach ($listeners as $listener) {
$called[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName);
}
foreach ($this->callStack as $listener) {
list($eventName) = $this->callStack->getInfo();
$called[] = $listener->getInfo($eventName);
}
return $called;
@ -188,9 +195,9 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
foreach ($allListeners as $eventName => $listeners) {
foreach ($listeners as $listener) {
$called = false;
if (isset($this->called[$eventName])) {
foreach ($this->called[$eventName] as $l) {
if ($l->getWrappedListener() === $listener) {
if (null !== $this->callStack) {
foreach ($this->callStack as $calledListener) {
if ($calledListener->getWrappedListener() === $listener) {
$called = true;
break;
@ -202,19 +209,19 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
if (!$listener instanceof WrappedListener) {
$listener = new WrappedListener($listener, null, $this->stopwatch, $this);
}
$notCalled[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName);
$notCalled[] = $listener->getInfo($eventName);
}
}
}
uasort($notCalled, array($this, 'sortListenersByPriority'));
uasort($notCalled, array($this, 'sortNotCalledListeners'));
return $notCalled;
}
public function reset()
{
$this->called = array();
$this->callStack = array();
}
/**
@ -258,6 +265,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
$this->wrappedListeners[$eventName][] = $wrappedListener;
$this->dispatcher->removeListener($eventName, $listener);
$this->dispatcher->addListener($eventName, $wrappedListener, $priority);
$this->callStack->attach($wrappedListener, array($eventName));
}
}
@ -286,8 +294,8 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
if (!isset($this->called[$eventName])) {
$this->called[$eventName] = new \SplObjectStorage();
}
$this->called[$eventName]->attach($listener);
} else {
$this->callStack->detach($listener);
}
if (null !== $this->logger && $skipped) {
@ -304,8 +312,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
}
}
private function sortListenersByPriority($a, $b)
private function sortNotCalledListeners(array $a, array $b)
{
if (0 !== $cmp = strcmp($a['event'], $b['event'])) {
return $cmp;
}
if (\is_int($a['priority']) && !\is_int($b['priority'])) {
return 1;
}

View File

@ -110,17 +110,17 @@ class TraceableEventDispatcherTest extends TestCase
$tdispatcher->addListener('foo', function () {}, 5);
$listeners = $tdispatcher->getNotCalledListeners();
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
unset($listeners['foo.closure']['stub']);
$this->assertArrayHasKey('stub', $listeners[0]);
unset($listeners[0]['stub']);
$this->assertEquals(array(), $tdispatcher->getCalledListeners());
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
$this->assertEquals(array(array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
$tdispatcher->dispatch('foo');
$listeners = $tdispatcher->getCalledListeners();
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
unset($listeners['foo.closure']['stub']);
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
$this->assertArrayHasKey('stub', $listeners[0]);
unset($listeners[0]['stub']);
$this->assertEquals(array(array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
}
@ -133,10 +133,10 @@ class TraceableEventDispatcherTest extends TestCase
$tdispatcher->reset();
$listeners = $tdispatcher->getNotCalledListeners();
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
unset($listeners['foo.closure']['stub']);
$this->assertArrayHasKey('stub', $listeners[0]);
unset($listeners[0]['stub']);
$this->assertEquals(array(), $tdispatcher->getCalledListeners());
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
$this->assertEquals(array(array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
}
public function testGetCalledListenersNested()