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 / class-berqwp.php

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

1,673 lines 54.6 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 as BerqWPCloud;
6 use BerqWP\RateLimiter;
7
8 if (!class_exists('berqWP')) {
9 class berqWP
10 {
11
12 public $is_key_verified = false;
13 public $key_response = false;
14 public static $instance = null;
15
16 public $conflicting_plugins = [
17 'autoptimize/autoptimize.php', // Autoptimize
18 'wp-super-cache/wp-cache.php', // WP Super Cache
19 'w3-total-cache/w3-total-cache.php', // W3 Total Cache
20 'wp-fastest-cache/wpFastestCache.php', // WP Fastest Cache
21 'litespeed-cache/litespeed-cache.php', // LiteSpeed Cache
22 'cache-enabler/cache-enabler.php', // Cache Enabler
23 'hummingbird-performance/wp-hummingbird.php', // Hummingbird – Speed up, Cache, Optimize Your CSS and JS
24 'sg-cachepress/sg-cachepress.php', // SiteGround Optimizer (for those hosted on SiteGround)
25 'wp-rocket/wp-rocket.php', // WP Rocket
26 'breeze/breeze.php', // Breeze (Cloudways)
27 'comet-cache/comet-cache.php', // Comet Cache
28 'hyper-cache/plugin.php', // Hyper Cache
29 'simple-cache/simple-cache.php', // Simple Cache
30 'wp-optimize/wp-optimize.php', // WP-Optimize
31 'swift-performance-lite/performance.php', // Swift Performance Lite
32 'nitropack/nitropack.php', // NitroPack
33 'nitropack/main.php', // NitroPack
34 'jetpack-boost/jetpack-boost.php', // Jetpack Boost
35 'tenweb-speed-optimizer/tenweb_speed_optimizer.php', // 10Web Booster
36 'speed-booster-pack/speed-booster-pack.php', // Speed booster pack
37 'wp-speed-of-light/wp-speed-of-light.php', // WP speed of light
38 'speedycache/speedycache.php', // Speedy cache
39 'powered-cache/powered-cache.php', // Powered cache
40 'clearfy/clearfy.php', // Clearfy
41 'rabbit-loader/rabbit-loader.php',
42 'psn-pagespeed-ninja/pagespeedninja.php',
43 'jch-optimize/jch-optimize.php',
44 'cache-enabler/cache-enabler.php',
45 'core-web-vitals-pagespeed-booster/core-web-vitals-pagespeed-booster.php',
46 'surge/surge.php',
47 'speedien/speedien.php',
48 'wpspeed/wpspeed.php',
49 'debloat/debloat.php',
50 'perfmatters/perfmatters.php',
51 'phastpress/phastpress.php',
52 'wp-meteor/wp-meteor.php',
53 ];
54
55 function __construct()
56 {
57
58 add_action('init', [$this, 'initialize']);
59
60 // Save settings
61 add_action('admin_init', [$this, 'save_settings']);
62
63 // Sitemap for cache warmup
64 // add_action('wp', 'bwp_get_sitemap');
65 add_action('wp_loaded', 'bwp_get_sitemap', 999);
66
67 // BerqWP display logs
68 add_action('init', 'bwp_display_logs');
69
70 require_once optifer_PATH . '/api/register_apis.php';
71
72 add_action('admin_menu', [$this, 'register_menu']);
73 // add_action('init', [$this, 'berq_post_types'], 20);
74 add_action('berqwp_notices', [$this, 'notices']);
75
76 add_filter('plugin_action_links_searchpro/berqwp.php', [$this, 'plugin_settings_links']);
77
78 // add_action('wp_ajax_berqwp_fetch_remote_html', [$this, 'fetch_remote_html']);
79
80 add_action('wp_ajax_berqwp_refresh_cache_stats', [$this, 'refresh_cache_stats']);
81
82 add_action('wp_ajax_berqwp_get_optimized_pages', [$this, 'berqwp_get_optimized_pages']);
83 add_action('wp_ajax_berqwp_recently_optimized_pages', [$this, 'ajax_recently_optimized_pages']);
84
85 add_action('admin_enqueue_scripts', [$this, 'admin_scripts']);
86
87 // add_filter( 'action_scheduler_queue_runner_concurrent_batches', [$this, 'ashp_increase_concurrent_batches'] );
88
89 // add_filter('action_scheduler_retention_period', function ($period) {
90 // return DAY_IN_SECONDS;
91 // });
92
93 // add_filter('action_scheduler_default_cleaner_statuses', function ($statuses) {
94 // $statuses[] = 'failed';
95 // return $statuses;
96 // });
97
98 // add_filter('action_scheduler_cleanup_batch_size', function ($batch_size) {
99 // return 100;
100 // });
101
102 // Refresh license key
103 add_action('admin_post_bwp_refresh_license', [$this, 'handle_refresh_license_action']);
104
105 add_action('admin_post_switch_optimization_method_local', [$this, 'switch_optimization_method']);
106 add_action('admin_post_switch_optimization_method_cloud', [$this, 'switch_optimization_method']);
107
108 add_action('in_admin_header', [$this, 'remove_admin_notices']);
109
110 // Increase nonce life
111 add_filter('nonce_life', [$this, 'increase_nonce_life']);
112
113 // Page compression test
114 add_action('wp_ajax_berqwp_enable_page_compression', [$this, 'enable_page_compression']);
115 add_action('template_redirect', [$this, 'page_compression_test']);
116
117 // Run daily maintenance tasks
118 // add_action('init', [$this, 'schedule_daily_maintenance']);
119 // add_action('berqwp_daily_maintenance_hook', [$this, 'daily_maintenance']);
120
121 // Revoke License
122 add_action('init', [$this, 'revoke_license']);
123
124 // Create dropin plugin file
125 add_action('init', 'berqwp_setup_dropin');
126
127 // Update settings via API
128 add_action('init', 'bwp_update_configs_webhook');
129
130 // Active-status check from optimization server
131 add_action('init', 'bwp_check_status_webhook');
132
133 // Sync addons from cloud
134 add_action('init', [$this, 'sync_addons']);
135
136 // Multisite support
137 if (function_exists('is_multisite') && is_multisite()) {
138 add_action('network_admin_menu', [$this, 'register_network_menu']);
139 add_action('network_admin_edit_berqwp_network_save', [$this, 'save_network_settings']);
140 add_action('wp_initialize_site', [$this, 'on_new_site_created'], 10, 1);
141 add_action('wp_delete_site', [$this, 'regenerate_blog_map']);
142 add_action('berqwp_activate_plugin', [$this, 'regenerate_blog_map']);
143 }
144 }
145
146 static function getInstance() {
147
148 if (self::$instance === null) {
149 $instance = new berqWP();
150 self::$instance = $instance;
151 return $instance;
152 }
153
154 return self::$instance;
155 }
156
157 function upgrade_notice() {
158
159 if (!berqwp_can_use_cloud()) {
160 return;
161 }
162
163 if (empty($this->key_response->product_ref)) {
164 return;
165 }
166
167 if ($this->key_response->product_ref == 'Free Account' && bwp_cached_pages_count() >= 10) {
168
169 bwp_notice('warning', 'Free Plan Limit Reached', "<p>You've reached the limit of 10 optimized pages for your free BerqWP account. Upgrade now to optimize unlimited pages and get the best performance for your entire site!</p>");
170 }
171 }
172
173 function switch_optimization_method() {
174 // Check if the user has the necessary nonce and the action matches
175 if (isset($_GET['action']) && $_GET['action'] === 'switch_optimization_method_local' && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'switch_optimization_method_local_action')) {
176
177
178 $berqconfigs = berqConfigs::getInstance();
179 $berqconfigs->update_configs(['optimization_method' => 'local']);
180
181 // Require flush cache
182 update_option('bwp_require_flush_cache', 1);
183
184 $redirect_url = wp_get_referer();
185
186 // Redirect back to the referring page after clearing the cache
187 wp_safe_redirect($redirect_url);
188 exit;
189 }
190
191 if (isset($_GET['action']) && $_GET['action'] === 'switch_optimization_method_cloud' && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'switch_optimization_method_cloud_action')) {
192
193 $berqconfigs = berqConfigs::getInstance();
194 $configs = $berqconfigs->get_configs();
195
196 if (empty($configs['secret'])) {
197 $berqconfigs->update_configs(['optimization_method' => '']);
198 } else {
199 $berqconfigs->update_configs(['optimization_method' => 'cloud']);
200 }
201
202 // Require flush cache
203 update_option('bwp_require_flush_cache', 1);
204
205 $redirect_url = wp_get_referer();
206
207 // Redirect back to the referring page after clearing the cache
208 wp_safe_redirect($redirect_url);
209 exit;
210 }
211 }
212
213 function sync_addons()
214 {
215 $license_key = berqwp_get_license_key();
216 if (get_option('berqwp_sync_addons') && !empty($this->key_response->product_ref) && $this->key_response->product_ref == 'AppSumo Deal' && !empty($license_key)) {
217 berqwp_sync_addons($license_key, home_url());
218 delete_option('berqwp_sync_addons');
219 }
220 }
221
222 function revoke_license()
223 {
224 if (isset($_GET['berqwp_revoke_license']) && !empty($_POST['key_hash'])) {
225 $hash = sanitize_text_field($_POST['key_hash']);
226
227 if ($hash == md5(berqwp_get_license_key())) {
228 berqwp_delete_license_key();
229 echo json_encode(['success' => true]);
230 exit;
231 }
232 }
233 }
234
235 function daily_maintenance()
236 {
237
238 // Perform connection test
239 bwp_check_connection(true);
240
241 $log_file = optifer_cache . 'berqwp.log';
242 if (file_exists($log_file)) {
243 @unlink($log_file);
244 }
245
246 $log_dir = optifer_cache . 'logs/';
247
248 // Check if directory exists
249 if (is_dir($log_dir)) {
250 // Get all files in the directory
251 $files = glob($log_dir . '*');
252
253 // Check if there are more than 10 files
254 if (count($files) > 10) {
255 // Sort files by modified time, newest first
256 usort($files, function ($a, $b) {
257 return filemtime($b) - filemtime($a);
258 });
259
260 // Get files beyond the first 10
261 $files_to_delete = array_slice($files, 10);
262
263 // Delete the extra files
264 foreach ($files_to_delete as $file) {
265 if (is_file($file)) {
266 @unlink($file);
267 }
268 }
269 }
270 }
271 }
272
273 function schedule_daily_maintenance()
274 {
275 if (!as_next_scheduled_action('berqwp_daily_maintenance_hook')) {
276 as_schedule_recurring_action(time(), DAY_IN_SECONDS, 'berqwp_daily_maintenance_hook');
277 }
278 }
279
280 function page_compression_test()
281 {
282 if (isset($_GET['berqwp_compression_test'])) {
283 $test_file_path = optifer_cache . 'gzip-compression-test.gz';
284 $accept_encoding = $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '';
285 $supports_gzip = strpos($accept_encoding, 'gzip') !== false;
286
287 // if ($supports_gzip) {
288 header('Content-Type: text/html; charset=utf-8');
289 // header_remove('Content-Encoding');
290 // header('Content-Encoding: gzip');
291 // readgzfile($test_file_path);
292
293 header('Vary: Accept-Encoding');
294 header('Content-Encoding: gzip', true);
295 header('Content-Length: ' . filesize($test_file_path), true);
296 readfile($test_file_path);
297 // }
298 // header('Content-Type: text/html');
299 // header('Content-Encoding: gzip');
300 // readfile($test_file_path);
301 exit;
302 }
303 }
304
305 function enable_page_compression()
306 {
307
308 check_ajax_referer('wp_rest', 'nonce');
309
310 $url = home_url('/?berqwp_compression_test=' . time());
311 $berqconfigs = berqConfigs::getInstance();
312 $testfile = optifer_cache . 'gzip-compression-test.gz';
313 $html = gzencode('Hello World!');
314 @file_put_contents($testfile, $html);
315
316 sleep(5);
317
318 $response = wp_remote_get($url);
319
320 if (!empty($response) && !is_wp_error($response)) {
321 $html = wp_remote_retrieve_body($response);
322
323 if ($html == 'Hello World!') {
324 $berqconfigs->update_configs(['page_compression' => true]);
325 wp_send_json_success('Compression test passed.');
326 }
327 }
328
329 $berqconfigs->update_configs(['page_compression' => false]);
330 wp_send_json_error('Compression test failed.');
331
332 die(); // Always exit in AJAX functions
333 }
334
335 function increase_nonce_life($default_life)
336 {
337
338 // if (!is_user_logged_in() && bwp_pass_account_requirement()) {
339 if (!is_user_logged_in()) {
340 return 30 * DAY_IN_SECONDS;
341 }
342
343 return $default_life;
344 }
345
346 function remove_admin_notices()
347 {
348
349 if (current_user_can('manage_options')) {
350 $screen = get_current_screen();
351 if ($screen->id === 'toplevel_page_berqwp') {
352 remove_all_actions('user_admin_notices');
353 remove_all_actions('admin_notices');
354 remove_all_actions('all_admin_notices');
355 } else {
356 add_action('admin_notices', function () {
357 do_action('berqwp_notices');
358 }, 10);
359 }
360 }
361 }
362
363 function admin_scripts()
364 {
365
366 // settings page specific assets
367 if ( isset($_GET['page']) && $_GET['page'] == 'berqwp' ) {
368
369 wp_enqueue_style(
370 'bwp-google-fonts',
371 "https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap",
372 [],
373 BERQWP_VERSION
374 );
375
376 wp_enqueue_style(
377 'bwp-jquery-datatable',
378 optifer_URL . '/admin/css/dataTables.dataTables.min.css',
379 [],
380 BERQWP_VERSION
381 );
382
383 wp_enqueue_style(
384 'bwp-settings-style',
385 optifer_URL . '/admin/css/style.css',
386 [],
387 BERQWP_VERSION
388 );
389
390 }
391
392 wp_enqueue_style(
393 'bwp-global-styles', // Handle for the style
394 optifer_URL . 'admin/css/global.css', // URL to the CSS file
395 [], // Dependencies (array of handles)
396 BERQWP_VERSION // Version number
397 );
398 }
399
400 function handle_refresh_license_action()
401 {
402 // Check if the user has the necessary nonce and the action matches
403 if (isset($_GET['action']) && $_GET['action'] === 'bwp_refresh_license' && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'bwp_refresh_license_action')) {
404
405 // $transient_key = 'berq_lic_response_cache';
406 // $expire_transient_key = 'berq_lic_cache_expire';
407
408 // berqwp_delete_network_option($transient_key);
409 // berqwp_delete_network_option($expire_transient_key);
410
411 berqwp_delete_network_option('berqwp_license_cache');
412
413 // clear cache from cloud
414 bwp_request_purge_license_key_cache();
415
416 global $berqNotifications;
417 $berqNotifications->success('License key successfully refreshed.');
418
419 $redirect_url = add_query_arg('berq_refresh_license', '', wp_get_referer());
420
421 // Redirect back to the referring page after clearing the cache
422 wp_safe_redirect($redirect_url);
423 exit;
424 }
425 }
426
427 function berqwp_get_optimized_pages()
428 {
429 check_ajax_referer('berqwp_get_optimized_pages_nonce', 'nonce');
430 if (!current_user_can('manage_options')) {
431 wp_send_json_error('Unauthorized', 403);
432 return;
433 }
434
435 if (!isset($_POST['start']) || !isset($_POST['length'])) {
436 wp_send_json_error('Invalid parameters');
437 return;
438 }
439
440 $start = intval($_POST['start']); // Offset for the query
441 $length = intval($_POST['length']); // Number of records to fetch per request
442 $search = isset($_POST['search']) ? sanitize_text_field($_POST['search']) : ''; // Search term if present
443
444 $post_types = get_option('berqwp_optimize_post_types');
445 $optimized_pages = [];
446
447 // Build the query arguments
448 $args = array(
449 'post_type' => $post_types,
450 'posts_per_page' => $length, // Limit the number of posts per request
451 'offset' => $start, // Set the offset for pagination
452 'post_status' => array('publish'), // Only published pages
453 );
454
455 // Add search filtering, if applicable
456 if (!empty($search)) {
457 $args['s'] = $search; // Add the search parameter to the query
458 }
459
460 if ($start === 0 && empty($search)) {
461 $url = bwp_admin_home_url('/');
462
463 if (strpos($url, bwp_admin_home_url()) === false) {
464 $url = str_replace(home_url(), bwp_admin_home_url(), $url);
465 }
466
467 $slug = bwp_url_into_path($url);
468
469 $cache_directory = bwp_get_cache_dir();
470 $cache_key = md5($url);
471 // $cache_key = md5($slug);
472 $cache_file = $cache_directory . $cache_key . '.gz';
473
474 if (is_file($cache_file)) {
475 $status = '<span class="bwp-cache-tag completed">Completed</span>';
476
477 // if (bwp_is_partial_cache($url) === true) {
478 // $status = '<span class="bwp-cache-tag part-completed">Partial cache</span>';
479 // }
480 } else {
481 $status = '<span class="bwp-cache-tag">Pending</span>';
482 }
483
484 $parsed_url = parse_url($url);
485 $decoded_path = isset($parsed_url['path']) ? urldecode($parsed_url['path']) : '';
486 $decoded_query = isset($parsed_url['query']) ? urldecode($parsed_url['query']) : '';
487
488 $decoded_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
489 if (isset($parsed_url['port'])) {
490 $decoded_url .= ':' . $parsed_url['port'];
491 }
492 $decoded_url .= $decoded_path;
493 if ($decoded_query) {
494 $decoded_url .= '?' . $decoded_query;
495 }
496 if (isset($parsed_url['fragment'])) {
497 $decoded_url .= '#' . $parsed_url['fragment'];
498 }
499
500 $page_arr = [
501 'url' => $decoded_url,
502 'status' => $status,
503 'last_modified' => file_exists($cache_file) ? date('Y-m-d H:i:s', filemtime($cache_file)) : ''
504 ];
505
506 array_push($optimized_pages, $page_arr);
507 }
508
509 $query = new WP_Query($args);
510 $total_posts = $query->found_posts; // Get the total number of records
511
512 $valid_posts_query = new WP_Query([
513 'post_type' => $post_types,
514 'posts_per_page' => -1,
515 'fields' => 'ids',
516 'post_status' => ['publish'],
517 ]);
518 $valid_posts = array_filter($valid_posts_query->posts, function ($post_id) {
519 $url = get_permalink($post_id);
520 return bwp_can_optimize_page_url($url);
521 });
522 $total_posts = count($valid_posts);
523
524 if ($query->have_posts()) {
525 while ($query->have_posts()) {
526 $query->the_post();
527
528 $url = get_permalink();
529
530 if (strpos($url, bwp_admin_home_url()) === false) {
531 $url = str_replace(home_url(), bwp_admin_home_url(), $url);
532 }
533
534 if (bwp_admin_home_url('/') == $url) {
535 continue;
536 }
537
538 $slug = bwp_url_into_path($url);
539
540 if (!bwp_can_optimize_page_url($url)) {
541 continue;
542 }
543
544 $cache_directory = bwp_get_cache_dir();
545 $cache_key = md5($url);
546 // $cache_key = md5($slug);
547 $cache_file = $cache_directory . $cache_key . '.gz';
548
549 if (is_file($cache_file)) {
550 $status = '<span class="bwp-cache-tag completed">Completed</span>';
551
552 // if (bwp_is_partial_cache($url) === true) {
553 // $status = '<span class="bwp-cache-tag part-completed">Partial cache</span>';
554 // }
555 } else {
556 $status = '<span class="bwp-cache-tag">Pending</span>';
557 }
558
559 $parsed_url = parse_url($url);
560 $decoded_path = isset($parsed_url['path']) ? urldecode($parsed_url['path']) : '';
561 $decoded_query = isset($parsed_url['query']) ? urldecode($parsed_url['query']) : '';
562
563 $decoded_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
564 if (isset($parsed_url['port'])) {
565 $decoded_url .= ':' . $parsed_url['port'];
566 }
567 $decoded_url .= $decoded_path;
568 if ($decoded_query) {
569 $decoded_url .= '?' . $decoded_query;
570 }
571 if (isset($parsed_url['fragment'])) {
572 $decoded_url .= '#' . $parsed_url['fragment'];
573 }
574
575 $page_arr = [
576 'url' => $decoded_url,
577 'status' => $status,
578 'last_modified' => file_exists($cache_file) ? date('Y-m-d H:i:s', filemtime($cache_file)) : ''
579 ];
580
581 array_push($optimized_pages, $page_arr);
582 }
583 }
584
585 wp_reset_postdata();
586
587 // Send the response with the optimized pages and total entries
588 wp_send_json_success([
589 'optimized_pages' => $optimized_pages,
590 'total_entries' => $total_posts, // Total number of posts (unfiltered)
591 'records_filtered' => $total_posts // Adjust if filtered by search
592 ]);
593 }
594
595
596
597 function ajax_recently_optimized_pages()
598 {
599 check_ajax_referer('wp_rest', 'nonce');
600
601 $search = isset($_POST['search']) ? sanitize_text_field($_POST['search']) : '';
602 $start = max(0, intval($_POST['start'] ?? 0));
603 $length = max(1, intval($_POST['length'] ?? 10));
604
605 $log = json_decode(get_option('berqwp_recently_optimized', '[]'), true);
606 if (!is_array($log)) $log = [];
607
608 if (!empty($search)) {
609 $s = strtolower(rtrim($search, '/'));
610 $home = strtolower(rtrim(home_url(), '/'));
611 // Strip the site root from the search term so we compare paths only.
612 // e.g. "http://plugin-berqwp.local/" → "", "/about" → "/about"
613 $s_path = ltrim(str_starts_with($s, $home) ? substr($s, strlen($home)) : $s, '/');
614
615 $log = array_values(array_filter($log, function ($e) use ($s, $home, $s_path) {
616 $url = strtolower(rtrim($e['url'], '/'));
617 $url_path = ltrim(str_starts_with($url, $home) ? substr($url, strlen($home)) : $url, '/');
618 // Exact path match (covers homepage: both empty)
619 if ($url_path === $s_path) return true;
620 // Path starts with the search path (only if search is non-empty to avoid matching everything)
621 if ($s_path !== '' && str_starts_with($url_path, $s_path)) return true;
622 // Full URL substring fallback
623 return $s_path === '' ? $url === $home : stripos($url_path, $s_path) !== false;
624 }));
625
626 // Sort: exact path match first, prefix match second, substring last
627 usort($log, function ($a, $b) use ($home, $s_path) {
628 $pa = ltrim(str_starts_with(strtolower(rtrim($a['url'], '/')), $home)
629 ? substr(strtolower(rtrim($a['url'], '/')), strlen($home)) : strtolower(rtrim($a['url'], '/')), '/');
630 $pb = ltrim(str_starts_with(strtolower(rtrim($b['url'], '/')), $home)
631 ? substr(strtolower(rtrim($b['url'], '/')), strlen($home)) : strtolower(rtrim($b['url'], '/')), '/');
632 $ra = $pa === $s_path ? 0 : (str_starts_with($pa, $s_path) ? 1 : 2);
633 $rb = $pb === $s_path ? 0 : (str_starts_with($pb, $s_path) ? 1 : 2);
634 return $ra <=> $rb;
635 });
636 }
637
638 $total = count($log);
639 $page_log = array_slice($log, $start, $length);
640
641 wp_send_json_success([
642 'data' => $page_log,
643 'total' => $total,
644 'records_filtered' => $total,
645 ]);
646 }
647
648 function ashp_increase_concurrent_batches($concurrent_batches)
649 {
650 return $concurrent_batches * 2;
651 }
652
653 function refresh_cache_stats()
654 {
655
656 check_ajax_referer('wp_rest', 'nonce');
657
658 $post_types = get_option('berqwp_optimize_post_types');
659 $args = array(
660 'post_type' => $post_types,
661 'posts_per_page' => -1,
662 'fields' => 'ids',
663 'post_status' => 'publish'
664 );
665 $query = new WP_Query($args);
666 $pages_to_exclude = get_option('berq_exclude_urls', []);
667 $total_pages = (int) $query->found_posts - count($pages_to_exclude);
668 $optimized_pages = bwp_cached_pages_count();
669
670 if (get_option('show_on_front') !== 'page') {
671 $total_pages++;
672 }
673
674 if (empty($total_pages) || $total_pages <= 0) {
675 $cached_percentage = 0;
676 } else {
677 $cached_percentage = round(($optimized_pages / $total_pages) * 100, 2);
678 }
679 if ($cached_percentage > 100) {
680 $cached_percentage = 100;
681 }
682
683 if ($cached_percentage < 0) {
684 $cached_percentage = 0;
685 }
686
687 $server_queue = get_option('berqwp_server_queue', []);
688
689 wp_send_json_success(['cache_count' => $optimized_pages, 'cache_percentage' => $cached_percentage, 'total' => $total_pages, 'server_queue' => count($server_queue)]);
690
691 die(); // Always exit in AJAX functions
692 }
693
694 function fetch_remote_html()
695 {
696
697 check_ajax_referer('wp_rest', 'nonce');
698
699 $url = get_option('berqwp_enable_sandbox') ? bwp_admin_home_url('/?berqwp') : bwp_admin_home_url('/');
700
701 $response = wp_remote_get($url);
702 // $response = bwp_wp_remote_get($url);
703
704 if (is_array($response) && !is_wp_error($response)) {
705 $html = wp_remote_retrieve_body($response);
706 echo $html;
707 } else {
708 echo 'Error fetching HTML.';
709 }
710
711 die(); // Always exit in AJAX functions
712 }
713
714 function activate_license_from_multi_site()
715 {
716 if (berq_is_localhost()) {
717 return;
718 }
719
720 $berqwp_license_key_from_parent = constant('BERQWP_LICENSE_KEY');
721
722 if (!empty($berqwp_license_key_from_parent) && empty(berqwp_get_license_key())) {
723 $key = sanitize_text_field($berqwp_license_key_from_parent);
724 $key_response = $this->verify_license_key($key, 'slm_activate');
725
726
727 if (!empty($key_response) && $key_response->result == 'success') {
728 berqwp_update_license_key($key);
729
730 if (is_admin()) {
731 ?>
732 <div class="notice notice-success is-dismissible">
733 <?php esc_html_e('The BerqWP license has been activated for your parent multisite.', 'searchpro'); ?>
734 </div>
735 <?php
736 }
737 } elseif ($key_response->result == 'error') {
738 $error = $key_response->message;
739
740 if (is_admin()) {
741 ?>
742 <div class="notice notice-error is-dismissible">
743 <?php echo esc_html($error); ?>
744 </div>
745 <?php
746
747 }
748 }
749 }
750 }
751
752 function handle_upgrade() {
753
754 $berqconfigs = berqConfigs::getInstance();
755 $configs = $berqconfigs->get_configs();
756 $site_id = $configs['site_id'];
757 $license_key = berqwp_get_license_key();
758 global $berq_log;
759
760 if (!empty($configs['optimization_method']) && $configs['optimization_method'] == 'cloud' && empty($license_key)) {
761
762 $berqconfigs->update_configs([
763 'secret' => '',
764 'optimization_method' => 'local'
765 ]);
766 return;
767 }
768
769 $license_check_only = false;
770
771 if ( !empty($configs['secret']) && !empty($configs['optimization_method']) && $configs['optimization_method'] == 'cloud' && !empty($license_key) && empty(berqwp_get_network_option('berqwp_license_cache')) ) {
772 $license_check_only = true;
773 }
774
775 // user first time upgrades to v4
776 $first_upgrade = empty($configs['optimization_method']) && !empty($license_key);
777 $missing_secret = empty($configs['secret']) && !empty($configs['optimization_method']) && $configs['optimization_method'] == 'cloud' && !empty($license_key);
778
779 if ($first_upgrade || $missing_secret || !empty($license_check_only)) {
780
781 // $berq_log->info("Authenticating secret");
782
783 // $lic_response = wp_remote_post(BerqWPCloud::$endpoint."authenticate", [
784 // 'timeout' => 30,
785 // 'body' => $request_body
786 // ]);
787
788 // if (is_wp_error($lic_response)) {
789 // $berq_log->info("Couldn't reach BerqWP server.");
790 // return;
791 // }
792
793 // $lic_body = wp_remote_retrieve_body($lic_response);
794 // $lic_json = json_decode($lic_body);
795
796 // if (empty($lic_json)) {
797 // $berq_log->info("Authenticate secret invalid response");
798 // return;
799 // }
800
801 $lic_json = $this->authenticate_license($license_key, $license_check_only);
802
803 if (!empty($lic_json->lic) && $lic_json->lic->result == 'success' && ($lic_json->lic->message == 'License key activated' || $lic_json->lic->status == 'active')) {
804
805 if (!empty($lic_json->secret)) {
806 $berqconfigs->update_configs([
807 'secret' => $lic_json->secret,
808 'optimization_method' => 'cloud'
809 ]);
810 }
811
812 berqwp_update_network_option('berqwp_license_cache', $lic_json->lic);
813
814 $berq_log->info("Authentication success.");
815
816 // Fresh installation
817 if (get_option('berqwp_can_use_fluid_images') === false) {
818
819 if ($lic_json->lic->product_ref !== 'AppSumo Deal') {
820 update_option('berqwp_can_use_fluid_images', 1);
821 } else {
822 update_option('berqwp_can_use_fluid_images', 0);
823 update_option('berqwp_sync_addons', true);
824 }
825 }
826
827 } else {
828
829 $berq_log->info("Authentication failed.");
830 berqwp_remove_license_key();
831
832 $berqconfigs->update_configs([
833 'secret' => '',
834 'optimization_method' => 'local'
835 ]);
836
837 berqwp_delete_network_option('berqwp_license_cache');
838 }
839
840 }
841
842 if (!empty(berqwp_get_network_option('berqwp_license_cache'))) {
843 $this->is_key_verified = true;
844 $this->key_response = berqwp_get_network_option('berqwp_license_cache');
845 }
846
847 }
848
849 function initialize()
850 {
851
852 if (defined('DOING_CRON') && DOING_CRON) {
853 return;
854 }
855
856 if (defined('DOING_AJAX') && DOING_AJAX) {
857 return;
858 }
859
860 // Set default settings
861 require_once optifer_PATH . '/inc/initialize.php';
862
863 $this->handle_upgrade();
864
865 if (berqwp_can_use_cloud()) {
866 $license_key = berqwp_get_license_key();
867 $lic_json = $this->authenticate_license($license_key, true);
868
869 if (!empty($lic_json->lic) && $lic_json->lic->result == 'success' && ($lic_json->lic->message == 'License key activated' || $lic_json->lic->status == 'active')) {
870 berqwp_update_network_option('berqwp_license_cache', $lic_json->lic);
871 }
872 }
873
874 // Activate the license from parent site
875 // if (defined('BERQWP_LICENSE_KEY')) {
876 // $this->activate_license_from_multi_site();
877 // }
878
879 if (is_admin()) {
880 $this->berq_post_types();
881 }
882
883 // if (is_admin() && isset($_GET['bwp_get_ip'])) {
884 // $ip = file_get_contents('https://api.ipify.org');
885 // echo 'Server Public IP Address: ' . $ip;
886 // exit;
887 // }
888
889 // if (is_admin() && !empty(berqwp_get_license_key())) {
890 // $license_key = berqwp_get_license_key();
891
892 // global $berq_log;
893 // // $berq_log->info("License key check from initialize function.");
894
895 // $key_response = $this->verify_license_key($license_key);
896
897 // if (!empty($key_response) && $key_response->result == 'success' && $key_response->status == 'active') {
898 // $this->is_key_verified = true;
899 // $this->key_response = $key_response;
900
901 // // Fresh installation
902 // if (get_option('berqwp_can_use_fluid_images') === false) {
903
904 // if ($key_response->product_ref !== 'AppSumo Deal') {
905 // update_option('berqwp_can_use_fluid_images', 1);
906 // } else {
907 // update_option('berqwp_can_use_fluid_images', 0);
908 // update_option('berqwp_sync_addons', true);
909 // }
910 // }
911
912 // } else {
913 // $this->is_key_verified = false;
914
915 // if (!empty($key_response) && $key_response->result == 'error') {
916 // berqwp_delete_license_key();
917 // }
918 // }
919 // }
920
921 // redirect to berqwp admin page
922 if (get_transient('berqwp_redirect')) {
923 delete_transient('berqwp_redirect');
924 // Set the URL to redirect to after activation
925 $redirect_url = admin_url('admin.php?page=berqwp');
926
927 // Redirect after activation
928 wp_redirect($redirect_url);
929
930 // Make sure to exit after the redirect
931 exit;
932 }
933
934 // Deactivate conflicting plugins
935 if (is_admin() && isset($_POST['berqwp_plugins_deactivate']) && wp_verify_nonce($_POST['berqwp_plugins_deactivate'], 'berqwp_plugins_deactivate')) {
936 foreach ($this->conflicting_plugins as $plugin) {
937 // Deactivate each conflicting plugin
938 if (is_plugin_active($plugin)) {
939 deactivate_plugins($plugin);
940 }
941 }
942 header('location: ' . esc_url(admin_url('admin.php') . add_query_arg(['page' => 'berqwp', 'tab_id' => sanitize_text_field(wp_unslash($_GET['tab_id'] ?? ''))])));
943 exit;
944 }
945 }
946
947 function save_settings()
948 {
949
950 if (!empty($_GET['page']) && $_GET['page'] == 'berqwp' && isset($_GET['activate-free'])) {
951 $berqconfigs = berqConfigs::getInstance();
952 $berqconfigs->update_configs(['optimization_method' => 'local']);
953
954 $location = get_admin_url() . 'admin.php?page=berqwp';
955 wp_safe_redirect($location);
956 exit;
957 }
958
959 require_once optifer_PATH . '/admin/save-settings.php';
960 }
961
962 function notices()
963 {
964
965 $plugin_name = defined('BERQWP_PLUGIN_NAME') ? BERQWP_PLUGIN_NAME : 'BerqWP';
966
967 $this->upgrade_notice();
968
969 if (isset($_GET['berqwp_page_compression_enabled'])) {
970 bwp_notice('success', 'Page Compression Enabled', "<p>Page compression has been successfully enabled on your website.</p>");
971 }
972
973 if (isset($_GET['dismiss_feedback'])) {
974 set_transient('bwp_hide_feedback_notice', true, DAY_IN_SECONDS * 14);
975 }
976
977 if (isset($_GET['bwp_quit_feedback'])) {
978 update_option('bwp_quit_feedback', true);
979 }
980
981
982 if (!empty($this->key_response) && $this->key_response->result == 'success' && $this->key_response->status == 'expired') {
983 ?>
984 <div class="notice notice-error">
985 <p><strong>Error:</strong> <?php echo $plugin_name; ?> license key has expired. Please renew your subscription.</p>
986 </div>
987 <?php
988 }
989
990 // Check connection
991 // $check_rest = bwp_check_connection(false, !empty($_GET['bwp_connection_test']) === true);
992 // if ($check_rest['status'] == 'error') {
993 // bwp_notice('error', 'Website Unreachable: Connection Blocked', "<p>$plugin_name server is unable to access this website, please whitelist our server IP address. <a href='https://berqwp.com/help-center/get-started-with-berqwp/' target='_blank'>Find our server IP address here.</a></p>", [
994 // [
995 // 'href' => esc_attr(add_query_arg(['bwp_connection_test' => true], get_admin_url())),
996 // 'text' => 'Check again',
997 // 'classes' => '',
998 // ]
999 // ]);
1000 // }
1001
1002 // Check Permissions
1003 $cache_directory = WP_CONTENT_DIR . '/cache/berqwp/';
1004 $wp_config_file = defined('BERQWP_WP_CONFIG') ? BERQWP_WP_CONFIG : ABSPATH . 'wp-config.php';
1005
1006 if (!is_writable($cache_directory)) {
1007 bwp_notice('error', 'Cache directory is not writable', "<p>The $plugin_name cache directory at /wp-content/cache/berqwp/ is not writable. Please update the directory permissions to allow the plugin to store cached files.</p>", []);
1008 }
1009
1010 if (!defined('WP_CACHE') && !is_writable($wp_config_file)) {
1011 bwp_notice('warning', 'wp-config.php is not writable', "<p>The wp-config.php file is not writable. $plugin_name needs to write configuration settings to this file. Please adjust the file permissions or manually add the WP_CACHE constant and set it to true.</p>", []);
1012 }
1013
1014 if (defined('BERQWP_ADVANCED_CACHE_PATH')) {
1015 $adv_cache_path = BERQWP_ADVANCED_CACHE_PATH;
1016 } else {
1017 $adv_cache_path = WP_CONTENT_DIR . '/advanced-cache.php';
1018 }
1019
1020 // if (file_exists($adv_cache_path) && !is_writable($adv_cache_path)) {
1021 // bwp_notice('warning', 'advanced-cache.php is not writable', "<p>$plugin_name can't write to wp-content/advanced-cache.php — please check file permissions or re-save settings to regenerate it.</p>", []);
1022 // }
1023
1024 $berqconfigs = berqConfigs::getInstance();
1025 $configs = $berqconfigs->get_configs();
1026 $readyForCache = !empty($configs['optimization_method']);
1027
1028 if ($readyForCache && bwp_is_home_cached() && !get_transient('bwp_hide_feedback_notice') && !get_option('bwp_quit_feedback') && bwp_show_account()) {
1029 bwp_notice('info bwp_feedback', 'Loving BerqWP\'s performance?', '<p>Show some love and help us grow 👉 - <a href="https://wordpress.org/support/plugin/searchpro/reviews/#new-post" target="_blank">Rate BerqWP Plugin</a>. Your insights shape our journey.</p>', [
1030 [
1031 'href' => 'https://wordpress.org/support/plugin/searchpro/reviews/#new-post',
1032 'text' => '❤️ You deserve it',
1033 'classes' => '',
1034 'target' => '_blank',
1035 ],
1036 [
1037 'href' => get_admin_url() . 'admin.php?page=berqwp&bwp_quit_feedback',
1038 'text' => '👍 Already done',
1039 'classes' => '',
1040 'target' => '',
1041 ],
1042 [
1043 'href' => get_admin_url() . 'admin.php?page=berqwp&dismiss_feedback',
1044 'text' => 'Not Now',
1045 'classes' => '',
1046 'target' => '',
1047 ]
1048 ]);
1049
1050 // $notice = '<div class="bwp-notice bwp_feedback">';
1051 // $notice .= '<p>';
1052 // $notice .= __('🎉 <b>Loving BerqWP\'s performance? 🚀</b> Show some love and help us grow 👉 - <a href="https://wordpress.org/support/plugin/searchpro/reviews/#new-post" target="_blank">Rate BerqWP Plugin</a>. Your insights shape our journey.', 'searchpro');
1053 // $notice .= '<a href="'.get_admin_url().'admin.php?page=berqwp&dismiss_feedback" style="display: table;margin-left: 50px;color: #969595;display: table;">Dismiss</a>';
1054 // $notice .= '</p>';
1055 // $notice .= '</div>';
1056 // echo wp_kses_post($notice);
1057 }
1058
1059 // purge single page notice
1060 if (get_transient('berq_purge_page_notice')) {
1061 $flushed_page = esc_url(get_transient('berq_purge_page_notice'));
1062 delete_transient('berq_purge_page_notice');
1063 bwp_notice('success', '', "<p>Page cache has been flushed for $flushed_page.</p>", []);
1064 }
1065
1066 // purge all cache notice
1067 if (get_transient('berq_cache_cleared_notice')) {
1068 delete_transient('berq_cache_cleared_notice');
1069 bwp_notice('success', '', '<p>The cache has been cleared. Our automatic cache warm-up system will generate the cache. Alternatively, you can
1070 visit any page to create its cache immediately.</p>', []);
1071 }
1072
1073 // purge cdn cache notice
1074 if (get_transient('berq_purge_cdn_notice')) {
1075 delete_transient('berq_purge_cdn_notice');
1076 bwp_notice('success', '', '<p>The CDN and page cache have been flushed.</p>', []);
1077 }
1078
1079 // purge critical css cache notice
1080 if (get_transient('berq_purge_criticalcss_notice')) {
1081 delete_transient('berq_purge_criticalcss_notice');
1082 bwp_notice('success', '', '<p>Critical CSS cache has been flushed from the cloud.</p>', []);
1083 }
1084
1085 // cache warmup notice
1086 if (get_transient('berq_cache_warmup_notice')) {
1087 delete_transient('berq_cache_warmup_notice');
1088 bwp_notice('success', 'Cache Warmup Queued', '<p>The cache warmup has been added to the queue. Your website pages will be optimized in the background and ready soon.</p>', []);
1089 }
1090
1091 // force page cache notice
1092 if (get_transient('berq_force_cache_notice')) {
1093 $forced_page = esc_url(get_transient('berq_force_cache_notice'));
1094 delete_transient('berq_force_cache_notice');
1095 bwp_notice('success', '', "<p>The cache for page ($forced_page) has been queued with high priority and will be generated soon.</p>", []);
1096 }
1097
1098 if ($readyForCache && get_option('bwp_require_flush_cache', false)) {
1099 $cache_rebuild_btns = [
1100 [
1101 'href' => esc_attr(wp_nonce_url(admin_url('admin-post.php?action=clear_cache'), 'clear_cache_action')),
1102 'text' => 'Flush cache',
1103 'classes' => '',
1104 ]
1105 ];
1106
1107 if (berqwp_can_use_cloud()) {
1108 $cache_rebuild_btns[] = [
1109 'href' => esc_attr(wp_nonce_url(admin_url('admin-post.php?action=warmup_cache'), 'warmup_cache_action')),
1110 'text' => 'Warmup cache',
1111 'classes' => '',
1112 ];
1113 }
1114
1115 bwp_notice('warning', 'Cache Flush Required', '<p>To apply the changes, please flush the cache.</p>', $cache_rebuild_btns);
1116 }
1117
1118 if (berq_is_localhost() && berqwp_can_use_cloud()) {
1119 bwp_notice('warning', 'Localhost environment detected:', "<p>$plugin_name requires a live, publicly accessible website to function.</p>", []);
1120 }
1121
1122 $plugins_to_deactivate = '';
1123
1124 foreach ($this->conflicting_plugins as $plugin) {
1125 if (is_plugin_active($plugin)) {
1126 $plugins_to_deactivate .= '<li><b>' . basename(dirname($plugin)) . '</b></li>';
1127 }
1128 }
1129
1130 if (!empty($plugins_to_deactivate)) {
1131 echo "<style>.berqwp-plugin-conflict ul {
1132 list-style: disc;
1133 margin-left: 20px;
1134 }.berqwp-plugin-conflict form {
1135 padding: 10px;
1136 }
1137 .berqwp-plugin-conflict {
1138 display: grid;
1139 grid-template-columns: auto min-content;
1140 }</style>";
1141 echo '<div class="bwp-notice notice notice-error berqwp-plugin-conflict">';
1142 echo wp_kses_post(__('<p><strong>BerqWP Plugin Conflict:</strong> The following plugins have a same nature as BerqWP plugin. Having multiple plugins of the same type can cause unexpected results.</p>', 'searchpro'));
1143 ?>
1144 <form action="<?php echo esc_url(admin_url('admin.php') . add_query_arg(['page' => 'berqwp', 'tab_id' => sanitize_text_field(wp_unslash($_GET['tab_id'] ?? ''))])); ?>" method="post">
1145
1146 <?php
1147 $my_nonce = wp_create_nonce('berqwp_plugins_deactivate');
1148 echo '<input type="hidden" name="berqwp_plugins_deactivate" value="' . esc_attr($my_nonce) . '" />';
1149 ?>
1150
1151 <input type="submit" class="button-secondary alignright" value="Deactivate Conflicting Plugins">
1152 </form>
1153 <?php
1154 echo wp_kses_post("<ul>$plugins_to_deactivate</ul>");
1155 echo '</div>';
1156 }
1157 }
1158
1159 function berq_post_types()
1160 {
1161 // Get post type names
1162 $post_type_names = get_post_types(['public' => true, 'exclude_from_search' => false], 'names');
1163 unset($post_type_names['attachment']);
1164
1165 // var_dump($post_type_names);
1166
1167 // Modify which post types to optimize
1168 $post_type_names = apply_filters('berqwp_post_types', $post_type_names);
1169
1170 // Save the names in a WordPress option
1171 update_option('berqwp_post_type_names', $post_type_names);
1172 }
1173
1174 function plugin_settings_links($links)
1175 {
1176 $mylinks = array(
1177 '<a target="_blank" href="https://berqwp.com/help-center/">' . __('Help Center', 'searchpro') . '</a>',
1178 '<a href="' . admin_url('admin.php?page=berqwp') . '">' . __('Settings', 'searchpro') . '</a>',
1179 );
1180
1181 return array_merge($links, $mylinks);
1182 }
1183
1184 function authenticate_license($license_key, $check_only = false) {
1185
1186 $berqconfigs = berqConfigs::getInstance();
1187 $berqwp_configs = $berqconfigs->get_configs();
1188 $site_id = $berqwp_configs['site_id'];
1189
1190 if (empty($site_id)) {
1191 $blog_id = get_current_blog_id();
1192 $network_id = function_exists('get_current_network_id') ? get_current_network_id() : 1;
1193 $siteurl = get_option('siteurl');
1194 $site_id = md5("berqwp|$network_id|$blog_id|$siteurl");
1195
1196 $berqconfigs->update_configs(['site_id' => $site_id]);
1197 }
1198
1199 global $berq_log;
1200 $transient_key = 'berqwp_lic_response_cache'; // Set a unique key for the transient
1201 $expire_transient_key = 'berqwp_lic_cache_expire'; // Set a unique key for the transient
1202
1203 if (!$check_only) {
1204 berqwp_delete_network_option($transient_key);
1205 }
1206
1207 // Check if the response is already cached
1208 $lic_json = berqwp_get_network_option($transient_key);
1209 $cache_expire_time = (int) berqwp_get_network_option($expire_transient_key);
1210
1211 if (false === $lic_json || $cache_expire_time < time()) {
1212
1213 $berq_log->info("Authenticating license key");
1214
1215 $body = [
1216 'license_key' => $license_key,
1217 'site_id' => $site_id,
1218 'site_url' => home_url(),
1219 ];
1220
1221 if ($check_only) {
1222 $body['check'] = true;
1223 }
1224
1225 $lic_response = wp_remote_post(BerqWPCloud::$endpoint."authenticate", [
1226 'timeout' => 30,
1227 'body' => $body
1228 ]);
1229
1230 if (is_wp_error($lic_response)) {
1231 $berq_log->info("Couldn't reach BerqWP server.".print_r($lic_response, true));
1232 return;
1233 }
1234
1235 $lic_body = wp_remote_retrieve_body($lic_response);
1236 $lic_json = json_decode($lic_body);
1237
1238 if (!empty($lic_json)) {
1239 berqwp_update_network_option($transient_key, $lic_json);
1240 berqwp_update_network_option($expire_transient_key, time() + DAY_IN_SECONDS);
1241 }
1242
1243 }
1244
1245
1246 return $lic_json;
1247
1248 }
1249
1250 function verify_license_key($license_key, $action = 'slm_check')
1251 {
1252 if ($action !== 'slm_deactivate') {
1253 return;
1254 }
1255
1256 // Action
1257 // slm_activate
1258 // slm_deactivate
1259 // slm_check
1260
1261 if (empty($license_key)) {
1262 return;
1263 }
1264
1265 if (defined('BERQWP_DOING_LICENSE_CHECK')) {
1266 // sleep(1);
1267 return;
1268 }
1269
1270 /**
1271 * Replaced transients with options
1272 */
1273
1274 global $berq_log;
1275 $transient_key = 'berq_lic_response_cache'; // Set a unique key for the transient
1276 $expire_transient_key = 'berq_lic_cache_expire'; // Set a unique key for the transient
1277
1278 if ($action !== 'slm_check') {
1279 // delete_transient( $transient_key );
1280 berqwp_delete_network_option($transient_key);
1281 }
1282
1283 // Check if the response is already cached
1284 // $cached_response = get_transient($transient_key);
1285 $cached_response = berqwp_get_network_option($transient_key);
1286 $cache_expire_time = (int) berqwp_get_network_option($expire_transient_key);
1287
1288
1289 if (false === $cached_response || $cache_expire_time < time()) {
1290 // If not cached, perform the API request
1291
1292 $rateLimiter = new RateLimiter(5, 60, optifer_cache . 'ratelimit/');
1293 $clientIdentifier = gethostname();
1294 if (function_exists('is_multisite') && is_multisite()) {
1295 $clientIdentifier .= '-site-' . get_current_blog_id();
1296 }
1297
1298 if ($rateLimiter->isRateLimited($clientIdentifier)) {
1299 return false;
1300 }
1301
1302 define('BERQWP_DOING_LICENSE_CHECK', true);
1303
1304 $berq_log->info('Checking the license key.');
1305
1306 $parsed_url = parse_url(home_url());
1307 $domain = $parsed_url['host'];
1308
1309 $api_params = array(
1310 'registered_domain' => $domain,
1311 'slm_action' => $action,
1312 'secret_key' => BERQ_SECRET,
1313 'license_key' => $license_key,
1314 'version' => BERQWP_VERSION,
1315 't' => '',
1316 );
1317
1318 $endpoint_url = esc_url(add_query_arg($api_params, BERQ_SERVER));
1319
1320 $args = array(
1321 'method' => 'POST', // Only POST works for unknown reason
1322 'timeout' => 20,
1323 'redirection' => 5,
1324 'blocking' => true,
1325 'headers' => array(
1326 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
1327 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
1328 'Accept-Encoding' => 'gzip, deflate, br',
1329 'Accept-Language' => 'en-US,en;q=0.9',
1330 'Connection' => 'keep-alive',
1331 'Referer' => 'https://berqwp.com/', // Adjust based on actual referer
1332 ),
1333 'cookies' => array(),
1334 'sslverify' => false, // Disable SSL verification (for debugging purposes)
1335 );
1336
1337 // $request = wp_remote_request( $endpoint_url, $args );
1338
1339
1340 $berq_log->info('Making request 1');
1341
1342 $query_string = http_build_query($api_params);
1343 // $client = new HttpClient(BERQ_SERVER);
1344 // $client->setUserAgent('BerqWP');
1345 // $client->post('?' . $query_string, $api_params);
1346 // $client->setTimeout(30);
1347
1348 $client = new \BerqWP_Deps\GuzzleHttp\Client([
1349 'timeout' => 60,
1350 'http_errors' => false,
1351 'verify' => false,
1352 ]);
1353
1354 $response = $client->post(BERQ_SERVER . '?' . $query_string, [
1355 'form_params' => $api_params,
1356 ]);
1357 $statusCode = $response->getStatusCode();
1358 $response = $response->getBody()->getContents();
1359
1360 // var_dump($client->getContent(), $client->getError(), $api_params);
1361
1362 // $berq_log->info(print_r($client->getContent(), true).'---'.$client->ok());
1363
1364 if ($statusCode >= 200 && $statusCode < 300) {
1365 // $response = $client->getContent();
1366 $JSON = json_decode($response);
1367
1368 if ($action == 'slm_activate' && isset($JSON->error_code) && $JSON->message !== 'Invalid license key') {
1369 sleep(1);
1370 $api_params = array(
1371 'registered_domain' => $domain,
1372 'slm_action' => 'slm_check',
1373 'secret_key' => BERQ_SECRET,
1374 'license_key' => $license_key,
1375 't' => '',
1376 );
1377
1378 $berq_log->info('Making request 2');
1379
1380 $query_string = http_build_query($api_params);
1381 // $client = new HttpClient(BERQ_SERVER);
1382 // $client->setUserAgent('BerqWP');
1383 // $client->post('?' . $query_string, $api_params);
1384
1385
1386 // if ($client->ok()) {
1387 // $response = $client->getContent();
1388 // }
1389
1390 $response = $client->post(BERQ_SERVER . '?' . $query_string, [
1391 'form_params' => $api_params,
1392 ]);
1393
1394 $response = $response->getBody()->getContents();
1395 }
1396 }
1397
1398 if ($action !== 'slm_check') {
1399 $api_params = array(
1400 'registered_domain' => $domain,
1401 'slm_action' => 'slm_check',
1402 'secret_key' => BERQ_SECRET,
1403 'license_key' => $license_key,
1404 'version' => BERQWP_VERSION,
1405 't' => '',
1406 );
1407
1408 $berq_log->info('Making request 3');
1409
1410 $query_string = http_build_query($api_params);
1411 // $client = new HttpClient(BERQ_SERVER);
1412 // $client->setUserAgent('BerqWP');
1413 // $client->post('?' . $query_string, $api_params);
1414
1415
1416 // if ($client->ok()) {
1417 // $response = $client->getContent();
1418 // }
1419
1420 $response = $client->post(BERQ_SERVER . '?' . $query_string, [
1421 'form_params' => $api_params,
1422 ]);
1423
1424 $response = $response->getBody()->getContents();
1425 }
1426
1427 if (empty($response)) {
1428 return;
1429 }
1430
1431 $cached_response = json_decode($response);
1432
1433
1434 if ($action == 'slm_check' && !empty($cached_response) && !empty($cached_response->result)) {
1435 $domain_found = false;
1436
1437 foreach ($cached_response->registered_domains as $reg_domain) {
1438 $domain_name = str_replace('www.', '', $domain);
1439 $domain_name_www = 'www.' . $domain;
1440
1441 if ($reg_domain->registered_domain == $domain_name || $reg_domain->registered_domain == $domain_name_www || $reg_domain->registered_domain == $domain) {
1442 $domain_found = true;
1443 break;
1444 }
1445 }
1446
1447 if ($domain_found) {
1448 // Cache the response for 24 hours
1449 // set_transient($transient_key, $cached_response, 24 * HOUR_IN_SECONDS);
1450 berqwp_update_network_option($transient_key, $cached_response);
1451 berqwp_update_network_option($expire_transient_key, time() + MONTH_IN_SECONDS);
1452 } else {
1453
1454 berqwp_delete_network_option($transient_key);
1455 berqwp_delete_network_option($expire_transient_key);
1456 berqwp_delete_license_key();
1457
1458 return false;
1459 }
1460 }
1461
1462 // if ($action == 'slm_check' && !empty($cached_response) && $cached_response->result == 'success' && $cached_response->status == 'active') {
1463 // // Cache the response for 24 hours
1464 // set_transient($transient_key, $cached_response, 24 * HOUR_IN_SECONDS);
1465 // }
1466
1467 // if ($action == 'slm_check' && !empty($cached_response) && $cached_response->result == 'error') {
1468 // // Key verification failed, cache the response for 14 hours
1469 // // preventing unnecessary verification requests
1470 // set_transient($transient_key, $cached_response, 14 * HOUR_IN_SECONDS);
1471 // }
1472
1473 } else {
1474 // $berq_log->info('Delivering license key object from the transient cache.');
1475 }
1476
1477 // Return the cached response
1478 return $cached_response;
1479 }
1480
1481 // Disable emoji functionality
1482 function disable_emoji()
1483 {
1484 // Remove emoji-related actions and filters
1485 remove_action('wp_head', 'print_emoji_detection_script', 7);
1486 remove_action('admin_print_scripts', 'print_emoji_detection_script');
1487 remove_action('wp_print_styles', 'print_emoji_styles');
1488 remove_action('admin_print_styles', 'print_emoji_styles');
1489 remove_filter('the_content_feed', 'wp_staticize_emoji');
1490 remove_filter('comment_text_rss', 'wp_staticize_emoji');
1491 remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
1492
1493 // Remove emoji-related TinyMCE plugins
1494 add_filter('tiny_mce_plugins', [$this, 'disable_emoji_tinymce']);
1495 }
1496
1497 // Filter function to disable emoji-related TinyMCE plugins
1498 function disable_emoji_tinymce($plugins)
1499 {
1500 if (is_array($plugins)) {
1501 return array_diff($plugins, array('wpemoji'));
1502 } else {
1503 return array();
1504 }
1505 }
1506
1507 // function clear_cache(WP_REST_Request $request)
1508 // {
1509 // require_once optifer_PATH . 'api/clear_cache.php';
1510 // }
1511
1512 // function warmup_cache(WP_REST_Request $request)
1513 // {
1514 // require_once optifer_PATH . 'api/warmup_cache.php';
1515 // }
1516
1517 // function store_cache(WP_REST_Request $request)
1518 // {
1519 // require_once optifer_PATH . 'api/store_cache.php';
1520 // }
1521
1522 // function store_javascript_cache(WP_REST_Request $request)
1523 // {
1524 // require_once optifer_PATH . 'api/store_javascript_cache.php';
1525 // }
1526
1527 // ==========================================
1528 // Multisite Network Support
1529 // ==========================================
1530
1531 function register_network_menu()
1532 {
1533 $svg = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1534 <path fill-rule="evenodd" clip-rule="evenodd" d="M6.43896 0H17.561C21.1172 0 24 2.88287 24 6.43903V17.561C24 21.1171 21.1172 24 17.561 24H6.43896C2.88281 24 0 21.1171 0 17.561V6.43903C0 2.88287 2.88281 0 6.43896 0ZM15.7888 4.09753L8.59961 12.7534H12.3517L7.02441 20.4878L16.3903 11.0222L12.7814 10.3799L15.7888 4.09753Z" fill="#a7aaad"/>
1535 </svg>';
1536
1537 $plugin_name = defined('BERQWP_PLUGIN_NAME') ? BERQWP_PLUGIN_NAME : 'BerqWP';
1538
1539 add_menu_page(
1540 $plugin_name . ' Network',
1541 $plugin_name,
1542 'manage_network_options',
1543 'berqwp-network',
1544 [$this, 'network_admin_page'],
1545 'data:image/svg+xml;base64,' . base64_encode($svg),
1546 80
1547 );
1548 }
1549
1550 function network_admin_page()
1551 {
1552 require_once optifer_PATH . 'admin/network-admin-page.php';
1553 }
1554
1555 function save_network_settings()
1556 {
1557 check_admin_referer('berqwp_network_save');
1558
1559 if (!current_user_can('manage_network_options')) {
1560 wp_die('Unauthorized');
1561 }
1562
1563 // License activation
1564 if (!empty($_POST['berqwp_license_key'])) {
1565 $key = sanitize_text_field($_POST['berqwp_license_key']);
1566 // $key_response = $this->verify_license_key($key, 'slm_activate');
1567 $key_response = $this->authenticate_license($key);
1568 if (!empty($key_response->lic) && isset($key_response->lic->result) && $key_response->lic->result == 'success') {
1569 berqwp_update_license_key($key);
1570 }
1571 }
1572
1573 // License deactivation
1574 if (!empty($_POST['berq_deactivate_key'])) {
1575 $existing_key = berqwp_get_license_key();
1576 if (!empty($existing_key)) {
1577 $this->verify_license_key($existing_key, 'slm_deactivate');
1578 }
1579 berqwp_delete_license_key();
1580 berqwp_delete_network_option('berq_lic_response_cache');
1581 berqwp_delete_network_option('berq_lic_cache_expire');
1582 berqwp_delete_network_option('berqwp_lic_response_cache');
1583 berqwp_delete_network_option('berqwp_lic_cache_expire');
1584 }
1585
1586 // Flush all sites cache
1587 if (!empty($_POST['berqwp_flush_all_cache'])) {
1588 $cache_directory = WP_CONTENT_DIR . '/cache/berqwp/html/';
1589 if (is_dir($cache_directory)) {
1590 berqwp_unlink_recursive($cache_directory);
1591 }
1592 }
1593
1594 wp_safe_redirect(network_admin_url('admin.php?page=berqwp-network&updated=true'));
1595 exit;
1596 }
1597
1598 function regenerate_blog_map()
1599 {
1600 if (!function_exists('is_multisite') || !is_multisite()) {
1601 return;
1602 }
1603
1604 $sites = get_sites(['fields' => 'ids', 'number' => 0]);
1605 $map = [
1606 'subdomains' => [],
1607 'subdirs' => [],
1608 ];
1609
1610 $is_subdomain = defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL;
1611
1612 foreach ($sites as $site_id) {
1613 $site = get_site($site_id);
1614 if (!$site) continue;
1615
1616 if ($is_subdomain) {
1617 $map['subdomains'][strtolower($site->domain)] = (int) $site_id;
1618 } else {
1619 $path = rtrim($site->path, '/') . '/';
1620 if ($path !== '/') {
1621 $map['subdirs'][$path] = (int) $site_id;
1622 }
1623 }
1624 }
1625
1626 $map_file = WP_CONTENT_DIR . '/cache/berqwp/blog-map.json';
1627 $map_dir = dirname($map_file);
1628 if (!is_dir($map_dir)) {
1629 wp_mkdir_p($map_dir);
1630 }
1631 file_put_contents($map_file, json_encode($map, JSON_PRETTY_PRINT));
1632 }
1633
1634 function on_new_site_created($new_site)
1635 {
1636 if (function_exists('is_plugin_active_for_network') && is_plugin_active_for_network('searchpro/berqwp.php')) {
1637 switch_to_blog($new_site->blog_id);
1638 berqwp_activate_single_site();
1639 restore_current_blog();
1640 }
1641 $this->regenerate_blog_map();
1642 }
1643
1644 function register_menu()
1645 {
1646 $svg = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1647 <path fill-rule="evenodd" clip-rule="evenodd" d="M6.43896 0H17.561C21.1172 0 24 2.88287 24 6.43903V17.561C24 21.1171 21.1172 24 17.561 24H6.43896C2.88281 24 0 21.1171 0 17.561V6.43903C0 2.88287 2.88281 0 6.43896 0ZM15.7888 4.09753L8.59961 12.7534H12.3517L7.02441 20.4878L16.3903 11.0222L12.7814 10.3799L15.7888 4.09753Z" fill="#a7aaad"/>
1648 </svg>';
1649
1650 $plugin_name = defined('BERQWP_PLUGIN_NAME') ? BERQWP_PLUGIN_NAME : 'BerqWP';
1651
1652 add_menu_page($plugin_name, $plugin_name, 'manage_options', 'berqwp', [$this, 'admin_page'], 'data:image/svg+xml;base64,' . base64_encode($svg), 80);
1653 }
1654
1655 function admin_page()
1656 {
1657
1658 $berqconfigs = berqConfigs::getInstance();
1659 $configs = $berqconfigs->get_configs();
1660
1661 if (!empty($configs['optimization_method'])) {
1662 require_once optifer_PATH . 'admin/admin-page.php';
1663 } else {
1664 require_once optifer_PATH . 'admin/intro-page.php';
1665 }
1666 }
1667 }
1668
1669 berqWP::getInstance();
1670 // global $berqWP;
1671 // $berqWP = new berqWP();
1672 }
1673