[TASK] Remove static method variables 67/57167/5
authorChristian Kuhn <lolli@schwarzbu.ch>
Sun, 10 Jun 2018 12:49:01 +0000 (14:49 +0200)
committerAndreas Fernandez <a.fernandez@scripting-base.de>
Sun, 10 Jun 2018 14:42:29 +0000 (16:42 +0200)
Static method variables are even more pita than static class
variables, especially if their state is created from db rows
or path information: It is nearly impossible to get rid of
this state at a later point again, even reflection does not
help here.

The patch abandons all 'static $foo' method variables from
the system, using these strategies:

* Remove some entirely which were used as first level cache
  and only cache-away simple non db related code structures.
* Switch some to use cache framework cache_runtime instead
  which can be evicted easily.
* Use class properties in some cases instead.

Change-Id: Ic699846a2c6ec661ee1124ace50df1aa04a1954b
Resolves: #85206
Releases: master
Reviewed-on: https://review.typo3.org/57167
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
26 files changed:
typo3/sysext/backend/Classes/Form/Utility/FormEngineUtility.php
typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaSelectItemsTest.php
typo3/sysext/backend/Tests/Unit/Form/InlineStackProcessorTest.php
typo3/sysext/backend/Tests/Unit/Utility/Fixtures/ProcessedValueForGroupWithMultipleAllowedTablesFixture.php
typo3/sysext/backend/Tests/Unit/Utility/Fixtures/ProcessedValueForGroupWithOneAllowedTableFixture.php
typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php
typo3/sysext/core/Classes/Resource/OnlineMedia/Processing/PreviewProcessing.php
typo3/sysext/core/Classes/Resource/Processing/LocalImageProcessor.php
typo3/sysext/core/Classes/Resource/ResourceStorage.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/core/Classes/Utility/PathUtility.php
typo3/sysext/core/Tests/Unit/Configuration/FlexForm/FlexFormToolsTest.php
typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
typo3/sysext/core/Tests/Unit/TypoScript/Parser/TypoScriptParserTest.php
typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php
typo3/sysext/fluid_styled_content/Classes/ViewHelpers/Link/ClickEnlargeViewHelper.php
typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractRenderable.php
typo3/sysext/form/Tests/Unit/Hooks/DataStructureIdentifierHookTest.php
typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php
typo3/sysext/frontend/Classes/Utility/EidUtility.php
typo3/sysext/indexed_search/Classes/FileContentParser.php
typo3/sysext/indexed_search/Classes/Indexer.php
typo3/sysext/lowlevel/Classes/Command/DeletedRecordsCommand.php
typo3/sysext/workspaces/Classes/Command/WorkspaceVersionRecordsCommand.php

