? page_cache.patch ? page_cache_0.patch ? sites/default/files ? sites/default/settings.php Index: includes/bootstrap.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v retrieving revision 1.256 diff -u -p -r1.256 bootstrap.inc --- includes/bootstrap.inc 30 Nov 2008 01:05:16 -0000 1.256 +++ includes/bootstrap.inc 1 Dec 2008 20:01:46 -0000 @@ -130,15 +130,14 @@ define('DRUPAL_BOOTSTRAP_SESSION', 4); define('DRUPAL_BOOTSTRAP_VARIABLES', 5); /** - * Seventh bootstrap phase: load bootstrap.inc and module.inc, start - * the variable system and try to serve a page from the cache. + * Seventh bootstrap phase: find out language of the page. */ -define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 6); - +define('DRUPAL_BOOTSTRAP_LANGUAGE', 6); /** - * Eighth bootstrap phase: find out language of the page. + * Eighth bootstrap phase: load bootstrap.inc and module.inc, start + * the variable system and try to serve a page from the cache. */ -define('DRUPAL_BOOTSTRAP_LANGUAGE', 7); +define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 7); /** * Nineth bootstrap phase: set $_GET['q'] to Drupal path of request. @@ -658,12 +657,12 @@ function variable_del($name) { * a redirected form submission which was completed). */ function page_get_cache() { - global $user, $base_root; + global $user; $cache = NULL; if (!$user->uid && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && count(drupal_set_message()) == 0) { - $cache = cache_get($base_root . request_uri(), 'cache_page'); + $cache = cache_get(drupal_get_page_cache_key(), 'cache_page'); if (empty($cache)) { ob_start(); @@ -674,6 +673,45 @@ function page_get_cache() { } /** + * Retrieve a cache key for the current page. + */ +function drupal_get_page_cache_key() { + global $base_root; + + $key = $base_root . request_uri(); + $keys = drupal_set_page_cache_key(); + // Append keys in GET encoding. + if (!empty($keys)) { + $key .= strpos($key, '?') === FALSE ? '?' : '&'; + $key .= http_build_query($keys); + } + return $key; +} + +/** + * Alter the cache key for the current page request. + * + * This function should be called only at or before the hook_boot() stage. + * Otherwise, the key tested for will be different from the key used when + * the page cache is set. + * + * @param $key + * The key to be set. E.g. 'language'. + * @param $value + * The value to be set. E.g. 'fr'. + * + * @return + * An array of any keys that have been set. + */ +function drupal_set_page_cache_key($key = NULL, $value = NULL) { + static $keys = array(); + if ($key && $value) { + $keys[$key] = $value; + } + return $keys; +} + +/** * Includes a file with the provided type and name. This prevents * including a theme, engine, module, etc., more than once. * @@ -1045,14 +1083,14 @@ function drupal_anonymous_user($session * DRUPAL_BOOTSTRAP_ACCESS: identify and reject banned hosts. * DRUPAL_BOOTSTRAP_SESSION: initialize session handling. * DRUPAL_BOOTSTRAP_VARIABLES: initialize variable handling. + * DRUPAL_BOOTSTRAP_LANGUAGE: identify the language used on the page. * DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: load bootstrap.inc and module.inc, start * the variable system and try to serve a page from the cache. - * DRUPAL_BOOTSTRAP_LANGUAGE: identify the language used on the page. * DRUPAL_BOOTSTRAP_PATH: set $_GET['q'] to Drupal path of request. * DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data. */ function drupal_bootstrap($phase = NULL) { - static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; + static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; if (isset($phase)) { while ($phases && $phase > $completed_phase) { @@ -1130,16 +1168,20 @@ function _drupal_bootstrap($phase) { $conf = variable_init(isset($conf) ? $conf : array()); break; + case DRUPAL_BOOTSTRAP_LANGUAGE: + drupal_init_language(); + break; + case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: $cache_mode = variable_get('cache', CACHE_DISABLED); - // Get the page from the cache. - $cache = $cache_mode == CACHE_DISABLED ? '' : page_get_cache(); // If the skipping of the bootstrap hooks is not enforced, call hook_boot. - if (!$cache || $cache_mode != CACHE_AGGRESSIVE) { + if ($cache_mode != CACHE_AGGRESSIVE) { // Load module handling. require_once DRUPAL_ROOT . '/includes/module.inc'; module_invoke_all('boot'); } + // Get the page from the cache. + $cache = $cache_mode == CACHE_DISABLED ? '' : page_get_cache(); // If there is a cached page, display it. if ($cache) { drupal_page_cache_header($cache); @@ -1150,14 +1192,15 @@ function _drupal_bootstrap($phase) { // We are done. exit; } + // If not skipped above, call hook_boot now. + if ($cache_mode == CACHE_AGGRESSIVE) { + require_once DRUPAL_ROOT . '/includes/module.inc'; + module_invoke_all('boot'); + } // Prepare for non-cached page workflow. drupal_page_header(); break; - case DRUPAL_BOOTSTRAP_LANGUAGE: - drupal_init_language(); - break; - case DRUPAL_BOOTSTRAP_PATH: require_once DRUPAL_ROOT . '/includes/path.inc'; // Initialize $_GET['q'] prior to loading modules and invoking hook_init(). @@ -1211,6 +1254,7 @@ function drupal_init_language() { include_once DRUPAL_ROOT . '/includes/language.inc'; $language = language_initialize(); } + drupal_set_page_cache_key('language', $language->language); } /** Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.832 diff -u -p -r1.832 common.inc --- includes/common.inc 30 Nov 2008 01:05:16 -0000 1.832 +++ includes/common.inc 1 Dec 2008 20:01:55 -0000 @@ -2813,7 +2813,7 @@ function _drupal_bootstrap_full() { * @see drupal_page_header */ function page_set_cache() { - global $user, $base_root; + global $user; if (!$user->uid && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && count(drupal_get_messages(NULL, FALSE)) == 0) { // This will fail in some cases, see page_get_cache() for the explanation. @@ -2833,7 +2833,7 @@ function page_set_cache() { } ob_end_flush(); if ($cache && $data) { - cache_set($base_root . request_uri(), $data, 'cache_page', CACHE_TEMPORARY, drupal_get_headers()); + cache_set(drupal_get_page_cache_key(), $data, 'cache_page', CACHE_TEMPORARY, drupal_get_headers()); } } } Index: modules/simpletest/tests/bootstrap.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/bootstrap.test,v retrieving revision 1.7 diff -u -p -r1.7 bootstrap.test --- modules/simpletest/tests/bootstrap.test 23 Nov 2008 18:12:08 -0000 1.7 +++ modules/simpletest/tests/bootstrap.test 1 Dec 2008 20:01:56 -0000 @@ -183,8 +183,9 @@ class HookBootExitTestCase extends Drupa // Test with aggressive cache. Boot and exit should not fire since the // page is cached. variable_set('cache', CACHE_AGGRESSIVE); - $this->assertTrue(cache_get(url('', array('absolute' => TRUE)), 'cache_page'), t('Page has been cached.')); $this->drupalGet(''); + $this->drupalHead(''); + $this->assertText('ETag: ', t('Verify presence of ETag header indicating that page caching is enabled.')); $this->assertEqual(db_query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'system_test' AND message = 'hook_boot'")->fetchField(), $calls, t('hook_boot not called with agressive cache and a cached page.')); $this->assertEqual(db_query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'system_test' AND message = 'hook_exit'")->fetchField(), $calls, t('hook_exit not called with agressive cache and a cached page.'));