Skip to content

Commit 47f9b9c

Browse files
westonrutersenadir
andcommitted
Reuse directives returned by wp_get_nocache_headers()
Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>
1 parent b99734a commit 47f9b9c

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

plugins/woocommerce/includes/class-wc-cache-helper.php

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class WC_Cache_Helper {
2626
* Hook in methods.
2727
*/
2828
public static function init() {
29-
add_action( 'wp_headers', array( __CLASS__, 'prevent_caching' ) );
29+
add_action( 'wp_headers', array( __CLASS__, 'prevent_caching' ), 5 ); // Lower priority than default to facilitate plugins enforcing `no-store` if desired.
3030
add_action( 'shutdown', array( __CLASS__, 'delete_transients_on_shutdown' ), 10 );
3131
add_action( 'template_redirect', array( __CLASS__, 'geolocation_ajax_redirect' ) );
3232
add_action( 'wc_ajax_update_order_review', array( __CLASS__, 'update_geolocation_hash' ), 5 );
@@ -40,6 +40,7 @@ public static function init() {
4040
* Prevent caching on certain pages.
4141
*
4242
* @since 3.6.0
43+
* @since 10.1.0 This is now a callback for the `wp_headers` filter as opposed to a callback for the `wp` action.
4344
*
4445
* @param array<string, string> $headers Header names and field values.
4546
* @return array<string, string> Filtered headers.
@@ -56,20 +57,57 @@ public static function prevent_caching( $headers ) {
5657

5758
self::set_nocache_constants();
5859

59-
// These directives are all included in `wp_get_nocache_headers()`, with the exclusion of `no-store` for the sake of bfcache.
60-
$new_directives = array(
61-
// Prevent caching the response in reverse proxies.
62-
'private',
63-
64-
// Ensure freshness of the response but without `no-store` so that bfcache won't be disabled.
65-
'no-cache',
66-
'must-revalidate',
67-
'max-age=0',
68-
);
69-
$old_directives = array();
60+
// Gather the original Cache-Control directives as well as the nocache ones to merge into one new Cache-Control header.
7061
if ( isset( $headers['Cache-Control'] ) ) {
71-
$old_directives = preg_split( '/\s*,\s*/', $headers['Cache-Control'] );
62+
$old_directives = preg_split( '/\s*,\s*/', trim( $headers['Cache-Control'] ) );
63+
} else {
64+
$old_directives = array();
7265
}
66+
$nocache_headers = wp_get_nocache_headers();
67+
if ( isset( $nocache_headers['Cache-Control'] ) ) {
68+
$new_directives = preg_split( '/\s*,\s*/', trim( $nocache_headers['Cache-Control'] ) );
69+
} else {
70+
$new_directives = array();
71+
}
72+
73+
$headers = array_merge( $headers, $nocache_headers );
74+
75+
/*
76+
* If the user is not logged in, remove the `no-store` directive so that bfcache is not blocked for visitors,
77+
* allowing them to benefit from instant back/forward navigations in the storefront. This essentially undoes
78+
* <https://core.trac.wordpress.org/ticket/61942> which seems to have been excessive since the `private`
79+
* directive was already being sent to prevent the page from being cached in a proxy server.
80+
*
81+
* Note that <https://core.trac.wordpress.org/ticket/63636> proposes removing `no-store` for logged-in users as
82+
* well. When that happens, the following if statement can be removed since core would no longer be sending
83+
* `no-store` in the first place.
84+
*
85+
* If a site really wants to enforce the `no-store` directive for some reason, they can do so by making sure
86+
* that the `no-store` directive is added to the `Cache-Control` header via the `wp_headers` filter, for
87+
* example:
88+
*
89+
* add_filter( 'wp_headers', function ( $headers ) {
90+
* if ( isset( $headers['Cache-Control'] ) ) {
91+
* $directives = preg_split( ':\s*,\s*:', trim( $headers['Cache-Control'] ) );
92+
* if ( in_array( 'private', $directives, true ) ) {
93+
* $headers['Cache-Control'] = join(
94+
* ', ',
95+
* array_unique(
96+
* array_merge(
97+
* $directives,
98+
* array( 'no-store' )
99+
* )
100+
* )
101+
* );
102+
* }
103+
* }
104+
* return $headers;
105+
* } );
106+
*/
107+
if ( ! is_user_logged_in() ) {
108+
$new_directives = array_diff( $new_directives, array( 'no-store' ) );
109+
}
110+
73111
$headers['Cache-Control'] = implode( ', ', array_unique( array_merge( $old_directives, $new_directives ) ) );
74112

75113
return $headers;

0 commit comments

Comments
 (0)