[FEATURE] stdWrap caching
authorFabrizio Branca <mail@fabrizio-branca.de>
Sun, 26 Feb 2012 20:59:53 +0000 (21:59 +0100)
committerTolleiv Nietsch <info@tolleiv.de>
Sun, 26 Feb 2012 22:49:12 +0000 (23:49 +0100)
Problem:
* Cacheable content is always page specific.
  Pages cannot share cached content.
* Cacheable content has no individual lifetime
  but is bound to the lifetime of the page where it is placed.

Solution:
Introduce new configuration options that will store the
content into the caching framework:

Examples:
5 = TEXT
5 {
  cache.key = mycurrenttimestamp
  cache.tags = tag_a,tag_b,tag_c
  cache.lifetime = 3600
  data = date : U
  strftime = %H:%M:%S
}

or (for page specific cache that doesn't take
other parameters into account)
5 = TEXT
5 {
  cache.key = mycurrenttimestamp_{page:id}
  cache.key.insertData = 1
}

Change-Id: Idd76f9c627a0dcb5eeb391da547ba412f8c72860
Fixes: #34299
Related: #34307
Releases: 4.7, 4.6-backports, 4.5-backports
Reviewed-on: http://review.typo3.org/9245
Reviewed-by: Philipp Gampe
Tested-by: Philipp Gampe
Reviewed-by: Tolleiv Nietsch
Tested-by: Tolleiv Nietsch
typo3/sysext/cms/tslib/class.tslib_content.php

index 9cf7f57..fde095b 100644 (file)
@@ -53,6 +53,7 @@ class tslib_cObj {
         */
        var $stdWrapOrder = array(
                'stdWrapPreProcess' => 'hook', // this is a placeholder for the first Hook
+               'cacheRead' => 'hook', // this is a placeholder for checking if the content is available in cache
                'setContentToCurrent' => 'boolean',
                'setContentToCurrent.' => 'array',
                'setCurrent' => 'string',
@@ -199,6 +200,7 @@ class tslib_cObj {
                'editIcons.' => 'array',
                'editPanel' => 'boolean',
                'editPanel.' => 'array',
+               'cacheStore' => 'hook', // this is a placeholder for storing the content in cache
                'stdWrapPostProcess' => 'hook', // this is a placeholder for the last Hook
                'debug' => 'boolean',
                'debug.' => 'array',
@@ -1833,7 +1835,19 @@ class tslib_cObj {
                                ;
                        }
                }
+
                if (is_array($conf) && count($conf)) {
+
+                       // cache handling
+                       if (is_array($conf['cache.'])) {
+                               $conf['cache.']['key'] = $this->stdWrap($conf['cache.']['key'], $conf['cache.']['key.']);
+                               $conf['cache.']['tags'] = $this->stdWrap($conf['cache.']['tags'], $conf['cache.']['tags.']);
+                               $conf['cache.']['lifetime'] = $this->stdWrap($conf['cache.']['lifetime'], $conf['cache.']['lifetime.']);
+
+                               $conf['cacheRead'] = 1;
+                               $conf['cacheStore'] = 1;
+                       }
+
                        // check, which of the available stdWrap functions is needed for the current conf Array
                        // and keep only those but still in the same order
                        $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
@@ -1923,6 +1937,24 @@ class tslib_cObj {
        }
 
        /**
+        * Check if content was cached before (depending on the given cache key)
+        *
+        * @param       string          Input value undergoing processing in these functions.
+        * @param       array           All stdWrap properties, not just the ones for a particular function.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_cacheRead($content = '', $conf = array()) {
+               if (!empty($conf['cache.']['key'])) {
+                       $cacheFrontend = $GLOBALS['typo3CacheManager']->getCache('cache_hash'); /* @var $cacheFrontend t3lib_cache_frontend_VariableFrontend */
+                       if ($cacheFrontend && $cacheFrontend->has($conf['cache.']['key'])) {
+                               $content = $cacheFrontend->get($conf['cache.']['key']);
+                               $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
+                       }
+               }
+               return $content;
+       }
+
+       /**
         * setContentToCurrent
         * actually it just does the contrary: Sets the value of 'current' based on current content
         *
@@ -3115,6 +3147,43 @@ class tslib_cObj {
        }
 
        /**
+        * Store content into cache
+        *
+        * @param       string          Input value undergoing processing in these functions.
+        * @param       array           All stdWrap properties, not just the ones for a particular function.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_cacheStore($content = '', $conf = array()) {
+               if (!empty($conf['cache.']['key'])) {
+                       if (defined('TYPO3_UseCachingFramework') && TYPO3_UseCachingFramework) {
+                               $cacheFrontend = $GLOBALS['typo3CacheManager']->getCache('cache_hash'); /* @var $cacheFrontend t3lib_cache_frontend_VariableFrontend */
+                               if ($cacheFrontend) {
+
+                                       $tags = !empty($conf['cache.']['tags']) ? t3lib_div::trimExplode(',', $conf['cache.']['tags']) : array();
+
+                                       if (strtolower($conf['cache.']['lifetime']) == 'unlimited') {
+                                               $lifetime = 0; // unlimited
+                                       } elseif (strtolower($conf['cache.']['lifetime']) == 'default') {
+                                               $lifetime = NULL; // default lifetime
+                                       } elseif (intval($conf['cache.']['lifetime']) > 0) {
+                                               $lifetime = intval($conf['cache.']['lifetime']); // lifetime in seconds
+                                       } else {
+                                               $lifetime = NULL; // default lifetime
+                                       }
+
+                                       $cacheFrontend->set(
+                                               $conf['cache.']['key'],
+                                               $content,
+                                               $tags,
+                                               $lifetime
+                                       );
+                               }
+                       }
+               }
+               return $content;
+       }
+
+       /**
         * stdWrap post process hook
         * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
         * this hook executes functions at after the content has been modified by the rest of the stdWrap functions but still before debugging