index 488679b..e7d0a4a 100644 (file)
@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Backend\Form\Utility;
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
@@ -95,13 +96,12 @@ class FormEngineUtility
      */
     public static function getTSconfigForTableRow($table, $row, $field = '')
     {
-        static $cache;
-        if ($cache === null) {
-            $cache = [];
-        }
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $cache = $runtimeCache->get('formEngineUtilityTsConfigForTableRow') ?: [];
         $cacheIdentifier = $table . ':' . $row['uid'];
         if (!isset($cache[$cacheIdentifier])) {
             $cache[$cacheIdentifier] = BackendUtility::getTCEFORM_TSconfig($table, $row);
+            $runtimeCache->set('formEngineUtilityTsConfigForTableRow', $cache);
         }
         if ($field && isset($cache[$cacheIdentifier][$field])) {
             return $cache[$cacheIdentifier][$field];
index 4a1b18d..14353b7 100644 (file)
@@ -278,6 +278,12 @@ abstract class AbstractTreeView
     public $recs = [];
 
     /**
+     * @var bool
+     * @deprecated since v9, will be removed in v10
+     */
+    private $setDataFromArrayDeprecationThrown = false;
+
+    /**
      * Constructor
      */
     public function __construct()
@@ -1015,10 +1021,9 @@ abstract class AbstractTreeView
      */
     public function setDataFromArray(&$dataArr, $traverse = false, $pid = 0)
     {
-        static $deprecationThrown = false;
-        if (!$deprecationThrown) {
+        if (!$this->setDataFromArrayDeprecationThrown) {
             // Throw deprecation only once for this recursive method
-            $deprecationThrown = true;
+            $this->setDataFromArrayDeprecationThrown = true;
             trigger_error('Method setDataFromArray() of AbstractTreeView has been deprecated', E_USER_DEPRECATED);
         }
 
index b7d239d..f521cdb 100644 (file)
@@ -364,12 +364,13 @@ class BackendUtility
      */
     public static function BEgetRootLine($uid, $clause = '', $workspaceOL = false, array $additionalFields = [])
     {
-        static $BEgetRootLine_cache = [];
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $beGetRootLineCache = $runtimeCache->get('backendUtilityBeGetRootLine') ?: [];
         $output = [];
         $pid = $uid;
         $ident = $pid . '-' . $clause . '-' . $workspaceOL . ($additionalFields ? '-' . implode(',', $additionalFields) : '');
-        if (is_array($BEgetRootLine_cache[$ident] ?? false)) {
-            $output = $BEgetRootLine_cache[$ident];
+        if (is_array($beGetRootLineCache[$ident] ?? false)) {
+            $output = $beGetRootLineCache[$ident];
         } else {
             $loopCheck = 100;
             $theRowArray = [];
@@ -422,7 +423,8 @@ class BackendUtility
                     $output[$c]['_ORIG_pid'] = $val['_ORIG_pid'];
                 }
             }
-            $BEgetRootLine_cache[$ident] = $output;
+            $beGetRootLineCache[$ident] = $output;
+            $runtimeCache->set('backendUtilityBeGetRootLine', $beGetRootLineCache);
         }
         return $output;
     }
@@ -439,10 +441,11 @@ class BackendUtility
      */
     protected static function getPageForRootline($uid, $clause, $workspaceOL, array $additionalFields = [])
     {
-        static $getPageForRootline_cache = [];
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $pageForRootlineCache = $runtimeCache->get('backendUtilityPageForRootLine') ?: [];
         $ident = $uid . '-' . $clause . '-' . $workspaceOL;
-        if (is_array($getPageForRootline_cache[$ident] ?? false)) {
-            $row = $getPageForRootline_cache[$ident];
+        if (is_array($pageForRootlineCache[$ident] ?? false)) {
+            $row = $pageForRootlineCache[$ident];
         } else {
             $queryBuilder = static::getQueryBuilderForTable('pages');
             $queryBuilder->getRestrictions()
@@ -485,7 +488,8 @@ class BackendUtility
                     } else {
                         self::fixVersioningPid('pages', $row);
                     }
-                    $getPageForRootline_cache[$ident] = $row;
+                    $pageForRootlineCache[$ident] = $row;
+                    $runtimeCache->set('backendUtilityPageForRootLine', $pageForRootlineCache);
                 }
             }
         }
@@ -3466,16 +3470,12 @@ class BackendUtility
      */
     public static function getTSCpidCached($table, $uid, $pid)
     {
-        // A local first level cache
-        static $firstLevelCache;
-
-        if (!is_array($firstLevelCache)) {
-            $firstLevelCache = [];
-        }
-
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $firstLevelCache = $runtimeCache->get('backendUtilityTscPidCached') ?: [];
         $key = $table . ':' . $uid . ':' . $pid;
         if (!isset($firstLevelCache[$key])) {
             $firstLevelCache[$key] = static::getTSCpid($table, $uid, $pid);
+            $runtimeCache->set('backendUtilityTscPidCached', $firstLevelCache);
         }
         return $firstLevelCache[$key];
     }
index 9ef45e3..4f25ebc 100644 (file)
@@ -21,6 +21,8 @@ use Prophecy\Prophecy\ObjectProphecy;
 use TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectItems;
 use TYPO3\CMS\Backend\Module\ModuleLoader;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
@@ -59,6 +61,13 @@ class TcaSelectItemsTest extends UnitTestCase
 
         $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
         $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
+
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get(Argument::cetera())->willReturn(false);
+        $cacheProphecy->set(Argument::cetera())->willReturn(false);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
     }
 
     protected function tearDown()
index 661d0d6..d6d88f8 100644 (file)
@@ -15,7 +15,11 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Form;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
 use TYPO3\CMS\Backend\Form\InlineStackProcessor;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
@@ -24,6 +28,35 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 class InlineStackProcessorTest extends UnitTestCase
 {
     /**
+     * @var array A backup of registered singleton instances
+     */
+    protected $singletonInstances = [];
+
+    /**
+     * Set up
+     */
+    public function setUp()
+    {
+        parent::setUp();
+        $this->singletonInstances = GeneralUtility::getSingletonInstances();
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get(Argument::cetera())->willReturn(false);
+        $cacheProphecy->set(Argument::cetera())->willReturn(false);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+    }
+
+    /**
+     * Tear down
+     */
+    protected function tearDown()
+    {
+        GeneralUtility::resetSingletonInstances($this->singletonInstances);
+        parent::tearDown();
+    }
+
+    /**
      * @return array
      */
     public function structureStringIsParsedDataProvider()
index eecbe2c..ababbfb 100644 (file)
@@ -24,14 +24,19 @@ class ProcessedValueForGroupWithMultipleAllowedTablesFixture extends \TYPO3\CMS\
      */
     public static function getRecordWSOL($table, $uid, $fields = '*', $where = '', $useDeleteClause = true, $unsetMovePointers = false)
     {
-        static $called = 0;
-        ++$called;
-        if ($called === 1) {
-            return ['title' => 'Page 1'];
+        if ($uid == 1) {
+            return [
+                'uid' => 1,
+                'title' => 'Page 1'
+            ];
         }
-        if ($called === 2) {
-            return ['header' => 'Configuration 2'];
+        if ($uid == 2) {
+            return [
+                'uid' => 2,
+                'header' => 'Configuration 2'
+            ];
         }
+        throw new \RuntimeException('Unexpected call', 1528631953);
     }
 
     /**
@@ -39,13 +44,12 @@ class ProcessedValueForGroupWithMultipleAllowedTablesFixture extends \TYPO3\CMS\
      */
     public static function getRecordTitle($table, $row, $prep = false, $forceResult = true)
     {
-        static $called = 0;
-        ++$called;
-        if ($called === 1) {
+        if ($row['uid'] === 1) {
             return 'Page 1';
         }
-        if ($called === 2) {
+        if ($row['uid'] === 2) {
             return 'Configuration 2';
         }
+        throw new \RuntimeException('Unexpected call', 1528631954);
     }
 }
index de69ee1..184709f 100644 (file)
@@ -24,14 +24,19 @@ class ProcessedValueForGroupWithOneAllowedTableFixture extends \TYPO3\CMS\Backen
      */
     public static function getRecordWSOL($table, $uid, $fields = '*', $where = '', $useDeleteClause = true, $unsetMovePointers = false)
     {
-        static $called = 0;
-        ++$called;
-        if ($called === 1) {
-            return ['title' => 'Page 1'];
+        if ($uid == 1) {
+            return [
+                'uid' => 1,
+                'title' => 'Page 1'
+            ];
         }
-        if ($called === 2) {
-            return ['title' => 'Page 2'];
+        if ($uid == 2) {
+            return [
+                'uid' => 2,
+                'title' => 'Page 2'
+            ];
         }
+        throw new \RuntimeException('Unexpected call', 1528631951);
     }
 
     /**
@@ -39,13 +44,12 @@ class ProcessedValueForGroupWithOneAllowedTableFixture extends \TYPO3\CMS\Backen
      */
     public static function getRecordTitle($table, $row, $prep = false, $forceResult = true)
     {
-        static $called = 0;
-        ++$called;
-        if ($called === 1) {
+        if ($row['uid'] === 1) {
             return 'Page 1';
         }
-        if ($called === 2) {
+        if ($row['uid'] === 2) {
             return 'Page 2';
         }
+        throw new \RuntimeException('Unexpected call', 1528631952);
     }
 }
index 9f17096..ba0e15e 100644 (file)
@@ -1664,7 +1664,8 @@ class BackendUserAuthentication extends AbstractUserAuthentication
      */
     public function getFileMountRecords()
     {
-        static $fileMountRecordCache = [];
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $fileMountRecordCache = $runtimeCache->get('backendUserAuthenticationFileMountRecords') ?: [];
 
         if (!empty($fileMountRecordCache)) {
             return $fileMountRecordCache;
@@ -1798,6 +1799,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication
             }
         }
 
+        $runtimeCache->set('backendUserAuthenticationFileMountRecords', $fileMountRecordCache);
         return $fileMountRecordCache;
     }
 
index 23e467e..2954985 100644 (file)
@@ -247,11 +247,8 @@ class PreviewProcessing
      */
     protected function getGraphicalFunctionsObject()
     {
-        static $graphicalFunctionsObject = null;
-        if ($graphicalFunctionsObject === null) {
-            $graphicalFunctionsObject = GeneralUtility::makeInstance(GraphicalFunctions::class);
-            $graphicalFunctionsObject->init();
-        }
+        $graphicalFunctionsObject = GeneralUtility::makeInstance(GraphicalFunctions::class);
+        $graphicalFunctionsObject->init();
         return $graphicalFunctionsObject;
     }
 }
index 7c2c412..e9b312d 100644 (file)
@@ -158,13 +158,8 @@ class LocalImageProcessor implements ProcessorInterface
      */
     protected function getGraphicalFunctionsObject()
     {
-        static $graphicalFunctionsObject = null;
-
-        if ($graphicalFunctionsObject === null) {
-            $graphicalFunctionsObject = GeneralUtility::makeInstance(GraphicalFunctions::class);
-            $graphicalFunctionsObject->init();
-        }
-
+        $graphicalFunctionsObject = GeneralUtility::makeInstance(GraphicalFunctions::class);
+        $graphicalFunctionsObject->init();
         return $graphicalFunctionsObject;
     }
 }
index 38bf6c8..b2f3d0f 100644 (file)
@@ -2731,8 +2731,10 @@ class ResourceStorage implements ResourceStorageInterface
 
     /**
      * Returns the destination path/fileName of a unique fileName/foldername in that path.
-     * If $theFile exists in $theDest (directory) the file have numbers appended up to $this->maxNumber. Hereafter a unique string will be appended.
-     * This function is used by fx. DataHandler when files are attached to records and needs to be uniquely named in the uploads/* folders
+     * If $theFile exists in $theDest (directory) the file have numbers appended up to $this->maxNumber.
+     * Hereafter a unique string will be appended.
+     * This function is used by fx. DataHandler when files are attached to records
+     * and needs to be uniquely named in the uploads/* folders
      *
      * @param FolderInterface $folder
      * @param string $theFile The input fileName to check
@@ -2744,14 +2746,9 @@ class ResourceStorage implements ResourceStorageInterface
      */
     protected function getUniqueName(FolderInterface $folder, $theFile, $dontCheckForUnique = false)
     {
-        static $maxNumber = 99, $uniqueNamePrefix = '';
+        $maxNumber = 99;
         // Fetches info about path, name, extension of $theFile
         $origFileInfo = PathUtility::pathinfo($theFile);
-        // Adds prefix
-        if ($uniqueNamePrefix) {
-            $origFileInfo['basename'] = $uniqueNamePrefix . $origFileInfo['basename'];
-            $origFileInfo['filename'] = $uniqueNamePrefix . $origFileInfo['filename'];
-        }
         // Check if the file exists and if not - return the fileName...
         // The destinations file
         $theDestFile = $origFileInfo['basename'];
index e122e67..22925a6 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Utility;
 use GuzzleHttp\Exception\RequestException;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Core\ApplicationContext;
 use TYPO3\CMS\Core\Core\ClassLoadingInformation;
 use TYPO3\CMS\Core\Core\Environment;
@@ -1578,17 +1579,15 @@ class GeneralUtility
      */
     public static function xml2array($string, $NSprefix = '', $reportDocTag = false)
     {
-        static $firstLevelCache = [];
+        $runtimeCache = static::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $firstLevelCache = $runtimeCache->get('generalUtilityXml2Array') ?: [];
         $identifier = md5($string . $NSprefix . ($reportDocTag ? '1' : '0'));
         // Look up in first level cache
-        if (!empty($firstLevelCache[$identifier])) {
-            $array = $firstLevelCache[$identifier];
-        } else {
-            $array = self::xml2arrayProcess(trim($string), $NSprefix, $reportDocTag);
-            // Store content in first level cache
-            $firstLevelCache[$identifier] = $array;
+        if (empty($firstLevelCache[$identifier])) {
+            $firstLevelCache[$identifier] = self::xml2arrayProcess(trim($string), $NSprefix, $reportDocTag);
+            $runtimeCache->set('generalUtilityXml2Array', $firstLevelCache);
         }
-        return $array;
+        return $firstLevelCache[$identifier];
     }
 
     /**
index d58d7ba..717dee3 100644 (file)
@@ -370,12 +370,6 @@ class PathUtility
      */
     public static function stripPathSitePrefix($path)
     {
-        static $pathSiteLength = null;
-
-        // calculate length when first needed
-        if (!isset($pathSiteLength)) {
-            $pathSiteLength = strlen(PATH_site);
-        }
-        return substr($path, $pathSiteLength);
+        return substr($path, strlen(PATH_site));
     }
 }
index 1c4a6d6..75f2f1b 100644 (file)
@@ -18,6 +18,8 @@ namespace TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm;
 use Doctrine\DBAL\Driver\Statement;
 use Prophecy\Argument;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidCombinedPointerFieldException;
 use TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidIdentifierException;
 use TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidParentRowException;
@@ -55,6 +57,36 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 class FlexFormToolsTest extends UnitTestCase
 {
     /**
+     * @var array A backup of registered singleton instances
+     */
+    protected $singletonInstances = [];
+
+    /**
+     * Set up
+     */
+    public function setUp()
+    {
+        parent::setUp();
+        $this->singletonInstances = GeneralUtility::getSingletonInstances();
+        // Underlying static GeneralUtility::xml2array() uses caches that have to be mocked here
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get(Argument::cetera())->willReturn(false);
+        $cacheProphecy->set(Argument::cetera())->willReturn(false);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+    }
+
+    /**
+     * Tear down
+     */
+    protected function tearDown()
+    {
+        GeneralUtility::resetSingletonInstances($this->singletonInstances);
+        parent::tearDown();
+    }
+
+    /**
      * @test
      */
     public function getDataStructureIdentifierCallsRegisteredPreProcessHook(): void
index 18659af..06fec88 100644 (file)
@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Core\Tests\Unit\Resource;
  */
 
 use Prophecy\Argument;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Resource\Driver\AbstractDriver;
 use TYPO3\CMS\Core\Resource\Driver\LocalDriver;
 use TYPO3\CMS\Core\Resource\DuplicationBehavior;
@@ -59,6 +61,12 @@ class ResourceStorageTest extends BaseTestCase
             FileRepository::class,
             $fileRepositoryMock
         );
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get(Argument::cetera())->willReturn(false);
+        $cacheProphecy->set(Argument::cetera())->willReturn(false);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
     }
 
     protected function tearDown()
index 23d5da1..a76f240 100644 (file)
@@ -16,6 +16,9 @@ namespace TYPO3\CMS\Core\Tests\Unit\TypoScript\Parser;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -42,7 +45,7 @@ class TypoScriptParserTest extends UnitTestCase
     }
 
     /**
-     *
+     * Tear down
      */
     protected function tearDown(): void
     {
@@ -375,6 +378,14 @@ class TypoScriptParserTest extends UnitTestCase
      */
     public function includeFilesWithConditions(string $typoScript): void
     {
+        // This test triggers an BackendUtility::BEgetRootLine() down below, we need to suppress the cache call
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get(Argument::cetera())->willReturn(false);
+        $cacheProphecy->set(Argument::cetera())->willReturn(false);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+
         $resolvedIncludeLines = TypoScriptParser::checkIncludeLines($typoScript);
         $this->assertContains('foo = bar', $resolvedIncludeLines);
         $this->assertNotContains('INCLUDE_TYPOSCRIPT', $resolvedIncludeLines);
index cc12701..4074085 100644 (file)
@@ -21,6 +21,8 @@ use Prophecy\Argument;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\StreamInterface;
 use Psr\Log\LoggerInterface;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Core\Environment;
 use TYPO3\CMS\Core\Http\RequestFactory;
 use TYPO3\CMS\Core\Package\Package;
@@ -36,11 +38,12 @@ use TYPO3\CMS\Core\Tests\Unit\Utility\Fixtures\TwoParametersConstructorFixture;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\TestingFramework\Core\FileStreamWrapper;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
- * Testcase for class \TYPO3\CMS\Core\Utility\GeneralUtility
+ * Test case
  */
-class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+class GeneralUtilityTest extends UnitTestCase
 {
     const NO_FIX_PERMISSIONS_ON_WINDOWS = 'fixPermissions() not available on Windows (method does nothing)';
 
@@ -4539,6 +4542,12 @@ class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function xml2arrayHandlesWhitespaces(string $input)
     {
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get('generalUtilityXml2Array')->shouldBeCalled()->willReturn(false);
+        $cacheProphecy->set('generalUtilityXml2Array', Argument::cetera())->shouldBeCalled();
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
         $expected = [
             'data' => [
                 'settings.persistenceIdentifier' => [
@@ -4595,6 +4604,12 @@ class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function xml2arrayHandlesTagNamespaces(string $input)
     {
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get('generalUtilityXml2Array')->shouldBeCalled()->willReturn(false);
+        $cacheProphecy->set('generalUtilityXml2Array', Argument::cetera())->shouldBeCalled();
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
         $expected = [
             'data' => [
                 'settings.persistenceIdentifier' => [
@@ -4655,6 +4670,12 @@ class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function xml2arrayHandlesDocumentTag(string $input, string $docTag)
     {
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get('generalUtilityXml2Array')->shouldBeCalled()->willReturn(false);
+        $cacheProphecy->set('generalUtilityXml2Array', Argument::cetera())->shouldBeCalled();
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
         $expected = [
             'data' => [
                 'settings.persistenceIdentifier' => [
@@ -4705,6 +4726,12 @@ class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function xml2ArrayHandlesBigXmlContent(string $input, string $testValue)
     {
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get('generalUtilityXml2Array')->shouldBeCalled()->willReturn(false);
+        $cacheProphecy->set('generalUtilityXml2Array', Argument::cetera())->shouldBeCalled();
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
         $expected = [
             'data' => [
                 'settings.persistenceIdentifier' => [
@@ -4726,6 +4753,12 @@ class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function xml2ArrayFailsWithXmlContentBiggerThanTenMegabytes()
     {
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get('generalUtilityXml2Array')->shouldBeCalled()->willReturn(false);
+        $cacheProphecy->set('generalUtilityXml2Array', Argument::cetera())->shouldBeCalled();
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
         $input = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
             <T3:T3FlexForms>
                 <data>
@@ -4820,6 +4853,12 @@ class GeneralUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     public function xml2ArrayHandlesAttributeTypes(string $input, $expected)
     {
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get('generalUtilityXml2Array')->shouldBeCalled()->willReturn(false);
+        $cacheProphecy->set('generalUtilityXml2Array', Argument::cetera())->shouldBeCalled();
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
         $result = GeneralUtility::xml2array($input);
         $this->assertSame($expected, $result['index']['vDEF']);
     }
index f555e5f..483419f 100644 (file)
@@ -89,12 +89,8 @@ class ClickEnlargeViewHelper extends AbstractViewHelper
     /**
      * @return TypoScriptService
      */
-    protected static function getTypoScriptService()
+    protected static function getTypoScriptService(): TypoScriptService
     {
-        static $typoScriptService;
-        if ($typoScriptService === null) {
-            $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
-        }
-        return $typoScriptService;
+        return GeneralUtility::makeInstance(TypoScriptService::class);
     }
 }
index c590931..7971811 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Form\Domain\Model\Renderable;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Object\ObjectManager;
@@ -151,7 +152,8 @@ abstract class AbstractRenderable implements RenderableInterface
         }
 
         if (isset($options['validators'])) {
-            static $configurationHashes = [];
+            $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+            $configurationHashes = $runtimeCache->get('formAbstractRenderableConfigurationHashes') ?: [];
             foreach ($options['validators'] as $validatorConfiguration) {
                 $configurationHash = md5($this->getIdentifier() . json_encode($validatorConfiguration));
                 if (in_array($configurationHash, $configurationHashes)) {
@@ -159,6 +161,7 @@ abstract class AbstractRenderable implements RenderableInterface
                 }
                 $this->createValidator($validatorConfiguration['identifier'], $validatorConfiguration['options'] ?? []);
                 $configurationHashes[] = $configurationHash;
+                $runtimeCache->set('formAbstractRenderableConfigurationHashes', $configurationHashes);
             }
         }
 
index b9a438a..288dea6 100644 (file)
@@ -15,6 +15,9 @@ namespace TYPO3\CMS\Form\Tests\Unit\Hooks;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Object\ObjectManager;
 use TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook;
@@ -38,6 +41,12 @@ class DataStructureIdentifierHookTest extends UnitTestCase
     public function setUp()
     {
         $this->singletonInstances = GeneralUtility::getSingletonInstances();
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        $cacheProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
+        $cacheProphecy->get(Argument::cetera())->willReturn(false);
+        $cacheProphecy->set(Argument::cetera())->willReturn(false);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
     }
 
     /**
index b173200..193fa14 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Frontend\Typolink;
 
 use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Backend\Routing\PageUriBuilder;
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
@@ -353,7 +354,8 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
      */
     protected function initializeMountPointMap(string $defaultMountPoints = null, string $mapRootPointList = null): array
     {
-        static $mountPointMap = [];
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $mountPointMap = $runtimeCache->get('pageLinkBuilderMountPointMap') ?: [];
         if (!empty($mountPointMap) || (empty($mapRootPointList) && empty($defaultMountPoints))) {
             return $mountPointMap;
         }
@@ -381,6 +383,7 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
             }
             $this->populateMountPointMapForPageRecursively($mountPointMap, $p, $initMParray);
         }
+        $runtimeCache->set('pageLinkBuilderMountPointMap', $mountPointMap);
         return $mountPointMap;
     }
 
index e06c904..d13d450 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Frontend\Utility;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -40,7 +41,6 @@ class EidUtility
     public static function initFeUser()
     {
         // Get TSFE instance. It knows how to initialize the user.
-        /** @var $tsfe \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
         $tsfe = self::getTSFE();
         $tsfe->initFEuser();
         // Return FE user object:
@@ -98,14 +98,15 @@ class EidUtility
     /**
      * Creating a single static cached instance of TSFE to use with this class.
      *
-     * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController New instance of \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+     * @return TypoScriptFrontendController
      */
-    private static function getTSFE()
+    private static function getTSFE(): TypoScriptFrontendController
     {
-        // Cached instance
-        static $tsfe = null;
+        $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+        $tsfe = $runtimeCache->get('eidUtilityTsfe') ?: null;
         if ($tsfe === null) {
             $tsfe = GeneralUtility::makeInstance(TypoScriptFrontendController::class, null, 0, 0);
+            $runtimeCache->set('eidUtilityTsfe', $tsfe);
         }
         return $tsfe;
     }
index 1642e79..187f02c 100644 (file)
@@ -62,6 +62,11 @@ class FileContentParser
     protected $langObject;
 
     /**
+     * @var string Backup for setLocaleForServerFileSystem()
+     */
+    protected $lastLocale;
+
+    /**
      * Constructs this external parsers object
      */
     public function __construct()
@@ -714,22 +719,21 @@ class FileContentParser
      */
     protected function setLocaleForServerFileSystem($resetLocale = false)
     {
-        static $lastLocale = null;
         if (!$GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
             return;
         }
 
         if ($resetLocale) {
-            if ($lastLocale == null) {
+            if ($this->lastLocale == null) {
                 throw new \RuntimeException('Cannot reset locale to NULL.', 1357064326);
             }
-            setlocale(LC_CTYPE, $lastLocale);
-            $lastLocale = null;
+            setlocale(LC_CTYPE, $this->lastLocale);
+            $this->lastLocale = null;
         } else {
-            if ($lastLocale !== null) {
+            if ($this->lastLocale !== null) {
                 throw new \RuntimeException('Cannot set new locale as locale has already been changed before.', 1357064437);
             }
-            $lastLocale = setlocale(LC_CTYPE, 0);
+            $this->lastLocale = setlocale(LC_CTYPE, 0);
             setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
         }
     }
index 979197d..098aea3 100644 (file)
@@ -960,7 +960,7 @@ class Indexer
     protected function createLocalPath($sourcePath)
     {
         $localPath = '';
-        static $pathFunctions = [
+        $pathFunctions = [
             'createLocalPathFromT3vars',
             'createLocalPathUsingAbsRefPrefix',
             'createLocalPathUsingDomainURL',
index 01a2db5..3b6ffcc 100644 (file)
@@ -250,16 +250,13 @@ class DeletedRecordsCommand extends Command
      */
     protected function getTablesWithDeletedFlags(): array
     {
-        static $tables;
-        if (!is_array($tables)) {
-            $tables = [];
-            foreach ($GLOBALS['TCA'] as $tableName => $configuration) {
-                if ($tableName !== 'pages' && isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
-                    $tables[$tableName] = $GLOBALS['TCA'][$tableName]['ctrl']['delete'];
-                }
+        $tables = [];
+        foreach ($GLOBALS['TCA'] as $tableName => $configuration) {
+            if ($tableName !== 'pages' && isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
+                $tables[$tableName] = $GLOBALS['TCA'][$tableName]['ctrl']['delete'];
             }
-            ksort($tables);
         }
+        ksort($tables);
         return $tables;
     }
 
index 3546fba..548a185 100644 (file)
@@ -683,13 +683,10 @@ class WorkspaceVersionRecordsCommand extends Command
      */
     protected function getAllVersionableTables(): array
     {
-        static $tables;
-        if (!is_array($tables)) {
-            $tables = [];
-            foreach ($GLOBALS['TCA'] as $tableName => $config) {
-                if (BackendUtility::isTableWorkspaceEnabled($tableName)) {
-                    $tables[] = $tableName;
-                }
+        $tables = [];
+        foreach ($GLOBALS['TCA'] as $tableName => $config) {
+            if (BackendUtility::isTableWorkspaceEnabled($tableName)) {
+                $tables[] = $tableName;
             }
         }
         return $tables;