Explorar el Código

made all event listeners lazy loaded

 * The register() method on all listeners has been removed
 * Instead, the information is now put directly in the DIC tag

For instance, a listener on core.request had this method:

   public function register(EventDispatcher $dispatcher, $priority = 0)
   {
       $dispatcher->connect('core.response', array($this, 'filter'), $priority);
   }

And this tag in the DIC configuration:

  <tag name="kernel.listener" />

Now, it only has the following configuration:

  <tag name="kernel.listener" event="core.response" method="filter" priority="0" />

The event and method attributes are now mandatory.
Fabien Potencier hace 14 años
padre
commit
1c11d81611
Se han modificado 23 ficheros con 106 adiciones y 142 borrados
  1. 2 9
      src/Symfony/Bundle/FrameworkBundle/Controller/ParamConverterListener.php
  2. 6 2
      src/Symfony/Bundle/FrameworkBundle/Debug/EventDispatcher.php
  3. 19 8
      src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php
  4. 35 4
      src/Symfony/Bundle/FrameworkBundle/EventDispatcher.php
  5. 2 11
      src/Symfony/Bundle/FrameworkBundle/RequestListener.php
  6. 1 0
      src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml
  7. 2 2
      src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml
  8. 2 2
      src/Symfony/Bundle/FrameworkBundle/Resources/config/param_converter.xml
  9. 3 2
      src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml
  10. 5 3
      src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml
  11. 1 0
      src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
  12. 6 6
      src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
  13. 2 2
      src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml
  14. 2 11
      src/Symfony/Bundle/WebProfilerBundle/WebDebugToolbarListener.php
  15. 3 15
      src/Symfony/Component/HttpKernel/Cache/EsiListener.php
  16. 2 11
      src/Symfony/Component/HttpKernel/Debug/ExceptionListener.php
  17. 3 12
      src/Symfony/Component/HttpKernel/Profiler/ProfilerListener.php
  18. 0 1
      src/Symfony/Component/HttpKernel/Resources/bin/packager.php
  19. 2 11
      src/Symfony/Component/HttpKernel/ResponseListener.php
  20. 4 13
      src/Symfony/Component/HttpKernel/Security/Firewall.php
  21. 0 4
      src/Symfony/Component/HttpKernel/bootstrap.php
  22. 3 12
      tests/Symfony/Tests/Component/HttpKernel/Cache/EsiListenerTest.php
  23. 1 1
      tests/Symfony/Tests/Component/HttpKernel/ResponseListenerTest.php

+ 2 - 9
src/Symfony/Bundle/FrameworkBundle/Controller/ParamConverterListener.php

@@ -23,6 +23,8 @@ use Symfony\Component\EventDispatcher\Event;
  * Converts \ReflectionParameters for Controller actions into Objects if the \ReflectionParameter have a class
  * (Typehinted).
  *
+ * The filterController method must be connected to the core.controller event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.org>
  * @author Henrik Bjornskov <hb@peytz.dk>
  */
@@ -41,15 +43,6 @@ class ParamConverterListener
         $this->manager = $manager;
     }
 
-    /**
-     * @param EventDispatcher $dispatcher
-     * @param integer         $priority = 0
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.controller', array($this, 'filterController'), $priority);
-    }
-
     /**
      * @param  Event $event
      * @param  mixed $controller

+ 6 - 2
src/Symfony/Bundle/FrameworkBundle/Debug/EventDispatcher.php

@@ -16,6 +16,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\EventDispatcher\Event;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\HttpKernel\Debug\EventDispatcherTraceableInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * EventDispatcher extends the original EventDispatcher class to add some debugging tools.
@@ -30,10 +31,13 @@ class EventDispatcher extends BaseEventDispatcher implements EventDispatcherTrac
     /**
      * Constructor.
      *
-     * @param LoggerInterface $logger A LoggerInterface instance
+     * @param ContainerInterface $container A ContainerInterface instance
+     * @param LoggerInterface    $logger    A LoggerInterface instance
      */
