@@ -26,7 +26,7 @@ class WC_Cache_Helper {
26
26
* Hook in methods.
27
27
*/
28
28
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.
30
30
add_action ( 'shutdown ' , array ( __CLASS__ , 'delete_transients_on_shutdown ' ), 10 );
31
31
add_action ( 'template_redirect ' , array ( __CLASS__ , 'geolocation_ajax_redirect ' ) );
32
32
add_action ( 'wc_ajax_update_order_review ' , array ( __CLASS__ , 'update_geolocation_hash ' ), 5 );
@@ -40,6 +40,7 @@ public static function init() {
40
40
* Prevent caching on certain pages.
41
41
*
42
42
* @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.
43
44
*
44
45
* @param array<string, string> $headers Header names and field values.
45
46
* @return array<string, string> Filtered headers.
@@ -56,20 +57,57 @@ public static function prevent_caching( $headers ) {
56
57
57
58
self ::set_nocache_constants ();
58
59
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.
70
61
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 ();
72
65
}
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
+
73
111
$ headers ['Cache-Control ' ] = implode ( ', ' , array_unique ( array_merge ( $ old_directives , $ new_directives ) ) );
74
112
75
113
return $ headers ;
0 commit comments