PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / trunk
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score vtrunk
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
← All changes | includes/classes/Preloader.php +138 -16 2.2trunk View file →
@@ -9,8 +9,9 @@
9 9
10 10 use PoweredCache\Async\CachePreloader;
11 11 use function PoweredCache\Utils\permalink_structure_has_trailingslash;
12 12 use function PoweredCache\Utils\site_cache_dir;
13 +use const PoweredCache\Constants\DEFERRED_PRELOAD_QUEUE_CRON_NAME;
13 14
14 15 /**
15 16 * Class Preloader
16 17 */
@@ -29,8 +30,15 @@
29 30 */
30 31 private $cache_preloader;
31 32
32 33 /**
34 + * Tracks whether we’ve added any URLs this request
35 + *
36 + * @var $queue_dirty
37 + */
38 + private $queue_dirty = false;
39 +
40 + /**
33 41 * Return an instance of the current class
34 42 *
35 43 * @return Preloader
36 44 * @since 1.0
@@ -59,9 +67,9 @@
59 67 if ( ! $this->settings['enable_cache_preload'] ) {
60 68 return;
61 69 }
62 70
63 - $this->cache_preloader = CachePreloader::factory();
71 + $this->get_preloader();
64 72
65 73 /**
66 74 * Page cache needs to be activated to get benefits of preloading
67 75 */
@@ -72,10 +80,12 @@
72 80 add_action( 'admin_bar_menu', [ $this, 'admin_bar_menu' ] );
73 81 add_action( 'admin_post_powered_cache_preload_cache', [ $this, 'start_preload' ] );
74 82 add_action( 'powered_cache_purge_all_cache', [ $this, 'setup_preload_queue' ] );
75 83 add_action( 'powered_cache_clean_site_cache_dir', [ $this, 'setup_preload_queue' ] );
76 - add_action( 'powered_cache_advanced_cache_purge_post', [ $this, 'add_purged_urls_to_preload_queue' ], 10, 2 );
84 + add_action( 'powered_cache_advanced_cache_purge_post', [ $this, 'deferred_preload_queue' ], 10, 2 );
77 85 add_action( 'powered_cache_expired_files_deleted', [ $this, 'add_expired_urls_to_preload_queue' ], 10, 2 );
86 + add_action( DEFERRED_PRELOAD_QUEUE_CRON_NAME, [ $this, 'add_purged_urls_to_preload_queue' ], 10, 2 );
87 + add_action( 'shutdown', [ $this, 'dispatch_preload_queue' ], 0 );
78 88 }
79 89
80 90 /**
81 91 * Preload Admin bar menu
@@ -102,13 +112,28 @@
102 112 )
103 113 );
104 114 }
105 115
116 +
106 117 /**
118 + * Get the instance of CachePreloader
119 + *
120 + * @return CachePreloader
121 + */
122 + private function get_preloader() {
123 + if ( ! $this->cache_preloader ) {
124 + $this->cache_preloader = CachePreloader::factory();
125 + }
126 +
127 + return $this->cache_preloader;
128 + }
129 +
130 + /**
107 131 * Add preloading items to queue
108 132 */
109 133 public function start_preload() {
110 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_preload_cache' ) ) {
134 + $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
135 + if ( ! wp_verify_nonce( $nonce, 'powered_cache_preload_cache' ) ) {
111 136 wp_nonce_ays( '' );
112 137 }
113 138
114 139 if ( POWERED_CACHE_IS_NETWORK && ! current_user_can( 'manage_network' ) ) {
@@ -122,8 +147,10 @@
122 147 wp_safe_redirect( esc_url_raw( $redirect_url ) );
123 148 exit;
124 149 }
125 150
151 + \PoweredCache\Utils\log( sprintf( 'Preload triggered from admin bar.' ) );
152 +
126 153 $this->setup_preload_queue();
127 154
128 155 $redirect_url = add_query_arg( 'pc_action', 'start_preload', wp_get_referer() );
129 156 wp_safe_redirect( esc_url_raw( $redirect_url ) );
@@ -134,9 +161,9 @@
134 161 * Setup preload
135 162 */
136 163 public function setup_preload_queue() {
137 164 // cancel existing process before populating
138 - $this->cache_preloader->cancel_process();
165 + $this->get_preloader()->cancel_process();
139 166
140 167 if ( POWERED_CACHE_IS_NETWORK ) {
141 168 $sites = get_sites( [ 'fields' => 'ids' ] );
142 169 foreach ( $sites as $site_id ) {
@@ -148,10 +175,8 @@
148 175 } else {
149 176 $this->populate_preload_queue();
150 177 }
151 178
152 - $this->cache_preloader->save()->dispatch();
153 -
154 179 if ( $this->settings['enable_sitemap_preload'] && function_exists( '\PoweredCachePremium\Utils\preload_sitemap' ) ) {
155 180 \PoweredCachePremium\Utils\preload_sitemap();
156 181 }
157 182 }
@@ -197,14 +222,46 @@
197 222 $preload_urls = array_merge( $preload_urls, $public_tax_term_urls );
198 223 \PoweredCache\Utils\log( sprintf( 'Public tax terms added to preload queue. ' ) );
199 224 }
200 225
226 + /**
227 + * Filters preload urls before sending to queue
228 + *
229 + * @hook populate_preload_queue_urls
230 + *
231 + * @param {array} $preload_urls The list of preload urls
232 + *
233 + * @return {array} New value.
234 + * @since 2.4
235 + */
236 + $preload_urls = apply_filters( 'populate_preload_queue_urls', $preload_urls );
237 +
201 238 foreach ( $preload_urls as $url ) {
202 - $this->cache_preloader->push_to_queue( $url );
239 + $this->add_url_to_preload_queue( $url );
203 240 }
204 241 }
205 242
243 + /**
244 + * Add URLs to preload queue with a delay
245 + *
246 + * @param int $post_id Post ID
247 + * @param array $urls The URL list of the related pages that will be preloaded
248 + *
249 + * @since 3.6
250 + */
251 + public function deferred_preload_queue( $post_id, $urls ) {
252 + \PoweredCache\Utils\log( sprintf( 'Post ID %d purged from cache, adding related URLs to preload queue with a delay.', $post_id ) );
253 + wp_schedule_single_event(
254 + time() + 10,
255 + DEFERRED_PRELOAD_QUEUE_CRON_NAME,
256 + [
257 + 'post_id' => $post_id,
258 + 'urls' => $urls,
259 + ]
260 + );
261 + }
206 262
263 +
207 264 /**
208 265 * Add related pages to preload queue when the cache got cleared
209 266 *
210 267 * @param int $post_id Post ID
@@ -212,18 +269,23 @@
212 269 *
213 270 * @since 2.0
214 271 */
215 272 public function add_purged_urls_to_preload_queue( $post_id, $urls ) {
273 + $post_url = get_permalink( $post_id );
274 +
275 + // include post itself all the time
276 + if ( ! empty( $post_url ) ) {
277 + $this->add_url_to_preload_queue( $post_url );
278 + }
279 +
216 280 if ( ! $urls ) {
217 281 return;
218 282 }
219 283
220 284 foreach ( $urls as $url ) {
221 - $this->cache_preloader->push_to_queue( $url );
222 - \PoweredCache\Utils\log( sprintf( 'Pushed to preload queue [add_purged_urls_to_preload_queue]: %s', $url ) );
285 + $this->add_url_to_preload_queue( $url );
223 286 }
224 287
225 - $this->cache_preloader->save()->dispatch();
226 288 }
227 289
228 290 /**
229 291 * Requeue deleted URLs
@@ -267,13 +329,11 @@
267 329 foreach ( $expired_urls as $url ) {
268 330 if ( $has_trailingslash ) {
269 331 $url = trailingslashit( $url );
270 332 }
271 - $this->cache_preloader->push_to_queue( $url );
272 - \PoweredCache\Utils\log( sprintf( 'Pushed to preload queue [add_expired_urls_to_preload_queue]: %s', $url ) );
333 + $this->add_url_to_preload_queue( $url );
273 334 }
274 335
275 - $this->cache_preloader->save()->dispatch();
276 336 }
277 337
278 338 /**
279 339 * Prep. public post urls for preload queue
@@ -584,9 +644,9 @@
584 644 * @since 2.0
585 645 */
586 646 do_action( 'powered_cache_preload_http_request', $url, $args );
587 647
588 - \PoweredCache\Utils\log( sprintf( 'Preloading...%s: %s', $url, print_r( $args, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
648 + \PoweredCache\Utils\log( sprintf( 'Processing..: %s', $url ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
589 649
590 650 return wp_remote_get( esc_url_raw( $url ), $args );
591 651 }
592 652
@@ -600,14 +660,29 @@
600 660 * Filters wait time between preload requests.
601 661 *
602 662 * @hook powered_cache_preload_request_interval
603 663 *
604 - * @param {int} $delay Delay time in milliseconds.
664 + * @param {int} $delay Delay time in microseconds.
605 665 *
606 666 * @return {int} New value.
607 667 * @since 2.0
608 668 */
609 - usleep( absint( apply_filters( 'powered_cache_preload_request_interval', $delay ) ) );
669 + $delay = absint( apply_filters( 'powered_cache_preload_request_interval', $delay ) );
670 +
671 + // Convert the delay to seconds and microseconds
672 + $seconds = intdiv( $delay, 1000000 ); // Get full seconds
673 + $microseconds = $delay % 1000000; // Get remaining microseconds
674 +
675 + // Use sleep() for full second delays
676 + if ( $seconds > 0 ) {
677 + sleep( $seconds );
678 + }
679 +
680 + // Use usleep() for remaining microseconds
681 + // sleeping more than 1 seconds may not be supported by the operating system with usleep
682 + if ( $microseconds > 0 ) {
683 + usleep( $microseconds );
684 + }
610 685 }
611 686
612 687
613 688 /**
@@ -626,7 +701,54 @@
626 701 * @return {string} New value.
627 702 * @since 2.0
628 703 */
629 704 return apply_filters( 'powered_cache_preload_mobile_user_agent', 'Powered Cache Preloader mobile iPhone' );
705 + }
706 +
707 + /**
708 + * Add a URL to the preload queue with optional filtering.
709 + *
710 + * @param string $url The URL to add to the preload queue.
711 + *
712 + * @since 3.4
713 + */
714 + protected function add_url_to_preload_queue( $url ) {
715 + /**
716 + * Filters whether a URL should be added to the preload queue.
717 + *
718 + * @hook powered_cache_preload_add_url_to_queue
719 + *
720 + * @param {boolean} $preload Whether to preload the URL. Default true.
721 + * @param {string} $url The URL to be preloaded.
722 + *
723 + * @return {boolean} Whether to preload the URL.
724 + * @since 3.4
725 + */
726 + $do_preload = apply_filters( 'powered_cache_preload_add_url_to_queue', true, $url );
727 +
728 + if ( $do_preload ) {
729 + $this->get_preloader()->push_to_queue( $url );
730 + $this->queue_dirty = true;
731 + \PoweredCache\Utils\log( sprintf( 'URL added to preload queue : %s', $url ) );
732 + } else {
733 + \PoweredCache\Utils\log( sprintf( 'URL skipped from preload queue: %s', $url ) );
734 + }
735 + }
736 +
737 + /**
738 + * Dispatch the preload queue if it has been modified.
739 + *
740 + * @return void
741 + * @since 3.6
742 + */
743 + public function dispatch_preload_queue() {
744 + if ( ! $this->queue_dirty ) {
745 + return;
746 + }
747 +
748 + // This will serialize the queue into the DB and fire off the async request
749 + $this->get_preloader()->save()->dispatch();
750 +
751 + \PoweredCache\Utils\log( 'Dispatched preload queue.' );
630 752 }
631 753
632 754 }