-    public function __construct(LoggerInterface $logger = null)
+    public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
     {
+        parent::__construct($container);
+
         $this->logger = $logger;
         $this->called = array();
     }

+ 19 - 8
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php

@@ -24,14 +24,25 @@ class RegisterKernelListenersPass implements CompilerPassInterface
         }
 
         $listeners = array();
-        foreach ($container->findTaggedServiceIds('kernel.listener') as $id => $attributes) {
-            $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
-
-            if (!isset($listeners[$priority])) {
-                $listeners[$priority] = array();
+        foreach ($container->findTaggedServiceIds('kernel.listener') as $id => $events) {
+            foreach ($events as $event) {
+                $priority = isset($event['priority']) ? $event['priority'] : 0;
+                if (!isset($event['event'])) {
+                    throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "kernel.listener" tags.', $id));
+                }
+                if (!isset($event['method'])) {
+                    throw new \InvalidArgumentException(sprintf('Service "%s" must define the "method" attribute on "kernel.listener" tags.', $id));
+                }
+
+                if (!isset($listeners[$event['event']][$priority])) {
+                    if (!isset($listeners[$event['event']])) {
+                        $listeners[$event['event']] = array();
+                    }
+                    $listeners[$event['event']][$priority] = array();
+                }
+
+                $listeners[$event['event']][$priority][$id] = $event['method'];
             }
-
-            $listeners[$priority][] = new Reference($id);
         }
 
         $container
@@ -39,4 +50,4 @@ class RegisterKernelListenersPass implements CompilerPassInterface
             ->addMethodCall('registerKernelListeners', array($listeners))
         ;
     }
-}
+}

+ 35 - 4
src/Symfony/Bundle/FrameworkBundle/EventDispatcher.php

@@ -12,6 +12,7 @@
 namespace Symfony\Bundle\FrameworkBundle;
 
 use Symfony\Component\EventDispatcher\EventDispatcher as BaseEventDispatcher;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * This EventDispatcher automatically gets the kernel listeners injected
