PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 2.2
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v2.2
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
powered-cache / includes / classes / AdvancedCache.php

AdvancedCache.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score 2.2, at includes/classes/AdvancedCache.php

489 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin
4 *
5 * @package PoweredCache
6 */
7
8 namespace PoweredCache;
9
10 use const PoweredCache\Constants\POST_META_DISABLE_CACHE_KEY;
11 use function PoweredCache\Utils\clean_page_cache_dir;
12 use function PoweredCache\Utils\clean_site_cache_dir;
13 use function PoweredCache\Utils\delete_page_cache;
14 use function PoweredCache\Utils\get_post_related_urls;
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit if accessed directly.
18 }
19
20 /**
21 * Class Admin
22 *
23 * @package PoweredCache
24 */
25 class AdvancedCache {
26
27 /**
28 * Return an instance of the current class
29 *
30 * @return AdvancedCache
31 * @since 1.0
32 */
33 public static function factory() {
34
35 static $instance;
36
37 if ( ! $instance ) {
38 $instance = new self();
39 $instance->setup();
40 }
41
42 return $instance;
43 }
44
45 /**
46 * Setup hooks
47 *
48 * @since 1.0
49 */
50 public function setup() {
51 $settings = \PoweredCache\Utils\get_settings();
52
53 if ( ! $settings['enable_page_cache'] ) {
54 return;
55 }
56
57 add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ) );
58 add_action( 'admin_post_powered_cache_purge_page_cache', array( $this, 'purge_page_cache' ) );
59 add_action( 'admin_post_powered_cache_purge_page_cache_network', array( $this, 'purge_page_cache_network_wide' ) );
60 add_action( 'pre_post_update', array( $this, 'purge_on_post_update' ), 10, 1 );
61 add_action( 'save_post', array( $this, 'purge_on_post_update' ), 10, 1 );
62 add_action( 'wp_trash_post', array( $this, 'purge_on_post_update' ), 10, 1 );
63 add_action( 'switch_theme', array( $this, 'purge_on_switch_theme' ) );
64 add_action( 'wp_set_comment_status', array( $this, 'purge_post_on_comment_status_change' ), 10, 2 );
65 add_action( 'set_comment_cookies', array( $this, 'set_comment_cookie' ), 10, 2 );
66 add_filter( 'powered_cache_post_related_urls', array( $this, 'powered_cache_post_related_urls' ) );
67 add_filter( 'powered_cache_page_cache_enable', array( $this, 'maybe_caching_disabled' ) );
68 add_filter( 'powered_cache_mod_rewrite', array( $this, 'maybe_disable_mod_rewrite' ), 99 );
69 }
70
71 /**
72 * Add purge button on admin bar
73 *
74 * @param object $wp_admin_bar Admin bar object
75 *
76 * @since 1.0
77 */
78 public function admin_bar_menu( $wp_admin_bar ) {
79 if ( POWERED_CACHE_IS_NETWORK && current_user_can( 'manage_network' ) ) {
80 $wp_admin_bar->add_menu(
81 array(
82 'id' => 'advanced-cache-purge-network',
83 'title' => __( 'Purge Page Cache [Network Wide - All Sites]', 'powered-cache' ),
84 'href' => wp_nonce_url( admin_url( 'admin-post.php?action=powered_cache_purge_page_cache_network' ), 'powered_cache_purge_page_cache_network' ),
85 'parent' => 'powered-cache',
86 )
87 );
88 }
89
90 if ( current_user_can( 'manage_options' ) ) {
91 $wp_admin_bar->add_menu(
92 array(
93 'id' => 'advanced-cache-purge',
94 'title' => __( 'Purge Page Cache', 'powered-cache' ),
95 'href' => wp_nonce_url( admin_url( 'admin-post.php?action=powered_cache_purge_page_cache' ), 'powered_cache_purge_page_cache' ),
96 'parent' => 'powered-cache',
97 )
98 );
99 }
100 }
101
102
103 /**
104 * Purge page cache network wide
105 *
106 * @since 2.0
107 */
108 public function purge_page_cache_network_wide() {
109 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_purge_page_cache_network' ) ) {
110 wp_nonce_ays( '' );
111 }
112
113 if ( current_user_can( 'manage_network' ) ) {
114 clean_page_cache_dir();
115 $redirect_url = add_query_arg( 'pc_action', 'flush_page_cache_network', wp_get_referer() );
116 } else {
117 $redirect_url = add_query_arg( 'pc_action', 'flush_page_cache_network_err_permission', wp_get_referer() );
118 }
119
120 wp_safe_redirect( esc_url_raw( $redirect_url ) );
121 exit;
122 }
123
124 /**
125 * Purge page cache directory
126 *
127 * @since 1.0
128 * @since 1.1 clean site dir instead of root page caching dir
129 */
130 public function purge_page_cache() {
131 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_purge_page_cache' ) ) {
132 wp_nonce_ays( '' );
133 }
134
135 if ( current_user_can( 'manage_options' ) ) {
136 clean_site_cache_dir();
137 $redirect_url = add_query_arg( 'pc_action', 'flush_page_cache', wp_get_referer() );
138 } else {
139 $redirect_url = add_query_arg( 'pc_action', 'flush_page_cache_err_permission', wp_get_referer() );
140 }
141
142 wp_safe_redirect( esc_url_raw( $redirect_url ) );
143 exit;
144 }
145
146
147 /**
148 * Purge post related page cache
149 *
150 * @param int $post_id Post ID
151 *
152 * @since 1.0
153 */
154 public function purge_on_post_update( $post_id ) {
155 $current_post_status = get_post_status( $post_id );
156
157 $urls = array();
158
159 if ( in_array( $current_post_status, array( 'publish', 'trash' ), true ) ) {
160 $urls = get_post_related_urls( $post_id );
161
162 /**
163 * Page cache purge urls.
164 *
165 * @hook powered_cache_advanced_cache_purge_urls
166 *
167 * @param {array} $urls The list of URLs that will purged
168 * @param {int} $post_id Post ID.
169 *
170 * @return {array} New value
171 * @since 1.0
172 */
173 $urls = apply_filters( 'powered_cache_advanced_cache_purge_urls', $urls, $post_id );
174
175 foreach ( $urls as $url ) {
176 delete_page_cache( $url );
177 }
178 }
179
180 /**
181 * Fires after purging cache on post update.
182 *
183 * @hook powered_cache_advanced_cache_purge_post
184 *
185 * @param {int} $post_id The Post ID.
186 * @param {array} $urls The list of related urls with the updated post.
187 *
188 * @since 1.0
189 */
190 do_action( 'powered_cache_advanced_cache_purge_post', $post_id, $urls );
191 }
192
193 /**
194 * Delete page cache when post update
195 *
196 * @param int $comment_id Comment ID
197 * @param string $comment_status Status of the comment
198 *
199 * @since 1.0
200 */
201 public function purge_post_on_comment_status_change( $comment_id, $comment_status ) {
202 $comment = get_comment( $comment_id );
203 $post_id = $comment->comment_post_ID;
204 $post_url = get_permalink( $post_id );
205 delete_page_cache( $post_url );
206
207 /**
208 * Fires after purging cache for a post that associated a comment
209 *
210 * @param {int} $post_id Post ID.
211 * @param {string} $post_url Post permalink.
212 * @param {int} $comment_id Comment ID.
213 *
214 * @since 2.0
215 */
216 do_action( 'powered_cache_advanced_cache_purge_on_comment_status_change', $post_id, $post_url, $comment_id );
217 }
218
219 /**
220 * Purge site when switching to a new theme
221 *
222 * @since 2.0
223 */
224 public function purge_on_switch_theme() {
225 clean_site_cache_dir();
226 }
227
228 /**
229 * Leave a cookie when commenting on a post as usual and don't show the cached page.
230 * `comment_author_*` cookies are site-wide available.
231 * Don't show cached results just for left a comment 5 months ago is not seems efficient here.
232 *
233 * @param object $comment Comment object
234 * @param object $user User Object
235 *
236 * @since 1.0
237 */
238 public function set_comment_cookie( $comment, $user ) {
239 $post_id = $comment->comment_post_ID;
240 $path = wp_parse_url( get_permalink( $post_id ), PHP_URL_PATH );
241 setcookie( 'powered_cache_commented_posts[' . $post_id . ']', $path, ( time() + DAY_IN_SECONDS * 30 ), $path );
242 }
243
244
245 /**
246 * Adds custom pages to post related urls
247 *
248 * @param array $urls The list of the urls
249 *
250 * @return array urls
251 * @since 1.1
252 */
253 public function powered_cache_post_related_urls( $urls ) {
254 $settings = \PoweredCache\Utils\get_settings();
255
256 $additional_pages = $settings['purge_additional_pages'];
257
258 if ( empty( $additional_pages ) ) {
259 return $urls;
260 }
261
262 // we only need relative path
263 $additional_pages = str_replace( site_url(), '', $additional_pages );
264 $additional_page_paths = explode( PHP_EOL, $additional_pages );
265 $additional_urls = array();
266
267 foreach ( $additional_page_paths as $page ) {
268 $additional_urls[] = site_url( $page );
269 }
270
271 $urls = array_merge( $urls, $additional_urls );
272
273 return $urls;
274 }
275
276
277 /**
278 * Get the list of rejected cookies
279 *
280 * @return mixed|void
281 * @since 2.0
282 */
283 public static function get_rejected_cookies() {
284 $settings = \PoweredCache\Utils\get_settings();
285 $cookies = [];
286
287 if ( ! empty( $settings['rejected_cookies'] ) ) {
288 $cookies = preg_split( '#(\r\n|\r|\n)#', $settings['rejected_cookies'], - 1, PREG_SPLIT_NO_EMPTY );
289 }
290
291 $wp_cookies = [ 'wp-postpass', 'wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_', 'powered_cache_commented_posts' ];
292
293 if ( ! empty( $cookies ) ) {
294 $wp_cookies = array_merge( $cookies, $wp_cookies );
295 }
296
297 /**
298 * Filter rejected cookie list.
299 *
300 * @hook powered_cache_rejected_cookies
301 *
302 * @param {array} $wp_cookies The rejected cookie list from the caching.
303 *
304 * @return {array} Rejected cookie list
305 * @since 2.0
306 */
307 return apply_filters( 'powered_cache_rejected_cookies', $wp_cookies );
308 }
309
310 /**
311 * Get the list of rejected cookies
312 *
313 * @return mixed|void
314 * @since 2.0
315 */
316 public static function get_vary_cookies() {
317 $settings = \PoweredCache\Utils\get_settings();
318 $cookies = [];
319
320 if ( ! empty( $settings['vary_cookies'] ) ) {
321 $cookies = preg_split( '#(\r\n|\r|\n)#', $settings['vary_cookies'], - 1, PREG_SPLIT_NO_EMPTY );
322 }
323
324 /**
325 * Filter vary cookie list.
326 *
327 * @hook powered_cache_vary_cookies
328 *
329 * @param {array} $cookies The varied cookie list, which allows to create separate cache based on the match.
330 *
331 * @return {array} Vary cookie list
332 * @since 2.0
333 */
334 return apply_filters( 'powered_cache_vary_cookies', $cookies );
335 }
336
337
338 /**
339 * Get the list of rejected user agents
340 *
341 * @return mixed|void
342 * @since 2.0
343 */
344 public static function get_rejected_user_agents() {
345 $settings = \PoweredCache\Utils\get_settings();
346 $rejected_user_agents = [];
347
348 if ( ! empty( $settings['rejected_user_agents'] ) ) {
349 $rejected_user_agents = preg_split( '#(\r\n|\r|\n)#', $settings['rejected_user_agents'], - 1, PREG_SPLIT_NO_EMPTY );
350 }
351
352 $rejected_user_agents[] = 'facebookexternalhit';
353
354 /**
355 * Filter rejected user agent list.
356 *
357 * @hook powered_cache_rejected_user_agents
358 *
359 * @param {array} $rejected_user_agents The user agents that will not see the cached page.
360 *
361 * @return {array} Rejected user agent list.
362 * @since 2.0
363 */
364 return apply_filters( 'powered_cache_rejected_user_agents', $rejected_user_agents );
365 }
366
367 /**
368 * Get the list of rejected uri that nerver get cached
369 *
370 * @return mixed|void
371 * @since 2.0
372 */
373 public static function get_rejected_uri() {
374 $settings = \PoweredCache\Utils\get_settings();
375 $rejected_uri_list = [];
376
377 if ( ! empty( $settings['rejected_uri'] ) ) {
378 $rejected_uri_list = preg_split( '#(\r\n|\r|\n)#', $settings['rejected_uri'], - 1, PREG_SPLIT_NO_EMPTY );
379 }
380
381 /**
382 * Filter rejected uri list
383 *
384 * @hook powered_cache_rejected_uri_list
385 *
386 * @param {array} $rejected_uri_list The list of rejected uri that nerver get cached.
387 *
388 * @return {array} New value
389 * @since 2.0
390 */
391 return apply_filters( 'powered_cache_rejected_uri_list', $rejected_uri_list );
392 }
393
394
395 /**
396 * These query strings will be ignored during the caching
397 *
398 * @return mixed|void
399 */
400 public static function get_accepted_query_strings() {
401 $settings = \PoweredCache\Utils\get_settings();
402 $accepted_query_strings = [];
403
404 if ( ! empty( $settings['accepted_query_strings'] ) ) {
405 $accepted_query_strings = preg_split( '#(\r\n|\r|\n)#', $settings['accepted_query_strings'], - 1, PREG_SPLIT_NO_EMPTY );
406 }
407
408 $query_strings = [
409 'fbclid',
410 'fb_action_ids',
411 'fb_action_types',
412 'ref',
413 'gclid',
414 'fb_source',
415 'utm_source',
416 'utm_medium',
417 'utm_campaign',
418 'utm_term',
419 'utm_content',
420 'utm_expid',
421 '_ga',
422 'mc_cid',
423 'mc_eid',
424 'campaignid',
425 'adgroupid',
426 'adid',
427 'age-verified',
428 'usqp',
429 'cn-reloaded',
430 'ao_noptimize',
431 'lang',
432 ];
433
434 if ( ! empty( $accepted_query_strings ) ) {
435 $query_strings = array_merge( $query_strings, $accepted_query_strings );
436 }
437
438 /**
439 * Filter accepted query strings.
440 *
441 * @hook powered_cache_accepted_query_strings
442 *
443 * @param {array} $query_strings The list of query strings will be ignored during the caching
444 *
445 * @return {array} New value
446 * @since 2.0
447 */
448 return apply_filters( 'powered_cache_accepted_query_strings', $query_strings );
449 }
450
451
452 /**
453 * Disable caching of the individual page when it marked as dont' cache
454 *
455 * @param bool $status Cache status
456 *
457 * @return bool
458 */
459 public function maybe_caching_disabled( $status ) {
460 if ( is_single() ) {
461 $is_cache_disabled = (bool) get_post_meta( get_the_ID(), POST_META_DISABLE_CACHE_KEY, true );
462 if ( $is_cache_disabled ) {
463 return false;
464 }
465 }
466
467 return $status;
468 }
469
470 /**
471 * Maybe disable rewrite rules based on the settings
472 *
473 * @param bool $rewrite_status mod rewrite status
474 *
475 * @return bool
476 * @since 2.0
477 */
478 public function maybe_disable_mod_rewrite( $rewrite_status ) {
479 $vary_cookies = self::get_vary_cookies();
480 if ( ! empty( $vary_cookies ) ) {
481 $rewrite_status = false;
482 }
483
484 return $rewrite_status;
485 }
486
487 }
488
489