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 +151 -21 3.2.5 → 4.7.0 View file →
@@ -21,9 +21,9 @@
21 21
22 22 /**
23 23 * Instance of this class
24 24 *
25 - * @var mixed
25 + * @var WPO_Cache_Rules | null
26 26 */
27 27 public static $instance;
28 28
29 29 public function __construct() {
@@ -45,17 +45,37 @@
45 45 add_action('wpo_cache_config_updated', array($this, 'cache_config_updated'), 10, 1);
46 46 add_action('wp_insert_comment', array($this, 'comment_inserted'), 10, 2);
47 47 add_action('import_start', array($this, 'remove_wp_insert_comment'));
48 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 +
49 53 add_action('woocommerce_variation_set_stock', array($this, 'purge_product_page'), 10, 1);
50 54 add_action('woocommerce_product_set_stock', array($this, 'purge_product_page'), 10, 1);
51 55
56 + add_filter('wpo_page_cache_preloader_dont_close_browser_connection', array($this, 'preloader_dont_close_browser_connection'), 10, 1);
57 +
52 58 /**
53 59 * List of hooks for which when executed, the cache will be purged
54 60 *
55 61 * @param array $actions The actions
56 62 */
57 - $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', 'update_option_permalink_structure'));
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);
58 78 foreach ($purge_on_action as $action) {
59 79 if (is_array($action)) {
60 80 add_action($action[0], array($this, 'purge_cache'), $action[1]);
61 81 } else {
@@ -80,13 +100,14 @@
80 100 $post_id = $commentdata['comment_post_ID'];
81 101
82 102 WPO_Page_Cache::delete_single_post_cache($post_id);
83 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);
84 105 }
85 106 }
86 107
87 108 /**
88 - * 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
89 110 *
90 111 * @param int $comment_id Comment ID.
91 112 */
92 113 public function purge_post_on_comment_status_change($comment_id) {
@@ -94,8 +115,9 @@
94 115 $comment = get_comment($comment_id);
95 116 if (is_object($comment) && !empty($comment->comment_post_ID)) {
96 117 WPO_Page_Cache::delete_single_post_cache($comment->comment_post_ID);
97 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);
98 120 }
99 121 }
100 122 }
101 123
@@ -115,14 +137,14 @@
115 137 * @param boolean $add_cookie
116 138 * @param WP_Comment $comment
117 139 * @return boolean
118 140 */
119 - $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);
120 142 if (!$add_cookie) return;
121 143
122 144 $url = get_permalink($comment->comment_post_ID);
123 - $url_info = parse_url($url);
124 - 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'] ?? '/');
125 147 }
126 148 }
127 149
128 150 /**
@@ -136,17 +158,21 @@
136 158 * Automatically purge all file based page cache on post changes
137 159 * We want the whole cache purged here as different parts
138 160 * of the site could potentially change on post updates
139 161 *
140 - * @param Integer $post_id - WP post id
162 + * @param int $post_id - WP post id
141 163 */
142 164 public function purge_post_on_update($post_id) {
143 165 $post_type = get_post_type($post_id);
144 166 $post_type_object = get_post_type_object($post_type);
145 167
146 - 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) {
147 169 return;
148 170 }
171 + $post_status = get_post_status($post_id);
172 + if ('publish' !== $post_status) {
173 + return;
174 + }
149 175
150 176 /**
151 177 * Purge the whole cache if set to true, only the edited post otherwise. Default is false.
152 178 *
@@ -154,15 +180,14 @@
154 180 * @param integer $post_id The saved post ID
155 181 */
156 182 if (apply_filters('wpo_purge_all_cache_on_update', false, $post_id)) {
157 183 $this->purge_cache();
158 - return;
159 184 } else {
160 185 if (apply_filters('wpo_delete_cached_homepage_on_post_update', true, $post_id)) WPO_Page_Cache::delete_homepage_cache();
161 186 WPO_Page_Cache::delete_feed_cache();
162 187 WPO_Page_Cache::delete_single_post_cache($post_id);
163 - WPO_Page_Cache::delete_sitemap_cache();
164 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);
165 190 }
166 191 }
167 192
168 193 /**
@@ -172,8 +197,10 @@
172 197 */
173 198 public function purge_archive_pages_on_post_update($post_id) {
174 199 $post_type = get_post_type($post_id);
175 200
201 + if (false === $post_type) return;
202 +
176 203 if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type) {
177 204 return;
178 205 }
179 206
@@ -178,24 +205,38 @@
178 205 }
179 206
180 207 $post_obj = get_post_type_object($post_type);
181 208
182 - 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) {
183 217 // delete blog page cache
184 218 $blog_post_id = get_option('page_for_posts');
185 219 if ($blog_post_id) {
186 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);
187 222 }
188 223
189 - // delete next and previus posts cache.
190 - $globals_post = isset($GLOBALS['post']) ? $GLOBALS['post'] : false;
224 + // delete next and previous posts cache.
225 + $globals_post = $GLOBALS['post'] ?? false;
191 226 $GLOBALS['post'] = get_post($post_id);
192 227 $previous_post = function_exists('get_previous_post') ? get_previous_post() : false;
193 228 $next_post = function_exists('get_next_post') ? get_next_post() : false;
194 229 if ($globals_post) $GLOBALS['post'] = $globals_post;
195 230
196 - if ($previous_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($previous_post), true);
197 - 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 + }
198 239
199 240 // delete all archive pages for post.
200 241 $post_date = get_post_time('Y-m-j', false, $post_id);
201 242 list($year, $month, $day) = $post_date;
@@ -208,13 +249,26 @@
208 249
209 250 foreach ($archive_links as $link) {
210 251 WPO_Page_Cache::delete_cache_by_url($link, true);
211 252 }
212 - } 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) {
213 256 // delete archive page for custom post type.
214 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);
215 259 }
216 -
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 + }
217 271 }
218 272
219 273 /**
220 274 * We use it with edit_terms action filter to purge cached elements related
@@ -223,8 +277,10 @@
223 277 * @param int $term_id Term taxonomy ID.
224 278 * @param string $taxonomy Taxonomy slug.
225 279 */
226 280 public function purge_related_elements_on_term_updated($term_id, $taxonomy) {
281 + if ('nav_menu' === $taxonomy) return;
282 +
227 283 // purge cached page for term.
228 284 $term = get_term($term_id, $taxonomy, ARRAY_A);
229 285 if (is_array($term)) {
230 286 $term_permalink = get_term_link($term['term_id']);
@@ -229,8 +285,9 @@
229 285 if (is_array($term)) {
230 286 $term_permalink = get_term_link($term['term_id']);
231 287 if (!is_wp_error($term_permalink)) {
232 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());
233 290 }
234 291 }
235 292
236 293 // get posts which belongs to updated term.
@@ -237,9 +294,9 @@
237 294 $posts = get_posts(array(
238 295 'numberposts' => -1,
239 296 'post_type' => 'any',
240 297 'fields' => 'ids',
241 - '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
242 299 'relation' => 'OR',
243 300 array(
244 301 'taxonomy' => $taxonomy,
245 302 'field' => 'term_id',
@@ -251,8 +308,11 @@
251 308 if (!empty($posts)) {
252 309 foreach ($posts as $post_id) {
253 310 WPO_Page_Cache::delete_single_post_cache($post_id);
254 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());
255 315 }
256 316 }
257 317
258 318 /**
@@ -275,9 +335,9 @@
275 335
276 336 /**
277 337 * Adds a way to exit the purge of terms permalink using the provided parameters.
278 338 *
279 - * @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
280 340 * @param int $object_id Object ID.
281 341 * @param array $terms An array of object terms.
282 342 * @param array $tt_ids An array of term taxonomy IDs.
283 343 * @param string $taxonomy Taxonomy slug.
@@ -292,8 +352,9 @@
292 352 $affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));
293 353
294 354 if (!empty($affected_terms_ids)) {
295 355 // walk through all changed terms and purge cached pages for them.
356 + $is_cache_purged = false;
296 357 foreach ($affected_terms_ids as $tt_id) {
297 358 $term = get_term($tt_id, $taxonomy, ARRAY_A);
298 359 if (!is_array($term)) continue;
299 360
@@ -298,14 +359,16 @@
298 359 if (!is_array($term)) continue;
299 360
300 361 $term_permalink = get_term_link($term['term_id']);
301 362 if (!is_wp_error($term_permalink)) {
302 - $url = parse_url($term_permalink);
363 + $url = wp_parse_url($term_permalink);
303 364 // Check if the permalink contains a valid path, to avoid deleting the whole cache.
304 365 if (!isset($url['path']) || '/' === $url['path']) return;
305 366 WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
367 + $is_cache_purged = true;
306 368 }
307 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());
308 371 }
309 372 }
310 373
311 374 /**
@@ -313,21 +376,87 @@
313 376 */
314 377 public function purge_product_page($product_with_stock) {
315 378 if (!empty($product_with_stock->get_id())) {
316 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());
317 381 }
318 382 }
319 383
320 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 + /**
321 431 * Clears the cache.
322 432 */
323 433 public function purge_cache() {
324 434 if (!empty($this->config['enable_page_caching'])) {
325 435 wpo_cache_flush();
436 + WPO_Page_Cache::instance()->file_log("Full Cache Purge triggered by action: " . current_filter());
326 437 }
327 438 }
328 439
329 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 + /**
330 459 * Triggered by wpo_cache_config_updated.
331 460 *
332 461 * @param array $config
333 462 */
@@ -334,8 +463,9 @@
334 463 public function cache_config_updated($config) {
335 464 // delete front page form cache if defined in the settings
336 465 if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
337 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());
338 468 }
339 469 }
340 470
341 471 /**
@@ -340,9 +470,9 @@
340 470
341 471 /**
342 472 * Returns an instance of the current class, creates one if it doesn't exist
343 473 *
344 - * @return object
474 + * @return self
345 475 */
346 476 public static function instance() {
347 477 if (empty(self::$instance)) {
348 478 self::$instance = new self();