PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.21
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.21
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
wp-optimize / cache / class-wpo-page-cache.php

class-wpo-page-cache.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.21, at cache/class-wpo-page-cache.php

1,465 lines 44.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Page caching functionality
4 *
5 * Acknowledgement: The page cache functionality was loosely based on the simple cache plugin - https://github.com/tlovett1/simple-cache
6 */
7
8 if (!defined('ABSPATH')) die('No direct access allowed');
9
10 /**
11 * Base cache directory, everything else goes under here
12 */
13 if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', untrailingslashit(WP_CONTENT_DIR).'/wpo-cache');
14
15 /**
16 * Extensions directory.
17 */
18 if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', dirname(__FILE__).'/extensions');
19
20 /**
21 * Directory that stores config and related files
22 */
23 if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');
24
25 /**
26 * Directory that stores the cache, including gzipped files and mobile specific cache
27 */
28 if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-cache');
29
30 require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';
31
32 if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
33 require_once dirname(__FILE__) . '/php-5.3-functions.php';
34 }
35
36 wpo_cache_load_extensions();
37
38 if (!class_exists('WPO_Page_Cache')) :
39
40 class WPO_Page_Cache {
41
42 /**
43 * Cache config object
44 *
45 * @var mixed
46 */
47 public $config;
48
49 /**
50 * Logger for this class
51 *
52 * @var mixed
53 */
54 public $logger;
55
56 /**
57 * Instance of this class
58 *
59 * @var mixed
60 */
61 public static $instance;
62
63 /**
64 * Store last advanced cache file writing status
65 * If true then last writing finished with error
66 *
67 * @var bool
68 */
69 public $advanced_cache_file_writing_error;
70
71 /**
72 * Store errors
73 *
74 * @var array
75 */
76 private $_errors = array();
77
78 /**
79 * Last advanced cache file content
80 *
81 * @var string
82 */
83 public $advanced_cache_file_content;
84
85 /**
86 * Store the latest advanced-cache.php version required
87 *
88 * @var string
89 */
90 private $_minimum_advanced_cache_file_version = '3.0.17';
91
92 public $should_purge;
93
94 /**
95 * Set everything up here
96 */
97 public function __construct() {
98 $this->config = WPO_Cache_Config::instance();
99 WPO_Cache_Rules::instance();
100 $this->logger = new Updraft_PHP_Logger();
101
102 add_action('activated_plugin', array($this, 'activate_deactivate_plugin'));
103 add_action('deactivate_plugin', array($this, 'activate_deactivate_plugin'));
104 add_action('wpo_purge_old_cache', array($this, 'purge_old'));
105
106 /**
107 * Regenerate config file on cache flush.
108 */
109 add_action('wpo_cache_flush', array($this, 'update_cache_config'));
110 add_action('wpo_cache_flush', array($this, 'delete_cache_size_information'));
111 add_action('update_option_permalink_structure', array($this, 'update_option_permalink_structure'), 10, 3);
112
113 // Add purge cache link to admin bar.
114 add_filter('wpo_cache_admin_bar_menu_items', array($this, 'admin_bar_purge_cache'), 20, 1);
115
116 // Handle single page purge.
117 add_action('wp_loaded', array($this, 'handle_purge_single_page_cache'));
118
119 add_action('admin_init', array($this, 'admin_init'));
120
121 add_action('update_option_gmt_offset', array($this, 'update_gmt_offset_timezone_string_config'), 10, 3);
122 add_action('update_option_timezone_string', array($this, 'update_gmt_offset_timezone_string_config'), 10, 3);
123 add_action('update_option_date_format', array($this, 'update_option_date_format'), 10, 2);
124 add_action('update_option_time_format', array($this, 'update_option_time_format'), 10, 2);
125
126 $this->check_compatibility_issues();
127
128 add_filter('cron_schedules', array($this, 'cron_schedules'));
129 add_action('wpo_save_images_settings', array($this, 'update_webp_images_option'));
130 }
131
132 /**
133 * Activate cron job for deleting expired cache files
134 */
135 public function cron_activate() {
136 $page_cache_length = $this->config->get_option('page_cache_length');
137 if (!wp_next_scheduled('wpo_purge_old_cache')) {
138 wp_schedule_event(time() + (false === $page_cache_length ? '86400' : $page_cache_length), 'wpo_purge_old_cache', 'wpo_purge_old_cache');
139 }
140 }
141
142 /**
143 * Do required actions on activate/deactivate any plugin.
144 */
145 public function activate_deactivate_plugin() {
146
147 wp_clear_scheduled_hook('wpo_purge_old_cache');
148
149 $this->update_cache_config();
150
151 $this->purge();
152 }
153
154 /**
155 * Check if current user can purge cache.
156 *
157 * @return bool
158 */
159 public function can_purge_cache() {
160 if (!$this->is_enabled()) return false;
161 $required_capability = is_multisite() ? 'manage_network_options' : 'manage_options';
162
163 if (WP_Optimize::is_premium()) {
164 return current_user_can($required_capability) || WP_Optimize_Premium()->can_purge_the_cache();
165 } else {
166 return current_user_can($required_capability);
167 }
168 }
169
170 /**
171 * Add Purge from cache in admin bar.
172 *
173 * @param array $menu_items
174 * @return array
175 */
176 public function admin_bar_purge_cache($menu_items) {
177 global $pagenow;
178 if (!$this->can_purge_cache()) return $menu_items;
179
180 $act_url = remove_query_arg(array('wpo_single_page_cache_purged', 'wpo_all_pages_cache_purged'));
181
182 $cache_size = $this->get_cache_size();
183 $cache_size_info = '<h4>'.__('Page cache', 'wp-optimize').'</h4>';
184 $cache_size_info .= '<span>'.__('Cache size:', 'wp-optimize').' '. WP_Optimize()->format_size($cache_size['size']).' '.sprintf(__('(%d files)', 'wp-optimize'), $cache_size['file_count']).'</span>';
185
186 $menu_items[] = array(
187 'id' => 'wpo_cache_stats',
188 'title' => $cache_size_info,
189 'meta' => array(
190 'class' => 'wpo-cache-stats',
191 ),
192 'parent' => 'wpo_purge_cache',
193 );
194
195 $menu_items[] = array(
196 'id' => 'wpo_purge_all_pages_cache',
197 'title' => __('Purge cache for all pages', 'wp-optimize'),
198 'href' => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_all_pages_cache'), $act_url),
199 'meta' => array(
200 'title' => __('Purge cache for all pages', 'wp-optimize'),
201 ),
202 'parent' => 'wpo_purge_cache',
203 );
204
205 if (!is_admin() || 'post.php' == $pagenow) {
206 $menu_items[] = array(
207 'id' => 'wpo_purge_this_page_cache',
208 'title' => __('Purge cache for this page', 'wp-optimize'),
209 'href' => add_query_arg('_wpo_purge', wp_create_nonce('wpo_purge_single_page_cache'), $act_url),
210 'meta' => array(
211 'title' => __('Purge cache for this page', 'wp-optimize'),
212 ),
213 'parent' => 'wpo_purge_cache',
214 );
215 }
216
217 return $menu_items;
218
219 }
220
221 /**
222 * Check if purge single page action sent and purge cache.
223 */
224 public function handle_purge_single_page_cache() {
225
226 if (!$this->can_purge_cache()) return;
227
228 if (isset($_GET['wpo_single_page_cache_purged']) || isset($_GET['wpo_all_pages_cache_purged'])) {
229 if (isset($_GET['wpo_single_page_cache_purged'])) {
230 $notice_function = $_GET['wpo_single_page_cache_purged'] ? 'notice_purge_single_page_cache_success' : 'notice_purge_single_page_cache_error';
231 } else {
232 $notice_function = $_GET['wpo_all_pages_cache_purged'] ? 'notice_purge_all_pages_cache_success' : 'notice_purge_all_pages_cache_error';
233 }
234
235 add_action('admin_notices', array($this, $notice_function));
236
237 return;
238 }
239
240 if (!isset($_GET['_wpo_purge'])) return;
241
242 if (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_single_page_cache')) {
243 $success = false;
244
245 if (is_admin()) {
246 $post = isset($_GET['post']) ? (int) $_GET['post'] : 0;
247 if ($post > 0) {
248 $success = self::delete_single_post_cache($post);
249 }
250 } else {
251 $success = self::delete_cache_by_url(wpo_current_url());
252 }
253
254 // remove nonce from url and reload page.
255 wp_redirect(add_query_arg('wpo_single_page_cache_purged', $success, remove_query_arg('_wpo_purge')));
256 exit;
257
258 } elseif (wp_verify_nonce($_GET['_wpo_purge'], 'wpo_purge_all_pages_cache')) {
259 $success = self::purge();
260
261 // remove nonce from url and reload page.
262 wp_redirect(add_query_arg('wpo_all_pages_cache_purged', $success, remove_query_arg('_wpo_purge')));
263 exit;
264 }
265 }
266
267 /**
268 * Show notification when page cache purged successfully.
269 */
270 public function notice_purge_single_page_cache_success() {
271 $this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
272 }
273
274 /**
275 * Show notification when page cache wasn't purged.
276 */
277 public function notice_purge_single_page_cache_error() {
278 $this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
279 }
280
281 /**
282 * Show notification when all pages cache purged successfully.
283 */
284 public function notice_purge_all_pages_cache_success() {
285 $this->show_notice(__('The page cache was successfully purged.', 'wp-optimize'), 'success');
286 }
287
288 /**
289 * Show notification when all pages cache wasn't purged.
290 */
291 public function notice_purge_all_pages_cache_error() {
292 $this->show_notice(__('The page cache was not purged.', 'wp-optimize'), 'error');
293 }
294
295 /**
296 * Show notification in WordPress admin.
297 *
298 * @param string $message HTML (no further escaping is performed)
299 * @param string $type error, warning, success, or info
300 */
301 public function show_notice($message, $type) {
302 global $current_screen;
303
304 if ($current_screen && is_callable(array($current_screen, 'is_block_editor')) && $current_screen->is_block_editor()) : ?>
305 <script>
306 window.addEventListener('load', function() {
307 (function(wp) {
308 if (window.wp && wp.hasOwnProperty('data') && 'function' == typeof wp.data.dispatch) {
309 wp.data.dispatch('core/notices').createNotice(
310 '<?php echo $type; ?>',
311 '<?php echo $message; ?>',
312 {
313 isDismissible: true,
314 }
315 );
316 }
317 })(window.wp);
318 });
319 </script>
320 <?php else : ?>
321 <div class="notice wpo-notice notice-<?php echo $type; ?> is-dismissible">
322 <p><?php echo $message; ?></p>
323 </div>
324 <?php
325 endif;
326 }
327
328 /**
329 * Enables page cache
330 *
331 * @param bool $force_enable - Force regenerating everything. E.g. we want to do that when saving the settings
332 *
333 * @return WP_Error|bool - true on success, error otherwise
334 */
335 public function enable($force_enable = false) {
336 static $already_ran_enable = false;
337
338 if ($already_ran_enable) return $already_ran_enable;
339
340 $folders_created = $this->create_folders();
341 if (is_wp_error($folders_created)) {
342 $already_ran_enable = $folders_created;
343 return $already_ran_enable;
344 }
345
346 // if WPO_ADVANCED_CACHE isn't set, or environment doesn't contain the right constant, force regeneration
347 if (!defined('WPO_ADVANCED_CACHE') || !defined('WP_CACHE')) {
348 $force_enable = true;
349 }
350
351 $this->maybe_regenerate_cache_config_file();
352
353 if (!$force_enable) {
354 $already_ran_enable = true;
355 return true;
356 }
357
358 if (!$this->write_advanced_cache() && version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<')) {
359 $message = sprintf("The request to write the file %s failed. ", htmlspecialchars($this->get_advanced_cache_filename()));
360 $message .= ' '.__('Please check file and directory permissions on the file paths up to this point, and your PHP error log.', 'wp-optimize');
361
362 if (!defined('WP_CLI') || !WP_CLI) {
363 $message .= "\n\n1. ".sprintf(__('Please navigate, via FTP, to the folder - %s', 'wp-optimize'), htmlspecialchars(dirname($this->get_advanced_cache_filename())));
364 $message .= "\n2. ".__('Edit or create a file with the name advanced-cache.php', 'wp-optimize');
365 $message .= "\n3. ".__('Copy and paste the following lines into the file:', 'wp-optimize');
366 }
367
368 $already_ran_enable = new WP_Error("write_advanced_cache", $message);
369 return $already_ran_enable;
370 }
371
372 if (!$this->write_wp_config(true)) {
373 $already_ran_enable = new WP_Error("write_wp_config", "Could not turn on the WP_CACHE constant in wp-config.php. Check your permissions.");
374 return $already_ran_enable;
375 }
376
377 if (!$this->verify_cache()) {
378 $errors = $this->get_errors();
379 $already_ran_enable = new WP_Error("verify_cache", "Could not verify if the cache was enabled: \n".implode("\n- ", $errors));
380 return $already_ran_enable;
381 }
382
383 $already_ran_enable = true;
384
385 return true;
386 }
387
388 /**
389 * Disables page cache
390 *
391 * @return bool - true on success, false otherwise
392 */
393 public function disable() {
394 $ret = true;
395
396 $advanced_cache_file = $this->get_advanced_cache_filename();
397
398 // N.B. The only use of WP_CACHE in WP core is to include('advanced-cache.php') (and run a function if it's then defined); so, if the decision to leave it enable is, for some unexpected reason, technically incorrect, it still can't cause a problem.
399 $disabled_wp_config = $this->write_wp_config(false);
400 if (!$disabled_wp_config) {
401 $plugin_basename = basename(WPO_PLUGIN_MAIN_PATH);
402 $action = "deactivate_".$plugin_basename."/wp-optimize.php";
403 if (current_action() === $action) {
404 $cache_config = WPO_Cache_Config::instance()->config;
405 $cache_config['enable_page_caching'] = false;
406 WPO_Cache_Config::instance()->update($cache_config, true);
407 }
408 $this->log("Could not turn off the WP_CACHE constant in wp-config.php");
409 $this->add_warning('error_disabling', __('Could not turn off the WP_CACHE constant in wp-config.php', 'wp-optimize'));
410 }
411
412 $disabled_advanced_cache = true;
413 // First try to remove (so that it doesn't look to any other plugin like the file is already 'claimed')
414 // We only touch advanched-cache.php and wp-config.php if it appears that we were in control of advanced-cache.php
415 if (!file_exists($advanced_cache_file) || false !== strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) {
416 if (file_exists($advanced_cache_file) && (!unlink($advanced_cache_file) && false === file_put_contents($advanced_cache_file, "<?php\n// WP-Optimize: page cache disabled"))) {
417 $disabled_advanced_cache = false;
418 $this->log("The request to the filesystem to remove or empty advanced-cache.php failed");
419 $this->add_warning('error_disabling', __('The request to the filesystem to remove or empty advanced-cache.php failed', 'wp-optimize'));
420 }
421 }
422
423 // If both actions failed, the cache wasn't disabled. So we send an error. If only one succeeds, it will still be disabled.
424 if (!$disabled_wp_config && !$disabled_advanced_cache) {
425 $ret = new WP_Error('error_disabling_cache', __('The page caching could not be disabled: the WP_CACHE constant could not be removed from wp-config.php and the request to the filesystem to remove or empty advanced-cache.php failed.', 'wp-optimize'));
426 }
427
428 // Delete cache to avoid stale cache on next activation
429 $this->purge();
430
431 return $ret;
432 }
433
434
435 /**
436 * Purges the cache
437 *
438 * @return bool - true on success, false otherwise
439 */
440 public function purge() {
441 /**
442 * Filters whether activating / deactivating a plugin will purge the cache.
443 */
444 $this->should_purge = apply_filters('wpo_purge_page_cache_on_activate_deactivate_plugin', true);
445 $purge_actions = array(
446 'deactivate_' . plugin_basename(WPO_PLUGIN_MAIN_PATH . 'wp-optimize.php'),
447 'deactivate_plugin',
448 'activated_plugin',
449 );
450 $is_deactivation_action = in_array(current_action(), $purge_actions, true);
451 if ($is_deactivation_action && !$this->should_purge) return false;
452
453 if (!self::delete(WPO_CACHE_FILES_DIR)) {
454 $this->log("The request to the filesystem to delete the cache failed");
455 return false;
456 }
457
458 /**
459 * Fires after purging the cache
460 */
461 do_action('wpo_cache_flush');
462
463 return true;
464 }
465
466 /**
467 * Purge cache files older than cache life span
468 *
469 * @return array Log messages.
470 */
471 public function purge_old() {
472 $log = array();
473 $page_cache_length = $this->config->get_option('page_cache_length');
474 if (0 === $page_cache_length) return $log;
475 $expires = time() - $page_cache_length;
476 $cache_folder = WPO_CACHE_FILES_DIR . '/' . str_ireplace(array('http://', 'https://'), '', get_site_url());
477 // get all directories that are a direct child of current directory
478 if (is_dir($cache_folder) && is_writable($cache_folder)) {
479 if ($handle = opendir($cache_folder)) {
480 while (false !== ($d = readdir($handle))) {
481 if (0 == strcmp($d, '.') || 0 == strcmp($d, '..')) {
482 continue;
483 }
484
485 if ($this->is_front_page_cache($d)) {
486 $modified_time = (int) filemtime("$cache_folder/$d");
487 if ($modified_time <= $expires) {
488 unlink("$cache_folder/$d");
489 }
490 continue;
491 }
492
493 $dir = $cache_folder.'/'.$d;
494 if (!is_dir($dir)) continue;
495
496 $stat = stat($dir);
497 $modified_time = $stat['mtime'];
498 $log[] = "checking if cache has expired - $d";
499 if ($modified_time <= $expires) {
500 $log[] = "deleting cache in $dir";
501 wpo_delete_files($dir, true);
502 if (file_exists($dir)) rmdir($dir);
503 }
504 }
505 closedir($handle);
506 }
507 }
508 return $log;
509 }
510
511 /**
512 * Finds out given cache file is of front page or not
513 *
514 * @return bool
515 */
516 private function is_front_page_cache($d) {
517 return in_array($d, array('index.html', 'index.html.gz'));
518 }
519
520 /**
521 * Purges the cache
522 *
523 * @return bool - true on success, false otherwise
524 */
525 public function clean_up() {
526
527 $this->disable();
528
529 if (!self::delete(WPO_CACHE_DIR, true)) {
530 $this->log("The request to the filesystem to clean up the cache failed");
531 return false;
532 }
533
534 return true;
535 }
536
537 /**
538 * Check if cache is enabled and working
539 *
540 * @return bool - true on success, false otherwise
541 */
542 public function is_enabled() {
543
544 if (!$this->config->get_option('enable_page_caching')) return false;
545
546 if (!defined('WP_CACHE') || !WP_CACHE) {
547 if ((!(defined('WP_CLI') && WP_CLI)) && (!defined('DOING_AJAX') || !DOING_AJAX)) {
548 $this->log("WP_CACHE constant is not present in wp-config.php");
549 return false;
550 }
551 }
552
553 if (!defined('WPO_ADVANCED_CACHE') || !WPO_ADVANCED_CACHE) {
554 if ((!(defined('WP_CLI') && WP_CLI)) && (!defined('DOING_AJAX') || !DOING_AJAX)) {
555 $this->log("WPO_ADVANCED_CACHE constant is not present in advanced-cache.php");
556 return false;
557 }
558 }
559
560 $config_file = WPO_CACHE_CONFIG_DIR . '/'.$this->config->get_cache_config_filename();
561 if (!file_exists($config_file)) {
562 if ((!(defined('WP_CLI') && WP_CLI)) && (!defined('DOING_AJAX') || !DOING_AJAX)) {
563 $this->log("Cache config file $config_file is not present");
564 return false;
565 }
566 }
567
568 return true;
569 }
570
571 /**
572 * Create the folder structure needed for cache to work
573 *
574 * @return bool - true on success, false otherwise
575 */
576 public function create_folders() {
577 $permissions_str = __('Please check your file permissions.', 'wp-optimize');
578
579 if (!is_dir(WPO_CACHE_DIR) && !wp_mkdir_p(WPO_CACHE_DIR)) {
580 return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s.', 'wp-optimize'), str_ireplace(ABSPATH, '', WPO_CACHE_DIR)) .' '. $permissions_str);
581 }
582
583 if (!is_dir(WPO_CACHE_CONFIG_DIR) && !wp_mkdir_p(WPO_CACHE_CONFIG_DIR)) {
584 return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s.', 'wp-optimize'), str_ireplace(ABSPATH, '', WPO_CACHE_CONFIG_DIR)) .' '. $permissions_str);
585 }
586
587 if (!is_dir(WPO_CACHE_FILES_DIR)) {
588 if (!wp_mkdir_p(WPO_CACHE_FILES_DIR)) {
589 return new WP_Error('create_folders', sprintf(__('The request to the filesystem failed: unable to create directory %s.', 'wp-optimize'), str_ireplace(ABSPATH, '', WPO_CACHE_FILES_DIR)) .' '. $permissions_str);
590 } else {
591 wpo_disable_cache_directories_viewing();
592 }
593 }
594
595 return true;
596 }
597
598 /**
599 * Get advanced-cache.php file name with full path.
600 *
601 * @return string
602 */
603 public function get_advanced_cache_filename() {
604 return untrailingslashit(WP_CONTENT_DIR) . '/advanced-cache.php';
605 }
606
607 /**
608 * Writes advanced-cache.php
609 *
610 * @param boolean $update_required - Whether the update is required or not.
611 * @return bool
612 */
613 private function write_advanced_cache($update_required = false) {
614 $config_file_basename = $this->config->get_cache_config_filename();
615 $cache_file_basename = untrailingslashit(plugin_dir_path(__FILE__));
616 $plugin_basename = basename(WPO_PLUGIN_MAIN_PATH);
617 $cache_path = '/wpo-cache';
618 $cache_files_path = '/cache/wpo-cache';
619 $cache_extensions_path = WPO_CACHE_EXT_DIR;
620 $wpo_version = WPO_VERSION;
621 $wpo_home_url = trailingslashit(home_url());
622
623 // CS does not like heredoc
624 // phpcs:disable
625 $this->advanced_cache_file_content = <<<EOF
626 <?php
627
628 if (!defined('ABSPATH')) die('No direct access allowed');
629
630 // WP-Optimize advanced-cache.php (written by version: $wpo_version) (do not change this line, it is used for correctness checks)
631
632 if (!defined('WPO_ADVANCED_CACHE')) define('WPO_ADVANCED_CACHE', true);
633
634 \$possible_plugin_locations = array(
635 defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR.'/$plugin_basename/cache' : false,
636 defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR.'/plugins/$plugin_basename/cache' : false,
637 dirname(__FILE__).'/plugins/$plugin_basename/cache',
638 '$cache_file_basename',
639 );
640
641 \$plugin_location = false;
642
643 foreach (\$possible_plugin_locations as \$possible_location) {
644 if (false !== \$possible_location && @file_exists(\$possible_location.'/file-based-page-cache.php')) {
645 \$plugin_location = \$possible_location;
646 break;
647 }
648 }
649
650 if (false === \$plugin_location) {
651 if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND')) define('WPO_PLUGIN_LOCATION_NOT_FOUND', true);
652 \$protocol = \$_SERVER['REQUEST_SCHEME'];
653 \$host = \$_SERVER['HTTP_HOST'];
654 \$request_uri = \$_SERVER['REQUEST_URI'];
655 if (strcasecmp('$wpo_home_url', \$protocol . '://' . \$host . \$request_uri) === 0) {
656 error_log('WP-Optimize: No caching took place, because the plugin location could not be found');
657 }
658 } else {
659 if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND')) define('WPO_PLUGIN_LOCATION_NOT_FOUND', false);
660 }
661
662 if (is_admin()) { return; }
663
664 if (!defined('WPO_CACHE_DIR')) define('WPO_CACHE_DIR', WP_CONTENT_DIR.'$cache_path');
665 if (!defined('WPO_CACHE_CONFIG_DIR')) define('WPO_CACHE_CONFIG_DIR', WPO_CACHE_DIR.'/config');
666 if (!defined('WPO_CACHE_FILES_DIR')) define('WPO_CACHE_FILES_DIR', WP_CONTENT_DIR.'$cache_files_path');
667 if (false !== \$plugin_location) {
668 if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', \$plugin_location.'/extensions');
669 } else {
670 if (!defined('WPO_CACHE_EXT_DIR')) define('WPO_CACHE_EXT_DIR', '$cache_extensions_path');
671 }
672
673 if (!@file_exists(WPO_CACHE_CONFIG_DIR . '/$config_file_basename')) { return; }
674
675 \$GLOBALS['wpo_cache_config'] = @json_decode(file_get_contents(WPO_CACHE_CONFIG_DIR . '/$config_file_basename'), true);
676
677 if (empty(\$GLOBALS['wpo_cache_config'])) {
678 include_once(WPO_CACHE_CONFIG_DIR . '/$config_file_basename');
679 }
680
681 if (empty(\$GLOBALS['wpo_cache_config'])) {
682 error_log('WP-Optimize: Caching failed because the configuration data could not be loaded from the config file.');
683 return;
684 }
685
686 if (empty(\$GLOBALS['wpo_cache_config']['enable_page_caching'])) { return; }
687
688 if (false !== \$plugin_location) { include_once(\$plugin_location.'/file-based-page-cache.php'); }
689
690 EOF;
691
692 // phpcs:enable
693 $advanced_cache_filename = $this->get_advanced_cache_filename();
694
695 // If the file content is already up to date, success
696 if (is_file($advanced_cache_filename) && file_get_contents($advanced_cache_filename) === $this->advanced_cache_file_content) {
697 $this->advanced_cache_file_writing_error = false;
698 return true;
699 }
700
701 // check if we can't write the advanced cache file
702 // case 1: the directory is read-only and the file doesn't exist
703 if (!is_file($advanced_cache_filename) && !is_writable(dirname($advanced_cache_filename))) {
704 $this->advanced_cache_file_writing_error = true;
705 return false;
706 }
707
708 // case 2: the file already exists but it's read-only
709 if (is_file($advanced_cache_filename) && !is_writable($advanced_cache_filename)) {
710 if (version_compare($this->get_advanced_cache_version(), $this->_minimum_advanced_cache_file_version, '<') || $update_required) {
711 $this->advanced_cache_file_writing_error = true;
712 return false;
713 } else {
714 $this->advanced_cache_file_writing_error = false;
715 return true;
716 }
717 }
718
719 if (!file_put_contents($this->get_advanced_cache_filename(), $this->advanced_cache_file_content)) {
720 $this->advanced_cache_file_writing_error = true;
721 return false;
722 }
723
724 $this->advanced_cache_file_writing_error = false;
725 return true;
726 }
727
728 /**
729 * Update advanced cache version if needed.
730 */
731 public function maybe_update_advanced_cache() {
732
733 if (!$this->is_enabled()) return;
734
735 if (!defined('WPO_PLUGIN_LOCATION_NOT_FOUND') || (defined('WPO_PLUGIN_LOCATION_NOT_FOUND') && true === WPO_PLUGIN_LOCATION_NOT_FOUND)) {
736 if (!$this->write_advanced_cache(true)) {
737 add_action('admin_notices', array($this, 'show_admin_notice_advanced_cache'));
738 }
739 }
740
741 // from 3.0.17 we use more secure way to store cache config files and need update advanced-cache.php
742 $advanced_cache_current_version = $this->get_advanced_cache_version();
743 if ($advanced_cache_current_version && version_compare($advanced_cache_current_version, $this->_minimum_advanced_cache_file_version, '>=')) return;
744
745 if (!$this->write_advanced_cache()) {
746 add_action('admin_notices', array($this, 'notice_advanced_cache_autoupdate_error'));
747 } else {
748 $this->update_cache_config();
749 }
750 }
751
752 /**
753 * Show notification when advanced-cache.php could not be updated.
754 */
755 public function notice_advanced_cache_autoupdate_error() {
756 $this->show_notice(__('The file advanced-cache.php needs to be updated, but the automatic process failed.', 'wp-optimize').
757 ' <a href="'.admin_url('admin.php?page=wpo_cache').'">'.__('Please try to disable and then re-enable the WP-Optimize cache manually.', 'wp-optimize').'</a>', 'error');
758 }
759
760 /**
761 * Get WPO version number from advanced-cache.php file.
762 *
763 * @return bool|mixed
764 */
765 public function get_advanced_cache_version() {
766 if (!is_file($this->get_advanced_cache_filename())) return false;
767
768 $version = false;
769 $content = file_get_contents($this->get_advanced_cache_filename());
770
771 if (preg_match('/WP\-Optimize advanced\-cache\.php \(written by version\: (.+)\)/Ui', $content, $match)) {
772 $version = $match[1];
773 }
774
775 return $version;
776 }
777
778 /**
779 * Set WP_CACHE on or off in wp-config.php
780 *
781 * @param boolean $status value of WP_CACHE.
782 * @return boolean true if the value was set, false otherwise
783 */
784 private function write_wp_config($status = true) {
785 // If we changed the value in wp-config, save it, in case we need to change it again in the same run.
786 static $changed = false;
787
788 if (defined('WP_CACHE') && WP_CACHE === $status && !$changed) {
789 return true;
790 }
791
792 $config_path = $this->_get_wp_config();
793
794 // Couldn't find wp-config.php.
795 if (!$config_path) {
796 return false;
797 }
798
799 $config_file_string = file_get_contents($config_path);
800
801 // Config file is empty. Maybe couldn't read it?
802 if (empty($config_file_string)) {
803 return false;
804 }
805
806 $config_file = preg_split("#(\n|\r\n)#", $config_file_string);
807 $line_key = false;
808
809 foreach ($config_file as $key => $line) {
810 if (!preg_match('/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/i', $line, $match)) {
811 continue;
812 }
813
814 if ('WP_CACHE' === $match[2]) {
815 $line_key = $key;
816 }
817 }
818
819 if (false !== $line_key) {
820 unset($config_file[$line_key]);
821 }
822
823
824 if ($status) {
825 array_shift($config_file);
826 array_unshift($config_file, '<?php', "define('WP_CACHE', true); // WP-Optimize Cache");
827 }
828
829 foreach ($config_file as $key => $line) {
830 if ('' === $line) {
831 unset($config_file[$key]);
832 }
833 }
834 if (!file_put_contents($config_path, implode(PHP_EOL, $config_file))) {
835 return false;
836 }
837 $changed = true;
838 return true;
839 }
840
841 /**
842 * Verify we can write to the file system
843 *
844 * @return boolean
845 */
846 private function verify_cache() {
847 if (function_exists('clearstatcache')) {
848 clearstatcache();
849 }
850 $errors = 0;
851
852 // First check wp-config.php.
853 if (!$this->_get_wp_config() && !is_writable($this->_get_wp_config())) {
854 $this->log("Unable to write to or find wp-config.php; please check file/folder permissions");
855 $this->add_warning('verify_cache', __("Unable to write to or find wp-config.php; please check file/folder permissions.", 'wp-optimize'));
856 }
857
858 $advanced_cache_file = untrailingslashit(WP_CONTENT_DIR).'/advanced-cache.php';
859
860 // Now check wp-content. We need to be able to create files of the same user as this file.
861 if ((!file_exists($advanced_cache_file) || false === strpos(file_get_contents($advanced_cache_file), 'WP-Optimize advanced-cache.php')) && !is_writable($advanced_cache_file) && !is_writable(untrailingslashit(WP_CONTENT_DIR))) {
862 $this->log("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions");
863 $this->add_error('verify_cache', __("Unable to write the file advanced-cache.php inside the wp-content folder; please check file/folder permissions", 'wp-optimize'));
864 $errors++;
865 }
866
867 if (file_exists(WPO_CACHE_FILES_DIR)) {
868 if (!is_writable(WPO_CACHE_FILES_DIR)) {
869 $this->log("Unable to write inside the cache files folder; please check file/folder permissions");
870 $this->add_warning('verify_cache', sprintf(__("Unable to write inside the cache files folder (%s); please check file/folder permissions (no cache files will be able to be created otherwise)", 'wp-optimize'), WPO_CACHE_FILES_DIR));
871 }
872 }
873
874 if (file_exists(WPO_CACHE_CONFIG_DIR)) {
875 if (!is_writable(WPO_CACHE_CONFIG_DIR)) {
876 $this->log("Unable to write inside the cache configuration folder; please check file/folder permissions");
877 // If the config exists, only send a warning. Otherwise send an error.
878 $type = 'warning';
879 if (!file_exists(WPO_CACHE_CONFIG_DIR . '/'.$this->config->get_cache_config_filename())) {
880 $type = 'error';
881 $errors++;
882 }
883 $this->add_error('verify_cache', sprintf(__("Unable to write inside the cache configuration folder (%s); please check file/folder permissions", 'wp-optimize'), WPO_CACHE_CONFIG_DIR), $type);
884 }
885 }
886
887 return !$errors;
888 }
889
890 /**
891 * Update permalink structure in cache config
892 *
893 * @param string $old_value Old value of permalink_structure option
894 * @param string $value New value of permalink_structure option
895 * @param string $option Option name `permalink_structure`
896 */
897 public function update_option_permalink_structure($old_value, $value, $option) {
898 $current_config = $this->config->get();
899 if ($old_value != $value) {
900 $current_config[$option] = $value;
901 $this->config->update($current_config, true);
902 }
903 }
904
905 /**
906 * Update cache config. Used to support 3d party plugins.
907 */
908 public function update_cache_config() {
909 // get current cache settings.
910 $current_config = $this->config->get();
911 // and call update to change if need cookies and query variable names.
912 $this->config->update($current_config, true);
913 }
914
915 /**
916 * Delete information about cache size.
917 */
918 public function delete_cache_size_information() {
919 delete_transient('wpo_get_cache_size');
920 }
921
922 /**
923 * Get current cache size.
924 *
925 * @return array
926 */
927 public function get_cache_size() {
928 $cache_size = get_transient('wpo_get_cache_size');
929
930 if (!empty($cache_size)) return $cache_size;
931
932 $infos = $this->get_dir_infos(WPO_CACHE_FILES_DIR);
933 $cache_size = array(
934 'size' => $infos['size'],
935 'file_count' => $infos['file_count']
936 );
937
938 set_transient('wpo_get_cache_size', $cache_size);
939
940 return $cache_size;
941 }
942
943 /**
944 * Fetch directory information.
945 *
946 * @param string $dir
947 * @return array
948 */
949 private function get_dir_infos($dir) {
950 $dir_size = 0;
951 $file_count = 0;
952
953 $handle = is_dir($dir) ? opendir($dir) : false;
954
955 if (false === $handle) {
956 return array('size' => 0, 'file_count' => 0);
957 }
958
959 $file = readdir($handle);
960
961 while (false !== $file) {
962
963 if ('.' != $file && '..' != $file) {
964 $current_file = $dir.'/'.$file;
965
966 if (is_dir($current_file)) {
967 $sub_dir_infos = $this->get_dir_infos($current_file);
968 $dir_size += $sub_dir_infos['size'];
969 $file_count += $sub_dir_infos['file_count'];
970 } elseif (is_file($current_file)) {
971 $dir_size += filesize($current_file);
972 $file_count++;
973 }
974 }
975
976 $file = readdir($handle);
977
978 }
979
980 return array('size' => $dir_size, 'file_count' => $file_count);
981 }
982
983 /**
984 * Returns the path to wp-config
985 *
986 * @return string|boolean wp-config.php path.
987 */
988 private function _get_wp_config() {
989
990 $config_path = false;
991
992 foreach (get_included_files() as $filename) {
993 if (preg_match('/(\\\\|\/)wp-config\.php$/i', $filename)) {
994 $config_path = $filename;
995 break;
996 }
997 }
998
999 // WP-CLI doesn't include wp-config.php that's why we use function from WP-CLI to locate config file.
1000 if (!$config_path && is_callable('wpo_wp_cli_locate_wp_config')) {
1001 $config_path = wpo_wp_cli_locate_wp_config();
1002 }
1003
1004 return $config_path;
1005 }
1006
1007 /**
1008 * Util to delete folders and/or files
1009 *
1010 * @param string $src
1011 * @return boolean
1012 */
1013 public static function delete($src) {
1014
1015 return wpo_delete_files($src);
1016
1017 }
1018
1019 /**
1020 * Delete cached files for specific url.
1021 *
1022 * @param string $url
1023 * @param bool $recursive If true child elements will deleted too
1024 *
1025 * @return bool
1026 */
1027 public static function delete_cache_by_url($url, $recursive = false) {
1028 if (!defined('WPO_CACHE_FILES_DIR') || '' == $url) return;
1029
1030 $path = self::get_full_path_from_url($url);
1031
1032 do_action('wpo_delete_cache_by_url', $url, $recursive);
1033
1034 return wpo_delete_files($path, $recursive);
1035 }
1036
1037 /**
1038 * Delete cached files for single post.
1039 *
1040 * @param integer $post_id The post ID
1041 *
1042 * @return bool
1043 */
1044 public static function delete_single_post_cache($post_id) {
1045 $is_cache_deleted = self::really_delete_single_post_cache($post_id);
1046
1047 do_action('wpo_single_post_cache_deleted', $post_id);
1048
1049 return $is_cache_deleted;
1050 }
1051
1052 /**
1053 * Really delete cached files for single post.
1054 *
1055 * @param integer $post_id The post ID
1056 *
1057 * @return bool
1058 */
1059 public static function really_delete_single_post_cache($post_id) {
1060
1061 if (!defined('WPO_CACHE_FILES_DIR')) return;
1062
1063 $post_url = get_permalink($post_id);
1064
1065 $path = self::get_full_path_from_url($post_url);
1066
1067 // for posts with pagination run purging cache recursively.
1068 $post = get_post($post_id);
1069 $recursive = preg_match('/\<\!--nextpage--\>/', $post->post_content) ? true : false;
1070
1071 do_action('wpo_delete_cache_by_url', $post_url, $recursive);
1072
1073 return wpo_delete_files($path, $recursive);
1074 }
1075
1076 /**
1077 * Delete cached home page files.
1078 */
1079 public static function delete_homepage_cache() {
1080
1081 if (!defined('WPO_CACHE_FILES_DIR')) return;
1082
1083 $homepage_url = get_home_url(get_current_blog_id());
1084
1085 $path = self::get_full_path_from_url($homepage_url);
1086
1087 do_action('wpo_delete_cache_by_url', $homepage_url, false);
1088
1089 wpo_delete_files($path, false);
1090 }
1091
1092 /**
1093 * Delete sitemap cache.
1094 */
1095 public static function delete_sitemap_cache() {
1096 if (!defined('WPO_CACHE_FILES_DIR')) return;
1097
1098 $homepage_url = get_home_url(get_current_blog_id());
1099
1100 $path = trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($homepage_url));
1101
1102 if (!is_dir($path)) return;
1103
1104 $handle = opendir($path);
1105
1106 if (false !== $handle) {
1107 $file = readdir($handle);
1108
1109 while (false !== $file) {
1110
1111 if ('.' != $file && '..' != $file && is_dir($path . $file) && preg_match('/.*sitemap.*\.xml/i', $file)) {
1112 do_action('wpo_delete_cache_by_url', $path . $file, false);
1113 wpo_delete_files($path . $file, true);
1114 }
1115
1116 $file = readdir($handle);
1117 }
1118 }
1119
1120 closedir($handle);
1121 }
1122
1123 /**
1124 * Delete feed from cache.
1125 */
1126 public static function delete_feed_cache() {
1127 if (!defined('WPO_CACHE_FILES_DIR')) return;
1128
1129 $homepage_url = get_home_url(get_current_blog_id());
1130
1131 $path = self::get_full_path_from_url($homepage_url) . 'feed/';
1132
1133 do_action('wpo_delete_cache_by_url', $path, true);
1134
1135 wpo_delete_files($path, true);
1136 }
1137
1138 /**
1139 * Delete post feed from cache.
1140 */
1141 public static function delete_post_feed_cache($post_id) {
1142 self::really_delete_post_feed_cache($post_id);
1143
1144 do_action('wpo_single_post_feed_cache_deleted', $post_id);
1145 }
1146
1147 /**
1148 * Really delete post feed from cache.
1149 */
1150 public static function really_delete_post_feed_cache($post_id) {
1151 if (!defined('WPO_CACHE_FILES_DIR')) return;
1152
1153 $post_url = get_permalink($post_id);
1154
1155 $path = self::get_full_path_from_url($post_url) . 'feed/';
1156
1157 do_action('wpo_delete_cache_by_url', $path, true);
1158
1159 wpo_delete_files($path, true);
1160 }
1161
1162 /**
1163 * Delete comments feed from cache.
1164 */
1165 public static function delete_comments_feed() {
1166 if (!defined('WPO_CACHE_FILES_DIR')) return;
1167
1168 $comments_feed_url = trailingslashit(get_home_url(get_current_blog_id())) . 'comments/feed/';
1169
1170 $path = self::get_full_path_from_url($comments_feed_url);
1171
1172 do_action('wpo_delete_cache_by_url', $comments_feed_url, true);
1173
1174 wpo_delete_files($path, true);
1175
1176 // delete empty comments dir from the cache
1177 $comments_url = trailingslashit(get_home_url(get_current_blog_id())) . 'comments/';
1178 $path = self::get_full_path_from_url($comments_url);
1179
1180 if (wpo_is_empty_dir($path)) {
1181 wpo_delete_files($path, true);
1182 }
1183 }
1184
1185 /**
1186 * Returns full path to the cache folder by url.
1187 *
1188 * @param string $url
1189 * @return string
1190 */
1191 private static function get_full_path_from_url($url) {
1192 return trailingslashit(WPO_CACHE_FILES_DIR) . trailingslashit(wpo_get_url_path($url));
1193 }
1194
1195 /**
1196 * Admin actions
1197 *
1198 * @return void
1199 */
1200 public function admin_init() {
1201 // Maybe update the advanced cache.
1202 if ((!defined('DOING_AJAX') || !DOING_AJAX) && current_user_can('update_plugins')) {
1203 $this->maybe_update_advanced_cache();
1204 $this->cron_activate();
1205 }
1206 }
1207
1208 /**
1209 * Logs error messages
1210 *
1211 * @param string $message
1212 * @return null|void
1213 */
1214 public function log($message) {
1215 if (isset($this->logger)) {
1216 $this->logger->log($message, 'error');
1217 }
1218 }
1219
1220 /**
1221 * Returns an instance of the current class, creates one if it doesn't exist
1222 *
1223 * @return object
1224 */
1225 public static function instance() {
1226 if (empty(self::$instance)) {
1227 self::$instance = new self();
1228 }
1229 return self::$instance;
1230 }
1231
1232
1233 /**
1234 * Update gmt_offset and timezone_string cache config value, used with hook `update_gmt_offset_timezone_string_config`.
1235 *
1236 * @param {float|string} $old_value GMT offset as a float value or timezone value supported by PHP as a string (https://www.php.net/manual/en/timezones.php)
1237 * @param {float|string} $new_value
1238 * @param {string} $option gmt_offset|timezone_string
1239 *
1240 * @return null
1241 */
1242 public function update_gmt_offset_timezone_string_config($old_value, $new_value, $option) {
1243 if ('' == $new_value) return;
1244
1245 $current_config = $this->config->get();
1246 if ('timezone_string' == $option) {
1247 $timeZone = new DateTimeZone($new_value);
1248 $dateTime = new DateTime("now");
1249 $gmt_offset = $timeZone->getOffset($dateTime);
1250 $current_config['gmt_offset'] = round($gmt_offset/3600, 1);
1251 $current_config['timezone_string'] = $new_value;
1252 } elseif ('' !== $new_value) {
1253 $current_config['gmt_offset'] = $new_value;
1254 $current_config['timezone_string'] = '';
1255 }
1256 $this->config->update($current_config, true);
1257 }
1258
1259 /**
1260 * Update `date_format` cache config value, used with hook `update_option_date_format`.
1261 *
1262 * @param string $old_value Old date format
1263 * @param string $new_value New date format
1264 *
1265 * @return void
1266 */
1267 public function update_option_date_format($old_value, $new_value) {
1268 $current_config = $this->config->get();
1269 $current_config['date_format'] = $new_value;
1270 $this->config->update($current_config, true);
1271 }
1272
1273 /**
1274 * Update `time_format` cache config value, used with hook `update_option_time_format`.
1275 *
1276 * @param string $old_value Old time format
1277 * @param string $new_value New time format
1278 *
1279 * @return void
1280 */
1281 public function update_option_time_format($old_value, $new_value) {
1282 $current_config = $this->config->get();
1283 $current_config['time_format'] = $new_value;
1284 $this->config->update($current_config, true);
1285 }
1286
1287 /**
1288 * Adds an error to the error store
1289 *
1290 * @param string $code - The error code
1291 * @param string $message - The error's message
1292 * @param string $type - The error's type (error, warning)
1293 * @return void
1294 */
1295 public function add_error($code, $message, $type = 'error') {
1296 if (!isset($this->_errors[$type])) {
1297 $this->_errors[$type] = new WP_Error($code, $message);
1298 } else {
1299 $this->_errors[$type]->add($code, $message);
1300 }
1301 }
1302
1303 /**
1304 * Adds a warning to the error store
1305 *
1306 * @param string $code - The error code
1307 * @param string $message - The error's message
1308 * @return void
1309 */
1310 public function add_warning($code, $message) {
1311 $this->add_error($code, $message, 'warning');
1312 }
1313
1314 /**
1315 * Get all recorded errors
1316 *
1317 * @param string $type - The error type
1318 * @param boolean $get_messages_only - Whether to get only the messages, or the full WP_Error object
1319 * @return boolean|array|WP_Error
1320 */
1321 public function get_errors($type = 'error', $get_messages_only = true) {
1322 if (!$this->has_errors($type)) return false;
1323 $errors = $this->_errors[$type];
1324 if ($get_messages_only) {
1325 return $errors->get_error_messages();
1326 }
1327 return $errors;
1328 }
1329
1330 /**
1331 * Check if any errors were recorded
1332 *
1333 * @param string $type - The error type
1334 * @return boolean
1335 */
1336 public function has_errors($type = 'error') {
1337 return isset($this->_errors[$type]) && !empty($this->_errors[$type]) && $this->_errors[$type]->has_errors();
1338 }
1339
1340 /**
1341 * Check if any warnings were recorded
1342 *
1343 * @return boolean
1344 */
1345 public function has_warnings() {
1346 return $this->has_errors('warning');
1347 }
1348
1349 /**
1350 * Check the cache compatibility issues.
1351 */
1352 public function check_compatibility_issues() {
1353 if (!$this->is_enabled()) return;
1354
1355 if ($this->is_pagespeedninja_gzip_active()) add_action('admin_notices', array($this, 'show_pagespeedninja_gzip_notice'));
1356 if ($this->is_farfutureexpiration_gzip_active()) add_action('admin_notices', array($this, 'show_farfutureexpiration_gzip_notice'));
1357 }
1358
1359 /**
1360 * Check if PageSpeed Ninja is active and GZIP compression option is enabled.
1361 *
1362 * @return bool
1363 */
1364 public function is_pagespeedninja_gzip_active() {
1365 if (!class_exists('PagespeedNinja')) return false;
1366
1367 $options = get_option('pagespeedninja_config');
1368 $gzip = !empty($options) ? (bool) $options['psi_EnableGzipCompression'] && (bool) $options['html_gzip'] : false;
1369
1370 return $gzip;
1371 }
1372
1373 /**
1374 * Output PageSpeed Ninja Gzip notice.
1375 */
1376 public function show_pagespeedninja_gzip_notice() {
1377 echo '<div id="wp-optimize-pagespeedninja-gzip-notice" class="error wpo-notice"><p><b>'.__('WP-Optimize:', 'wp-optimize').'</b> '.__('Please disable the feature "Gzip compression" in PageSpeed Ninja to prevent conflicts.', 'wp-optimize').'</p></div>';
1378 }
1379
1380 /**
1381 * Check if Far Future Expiration is active and GZIP compression option is enabled.
1382 *
1383 * @return bool
1384 */
1385 public function is_farfutureexpiration_gzip_active() {
1386 if (!class_exists('farFutureExpiration')) return false;
1387
1388 $options = get_option('far_future_expiration_settings');
1389 $gzip = !empty($options) ? (bool) $options['enable_gzip'] : false;
1390
1391 return $gzip;
1392 }
1393
1394 /**
1395 * Output Far Future Expiration Gzip notice.
1396 */
1397 public function show_farfutureexpiration_gzip_notice() {
1398 echo '<div id="wp-optimize-pagespeedninja-gzip-notice" class="error wpo-notice"><p><b>'.__('WP-Optimize:', 'wp-optimize').'</b> '.__('Please disable the feature "Gzip compression" in Far Future Expiration to prevent conflicts.', 'wp-optimize').'</p></div>';
1399 }
1400
1401 /**
1402 * This is a notice to show users that writing `advanced-cache.php` failed
1403 */
1404 public function show_admin_notice_advanced_cache() {
1405 $message = sprintf(__('The request to write the file %s failed.', 'wp-optimize'), htmlspecialchars($this->get_advanced_cache_filename()));
1406 $message .= ' '.__('Please check file and directory permissions on the file paths up to this point, and your PHP error log.', 'wp-optimize');
1407 WP_Optimize()->include_template('notices/cache-notice.php', false, array('message' => $message));
1408 }
1409
1410 /**
1411 * Scheduler public functions to update schedulers
1412 *
1413 * @param array $schedules An array of schedules being passed.
1414 * @return array An array of schedules being returned.
1415 */
1416 public function cron_schedules($schedules) {
1417 $page_cache_length = $this->config->get_option('page_cache_length');
1418 // When the interval is less than `WP_CRON_LOCK_TIMEOUT` error messages are triggered
1419 // So, instead of `0` (now) we are making it equal to the constant value.
1420 // https://github.com/WordPress/WordPress/commit/84d19848666a81584e0007a6ab7f7ad3c990d71a
1421 if (defined('WP_CRON_LOCK_TIMEOUT') && $page_cache_length < WP_CRON_LOCK_TIMEOUT) {
1422 $page_cache_length = WP_CRON_LOCK_TIMEOUT;
1423 }
1424
1425 $schedules['wpo_purge_old_cache'] = array('interval' => false === $page_cache_length ? 86400 : $page_cache_length, 'display' => __('Every time after the cache has expired', 'wp-optimize'));
1426
1427 $interval = WP_Optimize_Page_Cache_Preloader::instance()->get_continue_preload_cron_interval();
1428 $schedules['wpo_page_cache_preload_continue_interval'] = array(
1429 'interval' => $interval,
1430 'display' => sprintf(__('%d minutes', 'wp-optimize'), round($interval / 60, 1))
1431 );
1432
1433 $schedules['wpo_use_cache_lifespan'] = array(
1434 'interval' => $page_cache_length,
1435 'display' => sprintf(__('Same as cache lifespan: %s', 'wp-optimize'), WPO_Cache_Config::instance()->get_option('page_cache_length_value').' '.WPO_Cache_Config::instance()->get_option('page_cache_length_unit'))
1436 );
1437
1438 return $schedules;
1439 }
1440
1441 /**
1442 * Update cache config file to reflect the webp images option
1443 */
1444 public function update_webp_images_option() {
1445 if ($this->is_enabled()) {
1446 $cache_settings = WPO_Cache_Config::instance()->get();
1447 $cache_settings['use_webp_images'] = WP_Optimize()->get_options()->get_option('webp_conversion');
1448 WPO_Cache_Config::instance()->update($cache_settings);
1449 }
1450 }
1451
1452 /**
1453 * May be regenerate cache config file, in case of migrations
1454 */
1455 public function maybe_regenerate_cache_config_file() {
1456 $config_file = WPO_CACHE_CONFIG_DIR . '/'.$this->config->get_cache_config_filename();
1457 if (!file_exists($config_file)) {
1458 $config = $this->config->get();
1459 $this->config->write($config);
1460 }
1461 }
1462 }
1463
1464 endif;
1465