[BUGFIX] Prevent re-initialization of logger in SignalSlot Dispatcher 23/56823/5
authorNicole Cordes <typo3@cordes.co>
Sat, 28 Apr 2018 06:35:25 +0000 (08:35 +0200)
committerGeorg Ringer <georg.ringer@gmail.com>
Sun, 29 Apr 2018 20:11:39 +0000 (22:11 +0200)
Resolves: #84890
Releases: master
Change-Id: I41917d5d9feab62701da893c5c4c7ba08e5fbc58
Reviewed-on: https://review.typo3.org/56823
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Helmut Hummel <typo3@helhum.io>
Tested-by: Helmut Hummel <typo3@helhum.io>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
typo3/sysext/extbase/Classes/SignalSlot/Dispatcher.php
typo3/sysext/extbase/Tests/Unit/SignalSlot/DispatcherTest.php

index afe043a..3fd3375 100644 (file)
@@ -14,8 +14,10 @@ namespace TYPO3\CMS\Extbase\SignalSlot;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Log\Logger;
 use TYPO3\CMS\Core\Log\LogManager;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
 
 /**
  * A dispatcher which dispatches signals by calling its registered slot methods
@@ -46,6 +48,11 @@ class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface
     protected $slots = [];
 
     /**
+     * @var Logger
+     */
+    protected $logger;
+
+    /**
      * Initializes this object.
      *
      * This methods needs to be used as alternative to inject aspects.
@@ -56,7 +63,9 @@ class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface
     public function initializeObject()
     {
         if (!$this->isInitialized) {
-            $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
+            $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
+            $logManager = GeneralUtility::makeInstance(LogManager::class);
+            $this->logger = $logManager->getLogger(self::class);
             $this->isInitialized = true;
         }
     }
@@ -91,7 +100,7 @@ class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface
             'class' => $class,
             'method' => $method,
             'object' => $object,
-            'passSignalInformation' => $passSignalInformation === true
+            'passSignalInformation' => $passSignalInformation === true,
         ];
         // The in_array() comparision needs to be strict to avoid potential issues
         // with complex objects being registered as slot.
@@ -113,17 +122,15 @@ class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function dispatch($signalClassName, $signalName, array $signalArguments = [])
     {
-        // We can't use LoggerAwaireTrait/Interface here as this class is singleton and instanciated
-        // too early (before loading of ext_localconf.php of extensions) so any logger configuration
-        // done in an extension won't be used if injecting the logger at creation time
-        $logManager = GeneralUtility::makeInstance(LogManager::class);
-        $logger = $logManager->getLogger(self::class);
-        $logger->log(LOG_DEBUG, 'Triggered signal ' . $signalClassName . ' ' . $signalName, [
-            'signalClassName' => $signalClassName,
-            'signalName' => $signalName,
-            'signalArguments' => $signalArguments
-        ]);
         $this->initializeObject();
+        $this->logger->debug(
+            'Triggered signal ' . $signalClassName . ' ' . $signalName,
+            [
+                'signalClassName' => $signalClassName,
+                'signalName' => $signalName,
+                'signalArguments' => $signalArguments,
+            ]
+        );
         if (!isset($this->slots[$signalClassName][$signalName])) {
             return $signalArguments;
         }
index 7f60350..a26b637 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\SignalSlot;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Log\Logger;
 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
 use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
 use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException;
@@ -117,8 +118,10 @@ class DispatcherTest extends UnitTestCase
         $mockObjectManager = $this->createMock(ObjectManagerInterface::class);
         $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(true));
         $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
+        $mockLogger = $this->createMock(Logger::class);
         $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
         $this->signalSlotDispatcher->connect('Foo', 'emitBar', $slotClassName, 'slot', false);
         $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', ['bar', 'quux']);
         $this->assertSame($mockSlot->arguments, ['bar', 'quux']);
@@ -130,6 +133,8 @@ class DispatcherTest extends UnitTestCase
     public function dispatchHandsOverArgumentsReturnedByAFormerSlot()
     {
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
 
         $firstMockSlot = $this->createMock(SlotFixture::class);
         $firstMockSlot->expects($this->once())
@@ -157,6 +162,8 @@ class DispatcherTest extends UnitTestCase
     public function dispatchHandsOverArgumentsReturnedByAFormerSlotWithoutInterferingWithSignalSlotInformation()
     {
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
 
         $firstMockSlot = $this->createMock(SlotFixture::class);
         $firstMockSlot->expects($this->once())
@@ -184,6 +191,8 @@ class DispatcherTest extends UnitTestCase
     public function dispatchHandsOverFormerArgumentsIfPreviousSlotDoesNotReturnAnything()
     {
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
 
         $firstMockSlot = $this->createMock(SlotFixture::class);
         $firstMockSlot->expects($this->once())
@@ -218,6 +227,8 @@ class DispatcherTest extends UnitTestCase
         $this->expectException(InvalidSlotReturnException::class);
         $this->expectExceptionCode(1376683067);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
 
         $mockSlot = $this->createMock(SlotFixture::class);
         $mockSlot->expects($this->once())
@@ -240,6 +251,8 @@ class DispatcherTest extends UnitTestCase
         $this->expectException(InvalidSlotReturnException::class);
         $this->expectExceptionCode(1376683066);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
 
         $mockSlot = $this->createMock(SlotFixture::class);
         $mockSlot->expects($this->once())
@@ -265,6 +278,8 @@ class DispatcherTest extends UnitTestCase
         $mockObjectManager->expects($this->once())->method('isRegistered')->with('NonExistingClassName')->will($this->returnValue(false));
         $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
         $this->signalSlotDispatcher->connect('Foo', 'emitBar', 'NonExistingClassName', 'slot', true);
         $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', []);
     }
@@ -283,6 +298,8 @@ class DispatcherTest extends UnitTestCase
         $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
         $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
         $this->signalSlotDispatcher->connect('Foo', 'emitBar', $slotClassName, 'unknownMethodName', true);
         $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', ['bar', 'quux']);
         $this->assertSame($mockSlot->arguments, ['bar', 'quux']);
@@ -301,6 +318,8 @@ class DispatcherTest extends UnitTestCase
         $this->signalSlotDispatcher->connect('SignalClassName', 'methodName', $mockSlot, null, true);
         $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
         $this->signalSlotDispatcher->dispatch('SignalClassName', 'methodName', ['bar', 'quux']);
         $this->assertSame(['bar', 'quux', 'SignalClassName::methodName'], $arguments);
     }
@@ -352,6 +371,8 @@ class DispatcherTest extends UnitTestCase
         $this->expectException(InvalidSlotException::class);
         $this->expectExceptionCode(1298113624);
         $this->signalSlotDispatcher->_set('isInitialized', true);
+        $mockLogger = $this->createMock(Logger::class);
+        $this->signalSlotDispatcher->_set('logger', $mockLogger);
         $this->signalSlotDispatcher->_set('objectManager', null);
         $this->signalSlotDispatcher->_set('slots', ['ClassA' => ['emitSomeSignal' => [[]]]]);