[BUGFIX] Cache results of explodeSoftRefParserList() 62/38662/3
authorStephan Großberndt <stephan@grossberndt.de>
Tue, 9 Dec 2014 13:33:57 +0000 (14:33 +0100)
committerAndreas Fernandez <andreas.fernandez@aspedia.de>
Mon, 13 Apr 2015 15:32:53 +0000 (17:32 +0200)
BackendUtility::explodeSoftRefParserList() is called with a very
limited set of input parameters, but processing is rather expensive.

Introduce a runtime cache to avoid processing the softrefs over
and over.
This especially speeds up calls from ReferenceIndex::getRelations(),
which is called many times.

Resolves: #63675
Releases: master, 6.2
Change-Id: I34a4392533828667c1b63b1ecb4ca12580e05e06
Reviewed-on: http://review.typo3.org/38662
Reviewed-by: Xavier Perseguers <xavier@typo3.org>
Tested-by: Xavier Perseguers <xavier@typo3.org>
Reviewed-by: Andreas Fernandez <andreas.fernandez@aspedia.de>
Tested-by: Andreas Fernandez <andreas.fernandez@aspedia.de>
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/core/Classes/Database/ReferenceIndex.php
typo3/sysext/core/Classes/Database/SoftReferenceIndex.php
typo3/sysext/linkvalidator/Classes/LinkAnalyzer.php

index 877e5c7..c4ee321 100644 (file)
@@ -3647,20 +3647,38 @@ class BackendUtility {
        }
 
        /**
+        * Gets an instance of the runtime cache.
+        *
+        * @return VariableFrontend
+        */
+       static protected function getRuntimeCache() {
+               return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_runtime');
+       }
+
+       /**
         * Returns array of soft parser references
         *
         * @param string $parserList softRef parser list
-        * @return array Array where the parser key is the key and the value is the parameter string
+        * @return array|bool Array where the parser key is the key and the value is the parameter string, FALSE if no parsers were found
         */
        static public function explodeSoftRefParserList($parserList) {
+               $runtimeCache = self::getRuntimeCache();
+               $cacheId = 'backend-softRefList-' . md5($parserList);
+               if ($runtimeCache->has($cacheId)) {
+                       return $runtimeCache->get($cacheId);
+               }
+
                // Looking for global parsers:
                if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL']) && !empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'])) {
                        $parserList = implode(',', array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'])) . ',' . $parserList;
                }
+
                // Return immediately if list is blank:
-               if (!strlen($parserList)) {
+               if ($parserList === '') {
+                       $runtimeCache->set($cacheId, FALSE);
                        return FALSE;
                }
+
                // Otherwise parse the list:
                $keyList = GeneralUtility::trimExplode(',', $parserList, TRUE);
                $output = array();
@@ -3672,6 +3690,7 @@ class BackendUtility {
                                $output[$val] = '';
                        }
                }
+               $runtimeCache->set($cacheId, $output);
                return $output;
        }
 
index 7755b14..53f4ffa 100644 (file)
@@ -555,21 +555,24 @@ class ReferenceIndex {
                                        }
                                }
                                // Soft References:
-                               if (strlen($value) && ($softRefs = BackendUtility::explodeSoftRefParserList($conf['softref']))) {
+                               if ((string)$value !== '') {
                                        $softRefValue = $value;
-                                       foreach ($softRefs as $spKey => $spParams) {
-                                               $softRefObj = BackendUtility::softRefParserObj($spKey);
-                                               if (is_object($softRefObj)) {
-                                                       $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams);
-                                                       if (is_array($resultArray)) {
-                                                               $outRow[$field]['softrefs']['keys'][$spKey] = $resultArray['elements'];
-                                                               if (strlen($resultArray['content'])) {
-                                                                       $softRefValue = $resultArray['content'];
+                                       $softRefs = BackendUtility::explodeSoftRefParserList($conf['softref']);
+                                       if ($softRefs !== FALSE) {
+                                               foreach ($softRefs as $spKey => $spParams) {
+                                                       $softRefObj = BackendUtility::softRefParserObj($spKey);
+                                                       if (is_object($softRefObj)) {
+                                                               $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams);
+                                                               if (is_array($resultArray)) {
+                                                                       $outRow[$field]['softrefs']['keys'][$spKey] = $resultArray['elements'];
+                                                                       if ((string)$resultArray['content'] !== '') {
+                                                                               $softRefValue = $resultArray['content'];
+                                                                       }
                                                                }
                                                        }
                                                }
                                        }
-                                       if (is_array($outRow[$field]['softrefs']) && count($outRow[$field]['softrefs']) && (string)$value !== (string)$softRefValue && strstr($softRefValue, '{softref:')) {
+                                       if (!empty($outRow[$field]['softrefs']) && (string)$value !== (string)$softRefValue && strpos($softRefValue, '{softref:') !== FALSE) {
                                                $outRow[$field]['softrefs']['tokenizedContent'] = $softRefValue;
                                        }
                                }
@@ -634,21 +637,24 @@ class ReferenceIndex {
                        $this->temp_flexRelations['db'][$structurePath] = $resultsFromDatabase;
                }
                // Soft References:
-               if ((is_array($dataValue) || strlen($dataValue)) && $softRefs = BackendUtility::explodeSoftRefParserList($dsConf['softref'])) {
+               if (is_array($dataValue) || (string)$dataValue !== '') {
                        $softRefValue = $dataValue;
-                       foreach ($softRefs as $spKey => $spParams) {
-                               $softRefObj = BackendUtility::softRefParserObj($spKey);
-                               if (is_object($softRefObj)) {
-                                       $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams, $structurePath);
-                                       if (is_array($resultArray) && is_array($resultArray['elements'])) {
-                                               $this->temp_flexRelations['softrefs'][$structurePath]['keys'][$spKey] = $resultArray['elements'];
-                                               if (strlen($resultArray['content'])) {
-                                                       $softRefValue = $resultArray['content'];
+                       $softRefs = BackendUtility::explodeSoftRefParserList($dsConf['softref']);
+                       if ($softRefs !== FALSE) {
+                               foreach ($softRefs as $spKey => $spParams) {
+                                       $softRefObj = BackendUtility::softRefParserObj($spKey);
+                                       if (is_object($softRefObj)) {
+                                               $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams, $structurePath);
+                                               if (is_array($resultArray) && is_array($resultArray['elements'])) {
+                                                       $this->temp_flexRelations['softrefs'][$structurePath]['keys'][$spKey] = $resultArray['elements'];
+                                                       if ((string)$resultArray['content'] !== '') {
+                                                               $softRefValue = $resultArray['content'];
+                                                       }
                                                }
                                        }
                                }
                        }
-                       if (count($this->temp_flexRelations['softrefs']) && (string)$dataValue !== (string)$softRefValue) {
+                       if (!empty($this->temp_flexRelations['softrefs']) && (string)$dataValue !== (string)$softRefValue) {
                                $this->temp_flexRelations['softrefs'][$structurePath]['tokenizedContent'] = $softRefValue;
                        }
                }
index 415d868..adbe7ef 100644 (file)
@@ -32,6 +32,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  * Soft References:
  * if ($conf['softref'] && strlen($value))     {       // Check if a TCA configured field has softreferences defined (see TYPO3 Core API document)
  * $softRefs = \TYPO3\CMS\Backend\Utility\BackendUtility::explodeSoftRefParserList($conf['softref']);          // Explode the list of softreferences/parameters
+ * if ($softRefs !== FALSE) { // If there are soft references
  * foreach($softRefs as $spKey => $spParams)   {       // Traverse soft references
  * $softRefObj = &\TYPO3\CMS\Backend\Utility\BackendUtility::softRefParserObj($spKey); // create / get object
  * if (is_object($softRefObj)) {       // If there was an object returned...:
index 3c1ba08..c73076d 100644 (file)
@@ -229,19 +229,21 @@ class LinkAnalyzer {
                        if ($conf['softref'] && strlen($valueField)) {
                                // Explode the list of soft references/parameters
                                $softRefs = BackendUtility::explodeSoftRefParserList($conf['softref']);
-                               // Traverse soft references
-                               foreach ($softRefs as $spKey => $spParams) {
-                                       /** @var $softRefObj \TYPO3\CMS\Core\Database\SoftReferenceIndex */
-                                       $softRefObj = BackendUtility::softRefParserObj($spKey);
-                                       // If there is an object returned...
-                                       if (is_object($softRefObj)) {
-                                               // Do processing
-                                               $resultArray = $softRefObj->findRef($table, $field, $idRecord, $valueField, $spKey, $spParams);
-                                               if (!empty($resultArray['elements'])) {
-                                                       if ($spKey == 'typolink_tag') {
-                                                               $this->analyseTypoLinks($resultArray, $results, $htmlParser, $record, $field, $table);
-                                                       } else {
-                                                               $this->analyseLinks($resultArray, $results, $record, $field, $table);
+                               if ($softRefs !== FALSE) {
+                                       // Traverse soft references
+                                       foreach ($softRefs as $spKey => $spParams) {
+                                               /** @var $softRefObj \TYPO3\CMS\Core\Database\SoftReferenceIndex */
+                                               $softRefObj = BackendUtility::softRefParserObj($spKey);
+                                               // If there is an object returned...
+                                               if (is_object($softRefObj)) {
+                                                       // Do processing
+                                                       $resultArray = $softRefObj->findRef($table, $field, $idRecord, $valueField, $spKey, $spParams);
+                                                       if (!empty($resultArray['elements'])) {
+                                                               if ($spKey == 'typolink_tag') {
+                                                                       $this->analyseTypoLinks($resultArray, $results, $htmlParser, $record, $field, $table);
+                                                               } else {
+                                                                       $this->analyseLinks($resultArray, $results, $record, $field, $table);
+                                                               }
                                                        }
                                                }
                                        }