diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index 57780d2e52..eacc4587dc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -294,27 +294,21 @@ class JsonDescriptor extends Descriptor { $data = array(); - $registeredListeners = $eventDispatcher->getListeners($event, true); + $registeredListeners = $eventDispatcher->getListeners($event); if (null !== $event) { - krsort($registeredListeners); - foreach ($registeredListeners as $priority => $listeners) { - foreach ($listeners as $listener) { - $listener = $this->getCallableData($listener); - $listener['priority'] = $priority; - $data[] = $listener; - } + foreach ($registeredListeners as $listener) { + $l = $this->getCallableData($listener); + $l['priority'] = $eventDispatcher->getListenerPriority($event, $listener); + $data[] = $l; } } else { ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { - krsort($eventListeners); - foreach ($eventListeners as $priority => $listeners) { - foreach ($listeners as $listener) { - $listener = $this->getCallableData($listener); - $listener['priority'] = $priority; - $data[$eventListened][] = $listener; - } + foreach ($eventListeners as $eventListener) { + $l = $this->getCallableData($eventListener); + $l['priority'] = $eventDispatcher->getListenerPriority($eventListened, $eventListener); + $data[$eventListened][] = $l; } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 8f5437146b..34ca282be8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -273,30 +273,23 @@ class MarkdownDescriptor extends Descriptor $this->write(sprintf('# %s', $title)."\n"); - $registeredListeners = $eventDispatcher->getListeners($event, true); + $registeredListeners = $eventDispatcher->getListeners($event); if (null !== $event) { - krsort($registeredListeners); - $order = 1; - foreach ($registeredListeners as $priority => $listeners) { - foreach ($listeners as $listener) { - $this->write("\n".sprintf('## Listener %d', $order++)."\n"); - $this->describeCallable($listener); - $this->write(sprintf('- Priority: `%d`', $priority)."\n"); - } + foreach ($registeredListeners as $order => $listener) { + $this->write("\n".sprintf('## Listener %d', $order + 1)."\n"); + $this->describeCallable($listener); + $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener))."\n"); } } else { ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { $this->write("\n".sprintf('## %s', $eventListened)."\n"); - krsort($eventListeners); - $order = 1; - foreach ($eventListeners as $priority => $listeners) { - foreach ($listeners as $listener) { - $this->write("\n".sprintf('### Listener %d', $order++)."\n"); - $this->describeCallable($listener); - $this->write(sprintf('- Priority: `%d`', $priority)."\n"); - } + + foreach ($eventListeners as $order => $eventListener) { + $this->write("\n".sprintf('### Listener %d', $order + 1)."\n"); + $this->describeCallable($eventListener); + $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener))."\n"); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 6a763688d2..c9186793af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -358,15 +358,14 @@ class TextDescriptor extends Descriptor $options['output']->title($title); - $registeredListeners = $eventDispatcher->getListeners($event, true); - + $registeredListeners = $eventDispatcher->getListeners($event); if (null !== $event) { - $this->renderEventListenerTable($registeredListeners, $options['output']); + $this->renderEventListenerTable($eventDispatcher, $event, $registeredListeners, $options['output']); } else { ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { $options['output']->section(sprintf('"%s" event', $eventListened)); - $this->renderEventListenerTable($eventListeners, $options['output']); + $this->renderEventListenerTable($eventDispatcher, $eventListened, $eventListeners, $options['output']); } } } @@ -382,17 +381,14 @@ class TextDescriptor extends Descriptor /** * @param array $array */ - private function renderEventListenerTable(array $eventListeners, SymfonyStyle $renderer) + private function renderEventListenerTable(EventDispatcherInterface $eventDispatcher, $event, array $eventListeners, SymfonyStyle $renderer) { $tableHeaders = array('Order', 'Callable', 'Priority'); $tableRows = array(); - krsort($eventListeners); $order = 1; - foreach ($eventListeners as $priority => $listeners) { - foreach ($listeners as $listener) { - $tableRows[] = array(sprintf('#%d', $order++), $this->formatCallable($listener), $priority); - } + foreach ($eventListeners as $order => $listener) { + $tableRows[] = array(sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)); } $renderer->table($tableHeaders, $tableRows); diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index cc83d6cd1f..7137eca2c4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -449,9 +449,9 @@ class XmlDescriptor extends Descriptor $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher')); - $registeredListeners = $eventDispatcher->getListeners($event, true); + $registeredListeners = $eventDispatcher->getListeners($event); if (null !== $event) { - $this->appendEventListenerDocument($eventDispatcherXML, $registeredListeners); + $this->appendEventListenerDocument($eventDispatcher, $event, $eventDispatcherXML, $registeredListeners); } else { ksort($registeredListeners); @@ -459,7 +459,7 @@ class XmlDescriptor extends Descriptor $eventDispatcherXML->appendChild($eventXML = $dom->createElement('event')); $eventXML->setAttribute('name', $eventListened); - $this->appendEventListenerDocument($eventXML, $eventListeners); + $this->appendEventListenerDocument($eventDispatcher, $eventListened, $eventXML, $eventListeners); } } @@ -470,16 +470,13 @@ class XmlDescriptor extends Descriptor * @param \DOMElement $element * @param array $eventListeners */ - private function appendEventListenerDocument(\DOMElement $element, array $eventListeners) + private function appendEventListenerDocument(EventDispatcherInterface $eventDispatcher, $event, \DOMElement $element, array $eventListeners) { - krsort($eventListeners); - foreach ($eventListeners as $priority => $listeners) { - foreach ($listeners as $listener) { - $callableXML = $this->getCallableDocument($listener); - $callableXML->childNodes->item(0)->setAttribute('priority', $priority); + foreach ($eventListeners as $listener) { + $callableXML = $this->getCallableDocument($listener); + $callableXML->childNodes->item(0)->setAttribute('priority', $eventDispatcher->getListenerPriority($event, $listener)); - $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), true)); - } + $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), true)); } } diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 256652dafa..c77efbe157 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": ">=5.3.9", + "symfony/event-dispatcher": "~2.8|~3.0.0", "symfony/security": "~2.8|~3.0.0", "symfony/security-acl": "~2.7|~3.0.0", "symfony/http-kernel": "~2.2|~3.0.0" diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index 11f2bc7d09..6a02e9f96f 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -118,7 +118,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher /** * {@inheritdoc} */ - public function getListeners($eventName = null, $withPriorities = false) + public function getListeners($eventName = null) { if (null === $eventName) { foreach ($this->listenerIds as $serviceEventName => $args) { @@ -128,7 +128,17 @@ class ContainerAwareEventDispatcher extends EventDispatcher $this->lazyLoad($eventName); } - return parent::getListeners($eventName, $withPriorities); + return parent::getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority($eventName, $listener) + { + $this->lazyLoad($eventName); + + return parent::getListenerPriority($eventName, $listener); } /** diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 5ff9ec72a0..35df8162b1 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -94,9 +94,17 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface /** * {@inheritdoc} */ - public function getListeners($eventName = null, $withPriorities = false) + public function getListeners($eventName = null) { - return $this->dispatcher->getListeners($eventName, $withPriorities); + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority($eventName, $listener) + { + return $this->dispatcher->getListenerPriority($eventName, $listener); } /** @@ -141,8 +149,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface $called = array(); foreach ($this->called as $eventName => $listeners) { foreach ($listeners as $listener) { - $priority = $this->getListenerPriority($eventName, $listener); - $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName, $priority); + $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); $called[$eventName.'.'.$info['pretty']] = $info; } } @@ -156,7 +163,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface public function getNotCalledListeners() { try { - $allListeners = $this->getListeners(null, true); + $allListeners = $this->getListeners(); } catch (\Exception $e) { if (null !== $this->logger) { $this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e)); @@ -167,24 +174,22 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface } $notCalled = array(); - foreach ($allListeners as $eventName => $priorities) { - foreach ($priorities as $priority => $listeners) { - foreach ($listeners as $listener) { - $called = false; - if (isset($this->called[$eventName])) { - foreach ($this->called[$eventName] as $l) { - if ($l->getWrappedListener() === $listener) { - $called = true; + 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) { + $called = true; - break; - } + break; } } + } - if (!$called) { - $info = $this->getListenerInfo($listener, $eventName, $priority); - $notCalled[$eventName.'.'.$info['pretty']] = $info; - } + if (!$called) { + $info = $this->getListenerInfo($listener, $eventName); + $notCalled[$eventName.'.'.$info['pretty']] = $info; } } } @@ -286,11 +291,11 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface * * @return array Information about the listener */ - private function getListenerInfo($listener, $eventName, $priority = null) + private function getListenerInfo($listener, $eventName) { $info = array( 'event' => $eventName, - 'priority' => $priority, + 'priority' => $this->getListenerPriority($eventName, $listener), ); if ($listener instanceof \Closure) { $info += array( @@ -339,28 +344,6 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface return $info; } - private function getListenerPriority($eventName, $listenerConfig) - { - try { - $allListeners = $this->getListeners(null, true); - } catch (\Exception $e) { - if (null !== $this->logger) { - $this->logger->info('An exception was thrown while getting the listeners.', array('exception' => $e)); - } - - return; - } - - $listenerWrapper = $listenerConfig->getWrappedListener(); - foreach ($allListeners[$eventName] as $priority => $listeners) { - foreach ($listeners as $listener) { - if (is_array($listenerWrapper) && $listenerWrapper[0] === $listener[0]) { - return $priority; - } - } - } - } - private function sortListenersByPriority($a, $b) { if (is_int($a['priority']) && !is_int($b['priority'])) { diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index a7c805eaf0..e40ce01183 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -52,16 +52,8 @@ class EventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function getListeners($eventName = null, $withPriorities = false) + public function getListeners($eventName = null) { - if (true === $withPriorities) { - if (null !== $eventName) { - return isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : array(); - } - - return array_filter($this->listeners); - } - if (null !== $eventName) { if (!isset($this->listeners[$eventName])) { return array(); @@ -83,6 +75,29 @@ class EventDispatcher implements EventDispatcherInterface return array_filter($this->sorted); } + /** + * Gets the listener priority for a specific event. + * + * Returns null if the event or the listener does not exist. + * + * @param string $eventName The name of the event + * @param callable $listener The listener to remove + * + * @return int|null The event listener priority + */ + public function getListenerPriority($eventName, $listener) + { + if (!isset($this->listeners[$eventName])) { + return; + } + + foreach ($this->listeners[$eventName] as $priority => $listeners) { + if (false !== ($key = array_search($listener, $listeners, true))) { + return $priority; + } + } + } + /** * {@inheritdoc} */ @@ -177,8 +192,6 @@ class EventDispatcher implements EventDispatcherInterface */ private function sortListeners($eventName) { - $this->sorted[$eventName] = array(); - krsort($this->listeners[$eventName]); $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } diff --git a/src/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php index f979304e9c..13e8572ed6 100644 --- a/src/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php @@ -78,9 +78,17 @@ class ImmutableEventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function getListeners($eventName = null, $withPriorities = false) + public function getListeners($eventName = null) { - return $this->dispatcher->getListeners($eventName, $withPriorities); + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority($eventName, $listener) + { + return $this->dispatcher->getListenerPriority($eventName, $listener); } /** diff --git a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php index 2e4c3fd97f..0169ede0b0 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php @@ -108,6 +108,20 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertSame($expected, $this->dispatcher->getListeners()); } + public function testGetListenerPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + + $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1)); + $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2)); + $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2)); + $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {})); + } + public function testDispatch() { $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php index cd72dd3c3b..1d4a8c8506 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -25,7 +25,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $listeners = $dispatcher->getListeners('foo'); $this->assertCount(1, $listeners); $this->assertSame($listener, $listeners[0]); @@ -39,7 +39,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo')); } @@ -51,7 +51,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertFalse($dispatcher->hasListeners('foo')); $this->assertFalse($tdispatcher->hasListeners('foo')); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $this->assertTrue($dispatcher->hasListeners('foo')); $this->assertTrue($tdispatcher->hasListeners('foo')); } @@ -76,7 +76,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $this->assertEquals(array(), $tdispatcher->getCalledListeners()); $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure', 'priority' => 0)), $tdispatcher->getNotCalledListeners()); @@ -107,8 +107,8 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); - $tdispatcher->addListener('foo', $listener1 = function () {; }); - $tdispatcher->addListener('foo', $listener2 = function () {; }); + $tdispatcher->addListener('foo', $listener1 = function () {}); + $tdispatcher->addListener('foo', $listener2 = function () {}); $logger->expects($this->at(0))->method('debug')->with('Notified event "foo" to listener "closure".'); $logger->expects($this->at(1))->method('debug')->with('Notified event "foo" to listener "closure".'); @@ -123,7 +123,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); }); - $tdispatcher->addListener('foo', $listener2 = function () {; }); + $tdispatcher->addListener('foo', $listener2 = function () {}); $logger->expects($this->at(0))->method('debug')->with('Notified event "foo" to listener "closure".'); $logger->expects($this->at(1))->method('debug')->with('Listener "closure" stopped propagation of the event "foo".');