PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 1.9.7
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v1.9.7
4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.0.30 4.0.29 4.0.28 4.0.27 4.0.26 4.0.24 4.0.25 4.0.23 4.0.22 4.0.21 4.0.19 4.0.18 4.0.17 4.0.16 1.9.3 1.9.4 1.9.5 1.9.6 All 170 releases
searchpro / inc / class-berqcache.php

class-berqcache.php in BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript 1.9.7, at inc/class-berqcache.php

948 lines 34.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH'))
3 exit;
4
5 if (!class_exists('berqCache')) {
6 class berqCache
7 {
8 public $cache_file;
9 public $max_page_per_batch = 5;
10
11 function __construct()
12 {
13 $this->max_page_per_batch = apply_filters( 'berqwp_max_pages_per_batch', 5 );
14
15 add_filter( 'berqwp_ignored_urls_params', [$this, 'ingore_tracking_params'] );
16
17 // $this->cache_file = berqwp_current_page_cache_file();
18
19 // clear cache after migration
20 if (get_option('berqwp_site_url', home_url()) !== home_url()) {
21
22 if (get_option('berqwp_site_url', home_url()) !== null) {
23 global $berq_log;
24 $berq_log->info('Home url change detected, flushing all cache');
25 }
26
27 $this->delete_cache_files();
28 update_option('berqwp_site_url', home_url());
29 delete_transient( 'berq_lic_response_cache' );
30 }
31
32 global $berqwp_is_dropin;
33 if (empty($berqwp_is_dropin)) {
34 add_action('wp', [$this, 'html_cache'], 2);
35 }
36
37 // Add clear cache link to admin bar
38 add_action('admin_bar_menu', [$this, 'add_clear_cache_link_to_admin_bar'], 999);
39
40 // Flush cache
41 add_action('admin_post_clear_cache', [$this, 'handle_clear_cache_action']);
42
43 // Purge a page cache
44 add_action('admin_post_berq_purge_page', [$this, 'handle_berq_purge_page_action']);
45
46 // Request page cache
47 add_action('admin_post_berq_request_cache', [$this, 'handle_berq_request_cache_action']);
48
49 // Flush CDN cache
50 add_action('admin_post_berq_flush_cdn', [$this, 'handle_berq_flush_cdn_action']);
51
52 // Flush critical CSS cache
53 add_action('admin_post_berq_flush_criticalcss', [$this, 'handle_berq_flush_criticalcss_action']);
54
55 // Clear page cache on update
56 add_action('save_post', [$this, 'clear_cache_on_post_udpate'], 10, 3);
57
58 // Automatic cache warmup
59 add_action('init', [$this, 'warmup_queue']);
60 add_action('warmup_cache_by_slug', [$this, 'handle_warmup_cache_by_slug']);
61 add_action('warmup_cache_quickly', 'warmup_cache_by_slug');
62 add_action('admin_notices', [$this, 'cache_warmup_admin_notice']);
63
64
65 // add_action('wp_loaded', [$this, 'berqwp_warmup_cache_all_pages']);
66
67 add_action('berqwp_before_update_optimization_mode', [$this, 'delete_cache_files']);
68
69 // Reverse proxy cache support
70 add_action('berqwp_stored_page_cache', [$this, 'flush_reverse_proxy_cache']);
71 add_action('berqwp_flush_all_cache', [$this, 'flush_reverse_proxy_cache']);
72 add_action('berqwp_flush_page_cache', [$this, 'flush_reverse_proxy_cache']);
73
74 // Clear cache warmup lock after storing the cache
75 add_action('berqwp_stored_page_cache', 'bwp_clear_warmup_lock');
76
77 add_action('init', [$this, 'bypass_cache']);
78
79
80 }
81
82 function bypass_cache() {
83 if (isset($_GET['generating_critical_css'])
84 || isset($_GET['nocache'])
85 || isset($_GET['creating_cache']) || berqDetectCrawler::is_crawler() ||
86 (get_option('berqwp_enable_sandbox') == 1 && !isset($_GET['berqwp']) && !is_admin() && !isset($_POST))) {
87
88 add_filter( 'berqwp_bypass_cache', function () { return true; } );
89
90 // if (berqReverseProxyCache::is_reverse_proxy_cache_enabled()) {
91 berqReverseProxyCache::bypass();
92 // }
93
94 }
95 }
96
97 function flush_reverse_proxy_cache($slug = '/.*') {
98
99 if (empty($slug)) {
100 $slug = '/.*'; // Purge all cache
101 }
102
103 if ($slug == '/') {
104 $slug = '';
105 }
106
107 $page_url = home_url() . $slug;
108 berqReverseProxyCache::purge_cache($page_url);
109 }
110
111 function ingore_tracking_params($tracking_params) {
112 $tracking_params = array_merge($tracking_params, ignoreParams::$query_params);
113 return $tracking_params;
114 }
115
116 function berqwp_warmup_cache_all_pages()
117 {
118
119 if (isset($_GET['run_warmup'])) {
120
121 global $berq_log;
122 $berq_log->info('* * * * * * * * * * * * *');
123 $berq_log->info('* Manual Cache Warmup');
124 $berq_log->info('* * * * * * * * * * * * *');
125
126 // Get all published pages and posts
127 $args = array(
128 'post_type' => array('page'),
129 'post_status' => 'publish',
130 'posts_per_page' => -1, // Get all posts
131 );
132 $query = new WP_Query($args);
133
134 // API endpoint URL
135 $api_endpoint = 'https://boost.berqwp.com/photon/';
136
137 if (get_site_url() == 'http://berq-test.local') {
138 $api_endpoint = 'http://dev-berqwp.local/photon/';
139 }
140
141 $httpMulti = new bwp_multi_http();
142
143
144 // Loop through each post/page and warm up the cache
145 if ($query->have_posts()) {
146 while ($query->have_posts()) {
147 $query->the_post();
148 $url = trailingslashit(get_permalink()); // Get the permalink of the post/page
149
150 // $httpMulti->addRequest('GET', $url);
151 $slug = str_replace(home_url(), '', $url);
152 $post_data = berqwp_get_page_params($slug, true);
153
154 $httpMulti->addRequest('POST', $api_endpoint, $post_data);
155
156 $berq_log->info("Requesting cache for $slug");
157 }
158 }
159
160 $responses = $httpMulti->execute();
161 wp_reset_postdata();
162
163 }
164
165 }
166
167 function warmup_queue()
168 {
169 $wp_content_adv_cache = ABSPATH . 'wp-content/advanced-cache.php';
170 $bwp_adv_cache = optifer_PATH . 'advanced-cache.php';
171
172 if (
173 (!file_exists($wp_content_adv_cache) && get_option('berqwp_enable_sandbox') !== 1)
174 || (file_exists($wp_content_adv_cache) && md5_file($wp_content_adv_cache) !== md5_file($bwp_adv_cache))
175 ) {
176 // Specify the drop-in file path
177 $dropin_file = ABSPATH . 'wp-content/advanced-cache.php';
178
179 // Dynamically create the drop-in file
180 $dropin_content = file_get_contents(optifer_PATH . 'advanced-cache.php');
181
182 // Write the drop-in content to the file, replacing any existing file
183 file_put_contents($dropin_file, $dropin_content);
184
185 // Enable object cache in wp-config.php
186 berqwp_enable_object_cache(true);
187
188 if (function_exists('wp_cache_flush')) {
189 wp_cache_flush(); // Clear the entire object cache.
190 }
191 }
192
193 if (get_option('berqwp_enable_sandbox') == 1 && file_exists($wp_content_adv_cache)) {
194 unlink($wp_content_adv_cache);
195 }
196
197 if (false === as_has_scheduled_action('warmup_cache_by_slug')) {
198 $post_types = get_option('berqwp_optimize_post_types');
199
200 $args = array(
201 'post_type' => $post_types,
202 'posts_per_page' => -1,
203 'fields' => 'ids',
204 'post_status' => 'publish',
205 );
206
207 $query = new WP_Query($args);
208
209 // Calculate the total number of pages
210 $total_posts = count($query->posts);
211
212 $posts_per_batch = $this->max_page_per_batch;
213 $total_pages = ceil($total_posts / $posts_per_batch);
214
215
216 // Schedule the events
217 for ($page = 1; $page <= $total_pages; $page++) {
218 as_schedule_single_action(time() + (80 * $page), 'warmup_cache_by_slug', array($page));
219 }
220
221 wp_reset_postdata();
222 }
223
224 if (false === as_has_scheduled_action('warmup_cache_quickly') && (bwp_is_home_cached() === false || bwp_is_partial_cache('/')) && function_exists('as_enqueue_async_action')) {
225 as_enqueue_async_action('warmup_cache_quickly', ['/', true]);
226 }
227
228
229
230 }
231
232 function can_send_warmup_request()
233 {
234 $requests_sent = get_transient('berqwp_warmup_requests_count');
235
236 // If we haven't set the rate limiting transient yet, or if we're still below our rate, return true.
237 if (false === $requests_sent || $requests_sent < BERQWP_MAX_WARMUP_REQUESTS) {
238 return true;
239 }
240
241 return false;
242 }
243
244 function update_warmup_request_count()
245 {
246 $requests_sent = get_transient('berqwp_warmup_requests_count');
247
248 if (false === $requests_sent) {
249 // If this is the first request in our window, set the transient with a timeout.
250 set_transient('berqwp_warmup_requests_count', 1, BERQWP_WARMUP_RATE_LIMIT_WINDOW);
251 } else {
252 // Otherwise, just increment the counter.
253 set_transient('berqwp_warmup_requests_count', ++$requests_sent, BERQWP_WARMUP_RATE_LIMIT_WINDOW);
254 }
255 }
256
257
258
259 function handle_warmup_cache_by_slug($page)
260 {
261 global $berq_log;
262 $berq_log->info("handle_warmup_cache_by_slug triggered");
263
264 // error_log('-page-' . $page);
265 if ($this->can_send_warmup_request()) {
266 // error_log('page-' . $page);
267 $this->warmup_cache($page);
268 $this->update_warmup_request_count();
269 } else {
270 $berq_log->info("handle_warmup_cache_by_slug cache skipped");
271 // You've hit the rate limit.
272 $retry_after_seconds = 200; // Retry after 10 minutes. You can adjust this time as needed.
273 // as_schedule_single_action(time() + $retry_after_seconds, 'warmup_cache_by_slug', array($page));
274 }
275 }
276
277
278
279 function clear_cache_on_post_udpate($post_id, $post, $update)
280 {
281 // If this is just a revision, don't run the function.
282 if (wp_is_post_revision($post_id)) {
283 return;
284 }
285
286 $post_url = get_permalink($post_id);
287 $slug = str_replace(home_url(), '', $post_url);
288 $cache_key = md5($slug);
289 $cache_directory = optifer_cache . '/html/';
290 $cache_file = $cache_directory . $cache_key . '.html';
291
292 global $berq_log;
293 $berq_log->info("Post updated, deleting cache for $post_url");
294
295 if (file_exists($cache_file)) {
296 unlink($cache_file);
297 }
298
299 }
300
301 function flatten_array($array)
302 {
303 $result = array();
304 foreach ($array as $item) {
305 if (is_array($item)) {
306 $result = array_merge($result, $this->flatten_array($item));
307 } else {
308 $result[] = $item;
309 }
310 }
311 return $result;
312 }
313
314 function handle_berq_purge_page_action()
315 {
316 // Check if the user has the necessary nonce and the action matches
317 if (isset($_GET['action']) && $_GET['action'] === 'berq_purge_page' && wp_verify_nonce($_GET['_wpnonce'], 'berq_purge_page_action')) {
318
319 $slug = sanitize_text_field($_GET['uri']);
320 $cache_file = optifer_cache . '/html/' . md5($slug) . '.html';
321
322 if (is_file($cache_file)) {
323 unlink($cache_file);
324 }
325
326 $cache_file = optifer_cache . '/html/' . md5($slug) . '.gz';
327
328 if (is_file($cache_file)) {
329 unlink($cache_file);
330 }
331
332
333 if (function_exists('wp_cache_flush')) {
334 wp_cache_flush(); // Clear the entire object cache.
335 }
336
337 do_action('berqwp_flush_page_cache', $slug);
338
339 // Redirect back to the referring page after clearing the cache
340 wp_safe_redirect(wp_get_referer());
341 exit;
342 }
343 }
344
345 function handle_berq_request_cache_action()
346 {
347 // Check if the user has the necessary nonce and the action matches
348 if (isset($_GET['action']) && $_GET['action'] === 'berq_request_cache' && wp_verify_nonce($_GET['_wpnonce'], 'berq_request_cache_action')) {
349
350 $slug = sanitize_text_field($_GET['uri']);
351
352 as_enqueue_async_action('warmup_cache_quickly', [$slug, true]);
353
354 // Redirect back to the referring page after clearing the cache
355 wp_safe_redirect(wp_get_referer());
356 exit;
357 }
358 }
359
360 function handle_berq_flush_cdn_action()
361 {
362 // Check if the user has the necessary nonce and the action matches
363 if (isset($_GET['action']) && $_GET['action'] === 'berq_flush_cdn' && wp_verify_nonce($_GET['_wpnonce'], 'berq_flush_cdn_action')) {
364
365 $parsed_url = wp_parse_url(home_url());
366 $domain = $parsed_url['host'];
367
368 $args = [
369 'timeout' => 30,
370 'body' => ['flush_cdn' => $domain, 'license_key' => get_option('berqwp_license_key')]
371 ];
372
373 wp_remote_post( 'https://boost.berqwp.com/photon/', $args );
374
375 // Flush cache
376 $this->delete_cache_files();
377
378 do_action( 'berqwp_purge_cdn' );
379
380 set_transient('berq_purge_cdn_notice', 'true', 60);
381
382 // Redirect back to the referring page after clearing the cache
383 wp_safe_redirect(wp_get_referer());
384 exit;
385 }
386 }
387
388 function handle_berq_flush_criticalcss_action()
389 {
390 // Check if the user has the necessary nonce and the action matches
391 if (isset($_GET['action']) && $_GET['action'] === 'berq_flush_criticalcss' && wp_verify_nonce($_GET['_wpnonce'], 'berq_flush_criticalcss_action')) {
392
393 $parsed_url = wp_parse_url(home_url());
394 $domain = $parsed_url['host'];
395
396 $args = [
397 'timeout' => 30,
398 'body' => ['flush_criticalcss' => $domain, 'license_key' => get_option('berqwp_license_key')]
399 ];
400
401 wp_remote_post( 'https://boost.berqwp.com/photon/', $args );
402
403 do_action( 'berqwp_purge_criticalcss' );
404
405 set_transient('berq_purge_criticalcss_notice', 'true', 60);
406
407 // Redirect back to the referring page after clearing the cache
408 wp_safe_redirect(wp_get_referer());
409 exit;
410 }
411 }
412
413 function handle_clear_cache_action()
414 {
415 // Check if the user has the necessary nonce and the action matches
416 if (isset($_GET['action']) && $_GET['action'] === 'clear_cache' && wp_verify_nonce($_GET['_wpnonce'], 'clear_cache_action')) {
417 // Call your custom cache clearing function here
418 $this->delete_cache_files();
419
420 if (function_exists('wp_cache_flush')) {
421 wp_cache_flush(); // Clear the entire object cache.
422 }
423
424 set_transient('berq_cache_cleared_notice', 'true', 60);
425
426 $redirect_url = add_query_arg('berq_clear_cache', '', wp_get_referer());
427
428 // Redirect back to the referring page after clearing the cache
429 wp_safe_redirect($redirect_url);
430 exit;
431 }
432 }
433
434 function delete_cache_files()
435 {
436 global $berq_log;
437 $berq_log->info("Flushing all cache.");
438
439 // Define the cache directory
440 $cache_directory = optifer_cache . '/html/';
441
442 // Delete all cache files within the directory
443 berqwp_unlink_recursive($cache_directory);
444
445 delete_transient('berqwp_warmup_running');
446 delete_transient('cache_warmup_in_progress');
447 delete_transient('berqwp_doing_cache_warmup');
448
449 do_action('berqwp_flush_all_cache');
450 }
451
452 function add_clear_cache_link_to_admin_bar()
453 {
454 global $wp_admin_bar;
455
456 // Check if the user has the capability to clear the cache (adjust the capability as needed)
457 if (current_user_can('manage_options')) {
458 $wp_admin_bar->add_menu(
459 array(
460 'id' => 'berqWP',
461 'title' => 'BerqWP',
462 'href' => get_admin_url() . '/admin.php?page=berqwp',
463 )
464 );
465
466 // Add the sub-menu item
467 $wp_admin_bar->add_menu(
468 array(
469 'parent' => 'berqWP',
470 // ID of the parent menu item
471 'id' => 'flush-cache',
472 'title' => 'Flush cache',
473 'href' => wp_nonce_url(admin_url('admin-post.php?action=clear_cache'), 'clear_cache_action'),
474 'meta' => array(
475 'class' => 'clear-cache-link',
476 'title' => 'Clear BerqWP cache',
477 ),
478 )
479 );
480
481 $wp_admin_bar->add_menu(
482 array(
483 'parent' => 'berqWP',
484 // ID of the parent menu item
485 'id' => 'flush-cdn',
486 'title' => 'Flush CDN & page cache',
487 'href' => wp_nonce_url(admin_url('admin-post.php?action=berq_flush_cdn'), 'berq_flush_cdn_action'),
488 'meta' => array(
489 'class' => 'flush-cdn-cache',
490 'title' => 'Flush CDN & page cache',
491 ),
492 )
493 );
494
495 $wp_admin_bar->add_menu(
496 array(
497 'parent' => 'berqWP',
498 // ID of the parent menu item
499 'id' => 'flush-criticalcss',
500 'title' => 'Flush critical CSS cache',
501 'href' => wp_nonce_url(admin_url('admin-post.php?action=berq_flush_criticalcss'), 'berq_flush_criticalcss_action'),
502 'meta' => array(
503 'class' => 'flush-criticalcss',
504 'title' => 'Flush critical CSS cache',
505 ),
506 )
507 );
508
509 if (!is_admin()) {
510 // Add the sub-menu item
511 $wp_admin_bar->add_menu(
512 array(
513 'parent' => 'berqWP',
514 // ID of the parent menu item
515 'id' => 'purge-page',
516 'title' => 'Purge this page',
517 'href' => wp_nonce_url(admin_url('admin-post.php?action=berq_purge_page&uri=' . urlencode($_SERVER['REQUEST_URI'])), 'berq_purge_page_action'),
518 'meta' => array(
519 'class' => 'purge-page-link',
520 'title' => 'Clear this page cache',
521 ),
522 )
523 );
524
525 // Add the request cache
526 $wp_admin_bar->add_menu(
527 array(
528 'parent' => 'berqWP',
529 // ID of the parent menu item
530 'id' => 'request-page-cache',
531 'title' => 'Request cache',
532 'href' => wp_nonce_url(admin_url('admin-post.php?action=berq_request_cache&uri=' . urlencode($_SERVER['REQUEST_URI'])), 'berq_request_cache_action'),
533 'meta' => array(
534 'class' => 'request-page-cache-link',
535 'title' => 'Request cache for this page',
536 ),
537 )
538 );
539
540 }
541
542 }
543 }
544
545 static function is_cache_file_expired($cache_file) {
546 $cache_max_life = filemtime($cache_file) + (18 * 60 * 60);
547
548 // is still valide
549 if ($cache_max_life > time()) {
550 return false;
551 }
552
553 return true;
554 }
555
556
557 function html_cache()
558 {
559 // Check if the current user is logged in or if it's a POST request
560 if (is_user_logged_in() || $_SERVER['REQUEST_METHOD'] === 'POST') {
561 return;
562 }
563
564 if (is_admin()) {
565 return;
566 }
567
568 if (defined('DOING_CRON') && DOING_CRON) {
569 return;
570 }
571
572 if (defined('DOING_AJAX') && DOING_AJAX) {
573 return;
574 }
575
576 if (defined('REST_REQUEST') && REST_REQUEST) {
577 return;
578 }
579
580 if (php_sapi_name() === 'cli' || defined('WP_CLI')) {
581 return;
582 }
583
584 if (!bwp_is_webpage()) {
585 return;
586 }
587
588 $bypass_cache = apply_filters( 'berqwp_bypass_cache', false );
589
590 if ($bypass_cache) {
591 return;
592 }
593
594 $slug_uri = $_SERVER['REQUEST_URI'];
595
596 // if wordpress is installed in a sub directory
597 if (berqwp_is_sub_dir_wp()) {
598 // Parse strings to extract paths
599 $path1 = explode('/', parse_url(home_url(), PHP_URL_PATH));
600 $path2 = explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
601
602 // Find the common part of the paths
603 $commonPath = implode('/', array_intersect($path1, $path2));
604
605 // Subtract the common part from the first string
606 $slug_uri = str_replace($commonPath, '', $_SERVER['REQUEST_URI']);
607 }
608
609 // Return if page is excluded from cache
610 $pages_to_exclude = get_option('berq_exclude_urls', []);
611
612 if (in_array(home_url() . $slug_uri, $pages_to_exclude)) {
613 return;
614 }
615
616 // Remove ignored params from the slug
617 $slug = berqwp_remove_ignore_params($slug_uri);
618
619 if (isset($_GET['creating_cache'])) {
620 return;
621 }
622
623 if (get_option('berqwp_enable_sandbox') == 1 && isset($_GET['berqwp'])) {
624 $slug = explode('?berqwp', $slug_uri)[0];
625 } elseif (get_option('berqwp_enable_sandbox') == 1 && !isset($_GET['creating_cache'])) {
626 return;
627 }
628
629 if (is_singular()) {
630 $post_type = get_post_type();
631
632 if (empty($post_type) || !in_array($post_type, get_option('berqwp_optimize_post_types'))) {
633 return;
634 }
635 } elseif (is_archive()) {
636 $queried_object = get_queried_object();
637
638 if ($queried_object instanceof WP_Term && !empty($queried_object->taxonomy)) {
639 $current_taxonomy = $queried_object->taxonomy;
640
641 if (!in_array($current_taxonomy, get_option('berqwp_optimize_taxonomies'))) {
642 return;
643 }
644 }
645 }
646
647
648 // Attempt to retrieve the cached HTML from the cache directory
649 $cache_directory = optifer_cache . '/html/';
650
651 // Generate a unique cache key based on the current page URL
652 $cache_key = md5($slug);
653 $cache_file = $cache_directory . $cache_key . '.html';
654
655
656 $status_code = http_response_code();
657
658 if ($status_code !== 200) {
659 return;
660 }
661
662 if (berqwp_is_slug_excludable($slug)) {
663 return;
664 }
665
666 // Account requirement doesn't meet && not updating existing cache
667 if (!file_exists($cache_file) && bwp_pass_account_requirement() === false) {
668 return;
669 }
670
671
672 if (!isset($_GET['creating_cache'])) {
673 if (strpos($slug, '?creating_cache') === false) {
674 // $page_modified_time = berqwp_get_last_modified_timestamp();
675 $cache_life_span = time() - (18 * 60 * 60);
676
677 // Hook to modify cache lifespan
678 $cache_life_span = apply_filters('berqwp_cache_lifespan', $cache_life_span);
679
680 if (bwp_is_gzip_supported() && file_exists($cache_directory . $cache_key . '.gz')) {
681 $cache_file = $cache_directory . $cache_key . '.gz';
682 header('Content-Encoding: gzip');
683 header('Content-Type: text/html; charset=UTF-8');
684 }
685
686 if (
687 (!file_exists($cache_file) ||
688 (file_exists($cache_file) && $this->is_cache_file_expired($cache_file)) ) ||
689 (file_exists($cache_file) && bwp_is_partial_cache($slug) === true)
690 && bwp_can_warmup_cache($slug)
691 ) {
692
693 global $berq_log;
694 $startTime = microtime(true);
695
696 $args = array(
697 'timeout' => 0.01,
698 'body' => array(
699 'slug' => $slug,
700 ),
701 );
702
703 wp_remote_post(get_site_url() . '/wp-json/optifer/v1/warmup-cache', $args);
704
705 // Get end time
706 $endTime = microtime(true);
707
708 // Calculate runtime in milliseconds
709 $runtime = ($endTime - $startTime) * 1000;
710
711 $berq_log->info("Requesting cache for $slug took $runtime ms from frontend.");
712
713 }
714
715 }
716 }
717
718 $berqPageOptimizer = new berqPageOptimizer();
719 $berqPageOptimizer->set_slug($slug);
720 $berqPageOptimizer->start_cache();
721 unset($berqPageOptimizer);
722
723 // If the cached HTML file exists, serve it and stop further execution
724 if (!isset($_GET['creating_cache']) && file_exists($cache_file) && !$this->is_cache_file_expired($cache_file)) {
725 $lastModified = filemtime($cache_file);
726 $etag = md5_file($cache_file);
727 header('ETag: ' . $etag);
728 header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
729
730 // Check if the client has a cached copy and if it's still valid using Last-Modified
731 if ((isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified) || (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag)) {
732 // The client's cache is still valid based on Last-Modified, respond with a 304 Not Modified
733 header('HTTP/1.1 304 Not Modified');
734 header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
735 header('Cache-Control: no-cache, must-revalidate');
736 exit();
737
738 } else {
739
740 header('Cache-Control: public, max-age=86400');
741
742 if (file_exists($cache_file)) {
743 readfile($cache_file);
744 exit();
745 }
746
747 }
748 }
749
750 if (berqReverseProxyCache::is_reverse_proxy_cache_enabled()) {
751 berqReverseProxyCache::handle_bypass();
752 }
753
754 return;
755
756 }
757
758 function warmup_cache($page)
759 {
760 global $berq_log;
761 $berq_log->info("* * * * * * * * *");
762 $berq_log->info("* Cache Warmup");
763 $berq_log->info("* * * * * * * * *");
764
765 $posts_per_batch = $this->max_page_per_batch;
766
767 // if (get_transient('berqwp_doing_cache_warmup')) {
768 // return;
769 // }
770
771 // set_transient('berqwp_doing_cache_warmup', true, 120);
772
773 // Set a transient to indicate that the cache warmup is in progress
774 set_transient('cache_warmup_in_progress', true, 120);
775
776 // warmup_cache_by_slug('/');
777
778 // $post_types = get_post_types(array('publicly_queryable' => true), 'names');
779 $post_types = get_option('berqwp_optimize_post_types');
780
781 // API endpoint URL
782 $api_endpoint = 'https://boost.berqwp.com/photon/';
783
784 if (get_site_url() == 'http://berq-test.local') {
785 $api_endpoint = 'http://dev-berqwp.local/photon/';
786 }
787
788 // Modify photon engine endpoint for testing purposes
789 $api_endpoint = apply_filters( 'berqwp_photon_endpoint', $api_endpoint );
790
791 // $post_types[] = 'product';
792 $args = array(
793 'post_type' => $post_types,
794 'posts_per_page' => $posts_per_batch,
795 'paged' => $page,
796 );
797
798 $check_rest = bwp_check_rest_api(true);
799 if ( $check_rest['status'] == 'error' ) {
800 global $berq_log;
801 $berq_log->error('Exiting cron cache warmup, rest api not working.');
802 return;
803 }
804
805 $query = new WP_Query($args);
806
807 $httpMulti = new bwp_multi_http();
808
809 $post_data = berqwp_get_page_params('/');
810 $httpMulti->addRequest('POST', $api_endpoint, $post_data);
811
812 // Loop through all posts and make a GET request
813 while ($query->have_posts()) {
814 $query->the_post();
815
816 // Get the post URL and make a GET request
817 $url = trailingslashit(get_permalink());
818 $slug = str_replace(home_url(), '', $url);
819 $post_data = berqwp_get_page_params($slug);
820
821 // Skip if page is excluded from cache
822 $pages_to_exclude = get_option('berq_exclude_urls', []);
823
824 // Attempt to retrieve the cached HTML from the cache directory
825 $cache_directory = optifer_cache . '/html/';
826
827 // Generate a unique cache key based on the current page URL
828 $cache_key = md5($slug);
829 $cache_file = $cache_directory . $cache_key . '.html';
830 $page_modified_time = berqwp_get_last_modified_timestamp();
831 $cache_life_span = time() - (18 * 60 * 60);
832
833 if (!file_exists($cache_file) && bwp_pass_account_requirement() === false) {
834 $berq_log->info("Exiting cache $slug");
835 continue;
836 }
837
838 if (in_array($url, $pages_to_exclude)) {
839
840 if (file_exists($cache_file)) {
841 unlink($cache_file);
842 }
843
844 continue;
845 }
846
847 if (berqwp_is_slug_excludable($slug)) {
848 continue;
849 }
850
851 // Hook to modify cache lifespan
852 $cache_life_span = apply_filters('berqwp_cache_lifespan', $cache_life_span);
853
854 if (
855 !file_exists($cache_file) ||
856 ($this->is_cache_file_expired($cache_file)) ||
857 (file_exists($cache_file) && bwp_is_partial_cache($slug) === true) ||
858 (file_exists($cache_file) && !empty($page_modified_time) && $page_modified_time > filemtime($cache_file))
859 ) {
860 $httpMulti->addRequest('POST', $api_endpoint, $post_data);
861
862 $berq_log->info("Requesting cache for $slug");
863
864 }
865
866
867 }
868
869 $responses = $httpMulti->execute();
870
871 wp_reset_postdata();
872
873 delete_transient('cache_warmup_in_progress');
874 delete_transient('berqwp_doing_cache_warmup');
875
876 }
877
878
879 function cache_warmup_admin_notice()
880 {
881
882
883 if (get_transient('cache_warmup_in_progress')) {
884 ?>
885 <div class="notice notice-info is-dismissible">
886 <p>
887 <?php
888 esc_html_e('Cache warmup is in progress... This process could take some time depending on the number of pages on your website.', 'searchpro');
889 ?>
890 </p>
891 </div>
892 <?php
893 }
894
895 if (!get_transient('cache_warmup_in_progress') && isset($_GET['berq_warmingup'])) {
896 ?>
897 <div class="notice notice-info is-dismissible">
898 <p>
899 <?php esc_html_e('BerqWP is starting cache warmup. Please wait.', 'searchpro'); ?>
900 </p>
901 </div>
902 <?php
903 }
904
905 if (get_transient('berq_cache_cleared_notice')) {
906 delete_transient('berq_cache_cleared_notice');
907 ?>
908 <div class="notice notice-success is-dismissible">
909 <p>
910 <strong><?php esc_html_e('Success: ', 'searchpro'); ?></strong>
911 <?php esc_html_e('The cache has been cleared. Our automatic cache warm-up system will generate the cache. Alternatively, you can
912 visit any page to create its cache immediately.', 'searchpro'); ?>
913 </p>
914 </div>
915 <?php
916 }
917
918 if (get_transient('berq_purge_cdn_notice')) {
919 delete_transient('berq_purge_cdn_notice');
920 ?>
921 <div class="notice notice-success is-dismissible">
922 <p>
923 <strong><?php esc_html_e('Success: ', 'searchpro'); ?></strong>
924 <?php esc_html_e('The CDN and page cache have been flushed.', 'searchpro'); ?>
925 </p>
926 </div>
927 <?php
928 }
929
930 if (get_transient('berq_purge_criticalcss_notice')) {
931 delete_transient('berq_purge_criticalcss_notice');
932 ?>
933 <div class="notice notice-success is-dismissible">
934 <p>
935 <strong><?php esc_html_e('Success: ', 'searchpro'); ?></strong>
936 <?php esc_html_e('Critical CSS cache has been flushed from the cloud.', 'searchpro'); ?>
937 </p>
938 </div>
939 <?php
940 }
941 }
942
943 }
944
945 $cache = new berqCache();
946
947 }
948