PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 4.0.30
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v4.0.30
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 / cache / class-berqcache.php

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

1,036 lines 35.5 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 use BerqWP\BerqWP;
6
7 if (!class_exists('berqCache')) {
8 class berqCache
9 {
10 public static $instance = null;
11
12 function __construct()
13 {
14
15 $this->process_migration();
16
17 add_filter('berqwp_ignored_urls_params', [$this, 'ingore_tracking_params']);
18
19 add_action('template_redirect', [$this, 'queue_page'], 11);
20
21 if (!isset($_GET['bwp_preload'])) {
22 add_action('wp', [$this, 'html_cache'], 2);
23 }
24
25 // Clear page cache on update
26 add_action('save_post', [$this, 'clear_cache_on_post_update'], 10, 3);
27
28 // // Automatic cache warmup
29 // // add_action('init', [$this, 'warmup_home']);
30 // add_action('berqwp_flush_all_cache', [$this, 'warmup_home']);
31 // add_action('warmup_cache_quickly', 'warmup_cache_by_url');
32 // add_action('bwp_warmup_sitemap', [$this, 'warmup_sitemap']);
33 // add_action('berqwp_flush_all_cache', [$this, 'request_warmup_cache']);
34 // add_action('berqwp_cache_warmup', [$this, 'request_warmup_cache']);
35
36 // Delete cache files when the mode changes
37 // add_action('berqwp_before_update_optimization_mode', [$this, 'delete_cache_files']);
38 add_action('berqwp_on_update_optimization_mode', [$this, 'delete_cache_files']);
39
40 // Reverse proxy cache support
41 add_action('berqwp_stored_page_cache', [$this, 'flush_reverse_proxy_cache']);
42 add_action('berqwp_flush_all_cache', ['berqReverseProxyCache', 'flush_all']);
43 add_action('berqwp_flush_page_cache', [$this, 'flush_reverse_proxy_cache']);
44
45 // Clear cache warmup lock after storing the cache
46 add_action('berqwp_stored_page_cache', 'bwp_clear_warmup_lock');
47
48 // Log recently optimized pages
49 add_action('berqwp_stored_page_cache', 'bwp_log_recently_optimized_page', 20, 1);
50 add_action('berqwp_flush_all_cache', 'bwp_clear_recently_optimized_log');
51 add_action('berqwp_flush_page_cache', 'bwp_remove_recently_optimized_entry', 10, 1);
52
53 add_action('init', [$this, 'bypass_cache']);
54
55 // add_action('init', [$this, 'bypass_cache']);
56
57 // Flush cache when there's a new comment
58 add_action('wp_set_comment_status', [$this, 'handle_new_comment'], 10, 2);
59
60 // Store cache without any need for the rest api
61 add_action('init', 'bwp_webhook');
62
63 // Handle request new cache request
64 add_action('init', 'bwp_handle_request_cache');
65
66 // Flush cache when theme changes
67 add_action('switch_theme', [$this, 'delete_cache_files']);
68
69 // Flush critical css when theme changes
70 add_action('switch_theme', [$this, 'purge_critical_css_cache']);
71
72 // Flush critical css when custimizer additional css is updated
73 add_action('customize_save_css', [$this, 'purge_critical_css_cache']);
74
75 // Request cache when a post is published
76 // clear_cache_on_post_update and handle_post_status_update almost do the same thing
77 // add_action( 'transition_post_status', [$this, 'handle_post_status_update'], 10, 3 );
78
79 add_action('send_headers', [$this, 'brust_cache_for_loggedin']);
80
81 // Purge home page when new post is published
82 add_action('transition_post_status', [$this, 'purge_home'], 10, 3);
83
84 // flush cloudflare edge cache
85 add_action('berqwp_stored_page_cache', [$this, 'flush_cf_page']);
86 add_action('berqwp_flush_page_cache', [$this, 'flush_cf_page']);
87 add_action('berqwp_flush_all_cache', 'bwp_cf_flush_all');
88 add_action('berqwp_on_update_sandbox_mode', 'bwp_cf_flush_all');
89 add_action('berqwp_deactivate_plugin', 'bwp_cf_delete_rules');
90 add_action('berqwp_activate_plugin', [$this, 'check_cf_rules']);
91
92 // Apache htaccess cache rules (skip on LiteSpeed — remove any existing rules)
93 add_action('berqwp_activate_plugin', 'bwp_write_htaccess_rules');
94 add_action('berqwp_flush_all_cache', 'bwp_write_htaccess_rules');
95 add_action('berqwp_deactivate_plugin', 'bwp_remove_htaccess_rules');
96 if (bwp_is_openlitespeed_server()) {
97 add_action('berqwp_activate_plugin', 'bwp_remove_htaccess_rules');
98 }
99 add_action('berqwp_on_update_sandbox_mode', 'bwp_sync_htaccess_on_sandbox_change');
100
101 // Clear queue list on cloud
102 add_action('berqwp_deactivate_plugin', 'berqwp_clear_cache_queue');
103
104 // Edit post type list custom links
105 $bwp_post_types = get_option('berqwp_optimize_post_types');
106
107 if (is_admin() && !empty($bwp_post_types)) {
108 foreach ($bwp_post_types as $post_type) {
109 add_filter("{$post_type}_row_actions", [$this, 'post_type_action_links'], 10, 2);
110 }
111 }
112
113 // detect when theme/plugin is installed or updated
114 add_action( 'upgrader_process_complete', [$this, 'process_updates'], 10, 2 );
115
116 // handle menu update
117 add_action( 'wp_update_nav_menu', [$this, 'handle_menu_update'], 10, 2 );
118
119 // handle customizer save
120 add_action( 'customize_save', [$this, 'handle_customizer_update'] );
121
122 }
123
124 static function getInstance() {
125
126 if (self::$instance === null) {
127 $instance = new berqCache();
128 self::$instance = $instance;
129 return $instance;
130 }
131
132 return self::$instance;
133 }
134
135 function handle_customizer_update( $wp_customize ) {
136
137 global $berq_log;
138 $berq_log->info("Customizer updated");
139
140 $this->flush_all();
141
142 }
143
144 function handle_menu_update( $menu_id, $menu_data = null ) {
145
146 global $berq_log;
147 $berq_log->info("Site menu updated");
148
149 $this->flush_all();
150
151 }
152
153 function flush_all() {
154
155 global $berq_log;
156 $berq_log->info("Flushing everything");
157
158 if (berqwp_can_use_cloud()) {
159
160 // flush critical css
161 $this->purge_critical_css_cache();
162
163 // stale cdn
164 self::stale_cloud_assets();
165
166 }
167
168 // clear cache
169 $this->delete_cache_files();
170 }
171
172 function process_updates( WP_Upgrader $upgrader, array $hook_extra ) {
173
174 if (!berqwp_can_use_cloud()) {
175 return;
176 }
177
178 global $berq_log;
179 $berq_log->info("Processing updates");
180
181 self::stale_cloud_assets();
182 $this->purge_critical_css_cache();
183
184 }
185
186 static function stale_cloud_assets() {
187 if (!berqwp_can_use_cloud()) {
188 return;
189 }
190
191 global $berq_log;
192 $berq_log->info("Marking cloud assets stale");
193
194 $berqwp = new BerqWP(berqwp_get_license_key(), null, null);
195 $parsed_url = wp_parse_url(home_url());
196 $domain = $parsed_url['host'];
197
198 // mark cdn assets stale
199 $berqwp->cdn_stale_assets($domain);
200
201 // flush all critical css cache
202 $berqwp->purge_critilclcss($domain);
203 }
204
205 function process_migration() {
206 $raw_home = get_option('home');
207
208 if (defined('WP_HOME')) {
209 $raw_home = WP_HOME;
210 }
211
212 // detect migration when home changes
213 if (get_option('berqwp_raw_home', $raw_home) !== $raw_home) {
214 global $berq_log;
215 $berq_log->info('Raw home url change detected, flushing all cache');
216
217 if (get_option('berqwp_raw_home', $raw_home) !== null) {
218 $berq_log->info('Home url change detected, flushing all cache');
219 }
220
221 // regenerate site id
222 $berqconfigs = berqConfigs::getInstance();
223 $blog_id = get_current_blog_id();
224 $network_id = function_exists('get_current_network_id') ? get_current_network_id() : 1;
225 $siteurl = get_option('siteurl');
226 $site_id = md5("berqwp|$network_id|$blog_id|$siteurl");
227
228 $berqconfigs->update_configs(['site_id' => $site_id, 'secret' => '']);
229
230
231 // Flush critical css
232 $parsed_url = wp_parse_url(home_url());
233 $domain = $parsed_url['host'];
234 $berqwp = new BerqWP(berqwp_get_license_key(), null, null);
235 $berqwp->purge_critilclcss($domain);
236
237 // Flush page cache
238 $this->delete_cache_files();
239
240 update_option('berqwp_raw_home', $raw_home);
241 delete_transient('berq_lic_response_cache');
242 delete_transient('berqwp_lic_response_cache');
243 }
244 }
245
246 function post_type_action_links($actions, $post)
247 {
248
249 $page_url = get_permalink($post->ID);
250 $url = wp_nonce_url(admin_url('admin-post.php?action=berq_purge_page&uri=' . urlencode($page_url)), 'berq_purge_page_action');
251
252 $actions['berqwp_flush_cache'] = '<a href="' . esc_url($url) . '">Flush Cache</a>';
253
254 $url = wp_nonce_url(admin_url('admin-post.php?action=berq_request_cache&uri=' . urlencode($page_url)), 'berq_request_cache_action');
255
256 $actions['berqwp_force_cache'] = '<a href="' . esc_url($url) . '">Force Cache</a>';
257
258 return $actions;
259 }
260
261 function check_cf_rules()
262 {
263 if (!empty(get_option('berqwp_cf_creden'))) {
264 $email = get_option('berqwp_cf_creden')['email'];
265 $apitoken = get_option('berqwp_cf_creden')['apitoken'];
266 $zoneid = get_option('berqwp_cf_creden')['zoneid'];
267 $berqCloudflareAPIHandler = new berqCloudflareAPIHandler($email, $apitoken, $zoneid);
268
269 if ($berqCloudflareAPIHandler->verify_credentials()) {
270 $berqCloudflareAPIHandler->add_rule();
271 $berqCloudflareAPIHandler->purge_all_cache();
272 return;
273 }
274
275 delete_option('berqwp_cf_creden');
276 }
277 }
278
279 function flush_author_cache($post_id)
280 {
281 // Bail out on autosaves and revisions
282 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
283 return;
284 if (wp_is_post_revision($post_id))
285 return;
286
287 $post = get_post($post_id);
288 if (!$post)
289 return;
290
291 global $berq_log;
292
293 // Get current author ID
294 $current_author_id = $post->post_author;
295
296 // Get original author ID before any potential changes
297 $original_post = wp_get_post_revision($post_id);
298 $original_author_id = $original_post ? $original_post->post_author : $current_author_id;
299
300 // Collect all author IDs that need flushing
301 $author_ids = array_unique([$current_author_id, $original_author_id]);
302
303 foreach ($author_ids as $author_id) {
304 // Skip invalid author IDs
305 if (!$author_id || !get_userdata($author_id))
306 continue;
307
308 // Get author archive URL
309 $author_link = get_author_posts_url($author_id);
310 if (!is_wp_error($author_link) && !empty($author_link)) {
311 $berq_log->info("Purging author cache: $author_link");
312 self::purge_page($author_link);
313
314 // Handle translations for multilingual author archives
315 $translation_urls = apply_filters('berqwp_page_translation_urls', [], $author_link);
316 if (!empty($translation_urls)) {
317 foreach ($translation_urls as $url) {
318 $berq_log->info("Purging author translation cache: $url");
319 self::purge_page($url);
320 }
321 }
322 }
323 }
324 }
325
326 function flush_post_taxonomy_cache($post_id)
327 {
328 // Bail out on autosaves and revisions.
329 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
330 return;
331 }
332 if (wp_is_post_revision($post_id)) {
333 return;
334 }
335
336 $post = get_post($post_id);
337 if (!$post) {
338 return;
339 }
340
341 global $berq_log;
342
343 // Get all taxonomies registered for this post type.
344 $taxonomies = get_object_taxonomies($post->post_type);
345 if (!empty($taxonomies)) {
346 // Clear the object term cache for the post.
347 clean_object_term_cache($post_id, $taxonomies);
348
349 // Loop through each taxonomy.
350 foreach ($taxonomies as $taxonomy) {
351
352 if (!in_array($taxonomy, get_option('berqwp_optimize_taxonomies'))) {
353 continue;
354 }
355
356 // Get all terms for this post in the current taxonomy.
357 $terms = get_the_terms($post_id, $taxonomy);
358 if (empty($terms) || is_wp_error($terms)) {
359 continue;
360 }
361
362 foreach ($terms as $term) {
363 // Clear the term cache for the original term.
364 clean_object_term_cache($term->term_id, $taxonomy);
365
366 // Collect terms to purge: original term and its ancestors (if hierarchical)
367 $terms_to_purge = array($term);
368
369 // Check if taxonomy is hierarchical to process ancestors
370 if (is_taxonomy_hierarchical($taxonomy)) {
371 $ancestor_ids = get_ancestors($term->term_id, $taxonomy, 'taxonomy');
372 foreach ($ancestor_ids as $ancestor_id) {
373 $ancestor_term = get_term($ancestor_id, $taxonomy);
374 if ($ancestor_term && !is_wp_error($ancestor_term)) {
375 $terms_to_purge[] = $ancestor_term;
376 }
377 }
378 }
379
380 // Process each term (original and ancestors)
381 foreach ($terms_to_purge as $term_to_purge) {
382 $term_link = get_term_link($term_to_purge);
383 if (is_wp_error($term_link)) {
384 continue;
385 }
386
387 $berq_log->info("Purging cache for term $term_link");
388 self::purge_page($term_link);
389
390 // Handle translations
391 $translation_urls = apply_filters('berqwp_page_translation_urls', array(), $term_link);
392 if (!empty($translation_urls)) {
393 foreach ($translation_urls as $url) {
394 $berq_log->info("Purging taxonomy translation for $url");
395 self::purge_page($url);
396 }
397 }
398 }
399 }
400 }
401 }
402 }
403
404 function purge_critical_css_cache()
405 {
406 $parsed_url = wp_parse_url(home_url());
407 $domain = $parsed_url['host'];
408 $berqwp = new BerqWP(berqwp_get_license_key(), null, null);
409 $berqwp->purge_critilclcss($domain);
410 }
411
412 function flush_cf_page($slug = '')
413 {
414 if (empty($slug)) {
415 $slug = '/';
416 }
417 $url = home_url($slug);
418 bwp_cf_flush_page($url);
419 }
420
421 function purge_home($new_status, $old_status, $post)
422 {
423
424 $can_flush_cache = apply_filters('berqwp_can_flush_home_cache_on_post_update', true);
425
426 if (!$can_flush_cache) {
427 return;
428 }
429
430 if ($new_status == 'draft' && $old_status == 'draft') {
431 return;
432 }
433
434 if ($new_status == 'auto-draft') {
435 return;
436 }
437
438 if ($new_status == 'trash') {
439 return;
440 }
441
442 if ($new_status == 'publish' && $old_status == 'publish') {
443 return;
444 }
445
446 // if ($old_status == 'new' && $new_status == 'draft') {
447 // return;
448 // }
449
450 // if statement skips when scheduled post publishes
451 // with admin wp cron request
452 // if (!is_admin()) {
453 // $berq_log->info('Trasition post status admin' . ' ' . $new_status);
454 // return;
455 // }
456
457 $post_types = apply_filters('berqwp_purge_home_post_types', ['post']);
458
459 if (in_array($post->post_type, $post_types)) {
460 global $berq_log;
461 $berq_log->info('Purging homepage. Triggered by post type: ' . $post->post_type . ' ' . $old_status . ' ' . $new_status);
462 $home_url = home_url('/');
463 self::purge_page($home_url);
464 warmup_cache_by_url($home_url, true);
465 }
466
467 $blog_page_id = get_option('page_for_posts');
468
469 if ($blog_page_id) {
470
471 $blog_url = get_permalink($blog_page_id);
472
473 global $berq_log;
474 $berq_log->info('Purging blog page: ' . $blog_url);
475
476 self::purge_page($blog_url);
477 warmup_cache_by_url($blog_url);
478 }
479 }
480
481 function brust_cache_for_loggedin()
482 {
483 if (is_user_logged_in()) {
484 // Add Vary: Cookie header to differentiate cached versions for logged-in users
485 header('Vary: Accept-Encoding, Cookie');
486 // header("Cache-Control: no-cache, no-store, must-revalidate");
487 // header("Pragma: no-cache");
488 // header("Expires: 0");
489 }
490 }
491
492 function handle_post_status_update($new_status, $old_status, $post)
493 {
494 // Get the post types that should be optimized from BerqWP settings
495 $post_types = get_option('berqwp_optimize_post_types');
496
497 // Get the published post URL
498 $post_url = get_permalink($post);
499
500 // Only proceed if the post is being published (from any status to 'publish')
501 if ('publish' === $new_status && 'publish' !== $old_status) {
502
503 // Check if the post type is in the list of types to be optimized
504 if (in_array($post->post_type, $post_types)) {
505
506 // We need path with query parameters
507 $parsed_url = parse_url($post_url);
508 $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
509 $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
510 $path_with_query = $path . $query;
511
512 if (berqwp_is_slug_excludable($path_with_query)) {
513 return;
514 }
515
516 global $berq_log;
517 $berq_log->info("Post status updated $post_url");
518
519 if (bwp_can_optimize_page_url($post_url)) {
520 warmup_cache_by_url($post_url);
521 }
522
523 self::purge_page($post_url, true);
524
525 $this->flush_post_taxonomy_cache($post->ID);
526 $this->flush_author_cache($post->ID);
527 }
528 }
529 }
530
531 public static function delete_page_cache_files($page_url)
532 {
533 $cache_file = bwp_get_cache_dir() . bwp_build_cache_path($page_url) . '/index.html.gz';
534
535 if (file_exists($cache_file)) {
536 unlink($cache_file);
537 }
538 }
539
540 public static function purge_page($page_url, $flush_criticalcss = false)
541 {
542
543 if (!berqwp_can_use_cloud()) {
544 $flush_criticalcss = false;
545 }
546
547 $page_url = strtolower($page_url);
548
549 // $page_path = bwp_intersect_str(home_url(), $page_path);
550 $slug = bwp_url_into_path($page_url);
551
552 self::delete_page_cache_files($page_url);
553
554 do_action('berqwp_flush_page_cache', $slug);
555
556 if ($flush_criticalcss) {
557 $berqwp = new BerqWP(berqwp_get_license_key(), null, null);
558 $berqwp->purge_criticlecss_url($page_url);
559 }
560
561 bwp_cf_flush_page(home_url($slug));
562 }
563
564 function handle_new_comment($comment_id, $comment_status)
565 {
566 if ($comment_status === 'approve') {
567 $comment = get_comment($comment_id);
568 $post_id = $comment->comment_post_ID;
569 $post_url = get_permalink($post_id);
570
571 self::purge_page($post_url);
572
573 global $berq_log;
574 $berq_log->info("New comment added, deleting cache for $post_url");
575 }
576 }
577
578 function bypass_cache()
579 {
580 if (
581 isset($_GET['nocache'])
582 || isset($_GET['bwp_preload'])
583 // || isset($_GET['creating_cache'])
584 || berqDetectCrawler::is_crawler() ||
585 (get_option('berqwp_enable_sandbox') == 1 && !isset($_GET['berqwp']) && !is_admin() && !isset($_POST))
586 ) {
587
588 add_filter('berqwp_bypass_cache', function () {
589 return true;
590 });
591
592 // if (berqReverseProxyCache::is_reverse_proxy_cache_enabled()) {
593 berqReverseProxyCache::bypass();
594 // }
595
596 }
597 }
598
599 function flush_reverse_proxy_cache($slug = '/.*')
600 {
601
602 if (empty($slug)) {
603 $slug = '/';
604 }
605
606 // if ($slug == '/') {
607 // $slug = '';
608 // }
609
610 $page_url = home_url($slug);
611 $host = !empty($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
612 berqReverseProxyCache::purge_cache($page_url);
613 }
614
615 function ingore_tracking_params($tracking_params)
616 {
617 $tracking_params = array_merge($tracking_params, ignoreParams::$query_params);
618 return $tracking_params;
619 }
620
621 function clear_cache_on_post_update($post_id, $post, $update)
622 {
623
624 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
625 return;
626 }
627
628 // if (!$update) {
629 // return;
630 // }
631
632 $can_flush_cache = apply_filters('berqwp_can_flush_cache_on_post_update', true);
633
634 if (!$can_flush_cache) {
635 return;
636 }
637
638 // If this is just a revision, don't run the function.
639 if (wp_is_post_revision($post_id)) {
640 return;
641 }
642
643 // prevents scheduled post public
644 // via wp cron
645 // if (!is_admin()) {
646 // return;
647 // }
648
649 $post_type = get_post_type($post_id);
650 $post_url = get_permalink($post_id);
651
652 // We need path with query parameters
653 $parsed_url = parse_url($post_url);
654 $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
655 $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
656 $path_with_query = $path . $query;
657
658 if (berqwp_is_slug_excludable($path_with_query)) {
659 return;
660 }
661
662 // Potentially cachable post types
663 $cachable_post_type_names = get_post_types(array(
664 'public' => true,
665 ), 'names');
666 unset($cachable_post_type_names['attachment']);
667
668 if (!in_array($post_type, $cachable_post_type_names)) {
669 return;
670 }
671
672 global $berq_log;
673 $berq_log->info("Post updated [Post type - $post_type]: $post_url $post->post_status");
674
675 self::purge_page($post_url, true);
676
677 if (bwp_can_optimize_page_url($post_url)) {
678 warmup_cache_by_url($post_url);
679 }
680
681 $translation_urls = apply_filters('berqwp_page_translation_urls', [], $post_url);
682
683 if (!empty($translation_urls)) {
684 foreach ($translation_urls as $url) {
685
686 $berq_log->info("Purging translation for $post_url");
687 self::purge_page($url, true);
688 }
689 }
690
691 $this->flush_post_taxonomy_cache($post_id);
692 $this->flush_author_cache($post_id);
693 }
694
695 function flush_cdn()
696 {
697 $parsed_url = wp_parse_url(home_url());
698 $domain = $parsed_url['host'];
699
700 $args = [
701 'timeout' => 30,
702 'sslverify' => false,
703 'body' => ['flush_cdn' => $domain, 'license_key' => berqwp_get_license_key()]
704 ];
705
706 wp_remote_post('https://boost.berqwp.com/photon/', $args);
707
708 // Flush cache
709 $this->delete_cache_files();
710
711 // clear local static files
712
713 $dir = optifer_cache . '/static/';
714
715 if (! is_dir($dir)) {
716 return;
717 }
718
719 $files = glob(rtrim($dir, '/') . '/*');
720
721 foreach ($files as $file) {
722 if (is_file($file)) {
723 unlink($file);
724 }
725 }
726
727 update_option('berqwp_uploaded_assets', [], false);
728
729 do_action('berqwp_purge_cdn');
730 }
731
732 function delete_cache_files($flush_all_sites = false)
733 {
734 global $berq_log;
735 $berq_log->info("Flushing all cache.");
736
737 // Define the cache directory
738 $cache_directory = bwp_get_cache_dir();
739
740 if (is_multisite() && $flush_all_sites) {
741 $cache_directory = optifer_cache . '/html/';
742 }
743
744 // Delete all cache files within the directory
745 berqwp_unlink_recursive($cache_directory);
746
747 // Delete external CSS cache
748 $external_cache_dir = optifer_cache . 'external/';
749 if (is_dir($external_cache_dir)) {
750 berqwp_unlink_recursive($external_cache_dir);
751 }
752
753 delete_transient('berqwp_warmup_running');
754 delete_transient('cache_warmup_in_progress');
755 delete_transient('berqwp_doing_cache_warmup');
756
757 // Remove require cache warning
758 update_option('bwp_require_flush_cache', 0);
759
760 do_action('berqwp_flush_all_cache');
761 }
762
763 static function should_cache() {
764 // Check if the current user is logged in and only allow GET requests
765 if (is_user_logged_in() || $_SERVER['REQUEST_METHOD'] !== 'GET') {
766 return false;
767 }
768
769 if (isset($_GET['creating_cache'])) {
770 return false;
771 }
772
773 if (is_admin() || is_preview() || is_404() || is_search()) {
774 return false;
775 }
776
777 if (defined('DOING_CRON') && DOING_CRON) {
778 return false;
779 }
780
781 if (defined('DOING_AJAX') && DOING_AJAX) {
782 return false;
783 }
784
785 if (defined('REST_REQUEST') && REST_REQUEST) {
786 return false;
787 }
788
789 if (php_sapi_name() === 'cli' || defined('WP_CLI')) {
790 return false;
791 }
792
793 if (!bwp_is_webpage()) {
794 return false;
795 }
796
797 if (!bwp_pass_cookie_requirement()) {
798 return false;
799 }
800
801 $berqconfigs = berqConfigs::getInstance();
802 $configs = $berqconfigs->get_configs();
803
804 if (empty($configs['optimization_method'])) {
805 return false;
806 }
807
808 if (berqwp_can_use_cloud()) {
809
810 if (empty(berqwp_get_license_key())) {
811 return false;
812 }
813
814 // if (!bwp_pass_account_requirement()) {
815 // return false;
816 // }
817
818 }
819
820
821 $bypass_cache = apply_filters('berqwp_bypass_cache', false);
822
823 if ($bypass_cache) {
824 return false;
825 }
826
827 return true;
828 }
829
830 static function get_page_url() {
831 $page_url = bwp_get_request_url();
832
833 // For sitemaps
834 if (strpos($page_url, '.xml') !== false || strpos($page_url, '.xsl') !== false) {
835 return;
836 }
837
838 // Return if page is excluded from cache
839 $current_page_url = bwp_get_request_url();
840
841 if (strpos($current_page_url, '?') !== false) {
842 $current_page_url = explode('?', $current_page_url)[0];
843 }
844
845 if (berqwp_is_page_url_excluded($current_page_url)) {
846 return;
847 }
848
849 // Remove ignored params from the slug
850 // $slug = berqwp_remove_ignore_params($slug_uri);
851 $page_url = berqwp_remove_ignore_params($page_url);
852
853 if (get_option('berqwp_enable_sandbox') == 1 && isset($_GET['berqwp'])) {
854 $page_url = explode('?berqwp', $page_url)[0];
855 } elseif (get_option('berqwp_enable_sandbox') == 1 && !isset($_GET['creating_cache'])) {
856 return false;
857 }
858
859 if (berqwp_is_slug_excludable($page_url)) {
860 return false;
861 }
862
863 return $page_url;
864 }
865
866 static function queue_page($page_url = null) {
867
868
869 if (empty($page_url)) {
870
871 if (!self::should_cache()) {
872 return;
873 }
874
875 $page_url = self::get_page_url();
876 }
877
878 if (empty($page_url)) {
879 return false;
880 }
881
882 // Disable cache for unknown query parameters
883 if (strpos($page_url, '?') !== false) {
884 return false;
885 }
886
887 if (!berqwp_can_use_cloud()) {
888 return false;
889 }
890
891 $status_code = http_response_code();
892
893 if ($status_code !== 200) {
894 return false;
895 }
896
897 // berqHeartbeat::add_queue($page_url);
898 warmup_cache_by_url($page_url);
899 }
900
901 function html_cache()
902 {
903
904 // Bypass cache for Photon
905 if (!empty($_COOKIE['berqwpnocache'])) {
906 header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0', true);
907 header('CDN-Cache-Control: no-store', true); // Cloudflare
908 header('Surrogate-Control: no-store', true); // Varnish
909 header('X-Accel-Expires: 0', true); // Nginx FastCGI
910
911 return;
912 }
913
914 if (!self::should_cache()) {
915 return;
916 }
917
918 $page_url = self::get_page_url();
919
920 if (empty($page_url)) {
921 return;
922 }
923
924 // Disable cache for unknown query parameters
925 if (strpos($page_url, '?') !== false) {
926 return;
927 }
928
929 if (is_singular()) {
930 $post_type = get_post_type();
931
932 if (empty($post_type) || !in_array($post_type, get_option('berqwp_optimize_post_types'))) {
933 return;
934 }
935 } elseif (is_archive()) {
936 $queried_object = get_queried_object();
937
938 if ($queried_object instanceof WP_Term && !empty($queried_object->taxonomy)) {
939 $current_taxonomy = $queried_object->taxonomy;
940
941 if (!in_array($current_taxonomy, get_option('berqwp_optimize_taxonomies'))) {
942 return;
943 }
944 }
945 }
946
947
948 $status_code = http_response_code();
949
950 if ($status_code !== 200) {
951 return;
952 }
953
954 $berqconfigs = berqConfigs::getInstance();
955 $configs = $berqconfigs->get_configs();
956 $cache_key = md5($page_url);
957 $cache_directory = bwp_get_cache_dir();
958
959 $cache_file = $cache_directory . bwp_build_cache_path($page_url) . '/index.html.gz';
960 $cache_max_life = file_exists($cache_file) ? @filemtime($cache_file) + $configs['cache_lifespan'] : null;
961
962 if (file_exists($cache_file) && $cache_max_life > time()) {
963 header_remove('Content-Encoding');
964
965 $lastModified = filemtime($cache_file);
966 $etag = md5_file($cache_file);
967 header('ETag: ' . $etag);
968 header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
969 header('X-File-Size: ' . filesize($cache_file), true);
970 header('Content-Type: text/html; charset=utf-8');
971 header("X-served: WP Hook");
972 header('Vary: Accept-Encoding, Cookie');
973
974 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)) {
975 // The client's cache is still valid based on Last-Modified, respond with a 304 Not Modified
976 header('HTTP/1.1 304 Not Modified');
977 // header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
978 header("Expires: 0");
979 header('Cache-Control: no-cache, must-revalidate');
980 exit();
981 }
982
983 // Prevent PHP/Apache from re-compressing the already-gzipped cache file
984 if (ini_get('zlib.output_compression')) {
985 ini_set('zlib.output_compression', 'Off');
986 }
987
988 while (ob_get_level()) {
989 ob_end_clean();
990 }
991
992 header('Cache-Control: public, max-age=0, s-maxage=3600, must-revalidate', true);
993 // header("Content-Security-Policy: script-src 'self' blob: 'unsafe-inline'");
994 header('Content-Encoding: gzip', true);
995 header('Content-Length: ' . filesize($cache_file), true);
996 readfile($cache_file);
997 exit();
998 }
999
1000 header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
1001 header('CDN-Cache-Control: no-store'); // Cloudflare
1002 header('Surrogate-Control: no-store'); // Varnish
1003 header('X-Accel-Expires: 0'); // Nginx FastCGI
1004
1005 self::purge_page($page_url);
1006
1007 if (!berqwp_can_use_cloud()) {
1008 try {
1009
1010 $berqPageOptimizer = new berqPageOptimizer();
1011 $berqPageOptimizer->set_slug(bwp_url_into_path($page_url));
1012 $berqPageOptimizer->set_page($page_url);
1013 $berqPageOptimizer->start_cache();
1014 unset($berqPageOptimizer);
1015
1016 } catch (Exception $e) {
1017 global $berq_log;
1018 $berq_log->error($e->getMessage());
1019 return;
1020 } catch (Throwable $e) {
1021 global $berq_log;
1022 $berq_log->error($e->getMessage());
1023 return;
1024 }
1025
1026 }
1027
1028 return;
1029 }
1030
1031 }
1032
1033 // $cache = new berqCache();
1034 $cache = berqCache::getInstance();
1035 }
1036