Bläddra i källkod

[Framework] added a way to retrieve called and not-called events for a given dispatcher

Fabien Potencier 15 år sedan
förälder
incheckning
eeb0742826

+ 48 - 15
src/Symfony/Framework/Debug/EventDispatcher.php

@@ -6,7 +6,6 @@ use Symfony\Framework\EventDispatcher as BaseEventDispatcher;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\EventDispatcher\Event;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /*
  * This file is part of the Symfony package.
@@ -22,20 +21,20 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  *
  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
  */
-class EventDispatcher extends BaseEventDispatcher
+class EventDispatcher extends BaseEventDispatcher implements EventDispatcherTraceableInterface
 {
     protected $logger;
+    protected $called;
 
     /**
      * Constructor.
      *
      * @param LoggerInterface $logger A LoggerInterface instance
      */
-    public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
+    public function __construct(LoggerInterface $logger = null)
     {
         $this->logger = $logger;
-
-        parent::__construct($container);
+        $this->called = array();
     }
 
     /**
@@ -48,9 +47,7 @@ class EventDispatcher extends BaseEventDispatcher
     public function notify(Event $event)
     {
         foreach ($this->getListeners($event->getName()) as $listener) {
-            if (null !== $this->logger) {
-                $this->logger->debug(sprintf('Notifying event "%s" to listener "%s"', $event->getName(), $this->listenerToString($listener)));
-            }
+            $this->addCall($event, $listener, 'notify');
 
             call_user_func($listener, $event);
         }
@@ -68,9 +65,7 @@ class EventDispatcher extends BaseEventDispatcher
     public function notifyUntil(Event $event)
     {
         foreach ($this->getListeners($event->getName()) as $i => $listener) {
-            if (null !== $this->logger) {
-                $this->logger->debug(sprintf('Notifying (until) event "%s" to listener "%s"', $event->getName(), $this->listenerToString($listener)));
-            }
+            $this->addCall($event, $listener, 'notifyUntil');
 
             if (call_user_func($listener, $event)) {
                 if (null !== $this->logger) {
@@ -101,9 +96,7 @@ class EventDispatcher extends BaseEventDispatcher
     public function filter(Event $event, $value)
     {
         foreach ($this->getListeners($event->getName()) as $listener) {
-            if (null !== $this->logger) {
-                $this->logger->debug(sprintf('Notifying (filter) event "%s" to listener "%s"', $event->getName(), $this->listenerToString($listener)));
-            }
+            $this->addCall($event, $listener, 'filter');
 
             $value = call_user_func($listener, $event, $value);
         }
@@ -113,6 +106,31 @@ class EventDispatcher extends BaseEventDispatcher
         return $event;
     }
 
+    public function getCalledEvents()
+    {
+        return $this->called;
+    }
+
+    public function getNotCalledEvents()
+    {
+        $notCalled = array();
+
+        foreach (array_keys($this->listeners) as $name) {
+            foreach ($this->getListeners($name) as $listener) {
+                $listener = $this->listenerToString($listener);
+
+                if (!isset($this->called[$name.'.'.$listener])) {
+                    $notCalled[] = array(
+                        'event'    => $name,
+                        'listener' => $listener,
+                    );
+                }
+            }
+        }
+
+        return $notCalled;
+    }
+
     protected function listenerToString($listener)
     {
         if (is_object($listener) && $listener instanceof \Closure) {
@@ -124,7 +142,22 @@ class EventDispatcher extends BaseEventDispatcher
         }
 
         if (is_array($listener)) {
-            return sprintf('(%s, %s)', is_object($listener[0]) ? get_class($listener[0]) : $listener[0], $listener[1]);
+            return sprintf('%s::%s', is_object($listener[0]) ? get_class($listener[0]) : $listener[0], $listener[1]);
         }
     }
+
+    protected function addCall(Event $event, $listener, $type)
+    {
+        $listener = $this->listenerToString($listener);
+
+        if (null !== $this->logger) {
+            $this->logger->debug(sprintf('Notified event "%s" to listener "%s" (%s)', $event->getName(), $listener, $type));
+        }
+
+        $this->called[$event->getName().'.'.$listener] = array(
+            'event'    => $event->getName(),
+            'caller'   => null !== $event->getSubject() ? get_class($event->getSubject()) : null,
+            'listener' => $listener,
+        );
+    }
 }

+ 22 - 0
src/Symfony/Framework/Debug/EventDispatcherTraceableInterface.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace Symfony\Framework\Debug;
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+interface EventDispatcherTraceableInterface
+{
+    function getCalledEvents();
+
+    function getNotCalledEvents();
+}

+ 1 - 5
src/Symfony/Framework/EventDispatcher.php

@@ -22,11 +22,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  */
 class EventDispatcher extends BaseEventDispatcher
 {
-    /**
-     * Constructor.
-     *
-     */
-    public function __construct(ContainerInterface $container)
+    public function setContainer(ContainerInterface $container)
     {
         foreach ($container->findTaggedServiceIds('kernel.listener') as $id => $attributes) {
             $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;

+ 3 - 1
src/Symfony/Framework/Resources/config/debug.xml

@@ -10,8 +10,10 @@
 
     <services>
         <service id="debug.event_dispatcher" class="%debug.event_dispatcher.class%">
-            <argument type="service" id="service_container" />
             <argument type="service" id="logger" on-invalid="null" />
+            <call method="setContainer">
+                <argument type="service" id="service_container" />
+            </call>
         </service>
     </services>
 </container>

+ 3 - 1
src/Symfony/Framework/Resources/config/services.xml

@@ -15,7 +15,9 @@
 
     <services>
         <service id="event_dispatcher" class="%event_dispatcher.class%">
-            <argument type="service" id="service_container" />
+            <call method="setContainer">
+                <argument type="service" id="service_container" />
+            </call>
         </service>
 
         <service id="error_handler" class="%error_handler.class%">