diff --git a/UPGRADE-4.1.md b/UPGRADE-4.1.md index 2b23d370cf95e..a38288cd12f88 100644 --- a/UPGRADE-4.1.md +++ b/UPGRADE-4.1.md @@ -1,6 +1,11 @@ UPGRADE FROM 4.0 to 4.1 ======================= +EventDispatcher +--------------- + + * The `TraceableEventDispatcherInterface` has been deprecated and will be removed in 5.0. + HttpFoundation -------------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index 4fdb14222921a..705b3d80114c6 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -1,6 +1,11 @@ UPGRADE FROM 4.x to 5.0 ======================= +EventDispatcher +--------------- + + * The `TraceableEventDispatcherInterface` has been removed. + HttpFoundation -------------- diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index e87949cbd3da8..182a804583313 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.1.0 +----- + + * added information about orphaned events + 4.0.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig index 238096157acc3..d36bad9cda44b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig @@ -45,6 +45,26 @@ {% endif %} + +
+

Orphaned events {{ collector.orphanedEvents|length }}

+
+ {% if collector.orphanedEvents is empty %} +
+

+ There are no orphaned events. +

+

+ All dispatched events were handled or an error occurred + when trying to collect orphaned events (in which case check the + logs to get more information). +

+
+ {% else %} + {{ helper.render_table(collector.orphanedEvents) }} + {% endif %} +
+
{% endif %} {% endblock %} diff --git a/src/Symfony/Component/EventDispatcher/CHANGELOG.md b/src/Symfony/Component/EventDispatcher/CHANGELOG.md index e570303e742cc..7a87a8d7e6ab2 100644 --- a/src/Symfony/Component/EventDispatcher/CHANGELOG.md +++ b/src/Symfony/Component/EventDispatcher/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +4.1.0 +----- + + * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. + * The `TraceableEventDispatcherInterface` has been deprecated and will be removed in 5.0. + 4.0.0 ----- diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 9b5c689ad7137..7860e3b6d950b 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -32,6 +32,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface private $called; private $dispatcher; private $wrappedListeners; + private $orphanedEvents; public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) { @@ -40,6 +41,7 @@ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $sto $this->logger = $logger; $this->called = array(); $this->wrappedListeners = array(); + $this->orphanedEvents = array(); } /** @@ -207,6 +209,16 @@ public function getNotCalledListeners() return $notCalled; } + /** + * Gets the orphaned events. + * + * @return array An array of orphaned events + */ + public function getOrphanedEvents() + { + return $this->orphanedEvents; + } + public function reset() { $this->called = array(); @@ -247,6 +259,12 @@ protected function postDispatch($eventName, Event $event) private function preProcess($eventName) { + if (!$this->dispatcher->hasListeners($eventName)) { + $this->orphanedEvents[] = $eventName; + + return; + } + foreach ($this->dispatcher->getListeners($eventName) as $listener) { $priority = $this->getListenerPriority($eventName, $listener); $wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this); diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php index 4adbe9693a787..c76918d0cdb7c 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php @@ -14,6 +14,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** + * @deprecated since version 4.1, will be removed in 5.0. + * * @author Fabien Potencier */ interface TraceableEventDispatcherInterface extends EventDispatcherInterface diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php index 53a3421afaf6a..eac8c63eebdaf 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -153,6 +153,40 @@ public function testGetCalledListenersNested() $this->assertCount(2, $dispatcher->getCalledListeners()); } + public function testItReturnsNoOrphanedEventsWhenCreated() + { + // GIVEN + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + // WHEN + $events = $tdispatcher->getOrphanedEvents(); + // THEN + $this->assertEmpty($events); + } + + public function testItReturnsOrphanedEventsAfterDispatch() + { + // GIVEN + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->dispatch('foo'); + // WHEN + $events = $tdispatcher->getOrphanedEvents(); + // THEN + $this->assertCount(1, $events); + $this->assertEquals(array('foo'), $events); + } + + public function testItDoesNotReturnHandledEvents() + { + // GIVEN + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function () {}); + $tdispatcher->dispatch('foo'); + // WHEN + $events = $tdispatcher->getOrphanedEvents(); + // THEN + $this->assertEmpty($events); + } + public function testLogger() { $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index a8ec514ecc920..e22c724085cb4 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.1.0 ----- + * added orphaned events support to `EventDataCollector` * `ExceptionListener` now logs and collects exceptions at priority `2048` (previously logged at `-128` and collected at `0`) 4.0.0 diff --git a/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php index e82a1fc19bb09..f9d5bed130cbd 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php @@ -11,10 +11,11 @@ namespace Symfony\Component\HttpKernel\DataCollector; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; /** * EventDataCollector. @@ -38,6 +39,7 @@ public function collect(Request $request, Response $response, \Exception $except $this->data = array( 'called_listeners' => array(), 'not_called_listeners' => array(), + 'orphaned_events' => array(), ); } @@ -56,6 +58,11 @@ public function lateCollect() $this->setCalledListeners($this->dispatcher->getCalledListeners()); $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners()); } + + if ($this->dispatcher instanceof TraceableEventDispatcher) { + $this->setOrphanedEvents($this->dispatcher->getOrphanedEvents()); + } + $this->data = $this->cloneVar($this->data); } @@ -64,7 +71,7 @@ public function lateCollect() * * @param array $listeners An array of called listeners * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function setCalledListeners(array $listeners) { @@ -76,7 +83,7 @@ public function setCalledListeners(array $listeners) * * @return array An array of called listeners * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function getCalledListeners() { @@ -86,9 +93,9 @@ public function getCalledListeners() /** * Sets the not called listeners. * - * @param array $listeners An array of not called listeners + * @param array $listeners * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function setNotCalledListeners(array $listeners) { @@ -98,15 +105,39 @@ public function setNotCalledListeners(array $listeners) /** * Gets the not called listeners. * - * @return array An array of not called listeners + * @return array * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function getNotCalledListeners() { return $this->data['not_called_listeners']; } + /** + * Sets the orphaned events. + * + * @param array $events An array of orphaned events + * + * @see TraceableEventDispatcher + */ + public function setOrphanedEvents(array $events) + { + $this->data['orphaned_events'] = $events; + } + + /** + * Gets the orphaned events. + * + * @return array An array of orphaned events + * + * @see TraceableEventDispatcher + */ + public function getOrphanedEvents() + { + return $this->data['orphaned_events']; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php index ca2e6a693da6e..d5456fe5dcadc 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php @@ -11,10 +11,9 @@ namespace Symfony\Component\HttpKernel\Tests\Fixtures; -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; -class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface +class TestEventDispatcher extends TraceableEventDispatcher { public function getCalledListeners() { @@ -29,4 +28,9 @@ public function getNotCalledListeners() public function reset() { } + + public function getOrphanedEvents() + { + return array(); + } }