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 +145 -21 3.2.9 → 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 /**
@@ -182,24 +207,36 @@
182 207 $post_obj = get_post_type_object($post_type);
183 208
184 209 if (null === $post_obj) return;
185 210
186 - if ('post' == $post_type) {
211 + $post_status = get_post_status($post_id);
212 + if ('publish' !== $post_status) {
213 + return;
214 + }
215 +
216 + if ('post' === $post_type) {
187 217 // delete blog page cache
188 218 $blog_post_id = get_option('page_for_posts');
189 219 if ($blog_post_id) {
190 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);
191 222 }
192 223
193 - // delete next and previus posts cache.
194 - $globals_post = isset($GLOBALS['post']) ? $GLOBALS['post'] : false;
224 + // delete next and previous posts cache.
225 + $globals_post = $GLOBALS['post'] ?? false;
195 226 $GLOBALS['post'] = get_post($post_id);
196 227 $previous_post = function_exists('get_previous_post') ? get_previous_post() : false;
197 228 $next_post = function_exists('get_next_post') ? get_next_post() : false;
198 229 if ($globals_post) $GLOBALS['post'] = $globals_post;
199 230
200 - if ($previous_post) WPO_Page_Cache::delete_cache_by_url(get_permalink($previous_post), true);
201 - 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 + }
202 239
203 240 // delete all archive pages for post.
204 241 $post_date = get_post_time('Y-m-j', false, $post_id);
205 242 list($year, $month, $day) = $post_date;
@@ -212,13 +249,26 @@
212 249
213 250 foreach ($archive_links as $link) {
214 251 WPO_Page_Cache::delete_cache_by_url($link, true);
215 252 }
216 - } 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) {
217 256 // delete archive page for custom post type.
218 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);
219 259 }
220 -
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 + }
221 271 }
222 272
223 273 /**
224 274 * We use it with edit_terms action filter to purge cached elements related
@@ -235,8 +285,9 @@
235 285 if (is_array($term)) {
236 286 $term_permalink = get_term_link($term['term_id']);
237 287 if (!is_wp_error($term_permalink)) {
238 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());
239 290 }
240 291 }
241 292
242 293 // get posts which belongs to updated term.
@@ -243,9 +294,9 @@
243 294 $posts = get_posts(array(
244 295 'numberposts' => -1,
245 296 'post_type' => 'any',
246 297 'fields' => 'ids',
247 - '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
248 299 'relation' => 'OR',
249 300 array(
250 301 'taxonomy' => $taxonomy,
251 302 'field' => 'term_id',
@@ -257,8 +308,11 @@
257 308 if (!empty($posts)) {
258 309 foreach ($posts as $post_id) {
259 310 WPO_Page_Cache::delete_single_post_cache($post_id);
260 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());
261 315 }
262 316 }
263 317
264 318 /**
@@ -281,9 +335,9 @@
281 335
282 336 /**
283 337 * Adds a way to exit the purge of terms permalink using the provided parameters.
284 338 *
285 - * @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
286 340 * @param int $object_id Object ID.
287 341 * @param array $terms An array of object terms.
288 342 * @param array $tt_ids An array of term taxonomy IDs.
289 343 * @param string $taxonomy Taxonomy slug.
@@ -298,8 +352,9 @@
298 352 $affected_terms_ids = array_unique(array_merge($tt_ids, $old_tt_ids));
299 353
300 354 if (!empty($affected_terms_ids)) {
301 355 // walk through all changed terms and purge cached pages for them.
356 + $is_cache_purged = false;
302 357 foreach ($affected_terms_ids as $tt_id) {
303 358 $term = get_term($tt_id, $taxonomy, ARRAY_A);
304 359 if (!is_array($term)) continue;
305 360
@@ -304,14 +359,16 @@
304 359 if (!is_array($term)) continue;
305 360
306 361 $term_permalink = get_term_link($term['term_id']);
307 362 if (!is_wp_error($term_permalink)) {
308 - $url = parse_url($term_permalink);
363 + $url = wp_parse_url($term_permalink);
309 364 // Check if the permalink contains a valid path, to avoid deleting the whole cache.
310 365 if (!isset($url['path']) || '/' === $url['path']) return;
311 366 WPO_Page_Cache::delete_cache_by_url($term_permalink, true);
367 + $is_cache_purged = true;
312 368 }
313 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());
314 371 }
315 372 }
316 373
317 374 /**
@@ -319,21 +376,87 @@
319 376 */
320 377 public function purge_product_page($product_with_stock) {
321 378 if (!empty($product_with_stock->get_id())) {
322 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());
323 381 }
324 382 }
325 383
326 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 + /**
327 431 * Clears the cache.
328 432 */
329 433 public function purge_cache() {
330 434 if (!empty($this->config['enable_page_caching'])) {
331 435 wpo_cache_flush();
436 + WPO_Page_Cache::instance()->file_log("Full Cache Purge triggered by action: " . current_filter());
332 437 }
333 438 }
334 439
335 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 + /**
336 459 * Triggered by wpo_cache_config_updated.
337 460 *
338 461 * @param array $config
339 462 */
@@ -340,8 +463,9 @@
340 463 public function cache_config_updated($config) {
341 464 // delete front page form cache if defined in the settings
342 465 if (is_array($config['cache_exception_urls']) && in_array('/', $config['cache_exception_urls'])) {
343 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());
344 468 }
345 469 }
346 470
347 471 /**
@@ -346,9 +470,9 @@
346 470
347 471 /**
348 472 * Returns an instance of the current class, creates one if it doesn't exist
349 473 *
350 - * @return object
474 + * @return self
351 475 */
352 476 public static function instance() {
353 477 if (empty(self::$instance)) {
354 478 self::$instance = new self();