? modules/simpletest/tests/343502.test
? modules/simpletest/tests/343502.test.txt
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.258
diff -u -p -r1.258 bootstrap.inc
--- includes/bootstrap.inc	20 Dec 2008 18:24:32 -0000	1.258
+++ includes/bootstrap.inc	23 Dec 2008 06:08:16 -0000
@@ -650,23 +650,26 @@ function variable_del($name) {
   unset($conf[$name]);
 }
 
-
 /**
  * Retrieve the current page from the cache.
  *
- * Note: we do not serve cached pages when status messages are waiting (from
- * a redirected form submission which was completed).
+ * @return
+ *   A string of the saved page from the cache, or NULL if the page has not
+ *   been cached or is not allowed to be cached.
+ *
+ * @see page_cache_allowed()
  */
 function page_get_cache() {
-  global $user, $base_root;
+  global $base_root;
 
   $cache = NULL;
 
-  if (!$user->uid && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && count(drupal_set_message()) == 0) {
+  if (page_cache_allowed()) {
     $cache = cache_get($base_root . request_uri(), 'cache_page');
 
     if (empty($cache)) {
       ob_start();
+      page_cache_allowed(TRUE);
     }
   }
 
@@ -674,6 +677,36 @@ function page_get_cache() {
 }
 
 /**
+ * Retrieves and optionally sets the current page caching status.
+ *
+ * This function is useful if page caching has been started but needs to be
+ * disabled for the current page if something unique is being displayed on the
+ * page, like a message with drupal_set_message().
+ *
+ * @param $cache_status
+ *   (optional) A boolean that sets the current page caching status.
+ * @return
+ *   TRUE if the current page should be cached, FALSE if otherwise.
+ */
+function page_cache_allowed($cache_status = NULL) {
+  global $user;
+  static $status = NULL;
+
+  if (!isset($status)) {
+    // Do not allow caching when status messages are waiting (from a redirected
+    // form submission which was completed).
+    $status = count(drupal_set_message()) == 0;
+  }
+
+  if (isset($cache_status)) {
+    $status = $cache_status;
+  }
+
+  // Always check the request method and that the user is logged out.
+  return $status && !$user->uid && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
+}
+
+/**
  * Includes a file with the provided type and name. This prevents
  * including a theme, engine, module, etc., more than once.
  *
@@ -947,6 +980,8 @@ function drupal_set_message($message = N
 
     if ($repeat || !in_array($message, $_SESSION['messages'][$type])) {
       $_SESSION['messages'][$type][] = $message;
+      // Disable the current request from being cached.
+      page_cache_allowed(FALSE);
     }
   }
 
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.838
diff -u -p -r1.838 common.inc
--- includes/common.inc	20 Dec 2008 18:24:33 -0000	1.838
+++ includes/common.inc	23 Dec 2008 06:08:20 -0000
@@ -1771,7 +1771,6 @@ function l($text, $path, array $options 
  * react to the closing of the page by calling hook_exit().
  */
 function drupal_page_footer() {
-
   if (variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED) {
     page_set_cache();
   }
@@ -2906,31 +2905,27 @@ function _drupal_bootstrap_full() {
  * We thus only deal with the gzip variant and unzip the cache in case
  * the browser does not accept gzip encoding.
  *
- * @see drupal_page_header
+ * @see drupal_page_header()
+ * @see page_cache_allowed()
  */
 function page_set_cache() {
-  global $user, $base_root;
+  global $base_root;
 
-  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.
-    if ($data = ob_get_contents()) {
-      $cache = TRUE;
-      if (variable_get('page_compression', TRUE) && function_exists('gzencode')) {
-        // We do not store the data in case the zlib mode is deflate.
-        // This should be rarely happening.
-        if (zlib_get_coding_type() == 'deflate') {
-          $cache = FALSE;
-        }
-        elseif (zlib_get_coding_type() == FALSE) {
-          $data = gzencode($data, 9, FORCE_GZIP);
-        }
-        // The remaining case is 'gzip' which means the data is
-        // already compressed and nothing left to do but to store it.
+  if (ob_get_level() && ($data = ob_get_contents())) {
+    if (variable_get('page_compression', TRUE) && function_exists('gzencode')) {
+      // We do not store the data in case the zlib mode is deflate.
+      // This should be rarely happening.
+      if (zlib_get_coding_type() == 'deflate') {
+        page_cache_allowed(FALSE);
       }
-      ob_end_flush();
-      if ($cache && $data) {
-        cache_set($base_root . request_uri(), $data, 'cache_page', CACHE_TEMPORARY, drupal_get_headers());
+      elseif (zlib_get_coding_type() == FALSE) {
+        $data = gzencode($data, 9, FORCE_GZIP);
       }
+      // The remaining case is 'gzip' which means the data is
+      // already compressed and nothing left to do but to store it.
+    }
+    if (page_cache_allowed() && $data) {
+      cache_set($base_root . request_uri(), $data, 'cache_page', CACHE_TEMPORARY, drupal_get_headers());
     }
   }
 }
Index: modules/simpletest/tests/cache.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/cache.test,v
retrieving revision 1.3
diff -u -p -r1.3 cache.test
--- modules/simpletest/tests/cache.test	8 Dec 2008 21:41:54 -0000	1.3
+++ modules/simpletest/tests/cache.test	23 Dec 2008 06:08:22 -0000
@@ -224,4 +224,90 @@ class CacheClearCase extends CacheTestCa
                       || $this->checkCacheExists('test_cid_clear2', $this->default_value),
                       t('Two caches removed after clearing cid substring with wildcard true.'));
   }
-}
\ No newline at end of file
+}
+
+/**
+ * Test page caching.
+ */
+class CachePageCase extends CacheTestCase {
+
+  function getInfo() {
+    return array(
+      'name' => t('Cache page test'),
+      'description' => t('Check caching of pages and conditions for not caching pages.'),
+      'group' => t('Cache'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('system_test');
+
+    // Enable caching and clear the page cache.
+    variable_set('cache', CACHE_NORMAL);
+    cache_clear_all('*', 'cache_page', TRUE);
+  }
+
+  /**
+   * Test that pages with messages are not cached.
+   */
+  function testNoCacheMessages() {
+    // View the front page with a message on it and test it was not cached.
+    variable_set('front_page_output', 1);
+    $this->drupalGet('');
+    $this->assertText(t('On front page.'), t('Message found.'));
+    $this->assertPageNotCached();
+
+    // View the front page without a message on it and test it was cached.
+    variable_set('front_page_output', 0);
+    $this->drupalGet('');
+    $this->assertNoText(t('On front page.'), t('Message not found.'));
+    $this->assertPageCached();
+  }
+
+  /**
+   * Test that pages viewed by logged in users are not cached.
+   */
+  function testNoCacheLoggedIn() {
+    // Create a user, log in, and test that the request was not cached.
+    $cache_user = $this->drupalCreateUser(array('access content'));
+    $this->drupalLogin($cache_user);
+    $this->drupalGet('');
+    $this->assertPageNotCached();
+
+    // Logout and check that the next request is cached.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertPageCached();
+  }
+
+  /**
+   * Test that GET and HEAD requests are cached, while POST requests are not.
+   */
+  function testCacheMethods() {
+    $this->drupalGet('');
+    $this->assertPageCached();
+
+    // Clear the page from the cache for the POST test.
+    cache_clear_all('*', 'cache_page', TRUE);
+
+    $this->drupalPost(NULL, array(), t('Log in'));
+    $this->assertPageNotCached();
+
+    $this->drupalHead('');
+    $this->assertPageCached();
+  }
+
+  /**
+   * Test that a page has been cached.
+   */
+  private function assertPageCached($url = '') {
+    $this->assertCacheExists(t('Page has been cached.'), TRUE, url($url, array('absolute' => TRUE)), 'cache_page');
+  }
+
+  /**
+   * Test that a page has not bee cached.
+   */
+  private function assertPageNotCached($url = '') {
+    $this->assertCacheRemoved(t('Page has not been cached.'), url($url, array('absolute' => TRUE)), 'cache_page');
+  }
+}
