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

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