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 | cache/class-wpo-cache-rules.php +159 -39 3.2.3 → 4.7.0 View file →
@@ -5,10 +5,8 @@
5 5 /**
6 6 * Page caching rules and exceptions
7 7 */
8 8
9 -if (!class_exists('WPO_Cache_Config')) require_once('class-wpo-cache-config.php');
10 -
11 9 require_once dirname(__FILE__) . '/file-based-page-cache-functions.php';
12 10
13 11 if (!class_exists('WPO_Cache_Rules')) :
14 12
@@ -23,9 +21,9 @@
23 21
24 22 /**
25 23 * Instance of this class
26 24 *
27 - * @var mixed
25 + * @var WPO_Cache_Rules | null
28 26 */
29 27 public static $instance;
30 28
31 29 public function __construct() {
@@ -45,18 +43,39 @@
45 43 add_action('edit_terms', array($this, 'purge_related_elements_on_term_updated'), 10, 2);
46 44 add_action('set_object_terms', array($this, 'purge_related_elements_on_post_terms_change'), 10, 6);
47 45 add_action('wpo_cache_config_updated', array($this, 'cache_config_updated'), 10, 1);
48 46 add_action('wp_insert_comment', array($this, 'comment_inserted'), 10, 2);
47 + add_action('import_start', array($this, 'remove_wp_insert_comment'));
49 48
49 + add_action('update_option_page_on_front', array($this, 'purge_cache_on_homepage_change'));
50 + add_action('update_option_page_for_posts', array($this, 'purge_cache_on_blog_page_change'), 10, 2);
51 + add_action('update_option_show_avatars', array($this, 'purge_cache_on_avatars_change'), 10, 2);
52 +
50 53 add_action('woocommerce_variation_set_stock', array($this, 'purge_product_page'), 10, 1);
51 54 add_action('woocommerce_product_set_stock', array($this, 'purge_product_page'), 10, 1);
52 55
56 + add_filter('wpo_page_cache_preloader_dont_close_browser_connection', array($this, 'preloader_dont_close_browser_connection'), 10, 1);
57 +
53 58 /**
54 59 * List of hooks for which when executed, the cache will be purged
55 60 *
56 61 * @param array $actions The actions
57 62 */
58 - $purge_on_action = apply_filters('wpo_purge_cache_hooks', array('after_switch_theme', 'wp_update_nav_menu', 'customize_save_after', array('wp_ajax_save-widget', 0), array('wp_ajax_update-widget', 0), 'autoptimize_action_cachepurged', 'upgrader_overwrote_package', 'wpo_active_plugin_or_theme_updated', 'fusion_cache_reset_after'));
63 + $actions = array(
64 + 'after_switch_theme',
65 + 'wp_update_nav_menu',
66 + 'customize_save_after',
67 + array('wp_ajax_save-widget', 0),
68 + array('wp_ajax_update-widget', 0),
69 + 'autoptimize_action_cachepurged',
70 + 'upgrader_overwrote_package',
71 + 'wpo_active_plugin_or_theme_updated',
72 + 'fusion_cache_reset_after',
73 + 'update_option_permalink_structure',
74 + 'update_option_posts_per_page',
75 + 'wpml_st_add_string_translation',
76 + );
77 + $purge_on_action = apply_filters('wpo_purge_cache_hooks', $actions);
59 78 foreach ($purge_on_action as $action) {
60 79 if (is_array($action)) {
61 80 add_action($action[0], array($this, 'purge_cache'), $action[1]);
62 81 } else {
@@ -62,10 +81,8 @@
62 81 } else {
63 82 add_action($action, array($this, 'purge_cache'));
64 83 }
65 84 }
66 -
67 - add_filter('wpo_cache_cookies', array($this, 'wpo_cache_cookies'), 9);
68 85 }
69 86
70 87 /**
71 88 * Purge post cache when there is a new approved comment
@@ -83,13 +100,14 @@
83 100 $post_id = $commentdata['comment_post_ID'];
84 101
85 102 WPO_Page_Cache::delete_single_post_cache($post_id);
86 103 WPO_Page_Cache::delete_comments_feed();
104 + WPO_Page_Cache::instance()->file_log("Cache for URL: {{URL}} has been purged, triggered by action: " . current_filter(), $post_id);
87 105 }
88 106 }
89 107
90 108 /**
91 - * Every time a comment's status changes, purge it's parent posts cache
109 + * Every time a comment's status changes, purge its parent posts cache
92 110 *
93 111 * @param int $comment_id Comment ID.
94 112 */
95 113 public function purge_post_on_comment_status_change($comment_id) {
@@ -97,8 +115,9 @@
97 115 $comment = get_comment($comment_id);
98 116 if (is_object($comment) && !empty($comment->comment_post_ID)) {
99 117 WPO_Page_Cache::delete_single_post_cache($comment->comment_post_ID);
100 118 WPO_Page_Cache::delete_comments_feed();
119 + WPO_Page_Cache::instance()->file_log("Cache for URL: {{URL}} has been purged, triggered by action: " . current_filter(), $comment->comment_post_ID);
101 120 }
102 121 }
103 122 }
104 123
@@ -118,31 +137,42 @@
118 137 * @param boolean $add_cookie
119 138 * @param WP_Comment $comment
120 139 * @return boolean
121 140 */
122 - $add_cookie = apply_filters('wpo_add_commented_post_cookie', '' == $comment->comment_type || 'comment' == $comment->comment_type, $comment);
141 + $add_cookie = apply_filters('wpo_add_commented_post_cookie', '' === $comment->comment_type || 'comment' === $comment->comment_type, $comment);
123 142 if (!$add_cookie) return;
124 143
125 144 $url = get_permalink($comment->comment_post_ID);
126 - $url_info = parse_url($url);
127 - setcookie('wpo_commented_post', 1, time() + WEEK_IN_SECONDS, isset($url_info['path']) ? $url_info['path'] : '/');
145 + $url_info = wp_parse_url($url);
146 + setcookie('wpo_commented_post', 1, time() + WEEK_IN_SECONDS, $url_info['path'] ?? '/');
128 147 }
129 148 }
130 149
131 150 /**
151 + * Comment posted cookie is not needed for imports. So remove the action
152 + */
153 + public function remove_wp_insert_comment() {
154 + remove_action('wp_insert_comment', array($this, 'comment_inserted'), 10);
155 + }
156 +
157 + /**
132 158 * Automatically purge all file based page cache on post changes
133 159 * We want the whole cache purged here as different parts
134 160 * of the site could potentially change on post updates
135 161 *
136 - * @param Integer $post_id - WP post id
162 + * @param int $post_id - WP post id
137 163 */
138 164 public function purge_post_on_update($post_id) {
139 165 $post_type = get_post_type($post_id);
140 166 $post_type_object = get_post_type_object($post_type);
141 167
142 - if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || !$post_type_object->public) {
168 + if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || null === $post_type_object || !$post_type_object->public) {
143 169 return;
144 170 }
171 + $post_status = get_post_status($post_id);
172 + if ('publish' !== $post_status) {
173 + return;
174 + }
145 175
146 176 /**
147 177 * Purge the whole cache if set to true, only the edited post otherwise. Default is false.
148 178 *
@@ -150,15 +180,14 @@
150 180 * @param integer $post_id The saved post ID
151 181 */
152 182 if (apply_filters('wpo_purge_all_cache_on_update', false, $post_id)) {
153 183 $this->purge_cache();
154 - return;
155 184 } else {
156 185 if (apply_filters('wpo_delete_cached_homepage_on_post_update', true, $post_id)) WPO_Page_Cache::delete_homepage_cache();
157 186 WPO_Page_Cache::delete_feed_cache();
158 187 WPO_Page_Cache::delete_single_post_cache($post_id);
159 - WPO_Page_Cache::delete_sitemap_cache();
160 188 WPO_Page_Cache::delete_post_feed_cache($post_id);
189 + WPO_Page_Cache::instance()->file_log("Cache for URL: {{URL}} has been purged, triggered by action: " . current_filter(), $post_id);
161 190 }
162 191 }
163 192
164 193 /**
@@ -168,8 +197,10 @@
168 197 */
169 198 public function purge_archive_pages_on_post_update($post_id) {
170 199 $post_type = get_post_type($post_id);
171 200
201 + if (false === $post_type) return;
202 +
172 203 if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
173 204 return;
174 205 }
175 206
@@ -174,24 +205,38 @@
174 205 }
175 206
176 207 $post_obj = get_post_type_object($post_type);
177 208
178 - if ('post' == $post_type) {
209 + if (null === $post_obj) return;
210 +
211 + $post_status = get_post_status($post_id);
212 + if ('publish' !== $post_status) {
213 + return;
214 + }
215 +
216 + if ('post' === $post_type) {
179 217 // delete blog page cache
180 218 $blog_post_id = get_option('page_for_posts');
181 219 if ($blog_post_id) {
182 220 WPO_Page_Cache::delete_cache_by_url(get_permalink($blog_post_id), true);
221 + WPO_Page_Cache::instance()->file_log("Cache for blog post has been purged due to updates to post with Title: {{title}} and URL: {{URL}}, triggered by action: " . current_filter(), $post_id);
183 222 }
184 223
185 - // delete next and previus posts cache.
186 - $globals_post = isset($GLOBALS['post']) ? $GLOBALS['post'] : false;
224 + // delete next and previous posts cache.
225 + $globals_post = $GLOBALS['post'] ?? false;
187 226 $GLOBALS['post'] = get_post($post_id);
188 227 $previous_post = function_exists('get_previous_post') ? get_previous_post() : false;
189 228 $next_post = function_exists('get_next_post') ? get_next_post() : false;
190 229 if ($globals_post) $GLOBALS['post'] = $globals_post;
191 230
192 - if ($previous_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($previous_post), true);
193 - if ($next_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($next_post), true);
231 + if ($previous_post) {
232 + WPO_Page_Cache::delete_cache_by_url(get_permalink($previous_post), true);
233 + WPO_Page_Cache::instance()->file_log("Cache for previous post (with URL: {{URL}}) adjacent to post with id: " . $post_id . " has been purged, triggered by action: " . current_filter(), $previous_post->ID);
234 + }
235 + if ($next_post) {
236 + WPO_Page_Cache::delete_cache_by_url(get_permalink($next_post), true);
237 + WPO_Page_Cache::instance()->file_log("Cache for next post (with URL: {{URL}}) adjacent to post with id: " . $post_id . " has been purged, triggered by action: " . current_filter(), $next_post->ID);
238 + }
194 239
195 240 // delete all archive pages for post.
196 241 $post_date = get_post_time('Y-m-j', false, $post_id);
197 242 list($year, $month, $day) = $post_date;
@@ -204,13 +249,26 @@
204 249
205 250 foreach ($archive_links as $link) {
206 251 WPO_Page_Cache::delete_cache_by_url($link, true);
207 252 }
208 - } elseif ($post_obj->has_archive) {
253 + WPO_Page_Cache::instance()->file_log("Cache for all archives page associated with post_type: " . $post_type . " and Title: {{title}} have been purged, triggered by action: " . current_filter(), $post_id);
254 + }
255 + if ($post_obj->has_archive) {
209 256 // delete archive page for custom post type.
210 257 WPO_Page_Cache::delete_cache_by_url(get_post_type_archive_link($post_type), true);
258 + WPO_Page_Cache::instance()->file_log("Cache for archive page associated with post_type: " . $post_type . " and Title: {{title}} has been purged, triggered by action: " . current_filter(), $post_id);
211 259 }
212 -
260 + if (post_type_supports($post_type, 'author')) {
261 + $author_id = get_post_field('post_author', $post_id);
262 + $post_author = get_user_by('id', $author_id);
263 + if ($author_id && $post_author) {
264 + $author_url = get_author_posts_url($author_id);
265 + if (!empty($author_url)) {
266 + WPO_Page_Cache::delete_cache_by_url($author_url, true);
267 + WPO_Page_Cache::instance()->file_log("Cache for author page URL: " . $author_url . " associated with post_type: " . $post_type . " and Title: {{title}} has been purged, triggered by action: " . current_filter(), $post_id);
268 + }
269 + }
270 + }
213 271 }
214 272
215 273 /**
216 274 * We use it with edit_terms action filter to purge cached elements related
@@ -219,8 +277,10 @@
219 277 * @param int $term_id Term taxonomy ID.
220 278 * @param string $taxonomy Taxonomy slug.
221 279 */
222 280 public function purge_related_elements_on_term_updated($term_id, $taxonomy) {
281 + if ('nav_menu' === $taxonomy) return;
282 +
223 283 // purge cached page for term.
224 284 $term = get_term($term_id, $taxonomy, ARRAY_A);
225 285 if (is_array($term)) {
226 286 $term_permalink = get_term_link($term['term_id']);
@@ -225,8 +285,9 @@
225 285 if (is_array($term)) {
226 286 $term_permalink = get_term_link($term['term_id']);
227 287 if (!is_wp_error($term_permalink)) {
228 288 WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
289 + WPO_Page_Cache::instance()->file_log("Cache for term page with URL: " . $term_permalink . " have been purged, triggered by action: " . current_filter());
229 290 }
230 291 }
231 292
232 293 // get posts which belongs to updated term.
@@ -233,9 +294,9 @@
233 294 $posts = get_posts(array(
234 295 'numberposts' => -1,
235 296 'post_type' => 'any',
236 297 'fields' => 'ids',
237 - 'tax_query' => array(
298 + 'tax_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- because we can't use `get_objects_in_term` for `OR` relationships
238 299 'relation' => 'OR',
239 300 array(
240 301 'taxonomy' => $taxonomy,
241 302 'field' => 'term_id',
@@ -247,8 +308,11 @@
247 308 if (!empty($posts)) {
248 309 foreach ($posts as $post_id) {
249 310 WPO_Page_Cache::delete_single_post_cache($post_id);
250 311 }
312 + $term_permalink = get_term_link($term_id);
313 + WPO_Page_Cache::instance()->file_log("Cache for associated posts for term with URL: "
314 + . $term_permalink. " have been purged, triggered by action: " . current_filter());
251 315 }
252 316 }
253 317
254 318 /**
@@ -271,9 +335,9 @@
271 335
272 336 /**
273 337 * Adds a way to exit the purge of terms permalink using the provided parameters.
274 338 *
275 - * @param bool $purge The value filtered, whether or not to purge the related elements
339 + * @param bool $purge The value filtered, whether to purge the related elements or not
276 340 * @param int $object_id Object ID.
277 341 * @param array $terms An array of object terms.
278 342 * @param array $tt_ids An array of term taxonomy IDs.
279 343 * @param string $taxonomy Taxonomy slug.
@@ -288,8 +352,9 @@
288 352 $affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));
289 353
290 354 if (!empty($affected_terms_ids)) {
291 355 // walk through all changed terms and purge cached pages for them.
356 + $is_cache_purged = false;
292 357 foreach ($affected_terms_ids as $tt_id) {
293 358 $term = get_term($tt_id, $taxonomy, ARRAY_A);
294 359 if (!is_array($term)) continue;
295 360
@@ -294,14 +359,16 @@
294 359 if (!is_array($term)) continue;
295 360
296 361 $term_permalink = get_term_link($term['term_id']);
297 362 if (!is_wp_error($term_permalink)) {
298 - $url = parse_url($term_permalink);
363 + $url = wp_parse_url($term_permalink);
299 364 // Check if the permalink contains a valid path, to avoid deleting the whole cache.
300 365 if (!isset($url['path']) || '/' === $url['path']) return;
301 366 WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
367 + $is_cache_purged = true;
302 368 }
303 369 }
370 + if ($is_cache_purged) WPO_Page_Cache::instance()->file_log("Cache for multiple term taxonomy have been purged due to post terms update, triggered by action: " . current_filter());
304 371 }
305 372 }
306 373
307 374 /**
@@ -309,21 +376,87 @@
309 376 */
310 377 public function purge_product_page($product_with_stock) {
311 378 if (!empty($product_with_stock->get_id())) {
312 379 WPO_Page_Cache::delete_single_post_cache($product_with_stock->get_id());
380 + WPO_Page_Cache::instance()->file_log("Cache for URL: {{URL}} has been purged, triggered by action: " . current_filter(), $product_with_stock->get_id());
313 381 }
314 382 }
315 383
316 384 /**
385 + * Purges relevant caches when the "Homepage" option is changed.
386 + *
387 + * This method is also triggered when the "Homepage displays" option is changed
388 + * from a static page to latest posts. In this scenario, the "Homepage" option value
389 + * becomes zero. Since the cache for the front-page is already purged here, there's no need
390 + * to purge the cache using the`update_option_show_on_front` hook.
391 + *
392 + * @param string $old_value The old value of the "Homepage" option.
393 + */
394 + public function purge_cache_on_homepage_change($old_value) {
395 + if ($old_value) {
396 + WPO_Page_Cache::delete_cache_by_url(get_permalink($old_value));
397 + }
398 + WPO_Page_Cache::delete_homepage_cache();
399 + WPO_Page_Cache::instance()->file_log("Cache for homepage has been purged due to change in the Homepage displays options, triggered by action: " . current_filter());
400 + }
401 +
402 + /**
403 + * Purges relevant caches when the "Posts page" option is changed.
404 + *
405 + * @param string $old_value The old value of the "Posts page" option.
406 + * @param string $value The new value of the "Posts page" option.
407 + */
408 + public function purge_cache_on_blog_page_change($old_value, $value) {
409 + if ($old_value) {
410 + WPO_Page_Cache::delete_cache_by_url(get_permalink($old_value));
411 + }
412 + if ($value) {
413 + WPO_Page_Cache::delete_cache_by_url(get_permalink($value));
414 + }
415 + WPO_Page_Cache::instance()->file_log("Cache for homepage has been purged due to changes in the Posts page options, triggered by action: " . current_filter());
416 + }
417 +
418 + /**
419 + * Purges cache if the avatars option is changed
420 + *
421 + * @param boolean $old_value
422 + * @param boolean $value
423 + */
424 + public function purge_cache_on_avatars_change($old_value, $value) {
425 + if ($old_value !== $value) {
426 + $this->purge_cache();
427 + }
428 + }
429 +
430 + /**
317 431 * Clears the cache.
318 432 */
319 433 public function purge_cache() {
320 434 if (!empty($this->config['enable_page_caching'])) {
321 435 wpo_cache_flush();
436 + WPO_Page_Cache::instance()->file_log("Full Cache Purge triggered by action: " . current_filter());
322 437 }
323 438 }
324 439
325 440 /**
441 + * Filter to set the flag to not close the browser connection when running via AJAX in the preloader.
442 + *
443 + * @param bool $dont_close_browser_connection The current value of the flag to not close the browser connection. Default is false.
444 + *
445 + * @return bool
446 + */
447 + public function preloader_dont_close_browser_connection($dont_close_browser_connection) {
448 + if ($dont_close_browser_connection) return $dont_close_browser_connection;
449 +
450 + // In WooCommerce, when the stock is updated for a product or a variation, it triggers an AJAX request in the background.
451 + // In this case, we want to avoid closing the browser connection in the preloader, to allow the product edit page to receive the response.
452 + if (did_action('woocommerce_variation_set_stock') || did_action('woocommerce_product_set_stock')) {
453 + return true;
454 + }
455 + return false;
456 + }
457 +
458 + /**
326 459 * Triggered by wpo_cache_config_updated.
327 460 *
328 461 * @param array $config
329 462 */
@@ -330,29 +463,16 @@
330 463 public function cache_config_updated($config) {
331 464 // delete front page form cache if defined in the settings
332 465 if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
333 466 WPO_Page_Cache::delete_cache_by_url(home_url());
467 + WPO_Page_Cache::instance()->file_log("Cache for homepage has been purged due to changes in the cache configurations, triggered by action: " . current_filter());
334 468 }
335 469 }
336 470
337 471 /**
338 - * Add cookie names that are need separate caching
339 - */
340 - public function wpo_cache_cookies($cookies) {
341 - $cookies[] = 'cookie_notice_accepted';
342 - $cookies[] = 'cookielawinfo-checkbox-necessary';
343 - $cookies[] = 'cookielawinfo-checkbox-functional';
344 - $cookies[] = 'cookielawinfo-checkbox-advertisement';
345 - $cookies[] = 'cookielawinfo-checkbox-others';
346 - $cookies[] = 'cookielawinfo-checkbox-analytics';
347 - $cookies[] = 'cookielawinfo-checkbox-performance';
348 - return $cookies;
349 - }
350 -
351 - /**
352 472 * Returns an instance of the current class, creates one if it doesn't exist
353 473 *
354 - * @return object
474 + * @return self
355 475 */
356 476 public static function instance() {
357 477 if (empty(self::$instance)) {
358 478 self::$instance = new self();