[BUGFIX] ObjectManager dependencies in SignalSlot registration
authorOliver Hader <oliver@typo3.org>
Sun, 22 Jul 2012 15:10:23 +0000 (17:10 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Fri, 17 Aug 2012 13:51:02 +0000 (15:51 +0200)
The SignalSlotDispatcher has a connect() and dispatch() method.
The connect() method usually might be used in ext_localconf.php
to register accordant slots - however, the SignalSlotDispatcher
relies on a fully initialized ObjectManager that also relies on
a fully initialized Caching Framework.

Since the Caches are not ready yet in ext_localconf.php the
whole thing will fail.

This patch removes the dependency of the ObjectManager
injecting itself to the SignalSlotDispatcher by explicitely
calling the initializeObject() method at a later point.

The SignalSlotDispatcher can then be used like this:

t3lib_div::makeInstance('Tx_Extbase_SignalSlot_Dispatcher')
  ->connect('Tx_MyClass', 'MySignal', 'Slot', 'slotMethod');

Change-Id: Ib0122a341865c334448f23a46bc8841c4817fdf7
Fixes: #39174
Releases: 4.7, 6.0
Reviewed-on: http://review.typo3.org/12989
Reviewed-by: Daniel Lorenz
Reviewed-by: Jacob Rasmussen
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
typo3/sysext/extbase/Classes/SignalSlot/Dispatcher.php
typo3/sysext/extbase/Tests/Unit/SignalSlot/DispatcherTest.php

index a14063e..0bc0038 100644 (file)
  */
 class Tx_Extbase_SignalSlot_Dispatcher implements t3lib_Singleton {
 
+       /**
+        * @var boolean
+        */
+       protected $isInitialized = FALSE;
+
        /**
         * @var Tx_Extbase_Object_ObjectManagerInterface
         */
@@ -48,13 +53,21 @@ class Tx_Extbase_SignalSlot_Dispatcher implements t3lib_Singleton {
        protected $slots = array();
 
        /**
-        * Injects the object manager
+        * Initializes this object.
         *
-        * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
-        * @return void
+        * This methods needs to be used as alternative to inject aspects.
+        * Since this dispatches is used very early when the ObjectManager
+        * is not fully initialized (especially concerning caching framework),
+        * this is the only way.
         */
-       public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
-               $this->objectManager = $objectManager;
+       public function initializeObject() {
+               if ($this->isInitialized) {
+                       return;
+               }
+
+               $this->objectManager = t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
+
+               $this->isInitialized = TRUE;
        }
 
        /**
@@ -105,6 +118,8 @@ class Tx_Extbase_SignalSlot_Dispatcher implements t3lib_Singleton {
         * @api
         */
        public function dispatch($signalClassName, $signalName, array $signalArguments = array()) {
+               $this->initializeObject();
+
                if (!isset($this->slots[$signalClassName][$signalName])) {
                        return;
                }
index a4e7e0a..833abb9 100644 (file)
@@ -39,7 +39,8 @@ class Tx_Extbase_Tests_Unit_SignalSlot_DispatcherTest extends Tx_Extbase_Tests_U
        protected $signalSlotDispatcher;
 
        public function setUp() {
-               $this->signalSlotDispatcher = new Tx_Extbase_SignalSlot_Dispatcher();
+               $accessibleClassName = $this->buildAccessibleProxy('Tx_Extbase_SignalSlot_Dispatcher');
+               $this->signalSlotDispatcher = new $accessibleClassName();
        }
 
        /**
@@ -94,10 +95,7 @@ class Tx_Extbase_Tests_Unit_SignalSlot_DispatcherTest extends Tx_Extbase_Tests_U
                $arguments = array();
                $mockSlot = function() use (&$arguments) { $arguments =  func_get_args(); };
 
-               $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
-
                $this->signalSlotDispatcher->connect('Foo', 'bar', $mockSlot, NULL, FALSE);
-               $this->signalSlotDispatcher->injectObjectManager($mockObjectManager);
 
                $this->signalSlotDispatcher->dispatch('Foo', 'bar', array('foo' => 'bar', 'baz' => 'quux'));
                $this->assertSame(array('bar', 'quux'), $arguments);
@@ -115,7 +113,8 @@ class Tx_Extbase_Tests_Unit_SignalSlot_DispatcherTest extends Tx_Extbase_Tests_U
                $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(TRUE));
                $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
 
-               $this->signalSlotDispatcher->injectObjectManager($mockObjectManager);
+               $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
+               $this->signalSlotDispatcher->_set('isInitialized', TRUE);
                $this->signalSlotDispatcher->connect('Foo', 'emitBar', $slotClassName, 'slot', FALSE);
 
                $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', array('foo' => 'bar', 'baz' => 'quux'));
@@ -130,7 +129,8 @@ class Tx_Extbase_Tests_Unit_SignalSlot_DispatcherTest extends Tx_Extbase_Tests_U
                $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
                $mockObjectManager->expects($this->once())->method('isRegistered')->with('NonExistingClassName')->will($this->returnValue(FALSE));
 
-               $this->signalSlotDispatcher->injectObjectManager($mockObjectManager);
+               $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
+               $this->signalSlotDispatcher->_set('isInitialized', TRUE);
                $this->signalSlotDispatcher->connect('Foo', 'emitBar', 'NonExistingClassName', 'slot', TRUE);
                $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', array());
        }
@@ -148,7 +148,8 @@ class Tx_Extbase_Tests_Unit_SignalSlot_DispatcherTest extends Tx_Extbase_Tests_U
                $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(TRUE));
                $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
 
-               $this->signalSlotDispatcher->injectObjectManager($mockObjectManager);
+               $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
+               $this->signalSlotDispatcher->_set('isInitialized', TRUE);
                $this->signalSlotDispatcher->connect('Foo', 'emitBar', $slotClassName, 'unknownMethodName', TRUE);
 
                $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', array('foo' => 'bar', 'baz' => 'quux'));
@@ -165,7 +166,8 @@ class Tx_Extbase_Tests_Unit_SignalSlot_DispatcherTest extends Tx_Extbase_Tests_U
                $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
 
                $this->signalSlotDispatcher->connect('SignalClassName', 'methodName', $mockSlot, NULL, TRUE);
-               $this->signalSlotDispatcher->injectObjectManager($mockObjectManager);
+               $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
+               $this->signalSlotDispatcher->_set('isInitialized', TRUE);
 
                $this->signalSlotDispatcher->dispatch('SignalClassName', 'methodName', array('foo' => 'bar', 'baz' => 'quux'));
                $this->assertSame(array('bar', 'quux', 'SignalClassName::methodName'), $arguments);