PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
← All changes | includes/class-wp-optimize-browser-cache.php +349 -88 3.2.5 → 4.7.0 View file →
@@ -1,23 +1,23 @@
1 1 <?php
2 2
3 -if (!defined('WPO_VERSION')) die('No direct access allowed');
3 +if (!defined('ABSPATH')) die('No direct access allowed');
4 4
5 -require_once 'class-wp-optimize-htaccess.php';
6 -
7 5 /**
8 6 * Class WP_Optimize_Browser_Cache
9 7 */
10 8 class WP_Optimize_Browser_Cache {
11 9
12 - private $_htaccess = null;
10 + use WP_Optimize_HTTP_Error_Codes_Trait;
13 11
14 - private $_options = null;
12 + private $_htaccess;
15 13
16 - private $_wp_optimize = null;
14 + private $_options;
17 15
16 + private $_wp_optimize;
17 +
18 18 /**
19 - * Browser cache section in htaccess will wrapped with this comment
19 + * Browser cache section in htaccess will be wrapped with this comment
20 20 *
21 21 * @var string
22 22 */
23 23 private $_htaccess_section_comment = 'WP-Optimize Browser Cache';
@@ -30,25 +30,37 @@
30 30
31 31 $this->_htaccess = new WP_Optimize_Htaccess();
32 32
33 33 $this->_options = $this->_wp_optimize->get_options();
34 +
35 + $this->maybe_restore_expire_values_from_htaccess();
34 36 }
35 37
36 38 /**
39 + * Returns singleton instance object
40 + *
41 + * @return WP_Optimize_Browser_Cache Returns `WP_Optimize_Browser_Cache` object
42 + */
43 + public static function instance() {
44 + static $_instance = null;
45 + if (null === $_instance) {
46 + $_instance = new self();
47 + }
48 + return $_instance;
49 + }
50 +
51 + /**
37 52 * Check headers for Cache-Control and Etag. And if they are exist return true.
38 53 *
39 54 * @return bool|WP_Error
40 55 **/
41 56 public function is_enabled() {
57 + $headers = $this->get_stylesheet_headers();
42 58
43 - static $is_enabled;
44 - if (isset($is_enabled)) return $is_enabled;
45 -
46 - $headers = WP_Optimize()->get_stylesheet_headers();
47 -
48 59 if (is_wp_error($headers)) return $headers;
49 60
50 - if (array_key_exists('cache-control', $headers) && array_key_exists('expires', $headers)) {
61 + $cache_control = isset($headers['cache-control']) ? (is_array($headers['cache-control']) ? implode(', ', $headers['cache-control']) : $headers['cache-control']) : '';
62 + if (array_key_exists('expires', $headers) && array_key_exists('cache-control', $headers) && preg_match('/\b(public|private)\b/i', $cache_control)) {
51 63 $is_enabled = true;
52 64 } else {
53 65 $is_enabled = false;
54 66 }
@@ -53,9 +65,9 @@
53 65 $is_enabled = false;
54 66 }
55 67
56 68 if ($this->is_browser_cache_section_exists() && false === $this->_wp_optimize->is_apache_module_loaded(array('mod_expires', 'mod_headers'))) {
57 - $is_enabled = new WP_Error('Browser cache', __('We successfully updated your .htaccess file. But it seems one of Apache modules - mod_expires or mod_headers is not active.', 'wp-optimize'));
69 + $is_enabled = new WP_Error('Browser cache', __('We successfully updated your .htaccess file.', 'wp-optimize') . ' ' . __('But it seems one of Apache modules - mod_expires or mod_headers is not active.', 'wp-optimize'));
58 70 }
59 71
60 72 return $is_enabled;
61 73 }
@@ -60,41 +72,132 @@
60 72 return $is_enabled;
61 73 }
62 74
63 75 /**
76 + * Get expire days and hours values from options.
77 + *
78 + * @return array // [0] - expire days, [1] - expire hours
79 + */
80 + private function get_expire_data() {
81 + return array(
82 + absint($this->_options->get_option('browser_cache_expire_days', 0)),
83 + absint($this->_options->get_option('browser_cache_expire_hours', 0)),
84 + );
85 + }
86 +
87 +
88 + /**
89 + * Check if .htaccess has already updated settings (manually by user) then reset error message output
90 + *
91 + * @return void
92 + */
93 + public function maybe_reset_error_message_output() {
94 + $error_message = $this->_options->get_option('browser_cache_error_message', '');
95 + if ('' === $error_message) return;
96 +
97 + list($expire_days, $expire_hours) = $this->get_expire_data();
98 +
99 + $expire = $this->prepare_interval($expire_days, $expire_hours);
100 + $search = 'ExpiresByType text/css "access '.$expire.'"';
101 +
102 + // if we already have setting in the file then we can reset error message output
103 + if (false !== strpos($this->_htaccess->get_content(), $search)) {
104 + $this->_options->update_option('browser_cache_error_message', '');
105 + $this->_options->update_option('browser_cache_output', '');
106 + }
107 + }
108 +
109 + /**
110 + * Set expire days and hours values.
111 + *
112 + * @param int $expire_days
113 + * @param int $expire_hours
114 + * @return void
115 + */
116 + private function set_expire_values($expire_days, $expire_hours) {
117 + $this->_options->update_option('browser_cache_expire_days', absint($expire_days));
118 + $this->_options->update_option('browser_cache_expire_hours', absint($expire_hours));
119 + }
120 +
121 + /**
64 122 * Enable browser cache - add settings into .htaccess.
65 123 *
66 - * @param string $expiry_time
124 + * @return void
67 125 */
68 - public function enable($expiry_time = '1 month') {
69 - $this->_htaccess->update_commented_section($this->prepare_browser_cache_section($expiry_time), $this->_htaccess_section_comment);
126 + public function enable() {
127 + list($expire_days, $expire_hours) = $this->get_expire_data();
128 +
129 + $this->_htaccess->update_commented_section($this->prepare_browser_cache_section($expire_days, $expire_hours), $this->_htaccess_section_comment);
70 130 $this->_htaccess->write_file();
131 + $this->_options->update_option('enable_browser_cache', true);
71 132 }
72 133
73 134 /**
74 135 * Disable cache - remove settings from .htaccess added in enable() function.
136 + *
137 + * @return void
75 138 */
76 139 public function disable() {
77 140 $this->_htaccess->remove_commented_section($this->_htaccess_section_comment);
78 141 $this->_htaccess->write_file();
142 + $this->_options->update_option('enable_browser_cache', false);
79 143 }
80 144
81 145 /**
82 - * Check if browser chache option is set to true then add section with gzip settings into .htaccess (used when plugin being activated).
146 + * Restore expiration settings from .htaccess if the options are empty.
147 + *
148 + * @return void
83 149 */
84 - public function restore() {
150 + public function maybe_restore_expire_values_from_htaccess() {
85 151 $expire_days = $this->_options->get_option('browser_cache_expire_days', '');
86 152 $expire_hours = $this->_options->get_option('browser_cache_expire_hours', '');
87 153
88 - $expiry_time = $this->prepare_interval($expire_days, $expire_hours);
154 + if ('' === $expire_days && '' === $expire_hours) {
155 + $this->restore_expire_values_from_htaccess();
156 + }
157 + }
89 158
90 - $enabled = ('' == $expiry_time) ? false : true;
159 + /**
160 + * Check if browser cache option is set to true then add section with browser cache settings into .htaccess.
161 + *
162 + * @return void
163 + */
164 + public function restore() {
165 + list($expire_days, $expire_hours) = $this->get_expire_data();
91 166
92 - if ($enabled && $this->_htaccess->is_writable()) $this->enable($expiry_time);
167 + $enabled = 0 !== $expire_days || 0 !== $expire_hours;
168 +
169 + // If we don't have values in the database try to read them from .htaccess file
170 + if (!$enabled) {
171 + $this->restore_expire_values_from_htaccess();
172 +
173 + list($expire_days, $expire_hours) = $this->get_expire_data();
174 + $enabled = 0 !== $expire_days || 0 !== $expire_hours;
175 + }
176 +
177 + if ($enabled && $this->_htaccess->is_writable()) $this->enable();
93 178 }
94 179
95 180 /**
181 + * Restore expire days and expire hours values form .htaccess if possible.
182 + *
183 + * @return void
184 + */
185 + private function restore_expire_values_from_htaccess() {
186 + $htaccess_values = $this->get_browser_cache_section_expire_values();
187 + list($expire_days, $expire_hours) = $htaccess_values;
188 +
189 + $enabled = 0 !== $expire_days || 0 !== $expire_hours;
190 +
191 + if ($enabled) {
192 + $this->set_expire_values($expire_days, $expire_hours);
193 + }
194 + }
195 +
196 + /**
96 197 * Check if section with browser cache settings already exists.
198 + *
199 + * @return bool
97 200 */
98 201 public function is_browser_cache_section_exists() {
99 202 return $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
100 203 }
@@ -99,31 +202,106 @@
99 202 return $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
100 203 }
101 204
102 205 /**
206 + * Get expire days and hours values from the .htaccess file
207 + *
208 + * @return array|bool
209 + */
210 + private function get_browser_cache_section_expire_values() {
211 + $section_content = $this->_htaccess->get_section_content();
212 +
213 + if (preg_match('/ExpiresByType text\/css "access ([0-9a-z\s]+)"/i', $section_content, $matches)) {
214 + return $this->expire_string_to_days_hours($matches[1]);
215 + }
216 +
217 + return array(0, 0);
218 + }
219 +
220 + /**
221 + * Returns days and hours values from expire string
222 + *
223 + * @param string $string
224 + * @return array
225 + */
226 + private function expire_string_to_days_hours($string) {
227 + $days = 0;
228 + $hours = 0;
229 +
230 + preg_match_all(
231 + '/(\d+)\s+(year|years|month|months|day|days|hour|hours)/i',
232 + $string,
233 + $matches,
234 + PREG_SET_ORDER
235 + );
236 +
237 + foreach ($matches as $match) {
238 + $value = (int) $match[1];
239 + $unit = strtolower($match[2]);
240 +
241 + switch ($unit) {
242 + case 'year':
243 + case 'years':
244 + $days += $value * 365;
245 + break;
246 +
247 + case 'month':
248 + case 'months':
249 + $days += $value * 30;
250 + break;
251 +
252 + case 'day':
253 + case 'days':
254 + $days += $value;
255 + break;
256 +
257 + case 'hour':
258 + case 'hours':
259 + $hours += $value;
260 + break;
261 + }
262 + }
263 +
264 + // Convert extra hours into days
265 + $days += intdiv($hours, 24);
266 + $hours %= 24;
267 +
268 + return array(absint($days), absint($hours));
269 + }
270 +
271 + /**
103 272 * Handle for enable_browser_cache command used in WP_Optimize_Commands.
104 273 *
105 274 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
106 275 * @return array
107 276 */
108 - public function enable_browser_cache_command_handler($params) {
109 - $expire_days = isset($params['browser_cache_expire_days']) ? $params['browser_cache_expire_days'] : '';
110 - $expire_hours = isset($params['browser_cache_expire_hours']) ? $params['browser_cache_expire_hours'] : '';
277 + public function enable_browser_cache_command_handler(array $params): array {
278 + $expire_days = absint($params['browser_cache_expire_days']);
279 + $expire_hours = absint($params['browser_cache_expire_hours']);
111 280
112 - $current_expire_days = $this->_options->get_option('browser_cache_expire_days', '');
113 - $current_expire_hours = $this->_options->get_option('browser_cache_expire_hours', '');
281 + list($current_expire_days, $current_expire_hours) = $this->get_browser_cache_section_expire_values();
114 282
115 - $section_updated = false;
283 + // clear error message output
284 + $this->_options->update_option('browser_cache_error_message', '');
285 + $this->_options->update_option('browser_cache_output', '');
116 286
117 - $expiry_time = $this->prepare_interval($expire_days, $expire_hours);
287 + $enable = 0 !== $expire_days || 0 !== $expire_hours;
118 288
119 - $enable = ('' == $expiry_time) ? false : true;
289 + // Store new expire values in the database
290 + $this->set_expire_values($expire_days, $expire_hours);
120 291
121 292 /**
122 293 * If we don't need to do anything in .htaccess then return message.
123 294 */
124 - if ($enable == $this->_htaccess->is_commented_section_exists() && $expire_days == $current_expire_days && $expire_hours == $current_expire_hours) {
125 - $message = __('Browser static caching settings already exists in the .htaccess file', 'wp-optimize');
295 + if ($enable === $this->_htaccess->is_commented_section_exists()
296 + && $expire_days === $current_expire_days
297 + && $expire_hours === $current_expire_hours
298 + ) {
299 + if ($enable) {
300 + $message = __('Browser static caching settings already exists in the .htaccess file', 'wp-optimize');
301 + } else {
302 + $message = '';
303 + }
126 304
127 305 return array(
128 306 'success' => true,
129 307 'enabled' => $enable,
@@ -130,63 +308,51 @@
130 308 'message' => $message,
131 309 );
132 310 }
133 311
134 - if ($this->_htaccess->is_writable()) {
135 - // update commented section
312 + $section_updated = $this->update_htaccess_section($enable);
136 313
137 - if ($enable) {
138 - $this->enable($expiry_time);
139 - } else {
140 - $this->disable();
141 - }
314 + $is_enabled = $this->is_enabled();
142 315
143 - // read updated file.
144 - $this->_htaccess->read_file();
145 - // check if section added or removed successfully.
146 - $section_exists = $this->_htaccess->is_commented_section_exists();
147 - // set correct $section-updated flag.
148 - $section_updated = $enable === $section_exists;
149 - }
150 -
151 316 if ($section_updated) {
152 - $enabled = $this->is_enabled();
153 317
154 - // save $expire value to options.
155 - $this->_options->update_option('browser_cache_expire_days', $expire_days);
156 - $this->_options->update_option('browser_cache_expire_hours', $expire_hours);
157 -
158 - if (is_wp_error($enabled)) {
318 + if (is_wp_error($is_enabled)) {
159 319 return array(
160 320 'success' => true,
161 - 'enabled' => $enabled,
162 - 'error_message' => $enabled->get_error_message(),
321 + 'enabled' => false,
322 + 'error_message' => $is_enabled->get_error_message(),
163 323 );
164 324 } else {
165 325 return array(
166 326 'success' => true,
167 - 'enabled' => $enabled,
327 + 'enabled' => $is_enabled,
168 328 'message' => __('We successfully updated your .htaccess file.', 'wp-optimize'),
169 329 );
170 330 }
171 331 } else {
172 - $cache_section = $this->prepare_browser_cache_section($expiry_time);
173 332
174 333 if ($enable) {
175 - $message = sprintf(__('We can\'t update your %s file. Please try to add following lines manually:', 'wp-optimize'), $this->_htaccess->get_filename());
176 - $output = htmlentities($this->_htaccess->get_section_begin_comment() . PHP_EOL .
177 - join(PHP_EOL, $this->_htaccess->get_flat_array($cache_section)).
178 - PHP_EOL . $this->_htaccess->get_section_end_comment());
334 + // translators: %s is a file name
335 + $message = sprintf(__("We can't update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to add following lines manually:', 'wp-optimize');
179 336 } else {
180 - $message = sprintf(__('We can\'t update your %s file. Please try to remove following lines manually:', 'wp-optimize'), $this->_htaccess->get_filename());
181 - $output = htmlentities($this->_htaccess->get_section_begin_comment() . PHP_EOL .
182 - ' ... ... ... '.
183 - PHP_EOL . $this->_htaccess->get_section_end_comment());
337 + // translators: %s is a file name
338 + $message = sprintf(__("We can't update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to remove following lines manually:', 'wp-optimize');
184 339 }
185 340
341 + $output = htmlentities($this->get_htaccess_section_output($enable));
342 +
343 + // store error message output
344 + $this->_options->update_option('browser_cache_error_message', $message);
345 + $this->_options->update_option('browser_cache_output', $output);
346 +
347 + if (is_wp_error($is_enabled)) {
348 + $message .= ' ' .$is_enabled->get_error_message();
349 + $is_enabled = false;
350 + }
351 +
186 352 return array(
187 353 'success' => false,
188 - 'enabled' => $this->is_enabled(),
354 + 'enabled' => $is_enabled,
189 355 'error_message' => $message,
190 356 'output' => $output,
191 357 );
192 358 }
@@ -192,20 +358,68 @@
192 358 }
193 359 }
194 360
195 361 /**
196 - * Use $days an $hours values to build correct time interval as a string like '2 days 3 hours' or empty string if date is empty.
362 + * Update the .htaccess section for browser caching.
197 363 *
364 + * @param boolean $enable
365 + * @return bool True if section updated successfully, false otherwise
366 + */
367 + private function update_htaccess_section(bool $enable) {
368 +
369 + if (!$this->_htaccess->is_writable()) {
370 + return false;
371 + }
372 +
373 + // update commented section
374 + if ($enable) {
375 + $this->enable();
376 + } else {
377 + $this->disable();
378 + }
379 +
380 + // read updated file.
381 + $this->_htaccess->read_file();
382 + // check if section added or removed successfully.
383 + $section_exists = $this->_htaccess->is_commented_section_exists();
384 + // return true if section updated successfully, false otherwise.
385 + return $enable === $section_exists;
386 + }
387 +
388 + /**
389 + * Get output content for enable/disable browser cache in .htaccess.
390 + *
391 + * @param bool $enable
392 + * @return string
393 + */
394 + private function get_htaccess_section_output($enable) {
395 + list($expire_days, $expire_hours) = $this->get_expire_data();
396 +
397 + if ($enable) {
398 + $cache_section = $this->prepare_browser_cache_section($expire_days, $expire_hours);
399 +
400 + $output = $this->_htaccess->get_section_begin_comment() . PHP_EOL .
401 + join(PHP_EOL, $this->_htaccess->get_flat_array($cache_section)).
402 + PHP_EOL . $this->_htaccess->get_section_end_comment();
403 + } else {
404 + $output = $this->_htaccess->get_section_begin_comment() . PHP_EOL .
405 + ' ... ... ... '.
406 + PHP_EOL . $this->_htaccess->get_section_end_comment();
407 + }
408 +
409 + return $output;
410 + }
411 +
412 + /**
413 + * Use $days and $hours values to build correct time interval as a string like '2 days 3 hours' or empty string if date is empty.
414 + *
198 415 * @param int $days
199 416 * @param int $hours
200 417 * @return string
201 418 */
202 - private function prepare_interval($days, $hours) {
419 + private function prepare_interval(int $days, int $hours): string {
203 420
204 - $days = is_numeric($days) ? floor($days) : 0;
205 - $hours = is_numeric($hours) ? floor($hours) : 0;
206 -
207 - if (0 == $days && 0 == $hours) {
421 + if (0 === $days && 0 === $hours) {
208 422 return '';
209 423 }
210 424
211 425 $parts = array();
@@ -238,20 +452,42 @@
238 452 return join(' ', $parts);
239 453 }
240 454
241 455 /**
456 + * Converts a human-readable time string into total seconds
457 + *
458 + * @param int $days
459 + * @param int $hours
460 + * @return string Total number of seconds
461 + */
462 + private function convert_to_seconds(int $days, int $hours): string {
463 + // Split the string into parts
464 + $total_seconds = $days * 24 * 60 * 60 + $hours * 60 * 60;
465 +
466 + return strval($total_seconds);
467 + }
468 +
469 + /**
242 470 * Build browser cache section array.
243 471 *
244 - * @param string $expire - value like - 1 day 12 hours 15 minutes
472 + * @param int $expire_days
473 + * @param int $expire_hours
245 474 * @return array
246 475 */
247 - public function prepare_browser_cache_section($expire) {
476 + public function prepare_browser_cache_section(int $expire_days, int $expire_hours): array {
477 + $expire = $this->prepare_interval($expire_days, $expire_hours);
478 + $max_age = $this->convert_to_seconds($expire_days, $expire_hours);
479 +
248 480 return array(
249 481 array(
482 + '<IfModule mod_setenvif.c>',
483 + 'SetEnvIf Request_URI "/wp-admin/" WPO_NO_CACHE',
484 + '</IfModule>',
485 + ),
486 + array(
250 487 '<IfModule mod_expires.c>',
251 488 'ExpiresActive On',
252 489 'ExpiresByType text/css "access '.$expire.'"',
253 - 'ExpiresByType text/html "access '.$expire.'"',
254 490 'ExpiresByType image/gif "access '.$expire.'"',
255 491 'ExpiresByType image/png "access '.$expire.'"',
256 492 'ExpiresByType image/jpg "access '.$expire.'"',
257 493 'ExpiresByType image/jpeg "access '.$expire.'"',
@@ -260,9 +496,19 @@
260 496 'ExpiresByType application/pdf "access '.$expire.'"',
261 497 'ExpiresByType application/javascript "access '.$expire.'"',
262 498 'ExpiresByType text/x-javascript "access '.$expire.'"',
263 499 'ExpiresByType application/x-shockwave-flash "access '.$expire.'"',
264 - 'ExpiresDefault "access '.$expire.'"',
500 + 'ExpiresByType image/svg+xml "access '.$expire.'"',
501 + 'ExpiresByType font/woff "access '.$expire.'"',
502 + 'ExpiresByType font/woff2 "access '.$expire.'"',
503 + 'ExpiresByType font/x-woff "access '.$expire.'"',
504 + 'ExpiresByType application/font-woff "access '.$expire.'"',
505 + 'ExpiresByType application/x-font-woff "access '.$expire.'"',
506 + 'ExpiresByType font/ttf "access '.$expire.'"',
507 + 'ExpiresByType font/otf "access '.$expire.'"',
508 + 'ExpiresByType application/vnd.ms-fontobject "access '.$expire.'"',
509 + 'ExpiresByType application/json "access 0 seconds"',
510 + 'ExpiresByType application/xml "access 0 seconds"',
265 511 '</IfModule>',
266 512 ),
267 513 '',
268 514 array(
@@ -267,27 +513,42 @@
267 513 '',
268 514 array(
269 515 '<IfModule mod_headers.c>',
270 516 array(
271 - '<filesMatch "\.(ico|jpe?g|png|gif|webp|swf)$">',
272 - 'Header set Cache-Control "public"',
273 - '</filesMatch>',
517 + '<FilesMatch "\.(ico|jpe?g|png|gif|webp|swf|svg)$">',
518 + 'Header set Cache-Control "public, max-age='.$max_age.'" env=!WPO_NO_CACHE',
519 + '</FilesMatch>',
274 520 ),
275 521 array(
276 - '<filesMatch "\.(css)$">',
277 - 'Header set Cache-Control "public"',
278 - '</filesMatch>',
522 + '<FilesMatch "\.(css)$">',
523 + 'Header set Cache-Control "public, max-age='.$max_age.'" env=!WPO_NO_CACHE',
524 + '</FilesMatch>',
279 525 ),
280 526 array(
281 - '<filesMatch "\.(js)$">',
282 - 'Header set Cache-Control "private"',
283 - '</filesMatch>',
527 + '<FilesMatch "\.(js)$">',
528 + 'Header set Cache-Control "private, max-age='.$max_age.'" env=!WPO_NO_CACHE',
529 + '</FilesMatch>',
284 530 ),
285 531 array(
286 - '<filesMatch "\.(x?html?|php)$">',
287 - 'Header set Cache-Control "private, must-revalidate"',
288 - '</filesMatch>',
532 + '<FilesMatch "\.(woff2?|ttf|otf|eot)$">',
533 + 'Header set Cache-Control "public, max-age='.$max_age.'" env=!WPO_NO_CACHE',
534 + '</FilesMatch>',
289 535 ),
536 + array(
537 + '<FilesMatch "\.(x?html?)$">',
538 + 'Header set Cache-Control "private, must-revalidate, max-age='.$max_age.'" env=!WPO_NO_CACHE',
539 + '</FilesMatch>',
540 + ),
541 + array(
542 + '<FilesMatch "\.php$">',
543 + 'Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"',
544 + '</FilesMatch>',
545 + ),
546 + '</IfModule>',
547 + ),
548 + array(
549 + '<IfModule mod_headers.c>',
550 + 'Header unset Expires env=WPO_NO_CACHE',
290 551 '</IfModule>',
291 552 ),
292 553 '',
293 554 '#Disable ETag',