* Fixed bug #5152: "Duplicate entry" in cache_pagesection by rewriting parts of t3lib...
authorMichael Stucki <michael.stucki@typo3.org>
Sun, 3 Feb 2008 21:56:30 +0000 (21:56 +0000)
committerMichael Stucki <michael.stucki@typo3.org>
Sun, 3 Feb 2008 21:56:30 +0000 (21:56 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@3043 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/class.t3lib_tstemplate.php
typo3/sysext/cms/tslib/class.tslib_fe.php

index 67192a1..89d8762 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,7 @@
 
 2008-02-03  Michael Stucki  <michael@typo3.org>
 
+       * Fixed bug #5152: "Duplicate entry" in cache_pagesection by rewriting parts of t3lib_TStemplate and tslib_fe::getFromCache()
        * Reverted feature #7337 because it is faulty and lacks proper documentation
 
 2008-02-03  Ingo Renner  <ingo@typo3.org>
index fbd8c7c..5de19f0 100755 (executable)
@@ -135,7 +135,6 @@ class t3lib_TStemplate      {
        var $whereClause = '';                          // This MUST be initialized by the init() function
        var $debug = 0;
        var $allowedPaths = array();            // This is the only paths (relative!!) that are allowed for resources in TypoScript. Should all be appended with '/'. You can extend these by the global array TYPO3_CONF_VARS. See init() function.
-       var $currentPageData = '';                      // Contains "currentPageData" when rendered/fetched from cache. See getCurrentPageData()
        var $simulationHiddenOrTime=0;          // See init(); Set if preview of some kind is enabled.
 
        var $loaded = 0;                                        // Set, if the TypoScript template structure is loaded and OK, see ->start()
@@ -251,11 +250,11 @@ class t3lib_TStemplate    {
        function getCurrentPageData()   {
                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('content', 'cache_pagesection', 'page_id='.intval($GLOBALS['TSFE']->id).' AND mpvar_hash='.t3lib_div::md5int($GLOBALS['TSFE']->MP));
                if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-                       $this->currentPageData = unserialize($row['content']);
+                       $currentPageData = unserialize($row['content']);
                } else {
-                       $this->currentPageData = 'none';
+                       $currentPageData = false;
                }
-               return $this->currentPageData;
+               return $currentPageData;        // 2007-05-30 / Stucki: Notice that $this->currentPageData is not used anymore!
        }
 
        /**
@@ -292,34 +291,48 @@ class t3lib_TStemplate    {
        function start($theRootLine)    {
                if (is_array($theRootLine))     {
                        $setupData='';
-                       $cc=Array();
                        $hash='';
+                       $isCached = false;      // Flag that indicates that the existing data in cache_pagesection could be used (this is the case if $TSFE->all is set, and the rowSum still matches). Based on this we decide if cache_pagesection needs to be updated...
                        $this->runThroughTemplates($theRootLine);
 
                                // Getting the currentPageData if not already found
-                       if (!$this->currentPageData && !$GLOBALS['TSFE']->no_cache)     {
-                               $this->getCurrentPageData();
+                       if ($GLOBALS['TSFE']->all) {
+                               $cc = $GLOBALS['TSFE']->all;
+
+                                       // The two ROWsums must NOT be different from each other - which they will be if start/endtime or hidden has changed!
+                               if (strcmp(serialize($this->rowSum),serialize($cc['rowSum']))) {
+                                       unset($cc);
+                               } else {
+                                               // If $TSFE->all really contains valid data, we don't need to update cache_pagesection (because this data was fetched from there already)
+                                       if (!strcmp(serialize($this->rootLine),serialize($cc['rootLine']))) {
+                                               $isCached = true;
+                                       }
+                                               // When the data is serialized below (ROWSUM hash), it must not contain the rootline by concept. So this must be removed (and added again later)...
+                                       unset($cc['rootLine']);
+                               }
                        }
 
                                // This is about getting the hash string which is used to fetch the cached TypoScript template.
                                // If there was some cached currentPageData that's good (it gives us the hash),
                                // However if the actual rowSum and the rowSum of currentPageData is different from each other, thats a problem, and we should re-make the current page data.
-                       if (is_array($this->currentPageData) &&
-                               !strcmp(serialize($this->rowSum), serialize($this->currentPageData['rowSum']))  // The two ROWsums must NOT be different from each other - which they will be if start/endtime or hidden has changed!
-                       )       {
-                                       // If currentPageData was actually there, we match the result...
-                               $cc['all'] = $this->currentPageData['all'];
-                               $cc['rowSum'] = $this->currentPageData['rowSum'];
-                               $cc = $this->matching($cc);
+                       if (is_array($cc)) {
+                                       // If currentPageData was actually there, we match the result (if this wasn't done already in $TSFE->getFromCache()...)
+                               if (!$cc['match']) {
+                                       $cc = $this->matching($cc);
+                                       ksort($cc);
+                               }
                                $hash = md5(serialize($cc));
                        } else {
                                        // If currentPageData was not there, we first find $rowSum (freshly generated). After that we try to see, if rowSum is stored with a list of all matching-parameters. If so we match the result
                                $rowSumHash = md5('ROWSUM:'.serialize($this->rowSum));
                                $result = t3lib_pageSelect::getHash($rowSumHash, 0);
+
                                if ($result)    {
+                                       $cc = array();
                                        $cc['all'] = unserialize($result);
                                        $cc['rowSum'] = $this->rowSum;
                                        $cc = $this->matching($cc);
+                                       ksort($cc);
                                        $hash = md5(serialize($cc));
                                }
                        }
@@ -329,7 +342,7 @@ class t3lib_TStemplate      {
                                $setupData = t3lib_pageSelect::getHash($hash, 0);
                        }
 
-                       if ($hash && $setupData && !$this->forceTemplateParsing)                {
+                       if ($setupData && !$this->forceTemplateParsing) {
                                        // If TypoScript setup structure was cached we unserialize it here:
                                $this->setup = unserialize($setupData);
                        } else {
@@ -341,6 +354,7 @@ class t3lib_TStemplate      {
                                $cc['all']=$this->sections;     // All sections in the template at this point is found
                                $cc['rowSum']=$this->rowSum;    // The line of templates is collected
                                $cc = $this->matching($cc);
+                               ksort($cc);
 
                                $hash = md5(serialize($cc));
 
@@ -354,10 +368,15 @@ class t3lib_TStemplate    {
                        }
                                // Add rootLine
                        $cc['rootLine'] = $this->rootLine;
+                       ksort($cc);
+
                                // Make global and save.
                        $GLOBALS['TSFE']->all=$cc;
 
-                       if (!$this->simulationHiddenOrTime && !$GLOBALS['TSFE']->no_cache)      {       // Only save currentPageData, if we're not simulating by hidden/starttime/endtime
+                               // Matching must be executed for every request, so this must never be part of the pagesection cache!
+                       unset($cc['match']);
+
+                       if (!$isCached && !$this->simulationHiddenOrTime && !$GLOBALS['TSFE']->no_cache) {      // Only save the data if we're not simulating by hidden/starttime/endtime
                                $dbFields = array(
                                        'content' => serialize($cc),
                                        'tstamp' => $GLOBALS['EXEC_TIME']
index 4d7f897..2003de4 100755 (executable)
         */
        var $tmpl='';
        var $cacheTimeOutDefault='';            // Is set to the time-to-live time of cached pages. If false, default is 60*60*24, which is 24 hours.
-       var $cacheContentFlag='';                       // Set internally if cached content is fetched from the database
+       var $cacheContentFlag = 0;                      // Set internally if cached content is fetched from the database
        var $cacheExpires=0;                            // Set to the expire time of cached content
        var $isClientCachable=FALSE;            // Set if cache headers allowing caching are sent.
        var $all='';                                            // $all used by template fetching system. This array is an identification of the template. If $this->all is empty it's because the template-data is not cached, which it must be.
         */
        function getFromCache() {
                if (!$this->no_cache)   {
-                       $this->tmpl->getCurrentPageData();
-
-                       $cc = Array();
-                       if (is_array($this->tmpl->currentPageData))     {
-                                       // BE CAREFULL to change the content of the cc-array. This array is serialized and an md5-hash based on this is used for caching the page.
-                                       // If this hash is not the same in here in this section and after page-generation the page will not be properly cached!
-
-                               $cc['all'] = $this->tmpl->currentPageData['all'];
-                               $cc['rowSum'] = $this->tmpl->currentPageData['rowSum'];
-                               $cc['rootLine'] = $this->tmpl->currentPageData['rootLine'];             // This rootline is used with templates only (matching()-function)
-                               $this->all = $this->tmpl->matching($cc);        // This array is an identification of the template. If $this->all is empty it's because the template-data is not cached, which it must be.
-                               ksort($this->all);
+                       $cc = $this->tmpl->getCurrentPageData();
+                       if (is_array($cc)) {
+                                       // BE CAREFUL to change the content of the cc-array. This array is serialized and an md5-hash based on this is used for caching the page.
+                                       // If this hash is not the same in here in this section and after page-generation, then the page will not be properly cached!
+                               $cc = $this->tmpl->matching($cc);       // This array is an identification of the template. If $this->all is empty it's because the template-data is not cached, which it must be.
+                               ksort($cc);
+
+                               $this->all = $cc;
                        }
+                       unset($cc);
                }
 
                $this->content='';      // clearing the content-variable, which will hold the pagecontent
         * @return      void
         */
        function generatePage_preProcessing()   {
-               ksort($this->all);
                        // Same codeline as in getFromCache(). BUT $this->all has been set in the meantime, so we can't just skip this line and let it be set above! Keep this line!
                $this->newHash = $this->getHash();
                $this->config['hash_base'] = $this->hash_base;  // For cache management informational purposes.