From adb4d6e9b7a84a1c350c9564ed47b11c64306bd6 Mon Sep 17 00:00:00 2001 From: Leo Feyer Date: Wed, 18 Mar 2015 12:22:18 +0100 Subject: [PATCH] Improve the cache handling for empty URLs (see #7618). --- system/docs/CHANGELOG.md | 3 ++ .../core/controllers/FrontendIndex.php | 52 +++++++++++++++---- .../modules/core/library/Contao/Automator.php | 48 ++++++++++++++++- system/modules/core/models/PageModel.php | 22 ++++++++ 4 files changed, 113 insertions(+), 12 deletions(-) diff --git a/system/docs/CHANGELOG.md b/system/docs/CHANGELOG.md index 0620ab6968..4c7bb9f66a 100644 --- a/system/docs/CHANGELOG.md +++ b/system/docs/CHANGELOG.md @@ -4,5 +4,8 @@ Contao Open Source CMS changelog Version 3.5.0-beta1 (2015-XX-XX) -------------------------------- +### Fixed +Improve the cache handling for empty URLs (see #7618). + ### Improved Improved the IDE compatibility (see #7634). diff --git a/system/modules/core/controllers/FrontendIndex.php b/system/modules/core/controllers/FrontendIndex.php index 0e1c70ecaa..b592e12708 100644 --- a/system/modules/core/controllers/FrontendIndex.php +++ b/system/modules/core/controllers/FrontendIndex.php @@ -277,12 +277,7 @@ protected function outputFromCache() return; } - /** - * If the request string is empty, look for a cached page matching the - * primary browser language. This is a compromise between not caching - * empty requests at all and considering all browser languages, which - * is not possible for various reasons. - */ + // Try to map the empty request if (\Environment::get('request') == '' || \Environment::get('request') == 'index.php') { // Return if the language is added to the URL and the empty domain will be redirected @@ -291,8 +286,43 @@ protected function outputFromCache() return; } + $strCacheKey = null; $arrLanguage = \Environment::get('httpAcceptLanguage'); - $strCacheKey = \Environment::get('base') .'empty.'. $arrLanguage[0]; + + // Try to get the cache key from the mapper array + if (file_exists(TL_ROOT . '/system/cache/config/mapping.php')) + { + $arrMapper = include TL_ROOT . '/system/cache/config/mapping.php'; + + // Try the language specific keys + foreach ($arrLanguage as $strLanguage) + { + $strSpecificKey = \Environment::get('base') . 'empty.' . $strLanguage; + + if (isset($arrMapper[$strSpecificKey])) + { + $strCacheKey = $arrMapper[$strSpecificKey]; + break; + } + } + + // Try the fallback key + if ($strCacheKey === null) + { + $strSpecificKey = \Environment::get('base') . 'empty.fallback'; + + if (isset($arrMapper[$strSpecificKey])) + { + $strCacheKey = $arrMapper[$strSpecificKey]; + } + } + } + + // Fall back to the first accepted language + if ($strCacheKey === null) + { + $strCacheKey = \Environment::get('base') . 'empty.' . $arrLanguage[0]; + } } else { @@ -315,8 +345,8 @@ protected function outputFromCache() // Check for a mobile layout if (\Input::cookie('TL_VIEW') == 'mobile' || (\Environment::get('agent')->mobile && \Input::cookie('TL_VIEW') != 'desktop')) { - $strCacheKey = md5($strCacheKey . '.mobile'); - $strCacheFile = TL_ROOT . '/system/cache/html/' . substr($strCacheKey, 0, 1) . '/' . $strCacheKey . '.html'; + $strMd5CacheKey = md5($strCacheKey . '.mobile'); + $strCacheFile = TL_ROOT . '/system/cache/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html'; if (file_exists($strCacheFile)) { @@ -327,8 +357,8 @@ protected function outputFromCache() // Check for a regular layout if (!$blnFound) { - $strCacheKey = md5($strCacheKey); - $strCacheFile = TL_ROOT . '/system/cache/html/' . substr($strCacheKey, 0, 1) . '/' . $strCacheKey . '.html'; + $strMd5CacheKey = md5($strCacheKey); + $strCacheFile = TL_ROOT . '/system/cache/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html'; if (file_exists($strCacheFile)) { diff --git a/system/modules/core/library/Contao/Automator.php b/system/modules/core/library/Contao/Automator.php index 1b36b5b8c6..829a6fde1c 100644 --- a/system/modules/core/library/Contao/Automator.php +++ b/system/modules/core/library/Contao/Automator.php @@ -545,8 +545,54 @@ public function generateConfigCache() // Close the file (moves it to its final destination) $objCacheFile->close(); + // Generate the page mapping array + $arrMapper = []; + $objPages = \PageModel::findPublishedRootPages(); + + if ($objPages !== null) + { + while ($objPages->next()) + { + if ($objPages->dns != '') + { + $strBase = $objPages->useSSL ? 'https://' : 'http://'; + $strBase .= $objPages->dns . \Environment::get('path') . '/'; + } + else + { + $strBase = \Environment::get('base'); + } + + if ($objPages->fallback) + { + $arrMapper[$strBase . 'empty.fallback'] = $strBase . 'empty.' . $objPages->language; + } + + $arrMapper[$strBase . 'empty.' . $objPages->language] = $strBase . 'empty.' . $objPages->language; + } + } + + // Generate the page mapper file + $objCacheFile = new \File('system/cache/config/mapping.php', true); + $objCacheFile->write('$strCacheKey) + { + $strContent .= "\t'$strKey' => '$strCacheKey',\n"; + } + + $strContent .= ");"; + $objCacheFile->append($strContent); + + // Close the file (moves it to its final destination) + $objCacheFile->close(); + // Add a log entry - $this->log('Generated the autoload cache', __METHOD__, TL_CRON); + $this->log('Generated the config cache', __METHOD__, TL_CRON); } diff --git a/system/modules/core/models/PageModel.php b/system/modules/core/models/PageModel.php index a438e4ca52..baecaf7a19 100644 --- a/system/modules/core/models/PageModel.php +++ b/system/modules/core/models/PageModel.php @@ -643,6 +643,28 @@ public static function findPublishedFallbackByHostname($strHost, array $arrOptio } + /** + * Finds the published root pages + * + * @param array $arrOptions An optional options array + * + * @return \Model\Collection|null A collection of models or null if there are no parent pages + */ + public static function findPublishedRootPages(array $arrOptions=array()) + { + $t = static::$strTable; + $arrColumns = array("$t.type=?"); + + if (!BE_USER_LOGGED_IN) + { + $time = time(); + $arrColumns[] = "($t.start='' OR $t.start<$time) AND ($t.stop='' OR $t.stop>$time) AND $t.published=1"; + } + + return static::findBy($arrColumns, 'root', $arrOptions); + } + + /** * Find the parent pages of a page *