Index: typo3/sysext/cms/tslib/class.tslib_fe.php =================================================================== --- typo3/sysext/cms/tslib/class.tslib_fe.php (revision 8160) +++ typo3/sysext/cms/tslib/class.tslib_fe.php (working copy) @@ -254,6 +254,7 @@ */ 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. + protected $cacheExpirationTime = 0; 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. @@ -1872,6 +1873,8 @@ $this->all = $cc; } unset($cc); + + $this->setCacheExpirationTime($this->getExpirationTime($this->page)); } $this->content = ''; // clearing the content-variable, which will hold the pagecontent @@ -2804,7 +2807,7 @@ $timeOutTime = $GLOBALS['EXEC_TIME']+$cache_timeout; if ($this->config['config']['cache_clearAtMidnight']) { $midnightTime = mktime (0,0,0,date('m',$timeOutTime),date('d',$timeOutTime),date('Y',$timeOutTime)); - if ($midnightTime > $GLOBALS['EXEC_TIME']) { // If the midnight time of the expire-day is greater than the current time, we may set the timeOutTime to the new midnighttime. + if ($midnightTime > $GLOBALS['EXEC_TIME'] && $midnightTime < $timeOutTime) { // If the midnight time of the expire-day is greater than the current time, we may set the timeOutTime to the new midnighttime. $timeOutTime = $midnightTime; } } @@ -4619,13 +4622,28 @@ } /** + * Sets cache expiration time + * + * @param int $expirationTime + * @return void + */ + public function setCacheExpirationTime($expirationTime) { + if ($expirationTime > $GLOBALS['EXEC_TIME'] && + ($expirationTime < $this->cacheExpirationTime || $this->cacheExpirationTime == 0)) { + $this->cacheExpirationTime = $expirationTime; + } + } + + /** * Get the cache timeout for the current page. * * @return integer The cache timeout for the current page. */ function get_cache_timeout() { // Cache period was set for the page: - if ($this->page['cache_timeout']) { + if ($this->cacheExpirationTime > $GLOBALS['EXEC_TIME']) { + $cacheTimeout = $this->cacheExpirationTime - $GLOBALS['EXEC_TIME']; + } elseif ($this->page['cache_timeout']) { $cacheTimeout = $this->page['cache_timeout']; // Cache period was set for the whole site: } elseif ($this->cacheTimeOutDefault) { @@ -4638,6 +4656,68 @@ } /** + * Obtains page expiration time from start and end time of the page + * + * @param array $pageRecord + * @return int Unix time stamp or 0 if page never expires + */ + protected function getExpirationTime(array $pageRecord) { + $pageExpirationTime = $this->getPageExpirationTime($pageRecord); + $contentExpirationTime = $this->getContentExpirationTime($pageRecord['uid']); + if ($pageExpirationTime == 0) { + $pageExpirationTime = PHP_INT_MAX; + } + if ($contentExpirationTime == 0) { + $contentExpirationTime = PHP_INT_MAX; + } + $result = min($pageExpirationTime, $contentExpirationTime); + return $result == PHP_INT_MAX ? 0 : $result; + } + + /** + * Obtains the earliest time when content of the page expires + * + * @param int $pageId + * @return int Unix time stamp or 0 if content does not expire + */ + protected function getContentExpirationTime($pageId) { + $time = PHP_INT_MAX; + $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('starttime,endtime', 'tt_content', + 'pid=' . $pageId . $this->sys_page->enableFields('tt_content', -1, + array('starttime' => true, 'endtime' => true))); + while (false !== ($data = $GLOBALS['TYPO3_DB']->sql_fetch_row($res))) { + for ($index = 0; $index < 2; $index++) { + if ($data[$index] > $GLOBALS['EXEC_TIME']) { + $time = min($time, $data[$index]); + } + } + } + $GLOBALS['TYPO3_DB']->sql_free_result($res); + + return $time == PHP_INT_MAX ? 0 : $time; + } + + /** + * Obtains page expiration time from start and end time of the page + * + * @param array $pageRecord + * @return int Unix time stamp or 0 if page never expires + */ + public function getPageExpirationTime(array $pageRecord) { + $time = PHP_INT_MAX; + if ($pageRecord['starttime'] > $GLOBALS['EXEC_TIME']) { + $time = $pageRecord['starttime']; + } + if ($pageRecord['endtime'] > $GLOBALS['EXEC_TIME']) { + $time = min($time, $pageRecord['endtime']); + } + if ($time == PHP_INT_MAX) { + $time = 0; + } + return $time; + } + + /** * Substitute function for the PHP mail() function. * It will encode the email with the setting of TS 'config.notification_email_encoding' (base64 or none) * It will also find all links to http:// in the text and substitute with a shorter link using the redirect feature which stores the long link in the database. Depends on configuration in TS 'config.notification_email_urlmode' Index: typo3/sysext/cms/tslib/class.tslib_menu.php =================================================================== --- typo3/sysext/cms/tslib/class.tslib_menu.php (revision 8160) +++ typo3/sysext/cms/tslib/class.tslib_menu.php (working copy) @@ -364,6 +364,32 @@ } /** + * Creates an SQL condition to access pages in menu. Excludes start time + * because it is needed by cache calculation. + * + * @return string + */ + protected function getPageAccessConditionForMenu() { + $condition = $GLOBALS['TSFE']->sys_page->where_hid_del; + $startPosition = strpos($condition, 'pages.starttime'); + if ($startPosition !== false) { + $endPosition = stripos($condition, 'and', $startPosition); + $result = substr($condition, 0, $startPosition); + if ($endPosition !== false) { + $result .= substr($condition, $endPosition + 3); + } + + $result = rtrim($result); + if (strtolower(substr($result, -3)) == 'and') { + $result = substr($result, 0, -3); + } + + $condition = $result; + } + return $condition; + } + + /** * Creates the menu in the internal variables, ready for output. * Basically this will read the page records needed and fill in the internal $this->menuArr * Based on a hash of this array and some other variables the $this->result variable will be loaded either from cache OR by calling the generate() method of the class to create the menu for real. @@ -380,6 +406,10 @@ $this->sys_page->where_groupAccess = ''; // Temporarily removing fe_group checking! } + // Allow pages that are not started yet + $savedEnableClause = $GLOBALS['TSFE']->sys_page->where_hid_del; + $GLOBALS['TSFE']->sys_page->where_hid_del = $this->getPageAccessConditionForMenu(); + // Begin production of menu: $temp = array(); $altSortFieldValue = trim($this->mconf['alternativeSortingField']); @@ -867,8 +897,14 @@ foreach($temp as $data) { $spacer = (t3lib_div::inList($this->spacerIDList,$data['doktype']) || !strcmp($data['ITEM_STATE'],'SPC')) ? 1 : 0; // if item is a spacer, $spacer is set if ($this->filterMenuPages($data, $banUidArray, $spacer)) { + if ($data['starttime'] > $GLOBALS['SIM_EXEC_TIME']) { + // Page is not visible yet. Notice: SIM_EXEC_TIME is because sys_page uses that! + $GLOBALS['TSFE']->setCacheExpirationTime($data['starttime']); + continue; + } $c_b++; if ($begin<=$c_b) { // If the beginning item has been reached. + $GLOBALS['TSFE']->setCacheExpirationTime($GLOBALS['TSFE']->getPageExpirationTime($data)); $this->menuArr[$c] = $data; $this->menuArr[$c]['isSpacer'] = $spacer; $c++; @@ -879,6 +915,9 @@ } } + // Restore enable clause for pages + $GLOBALS['TSFE']->sys_page->where_hid_del = $savedEnableClause; + // Fill in fake items, if min-items is set. if ($minItems) { while($c<$minItems) {