[BUGFIX] Make ReferenceIndex caching optional 24/54424/3
authorBenni Mack <benni@typo3.org>
Mon, 3 Jul 2017 13:21:03 +0000 (15:21 +0200)
committerBenni Mack <benni@typo3.org>
Wed, 18 Oct 2017 19:44:58 +0000 (21:44 +0200)
The runtime caches used in the ReferenceIndex class
added in TYPO3 8.7.2 should not be added by default
but included on a per-runtime basis when extensions
would use the ReferenceIndex. Otherwise this issue
might lead to side-effects.

For master/9.0 the caches are enabled by default.

Relates: #78634
Resolves: #81771
Releases: master, 8.7
Change-Id: If7ca173d93c05658bce5f57c38842555a439d2ea
Reviewed-on: https://review.typo3.org/54424
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Classes/Database/ReferenceIndex.php

index 39c5a68..7627168 100644 (file)
@@ -147,6 +147,12 @@ class ReferenceIndex
     protected $runtimeCache = null;
 
     /**
+     * Enables $runtimeCache and $recordCache
+     * @var bool
+     */
+    protected $useRuntimeCache = false;
+
+    /**
      * Constructor
      */
     public function __construct()
@@ -212,7 +218,7 @@ class ReferenceIndex
 
         // Fetch tableRelationFields and save them in cache if not there yet
         $cacheId = static::$cachePrefixTableRelationFields . $tableName;
-        if (!$this->runtimeCache->has($cacheId)) {
+        if (!$this->useRuntimeCache || !$this->runtimeCache->has($cacheId)) {
             $tableRelationFields = $this->fetchTableRelationFields($tableName);
             $this->runtimeCache->set($cacheId, $tableRelationFields);
         } else {
@@ -1478,6 +1484,10 @@ class ReferenceIndex
      * - Relations may change during indexing, which is why only the origin record is cached and all relations are re-process even when repeating
      *   indexing of the same origin record
      *
+     * Please note that the cache is disabled by default but can be enabled using $this->enableRuntimeCaches()
+     * due to possible side-effects while handling references that were changed during one single
+     * request.
+     *
      * @param string $tableName
      * @param int $uid
      * @return array|false
@@ -1485,13 +1495,15 @@ class ReferenceIndex
     protected function getRecordRawCached(string $tableName, int $uid)
     {
         $recordCacheId = $tableName . ':' . $uid;
-        if (!isset($this->recordCache[$recordCacheId])) {
+        if (!$this->useRuntimeCache || !isset($this->recordCache[$recordCacheId])) {
 
             // Fetch fields of the table which might contain relations
             $cacheId = static::$cachePrefixTableRelationFields . $tableName;
-            if (!$this->runtimeCache->has($cacheId)) {
+            if (!$this->useRuntimeCache || !$this->runtimeCache->has($cacheId)) {
                 $tableRelationFields = $this->fetchTableRelationFields($tableName);
-                $this->runtimeCache->set($cacheId, $tableRelationFields);
+                if ($this->useRuntimeCache) {
+                    $this->runtimeCache->set($cacheId, $tableRelationFields);
+                }
             } else {
                 $tableRelationFields = $this->runtimeCache->get($cacheId);
             }
@@ -1581,6 +1593,24 @@ class ReferenceIndex
     }
 
     /**
+     * Enables the runtime-based caches
+     * Could lead to side effects, depending if the reference index instance is run multiple times
+     * while records would be changed.
+     */
+    public function enableRuntimeCache()
+    {
+        $this->useRuntimeCache = true;
+    }
+
+    /**
+     * Disables the runtime-based cache
+     */
+    public function disableRuntimeCache()
+    {
+        $this->useRuntimeCache = false;
+    }
+
+    /**
      * Returns the current BE user.
      *
      * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication