-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathdefault-cache-control.php
More file actions
233 lines (205 loc) · 7.35 KB
/
default-cache-control.php
File metadata and controls
233 lines (205 loc) · 7.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<?php
/**
* Plugin Name: Be API - Cache-control Defaults
* Description: Configure default cache-control settings for the cache-control plugin.
* Version: 2.0
* Author: BE API Technical team
* Author URI: https://www.beapi.fr
* License: GPL v2 or later
*/
namespace BEAPI\Plugin_Defaults\cache_control;
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Default cache control configuration
*
* This array defines the default settings for each cache control option.
* The structure follows the same pattern as the cache-control plugin.
*
* Available options for each entry:
* - max_age: Cache duration in seconds for browsers (defined only 1 time on default_settings function)
* - s_maxage: Cache duration in seconds for CDN/proxies
* - staleerror: Duration to serve stale content on server errors (auto-defined x3 s_maxage)
* - stalereval: Duration to serve stale content while revalidating (auto-defined x5 s_maxage)
* - paged: Pagination factor (only for paginated content)
* - mmulti: Enable age multiplier based on last modification (only for singles)
*
* @return array Default cache control settings
*/
function get_default_cache_control_settings() {
// WordPress constants: HOUR_IN_SECONDS = 3600, DAY_IN_SECONDS = 86400
return [
'front_page' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
'singles' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
'mmulti' => 1, // Enable age multiplier
],
'pages' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
'home' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
'paged' => 5, // 5 seconds pagination factor. Example : 10 pages * 5 seconds = 50 seconds
],
'categories' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
'paged' => 8, // 8 seconds pagination factor
],
'tags' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
'paged' => 10, // 10 seconds pagination factor
],
'authors' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
'paged' => 10, // 10 seconds pagination factor
],
'dates' => [
's_maxage' => 12 * \HOUR_IN_SECONDS, // 12 hours
],
'feeds' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
'attachment' => [
's_maxage' => 12 * \HOUR_IN_SECONDS, // 12 hours
],
'search' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
'notfound' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
'redirect_permanent' => [
's_maxage' => 7 * \DAY_IN_SECONDS, // 1 week
],
// WooCommerce specific settings (if WooCommerce is active)
'woocommerce_product' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
'woocommerce_category' => [
's_maxage' => 10 * \HOUR_IN_SECONDS, // 10 hours
],
];
}
/**
* Apply default cache control settings
*/
function default_settings() {
global $cache_control_options;
if ( empty( $cache_control_options ) ) {
return;
}
$default_settings = get_default_cache_control_settings();
foreach ( $cache_control_options as $index => $options ) {
// Set browser cache to 5 seconds to enable cache validation testing via HTTP headers
$options['max_age'] = 5;
// If default settings for this option, set them
if ( isset( $default_settings[ $index ] ) ) {
// Set s_maxage
$options['s_maxage'] = $default_settings[ $index ]['s_maxage'];
// Set staleerror
// On Server error, the page can be served 3 times the original value
$options['staleerror'] = $default_settings[ $index ]['s_maxage'] * 3;
// The stored by Varnish will be served for 5 times the original value even if the page is expired.
// Server will get the new version as soon as one new user get it.
$options['stalereval'] = $default_settings[ $index ]['s_maxage'] * 5;
}
$cache_control_options[ $index ] = $options;
}
}
// Hook to apply default settings after plugins are loaded
\add_action( 'plugins_loaded', __NAMESPACE__ . '\\default_settings' );
/**
* Filter cache-control options when they are read from database
*
* @param mixed $pre Pre-filtered value
* @param string $option Option name
* @param mixed $default_value Default value
* @return mixed Filtered value
*/
function filter_option( $pre, $option, $default_value ) {
// Use always default value for cache-control options
if ( str_contains( $option, 'cache_control_' ) ) {
return $default_value;
}
return $pre;
}
// Hook to filter options when they are read
\add_filter( 'pre_option', __NAMESPACE__ . '\\filter_option', 10, 3 );
/**
* Disable cache-control admin page
*/
function disable_admin_page() {
// Remove the admin menu page
\remove_submenu_page( 'options-general.php', 'cache_control' );
// Remove action links from plugin list
\remove_filter( 'plugin_action_links_' . \plugin_basename( 'cache-control/cache-control.php' ), 'cache_control_admin_action_links' );
// Remove meta links from plugin list
\remove_filter( 'plugin_row_meta', 'cache_control_admin_actions', 10 );
}
// Hook to disable admin page after it's been added
\add_action( 'admin_menu', __NAMESPACE__ . '\\disable_admin_page', 999 );
/**
* Add warning notice on cache-control admin page
*/
function add_admin_notice() {
// Only show on cache-control admin page
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only reading $_GET['page'], no action performed
if ( 'cache_control' === ( isset( $_GET['page'] ) ? $_GET['page'] : '' ) ) {
?>
<div class="notice notice-warning is-dismissible">
<p>
<strong>⚠️ Configuration locked</strong><br>
This page is displayed but no action is possible. Cache settings are automatically managed by the mu-plugin <code>default-cache-control.php</code>.
</p>
</div>
<?php
}
}
// Hook to add notice on admin pages
\add_action( 'admin_notices', __NAMESPACE__ . '\\add_admin_notice' );
/**
* Sends HTTP cache control headers for post type archives.
*
* This function checks if `cache_control_send_http_header` exists
* and if the current page is a post type archive (`is_post_type_archive()`).
* If both conditions are met, it removes its own hook to prevent duplicate execution
* and sends cache headers based on the 'categories' option.
*
* @return void
*/
function cache_control_send_post_type_archive_headers() {
if ( ! function_exists( 'cache_control_send_http_header' ) || ! is_post_type_archive() ) {
return;
}
remove_action( 'template_redirect', 'cache_control_send_headers' );
cache_control_send_http_header( cache_control_build_directive_from_option( 'categories' ) );
}
\add_action( 'template_redirect', __NAMESPACE__ . '\\cache_control_send_post_type_archive_headers', 9 );
/**
* Sends HTTP cache control headers for robots.txt.
*
* This function hooks into 'do_robots' action to send cache headers
* Cache duration: 1 hour.
*
* @return void
*/
function cache_control_send_robots_headers() {
// 1 hour cache for robots.txt
$s_maxage = \HOUR_IN_SECONDS;
// Send cache headers directly
header(
sprintf(
'Cache-Control: public, max-age=%d, s-maxage=%d, stale-while-revalidate=%d, stale-if-error=%d',
$s_maxage,
$s_maxage,
$s_maxage * 5,
$s_maxage * 3
),
true // Replace existing Cache-Control header
);
}
\add_action( 'do_robots', __NAMESPACE__ . '\\cache_control_send_robots_headers', 1 );