@@ -20,12 +21,42 @@ use Symfony\Component\EventDispatcher\EventDispatcher as BaseEventDispatcher;
  */
 class EventDispatcher extends BaseEventDispatcher
 {
-    public function registerKernelListeners(array $kernelListeners)
+    protected $container;
+    protected $ids;
+
+    /**
+     * Constructor.
+     *
+     * @param ContainerInterface $container A ContainerInterface instance
+     */
+    public function __construct(ContainerInterface $container)
+    {
+        $this->container = $container;
+    }
+
+    public function registerKernelListeners(array $ids)
+    {
+        $this->ids = $ids;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getListeners($name)
     {
-        foreach ($kernelListeners as $priority => $listeners) {
-            foreach ($listeners as $listener) {
-                $listener->register($this, $priority);
+        if (!isset($this->ids[$name])) {
+            return array();
+        }
+
+        $listeners = array();
+        $all = $this->ids[$name];
+        krsort($all);
+        foreach ($all as $l) {
+            foreach ($l as $id => $method) {
+                $listeners[] = array($this->container->get($id), $method);
             }
         }
+
+        return $listeners;
     }
 }

+ 2 - 11
src/Symfony/Bundle/FrameworkBundle/RequestListener.php

@@ -21,6 +21,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 /**
  * RequestListener.
  *
+ * The handle method must be connected to the core.request event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class RequestListener
@@ -36,17 +38,6 @@ class RequestListener
         $this->logger = $logger;
     }
 
-    /**
-     * Registers a core.request listener.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.request', array($this, 'handle'), $priority);
-    }
-
     public function handle(Event $event)
     {
         $request = $event->get('request');

+ 1 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml

@@ -10,6 +10,7 @@
 
     <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" />
         </service>
     </services>

+ 2 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml

@@ -12,8 +12,8 @@
     <services>
         <service id="esi" class="%esi.class%" public="false" />
 
-        <service id="esi_listener" class="%esi_listener.class%" public="false">
-          <tag name="kernel.listener" />
+        <service id="esi_listener" class="%esi_listener.class%">
+          <tag name="kernel.listener" event="core.response" method="filter" />
           <argument type="service" id="esi" on-invalid="ignore" />
         </service>
     </services>

+ 2 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/config/param_converter.xml

@@ -14,8 +14,8 @@
         <service id="request.param_converter.manager" class="%request.param_converter.manager.class%" public="false" />
 
         <!-- ParamConverterListener -->
-        <service id="request.param_converter.listener" class="%request.param_converter.listener.class%" public="false">
-            <tag name="kernel.listener" />
+        <service id="request.param_converter.listener" class="%request.param_converter.listener.class%">
+            <tag name="kernel.listener" event="core.controller" method="filterController" />
             <argument type="service" id="request.param_converter.manager" />
         </service>
     </services>

+ 3 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml

@@ -24,8 +24,9 @@
             <argument>%profiler.storage.lifetime%</argument>
         </service>
 
-        <service id="profiler_listener" class="%profiler_listener.class%" public="false">
-            <tag name="kernel.listener" />
+        <service id="profiler_listener" class="%profiler_listener.class%">
+            <tag name="kernel.listener" event="core.response" method="handleResponse" />
+            <tag name="kernel.listener" event="core.exception" method="handleException" />
             <argument type="service" id="profiler" />
             <argument type="service" id="profiler.request_matcher" on-invalid="null" />
             <argument>%profiler_listener.only_exceptions%</argument>

+ 5 - 3
src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml

@@ -154,15 +154,17 @@
             <argument type="service" id="security.role_hierarchy" />
         </service>
 
-        <service id="security.firewall" class="%security.firewall.class%" public="false">
-            <tag name="kernel.listener" priority="-128" />
+        <service id="security.firewall" class="%security.firewall.class%">
+            <tag name="kernel.listener" event="core.request" method="handle" priority="-128" />
             <argument type="service" id="security.firewall.map" />
+            <argument type="service" id="event_dispatcher" />
         </service>
+
         <service id="security.firewall.map" class="%security.firewall.map.class%" public="false">
             <argument type="service" id="service_container" />
             <argument type="collection" />
         </service>
-        
+
         <service id="security.context_listener" class="%security.context_listener.class%" public="false">
             <argument type="service" id="security.context" />
             <argument type="collection"></argument>

+ 1 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml

@@ -15,6 +15,7 @@
 
     <services>
         <service id="event_dispatcher" class="%event_dispatcher.class%">
+            <argument type="service" id="service_container" />
         </service>
 
         <service id="error_handler" class="%error_handler.class%" public="false">

+ 6 - 6
src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml

@@ -25,19 +25,19 @@
             <argument type="service" id="logger" on-invalid="ignore" />
         </service>
 
-        <service id="request_listener" class="%request_listener.class%" public="false">
-            <tag name="kernel.listener" />
+        <service id="request_listener" class="%request_listener.class%">
+            <tag name="kernel.listener" event="core.request" method="handle" />
             <argument type="service" id="service_container" />
             <argument type="service" id="router" />
             <argument type="service" id="logger" on-invalid="ignore" />
         </service>
 
-        <service id="response_listener" class="%response_listener.class%" public="false">
-            <tag name="kernel.listener" />
+        <service id="response_listener" class="%response_listener.class%">
+            <tag name="kernel.listener" event="core.response" method="filter" />
         </service>
 
-        <service id="exception_listener" class="%exception_listener.class%" public="false">
-            <tag name="kernel.listener" priority="-128" />
+        <service id="exception_listener" class="%exception_listener.class%">
+            <tag name="kernel.listener" event="core.exception" method="handle" priority="-128" />
             <argument>%exception_listener.controller%</argument>
             <argument type="service" id="logger" on-invalid="null" />
         </service>

+ 2 - 2
src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml

@@ -10,8 +10,8 @@
     </parameters>
 
     <services>
-        <service id="debug.toolbar" class="%debug.toolbar.class%" public="false">
-            <tag name="kernel.listener" priority="-128" />
+        <service id="debug.toolbar" class="%debug.toolbar.class%">
+            <tag name="kernel.listener" event="core.response" method="handle" priority="-128" />
             <argument type="service" id="http_kernel" />
             <argument>%debug.toolbar.intercept_redirects%</argument>
         </service>

+ 2 - 11
src/Symfony/Bundle/WebProfilerBundle/WebDebugToolbarListener.php

@@ -21,6 +21,8 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
 /**
  * WebDebugToolbarListener injects the Web Debug Toolbar.
  *
+ * The handle method must be connected to the core.response event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class WebDebugToolbarListener
@@ -34,17 +36,6 @@ class WebDebugToolbarListener
         $this->interceptRedirects = $interceptRedirects;
     }
 
-    /**
-     * Registers a core.response listener.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.response', array($this, 'handle'), $priority);
-    }
-
     public function handle(Event $event, Response $response)
     {
         if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {

+ 3 - 15
src/Symfony/Component/HttpKernel/Cache/EsiListener.php

@@ -18,6 +18,8 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
 /**
  * EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI.
  *
+ * The filter method must be connected to the core.response event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class EsiListener
@@ -35,20 +37,6 @@ class EsiListener
         $this->esi = $esi;
     }
 
-    /**
-     * Registers a core.response listener to add the Surrogate-Control header to a Response when needed.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        if (null !== $this->esi)
-        {
-            $dispatcher->connect('core.response', array($this, 'filter'), $priority);
-        }
-    }
-
     /**
      * Filters the Response.
      *
@@ -57,7 +45,7 @@ class EsiListener
      */
     public function filter($event, Response $response)
     {
-        if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
+        if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type') || null === $this->esi) {
             return $response;
         }
 

+ 2 - 11
src/Symfony/Component/HttpKernel/Debug/ExceptionListener.php

@@ -22,6 +22,8 @@ use Symfony\Component\HttpFoundation\Request;
 /**
  * ExceptionListener.
  *
+ * The handle method must be connected to the core.exception event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class ExceptionListener
@@ -35,17 +37,6 @@ class ExceptionListener
         $this->logger = $logger;
     }
 
-    /**
-     * Registers a core.exception listener.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.exception', array($this, 'handle'), $priority);
-    }
-
     public function handle(Event $event)
     {
         static $handling;

+ 3 - 12
src/Symfony/Component/HttpKernel/Profiler/ProfilerListener.php

@@ -20,6 +20,9 @@ use Symfony\Component\HttpFoundation\RequestMatcherInterface;
 /**
  * ProfilerListener collects data for the current request by listening to the core.response event.
  *
+ * The handleException method must be connected to the core.exception event.
+ * The handleResponse method must be connected to the core.response event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class ProfilerListener
@@ -43,18 +46,6 @@ class ProfilerListener
         $this->onlyException = $onlyException;
     }
 
-    /**
-     * Registers a core.response and core.exception listeners.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.exception', array($this, 'handleException'), $priority);
-        $dispatcher->connect('core.response', array($this, 'handleResponse'), $priority);
-    }
-
     /**
      * Handles the core.exception event.
      *

+ 0 - 1
src/Symfony/Component/HttpKernel/Resources/bin/packager.php

@@ -27,7 +27,6 @@ ClassCollectionLoader::load(array(
     'Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface',
     'Symfony\\Component\\HttpKernel\\Debug\\ErrorHandler',
     'Symfony\\Component\\HttpKernel\\ClassCollectionLoader',
-    'Symfony\\Component\\HttpKernel\\Debug\\ExceptionListener',
 
     'Symfony\\Component\\DependencyInjection\\Container',
     'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface',

+ 2 - 11
src/Symfony/Component/HttpKernel/ResponseListener.php

@@ -18,21 +18,12 @@ use Symfony\Component\HttpFoundation\Response;
 /**
  * ResponseListener fixes the Response Content-Type.
  *
+ * The filter method must be connected to the core.response event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class ResponseListener
 {
-    /**
-     * Registers a core.response listener to change the Content-Type header based on the Request format.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.response', array($this, 'filter'), $priority);
-    }
-
     /**
      * Filters the Response.
      *

+ 4 - 13
src/Symfony/Component/HttpKernel/Security/Firewall.php

@@ -24,6 +24,8 @@ use Symfony\Component\HttpFoundation\Request;
  * (a Basic authentication for the /api, and a web based authentication for
  * everything else for instance).
  *
+ * The handle method must be connected to the core.request event.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 class Firewall
@@ -37,22 +39,11 @@ class Firewall
      *
      * @param FirewallMap $map A FirewallMap instance
      */
-    public function __construct(FirewallMapInterface $map)
+    public function __construct(FirewallMapInterface $map, EventDispatcher $dispatcher)
     {
         $this->map = $map;
-        $this->currentListeners = array();
-    }
-
-    /**
-     * Registers a core.request listener to enforce security.
-     *
-     * @param EventDispatcher $dispatcher An EventDispatcher instance
-     * @param integer         $priority   The priority
-     */
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.request', array($this, 'handle'), $priority);
         $this->dispatcher = $dispatcher;
+        $this->currentListeners = array();
     }
 
     /**

+ 0 - 4
src/Symfony/Component/HttpKernel/bootstrap.php

@@ -232,10 +232,6 @@ class ExceptionListener
         $this->controller = $controller;
         $this->logger = $logger;
     }
-    public function register(EventDispatcher $dispatcher, $priority = 0)
-    {
-        $dispatcher->connect('core.exception', array($this, 'handle'), $priority);
-    }
     public function handle(Event $event)
     {
         static $handling;

+ 3 - 12
tests/Symfony/Tests/Component/HttpKernel/Cache/EsiListenerTest.php

@@ -24,7 +24,7 @@ class EsiListenerTest extends \PHPUnit_Framework_TestCase
     {
         $dispatcher = new EventDispatcher();
         $listener = new EsiListener(new Esi());
-        $listener->register($dispatcher);
+        $dispatcher->connect('core.response', array($listener, 'filter'));
 
         $event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::SUB_REQUEST));
         $dispatcher->filter($event, $response = new Response('foo <esi:include src="" />'));
@@ -32,20 +32,11 @@ class EsiListenerTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals('', $response->headers->get('Surrogate-Control'));
     }
 
-    public function testNothingIsRegisteredIfEsiIsNull()
-    {
-        $dispatcher = new EventDispatcher();
-        $listener = new EsiListener();
-        $listener->register($dispatcher);
-
-        $this->assertEquals(array(), $dispatcher->getListeners('core.response'));
-    }
-
     public function testFilterWhenThereIsSomeEsiIncludes()
     {
         $dispatcher = new EventDispatcher();
         $listener = new EsiListener(new Esi());
-        $listener->register($dispatcher);
+        $dispatcher->connect('core.response', array($listener, 'filter'));
 
         $event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST));
         $dispatcher->filter($event, $response = new Response('foo <esi:include src="" />'));
@@ -57,7 +48,7 @@ class EsiListenerTest extends \PHPUnit_Framework_TestCase
     {
         $dispatcher = new EventDispatcher();
         $listener = new EsiListener(new Esi());
-        $listener->register($dispatcher);
+        $dispatcher->connect('core.response', array($listener, 'filter'));
 
         $event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST));
         $dispatcher->filter($event, $response = new Response('foo'));

+ 1 - 1
tests/Symfony/Tests/Component/HttpKernel/ResponseListenerTest.php

@@ -60,7 +60,7 @@ class ResponseListenerTest extends \PHPUnit_Framework_TestCase
     {
         $dispatcher = new EventDispatcher();
         $listener = new ResponseListener();
-        $listener->register($dispatcher);
+        $dispatcher->connect('core.response', array($listener, 'filter'));
 
         return $dispatcher;
     }