PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 1.9.5
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v1.9.5
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 / helper-functions.php

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

783 lines 26.0 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
6 function berqwp_is_slug_excludable($slug)
7 {
8 if (empty($slug)) {
9 return true;
10 }
11
12 $exclude_items = ["elementor_library=", "add_to_wishlist=", "robots.txt", ".html", ".php", "run_warmup=", "et-compare-page=", "add_to_compare=", "min_price=", "max_price=", "view_mode=", "view_mode_smart=", "et_columns-count=", "add_to_wishlist=", "et-wishlist-page=", "remove_wishlist=", "stock_status=", "page_id=", "?p="];
13
14 $exclude_items = apply_filters('berqwp_exclude_slug_match', $exclude_items);
15
16 foreach ($exclude_items as $item) {
17 if (strpos($slug, $item) !== false) {
18 return true;
19 }
20 }
21
22 return false;
23 }
24
25 function berqwp_get_page_params($slug, $is_forced = false) {
26 if (empty($slug)) {
27 return;
28 }
29
30 $url = home_url() . $slug;
31 $slug_md5 = md5($slug);
32
33 $cache_directory = optifer_cache . '/html/';
34 $cache_file = $cache_directory . $slug_md5 . '.html';
35 $key = uniqid();
36 $cache_max_life = @filemtime($cache_file) + (18 * 60 * 60);
37
38 if (!file_exists($cache_file) || (file_exists($cache_file) && $cache_max_life < time()) || (file_exists($cache_file) && bwp_is_partial_cache($slug) === true)) {
39 // Priority 1
40 $key = '';
41 }
42
43 $optimization_mode = get_option('berq_opt_mode');
44
45 if ($optimization_mode == 4) {
46 $optimization_mode = 'aggressive';
47 } elseif ($optimization_mode == 3) {
48 $optimization_mode = 'blaze';
49 } elseif ($optimization_mode == 2) {
50 $optimization_mode = 'medium';
51 } elseif ($optimization_mode == 1) {
52 $optimization_mode = 'basic';
53 }
54
55 // Data to send as POST parameters
56 $post_data = array(
57 'license_key' => get_option('berqwp_license_key'),
58 'page_url' => $url,
59 'page_slug' => $slug,
60 'site_url' => home_url(),
61 'webp_max_width' => (int) get_option('berqwp_webp_max_width'),
62 'webp_quality' => (int) get_option('berqwp_webp_quality'),
63 'img_lazyloading' => get_option('berqwp_image_lazyloading'),
64 'youtube_lazyloading' => get_option('berqwp_lazyload_youtube_embed'),
65 'js_mode' => get_option('berqwp_javascript_execution_mode'),
66 'key' => $key,
67 'interaction_delay' => get_option('berqwp_interaction_delay'),
68 'cache_js' => true,
69 'use_cdn' => get_option('berqwp_enable_cdn'),
70 'opt_mode' => $optimization_mode,
71 'disable_webp' => get_option('berqwp_disable_webp'),
72 'js_css_exclude_urls' => get_option('berq_exclude_js_css', []),
73 'preload_fontfaces' => get_option('berqwp_preload_fontfaces'),
74 // 'mobile_lcp' => json_encode($mobile_lcp),
75 // 'desktop_lcp' => json_encode($desktop_lcp),
76 'version' => BERQWP_VERSION
77 );
78
79 if (defined('BERQ_STAGING') || $is_forced) {
80 $post_data['run_queue'] = 1;
81 $post_data['doing_queue'] = true;
82 }
83
84 return $post_data;
85
86
87 }
88
89 function bwp_pass_account_requirement() {
90 global $berqWP, $berq_log;
91
92 $license_key = get_option('berqwp_license_key');
93 $key_response = $berqWP->verify_license_key($license_key);
94
95 if (empty($key_response->product_ref)) {
96 return false;
97 }
98
99 if ($key_response->result !== 'success' || $key_response->status !== 'active') {
100 $berq_log->error("account requirement: license verification failed");
101 return false;
102 }
103
104 if ($key_response->product_ref == 'Free Account' && bwp_cached_pages_count() >= 10) {
105 return false;
106 }
107
108 if ($key_response->product_ref == 'Starter' && bwp_cached_pages_count() >= 100) {
109 return false;
110 }
111
112 return true;
113 }
114
115 function warmup_cache_by_slug($slug, $is_forced = false)
116 {
117 if (empty($slug)) {
118 return;
119 }
120
121 if (berqwp_is_slug_excludable($slug)) {
122 return;
123 }
124
125 $slug_md5 = md5($slug);
126
127 $cache_directory = optifer_cache . '/html/';
128 $cache_file = $cache_directory . $slug_md5 . '.html';
129 $cache_max_life = @filemtime($cache_file) + (18 * 60 * 60);
130
131 if (!file_exists($cache_file) && bwp_pass_account_requirement() === false) {
132 return;
133 }
134
135 // Return if page is excluded from cache
136 $pages_to_exclude = get_option('berq_exclude_urls', []);
137
138 if (in_array(home_url() . $slug, $pages_to_exclude)) {
139 return;
140 }
141
142 $check_rest = bwp_check_rest_api(true);
143 if ( $check_rest['status'] == 'error' ) {
144 global $berq_log;
145 $berq_log->error('Exiting cache warmup by slug, rest api not working.');
146 return;
147 }
148
149 // Hook to modify cache lifespan
150 $cache_max_life = apply_filters('berqwp_cache_lifespan', $cache_max_life);
151
152 if (file_exists($cache_file) && bwp_is_partial_cache($slug) === false && $cache_max_life > time()) {
153 return;
154 }
155
156 // API endpoint URL
157 $api_endpoint = 'https://boost.berqwp.com/photon/';
158
159 if (get_site_url() == 'http://berq-test.local') {
160 $api_endpoint = 'http://dev-berqwp.local/photon/';
161 }
162
163 // Modify photon engine endpoint for testing purposes
164 $api_endpoint = apply_filters( 'berqwp_photon_endpoint', $api_endpoint );
165
166 $post_data = berqwp_get_page_params($slug, $is_forced);
167
168 // Set up the request arguments
169 $args = array(
170 'body' => $post_data, // Pass the POST data here
171 'method' => 'POST',
172 // 'blocking' => false,
173 'timeout' => $is_forced === true ? 20 : 0.1,
174 'headers' => array(
175 'Content-Type' => 'application/x-www-form-urlencoded', // Adjust content type if needed
176 ),
177 );
178
179 // Send the POST request
180 $response = wp_remote_post($api_endpoint, $args);
181
182 // Check for errors and handle the response
183 if (is_wp_error($response)) {
184 // There was an error with the request
185 error_log('Error: ' . $response->get_error_message());
186 }
187
188 }
189
190 function bwp_is_home_cached() {
191 $slug_md5 = md5('/');
192 $cache_directory = optifer_cache . '/html/';
193 $cache_file = $cache_directory . $slug_md5 . '.html';
194
195 return file_exists($cache_file);
196 }
197
198 function bwp_is_partial_cache($slug) {
199
200 if (!function_exists('str_get_html')) {
201 require_once optifer_PATH . '/simplehtmldom/simple_html_dom.php';
202 }
203
204 $cache_directory = optifer_cache . '/html/';
205 $cache_key = md5($slug);
206 $cache_file = $cache_directory . $cache_key . '.html';
207
208 if (file_exists($cache_file)) {
209 $buffer = file_get_contents($cache_file);
210
211 if (!empty($buffer)) {
212 $html = str_get_html($buffer);
213
214 if ($html !== false) {
215 $style_tag = $html->find('style#berqwp-critical-css', 0);
216
217 if ($style_tag === null) {
218 return true;
219 }
220 }
221
222 }
223 }
224
225 return false;
226
227 }
228
229 function berq_is_localhost()
230 {
231 $whitelist = array('127.0.0.1', '::1');
232
233 if (in_array($_SERVER['REMOTE_ADDR'], $whitelist)) {
234 return true;
235 }
236
237 return false;
238 }
239
240 function berqwp_remove_ignore_params($slug)
241 {
242 // List of tracking parameters to remove
243 $tracking_params = get_option('berq_ignore_urls_params', []);
244
245 $tracking_params = apply_filters( 'berqwp_ignored_urls_params', $tracking_params );
246
247 // Parse the provided slug
248 $url_parts = parse_url($slug);
249
250 // Get the current URL parameters
251 $url_params = array();
252 if (isset($url_parts['query'])) {
253 parse_str($url_parts['query'], $url_params);
254 }
255
256 // Remove specified tracking parameters from the URL
257 foreach ($tracking_params as $param) {
258 $param = trim($param);
259 if (isset($url_params[$param])) {
260 unset($url_params[$param]);
261 }
262 }
263
264 // Build the new query string
265 $new_query_string = http_build_query($url_params);
266
267 // Reconstruct the URL with the new query string
268 $new_slug = $url_parts['path'];
269 if (!empty($new_query_string)) {
270 $new_slug .= '?' . $new_query_string;
271 }
272
273 return $new_slug;
274 }
275
276 function berqwp_is_sub_dir_wp()
277 {
278 // remove http
279 $site_url = explode('//', home_url())[1];
280 $break_slash = explode('/', $site_url);
281
282 return count($break_slash) > 1;
283 }
284
285 function berqwp_current_page_cache_file()
286 {
287 $slug_uri = $_SERVER['REQUEST_URI'];
288
289 // if wordpress is installed in a sub directory
290 if (berqwp_is_sub_dir_wp()) {
291 // Parse strings to extract paths
292 $path1 = explode('/', parse_url(home_url(), PHP_URL_PATH));
293 $path2 = explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
294
295 // Find the common part of the paths
296 $commonPath = implode('/', array_intersect($path1, $path2));
297
298 // Subtract the common part from the first string
299 $slug_uri = str_replace($commonPath, '', $_SERVER['REQUEST_URI']);
300 }
301
302 // Return if page is excluded from cache
303 $pages_to_exclude = get_option('berq_exclude_urls', []);
304
305 if (in_array(get_site_url() . $slug_uri, $pages_to_exclude)) {
306 return;
307 }
308
309
310 $slug = berqwp_remove_ignore_params($slug_uri);
311
312 if (isset($_GET['creating_cache'])) {
313 return;
314 }
315
316 if (get_option('berqwp_enable_sandbox') == 1 && isset($_GET['berqwp'])) {
317 $slug = explode('?berqwp', $slug_uri)[0];
318 } elseif (get_option('berqwp_enable_sandbox') == 1 && !isset($_GET['creating_cache'])) {
319 return;
320 }
321
322
323 // Attempt to retrieve the cached HTML from the cache directory
324 $cache_directory = optifer_cache . '/html/';
325
326 // Generate a unique cache key based on the current page URL
327 $cache_key = md5($slug);
328 $cache_file = $cache_directory . $cache_key . '.html';
329
330 return $cache_file;
331
332 }
333
334 function berqwp_get_LCP_details($url, $device = 'mobile')
335 {
336 $google_pagespeed_api_url = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=$url&strategy=$device ";
337
338 // Send a GET request to the Google PageSpeed Insights API
339 // $response = wp_remote_get($google_pagespeed_api_url, array('timeout' => 60));
340 $response = bwp_wp_remote_get($google_pagespeed_api_url, array('timeout' => 60));
341
342 if (is_wp_error($response)) {
343 return 'Error: ' . $response->get_error_message();
344 }
345
346 // Convert the JSON response to a PHP array
347 $body = wp_remote_retrieve_body($response);
348 $output = json_decode($body, true);
349
350 // Get the LCP data
351 return $output['lighthouseResult']['audits']['largest-contentful-paint-element']['details']['items'][0]['items'][0]['node'];
352 }
353
354 function berqwp_enable_object_cache($enable) {
355 global $berq_log;
356 $berq_log->info("Updating wp-config.php");
357
358 // Specify the wp-config.php file path
359 $wp_config_file = ABSPATH . 'wp-config.php';
360
361 // Read the contents of wp-config.php
362 $wp_config_content = file_get_contents($wp_config_file);
363
364 // Find the position of the first PHP tag using a regular expression
365 preg_match('/<\?php/', $wp_config_content, $matches, PREG_OFFSET_CAPTURE);
366
367 // Check if the PHP opening tag exists
368 if (!empty($matches)) {
369 $first_php_comment_position = $matches[0][1] + 5; // Move past the length of '<?php'
370
371 // Check if the WP_CACHE definition exists in the file
372 if (strpos($wp_config_content, "define('WP_CACHE'") === false && strpos($wp_config_content, "define( 'WP_CACHE' ") === false) {
373 // If not, add the definition right after the opening PHP tag
374 $wp_config_content = substr_replace($wp_config_content, "\n"
375 . "// Enable or disable BerqWP object cache\n"
376 . "define('WP_CACHE', " . ($enable ? 'true' : 'false') . ");\n",
377 $first_php_comment_position, 0);
378 } else {
379 // Otherwise, enable or disable the existing definition
380 // $wp_config_content = preg_replace(
381 // "/define\('WP_CACHE', [^\n]*\);/",
382 // "define('WP_CACHE', " . ($enable ? 'true' : 'false') . ");",
383 // $wp_config_content
384 // );
385
386 $wp_config_content = preg_replace(
387 "/define\(\s*'WP_CACHE'\s*,\s*[^\n]*\);/",
388 "define('WP_CACHE', " . ($enable ? 'true' : 'false') . ");",
389 $wp_config_content
390 );
391 }
392
393 // Write the modified content back to wp-config.php
394 file_put_contents($wp_config_file, $wp_config_content);
395 } else {
396
397 global $berq_log;
398 $berq_log->error("Error: PHP opening tag not found in wp-config.php");
399
400 }
401 }
402
403 // Copied from Nginx Helper plugin
404 function berqwp_unlink_recursive( $dir ) {
405
406 if ( ! is_dir( $dir ) ) {
407 return;
408 }
409
410 $dh = opendir( $dir );
411
412 if ( ! $dh ) {
413 return;
414 }
415
416 // phpcs:ignore -- WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition -- Variable assignment required for recursion.
417 while ( false !== ( $obj = readdir( $dh ) ) ) {
418
419 if ( '.' === $obj || '..' === $obj ) {
420 continue;
421 }
422
423 if ( ! @unlink( $dir . '/' . $obj ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
424 berqwp_unlink_recursive( $dir . '/' . $obj, false );
425 }
426 }
427
428 closedir( $dh );
429 }
430
431 function berqwp_get_last_modified_timestamp() {
432 global $post;
433
434 // Check if it's a single post or page
435 if (is_singular()) {
436 return get_the_modified_time('U', $post->ID); // 'U' format parameter returns Unix timestamp
437 }
438
439 // Check if it's a taxonomy term
440 if (is_tax() || is_category() || is_tag()) {
441 $term = get_queried_object(); // Get the current term object
442
443 // For tags, get the last modified date of the most recent post associated with the tag
444 if (is_tag()) {
445 $args = array(
446 'tag_id' => $term->term_id,
447 'posts_per_page' => 1,
448 'orderby' => 'modified',
449 'order' => 'DESC',
450 'fields' => 'ids', // Return only post IDs to reduce overhead
451 );
452 $posts = get_posts($args);
453 if ($posts) {
454 $latest_post_id = $posts[0];
455 return get_the_modified_time('U', $latest_post_id); // 'U' format parameter returns Unix timestamp
456 }
457 }
458
459 // For category archives, get the last modified date of the most recent post within the category
460 if (is_category()) {
461 $args = array(
462 'category' => $term->term_id,
463 'posts_per_page' => 1,
464 'orderby' => 'modified',
465 'order' => 'DESC',
466 'fields' => 'ids', // Return only post IDs to reduce overhead
467 );
468 $posts = get_posts($args);
469 if ($posts) {
470 $latest_post_id = $posts[0];
471 return get_the_modified_time('U', $latest_post_id); // 'U' format parameter returns Unix timestamp
472 }
473 }
474
475 return strtotime($term->modified); // Convert modified date to timestamp
476 }
477
478 // Check if it's an archive
479 if (is_archive()) {
480 // For other archives
481 $archive_id = get_queried_object_id(); // Get the ID of the current archive
482 $archive = get_post($archive_id); // Get the archive post object
483 return strtotime($archive->post_modified); // Convert modified date to timestamp
484 }
485
486 // For other cases (fallback)
487 return false;
488 }
489
490 function bwp_is_gzip_supported() {
491 return function_exists('gzencode') && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false;
492 }
493
494 function bwp_cached_pages_count() {
495 $cache_directory = optifer_cache . DIRECTORY_SEPARATOR . 'html';
496 $cache_files = glob($cache_directory . DIRECTORY_SEPARATOR . "*.html");
497 return count($cache_files);
498 }
499
500 function bwp_wp_remote_get($url, $args = array()) {
501 // Default arguments
502 $defaults = array(
503 'headers' => array(
504 'User-Agent' => 'BerqWP Bot', // Customize user agent if needed
505 ),
506 );
507
508 // Merge provided arguments with defaults
509 $args = wp_parse_args($args, $defaults);
510
511 if (empty($args['timeout'])) {
512 $args['timeout'] = 30;
513 }
514
515 // Initialize cURL session
516 $ch = curl_init();
517
518 // Set the URL
519 curl_setopt($ch, CURLOPT_URL, $url);
520
521 // Set to return the transfer as a string
522 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
523
524 // Set timeout in seconds
525 curl_setopt($ch, CURLOPT_TIMEOUT, $args['timeout']);
526
527 // Set the user-agent
528 curl_setopt($ch, CURLOPT_USERAGENT, $args['headers']['User-Agent']);
529
530 // Include header in the output
531 curl_setopt($ch, CURLOPT_HEADER, true);
532
533 // Execute the request
534 $response = curl_exec($ch);
535
536 // Check for errors
537 if (curl_errno($ch)) {
538 $error_message = curl_error($ch);
539 curl_close($ch);
540 return new WP_Error('curl_error', $error_message);
541 }
542
543 // Close cURL session
544 curl_close($ch);
545
546 // Separate headers and body
547 list($headers, $body) = explode("\r\n\r\n", $response, 2);
548
549 // Parse headers into array
550 $header_lines = explode("\r\n", $headers);
551 $headers = array();
552 foreach ($header_lines as $line) {
553 $parts = explode(':', $line, 2);
554 if (count($parts) == 2) {
555 $headers[trim($parts[0])] = trim($parts[1]);
556 }
557 }
558
559 // Construct response array similar to wp_remote_get
560 $response = array(
561 'headers' => $headers,
562 'body' => $body,
563 'response' => array(
564 'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
565 'message' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
566 ),
567 'cookies' => array(),
568 'filename' => '',
569 );
570
571 return $response;
572 }
573
574 function bwp_is_openlitespeed_server() {
575 return isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false;
576 }
577
578 function verify_request_origin($request) {
579 // Check the referrer header to ensure the request is coming from the same site
580 $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
581 $site_url = get_site_url();
582
583 // Optionally, check the origin header
584 $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
585
586 // Ensure the request comes from the same site
587 if (strpos($referrer, $site_url) !== 0 && strpos($origin, $site_url) !== 0) {
588 return new WP_Error('rest_forbidden', esc_html__('You cannot access this resource.', 'searchpro'), array('status' => 403));
589 }
590
591 // Ensure the origin is a subdomain of berqwp.com
592 if (!preg_match('/^https?:\/\/([a-z0-9-]+\.)?berqwp\.com$/', $origin)) {
593 return new WP_Error('rest_forbidden', esc_html__('You cannot access this resource.', 'searchpro'), array('status' => 403));
594 }
595
596 return true;
597 }
598
599 function berq_rest_permission_callback(WP_REST_Request $request) {
600 // Get the nonce from the request
601 $nonce = $request->get_header('X-WP-Nonce');
602
603 // Verify the nonce
604 if (!wp_verify_nonce($nonce, 'wp_rest')) {
605 return new WP_Error('rest_invalid_nonce', __('Invalid nonce', 'searchpro'), array('status' => 403));
606 }
607
608 return true; // Return true to allow the request
609 }
610
611 function berq_rest_verify_license_callback(WP_REST_Request $request) {
612 $license_key_hash = sanitize_text_field($request->get_param('license_key_hash'));
613
614 if (empty($license_key_hash) || $license_key_hash !== md5(get_option('berqwp_license_key'))) {
615 global $berq_log;
616 $berq_log->error("Exiting... Invalid license key.");
617 return new WP_Error('rest_invalid_nonce', __('Invalid license key', 'searchpro'), array('status' => 403));
618
619 }
620
621 return true; // Return true to allow the request
622 }
623
624 function bwp_dash_notification($msg = '', $status = 'warning') {
625 ?>
626 <div class="berqwp-notification <?php echo esc_attr($status)?>">
627 <?php
628
629 echo "<div class='icon'>";
630 if ($status == 'warning') {
631 echo '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40 480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"/></svg>';
632 } elseif ($status == 'error') {
633 echo '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M256 0c53 0 96 43 96 96l0 3.6c0 15.7-12.7 28.4-28.4 28.4l-135.1 0c-15.7 0-28.4-12.7-28.4-28.4l0-3.6c0-53 43-96 96-96zM41.4 105.4c12.5-12.5 32.8-12.5 45.3 0l64 64c.7 .7 1.3 1.4 1.9 2.1c14.2-7.3 30.4-11.4 47.5-11.4l112 0c17.1 0 33.2 4.1 47.5 11.4c.6-.7 1.2-1.4 1.9-2.1l64-64c12.5-12.5 32.8-12.5 45.3 0s12.5 32.8 0 45.3l-64 64c-.7 .7-1.4 1.3-2.1 1.9c6.2 12 10.1 25.3 11.1 39.5l64.3 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-64 0c0 24.6-5.5 47.8-15.4 68.6c2.2 1.3 4.2 2.9 6 4.8l64 64c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0l-63.1-63.1c-24.5 21.8-55.8 36.2-90.3 39.6L272 240c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 239.2c-34.5-3.4-65.8-17.8-90.3-39.6L86.6 502.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l64-64c1.9-1.9 3.9-3.4 6-4.8C101.5 367.8 96 344.6 96 320l-64 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l64.3 0c1.1-14.1 5-27.5 11.1-39.5c-.7-.6-1.4-1.2-2.1-1.9l-64-64c-12.5-12.5-12.5-32.8 0-45.3z"/></svg>';
634 } elseif ($status == 'info') {
635 echo '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M96 64c0-17.7-14.3-32-32-32S32 46.3 32 64l0 256c0 17.7 14.3 32 32 32s32-14.3 32-32L96 64zM64 480a40 40 0 1 0 0-80 40 40 0 1 0 0 80z"/></svg>';
636 } else {
637 return;
638 }
639 echo "</div>";
640 echo esc_html($msg);
641 ?>
642 </div>
643 <?php
644 }
645
646 function bwp_can_warmup_cache($slug) {
647
648 if (get_transient( 'bwp_warmup_lock_'.md5($slug) ) === false) {
649
650 set_transient( 'bwp_warmup_lock_'.md5($slug), true, 100 );
651 return true;
652
653 }
654
655 return false;
656 }
657
658 function bwp_clear_warmup_lock($slug) {
659 delete_transient( 'bwp_warmup_lock_'.md5($slug) );
660 }
661
662 function bwp_extractUrlsFromCss($cssContent) {
663 $urls = [];
664 $pattern = '/url\((.*?)\)/i';
665
666 preg_match_all($pattern, $cssContent, $matches);
667
668 if (!empty($matches[1])) {
669 foreach ($matches[1] as $match) {
670 // Trim any surrounding quotes and whitespace
671 $urls[] = trim($match, '\'" ');
672 }
673 }
674
675 return $urls;
676 }
677
678 function bwp_getBaseUrl($fileUrl) {
679 // Parse the URL and get its components
680 $parsedUrl = parse_url($fileUrl);
681 $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] . '://' : '';
682 $host = isset($parsedUrl['host']) ? $parsedUrl['host'] : '';
683 $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
684
685 // Remove the file name from the path to get the base URL
686 $basePath = preg_replace('/\/[^\/]+$/', '/', $path);
687
688 // Construct the base URL
689 return $scheme . $host . $basePath;
690 }
691
692 function bwp_rel2abs($rel, $base)
693 {
694 /* return if already absolute URL */
695 if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;
696
697 /* queries and anchors */
698 if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;
699
700 /* parse base URL and convert to local variables:
701 $scheme, $host, $path */
702 extract(parse_url($base));
703
704 /* remove non-directory element from path */
705 $path = preg_replace('#/[^/]*$#', '', $path);
706
707 /* destroy path if relative url points to root */
708 if ($rel[0] == '/') $path = '';
709
710 /* dirty absolute URL */
711 $abs = "$host$path/$rel";
712
713 /* replace '//' or '/./' or '/foo/../' with '/' */
714 $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
715 for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}
716
717 /* absolute URL is ready! */
718 return $scheme.'://'.$abs;
719 }
720
721 function update_image_url_extension($image_url, $file_extension) {
722 $url_arr = explode('.', $image_url);
723 $last_index = count($url_arr) - 1;
724
725 // Extract the file extension
726 $current_file_extension = pathinfo($image_url, PATHINFO_EXTENSION);
727
728 $url_arr[$last_index] = str_replace("$current_file_extension", $file_extension, $url_arr[$last_index]);
729 $new_image_url = implode('.', $url_arr);
730
731 return $new_image_url;
732
733 }
734
735 if (!function_exists('str_contains')) {
736 function str_contains(string $haystack, string $needle): bool {
737 return strpos($haystack, $needle) !== false;
738 }
739 }
740
741 function bwp_check_rest_api($force_check = false) {
742 // Allow cache busting by passing $force_check = true
743 if ($force_check) {
744 delete_transient('berqwp_rest_api_status');
745 }
746
747 // Check if the result is cached
748 $cached_status = get_transient('berqwp_rest_api_status');
749
750 if ($cached_status && !$force_check) {
751 return $cached_status;
752 }
753
754 // Perform the actual REST API check
755 $response = wp_safe_remote_get( rest_url(), ['timeout' => 10] );
756
757 if ( is_wp_error( $response ) ) {
758 $result = array(
759 'status' => 'error',
760 'message' => 'The REST API is not working. Error: ' . $response->get_error_message(),
761 );
762 } else {
763 $status_code = wp_remote_retrieve_response_code( $response );
764
765 if ( $status_code == 200 ) {
766 $result = array(
767 'status' => 'success',
768 'message' => 'The REST API is working correctly.',
769 );
770 } else {
771 $result = array(
772 'status' => 'error',
773 'message' => 'The REST API returned an unexpected status code: ' . $status_code,
774 );
775 }
776 }
777
778 set_transient('berqwp_rest_api_status', $result, 60 * 60 * 24);
779
780 return $result;
781 }
782
783