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

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