Browse Source

[WebProfilerBundle] Event panel: details & links to the listener method when applicable

Victor Berchet 14 years ago
parent
commit
b5f3d14714

+ 29 - 18
src/Symfony/Bundle/FrameworkBundle/Debug/TraceableEventDispatcher.php

@@ -54,10 +54,7 @@ class TraceableEventDispatcher extends ContainerAwareEventDispatcher implements
             $this->logger->debug(sprintf('Notified event "%s" to listener "%s"', $eventName, $listenerString));
         }
 
-        $this->called[$eventName.'.'.$listenerString] = array(
-            'class' => $listenerString,
-            'event' => $eventName,
-        );
+        $this->called[$eventName.'.'.$listenerString] = $this->getListenerInfo($listener, $eventName);
 
         if ($event->isPropagationStopped() && null !== $this->logger) {
             $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s"', $this->listenerToString($listener), $eventName));
@@ -93,12 +90,9 @@ class TraceableEventDispatcher extends ContainerAwareEventDispatcher implements
         $notCalled = array();
         foreach (array_keys($this->getListeners()) as $name) {
             foreach ($this->getListeners($name) as $listener) {
-                $listener = $this->listenerToString($listener);
-                if (!isset($this->called[$name.'.'.$listener])) {
-                    $notCalled[$name.'.'.$listener] = array(
-                        'class' => $listener,
-                        'event' => $name,
-                    );
+                $listenerString = $this->listenerToString($listener);
+                if (!isset($this->called[$name.'.'.$listenerString])) {
+                    $notCalled[$name.'.'.$listenerString] = $this->getListenerInfo($listener, $name);
                 }
             }
         }
@@ -108,16 +102,33 @@ class TraceableEventDispatcher extends ContainerAwareEventDispatcher implements
 
     protected function listenerToString($listener)
     {
-        if (is_object($listener)) {
-            if ($listener instanceof \Closure) {
-                return 'Closure';
-            }
+        return $listener instanceof \Closure ? 'Closure' : get_class($listener);
+    }
 
-            return get_class($listener);
+    protected function getListenerInfo($listener, $eventName)
+    {
+        $info = array('event' => $eventName);
+        if ($listener instanceof \Closure) {
+            $info += array('type' => 'Closure');
+        } else {
+            $info += array(
+                'type'  => 'Method',
+                'class' => $class = get_class($listener)
+            );
+            try {
+                $r = new \ReflectionMethod($class, $eventName);
+                $info += array(
+                    'file'  => $r->getFileName(),
+                    'line'  => $r->getStartLine()
+                );
+            } catch (\ReflectionException $e) {
+                $info += array(
+                    'file'  => null,
+                    'line'  => null
+                );
+            }
         }
 
-        if (is_array($listener)) {
-            return is_object($listener[0]) ? get_class($listener[0]) : implode('::', $listener);
-        }
+        return $info;
     }
 }

+ 8 - 8
src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig

@@ -13,12 +13,12 @@
     <table>
         <tr>
             <th>Event name</th>
-            <th>Class</th>
+            <th>Listener</th>
         </tr>
-        {% for elements in collector.calledlisteners %}
+        {% for listener in collector.calledlisteners %}
             <tr>
-                <td><code>{{ elements.event }}</code></td>
-                <td><code>{{ elements.class|abbr_class }}</code></td>
+                <td><code>{{ listener.event }}</code></td>
+                <td><code>{% include 'WebProfilerBundle:Collector:listener.html.twig' with { 'listener': listener } only %}</code></td>
             </tr>
         {% endfor %}
     </table>
@@ -29,12 +29,12 @@
         <table>
             <tr>
                 <th>Event name</th>
-                <th>Class</th>
+                <th>Listener</th>
             </tr>
-            {% for elements in collector.notcalledlisteners %}
+            {% for listener in collector.notcalledlisteners %}
                 <tr>
-                    <td><code>{{ elements.event }}</code></td>
-                    <td><code>{{ elements.class|abbr_class }}</code></td>
+                    <td><code>{{ listener.event }}</code></td>
+                    <td><code>{% include 'WebProfilerBundle:Collector:listener.html.twig' with { 'listener': listener } only %}</code></td>
                 </tr>
             {% endfor %}
         </table>

+ 6 - 0
src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/listener.html.twig

@@ -0,0 +1,6 @@
+{% if listener.type == "Closure" %}
+    Closure
+{% else %}
+    {% set link = listener.file|file_link(listener.line) %}
+    {{ listener.class|abbr_class }}::{% if link %}<a href="{{ link }}">{{ listener.event }}</a>{% else %}{{ listener.event }}{% endif %}
+{% endif %}