get_configs(); $optimization_mode = get_option('berq_opt_mode'); if ($optimization_mode == 4) { $optimization_mode = 'aggressive'; } elseif ($optimization_mode == 3) { $optimization_mode = 'blaze'; } elseif ($optimization_mode == 2) { $optimization_mode = 'medium'; } elseif ($optimization_mode == 1) { $optimization_mode = 'basic'; } // Data to send as POST parameters $post_data = array( 'site_id' => $berqwp_configs['site_id'], 'license_key' => berqwp_get_license_key(), 'page_url' => $page_url, 'page_slug' => $page_slug, 'site_url' => home_url(), 'webp_max_width' => (int) get_option('berqwp_webp_max_width'), 'webp_quality' => (int) get_option('berqwp_webp_quality'), 'fluid_images' => get_option('berqwp_fluid_images'), 'enable_critical_css' => get_option('berqwp_enable_critical_css'), 'force_include_critical_css'=> get_option('berqwp_force_include_critical_css', []), 'exclude_css' => get_option('berqwp_exclude_css', []), 'exclude_js' => get_option('berqwp_exclude_js', []), 'exclude_third_party_js' => get_option('berqwp_exclude_third_party_js', []), 'async_excluded_styles' => get_option('berqwp_async_excluded_styles'), 'prerender_link' => get_option('berqwp_prerender_on_hover'), 'defer_excluded_js' => get_option('berqwp_defer_excluded_js'), 'delay_third_party_scripts' => get_option('berqwp_delay_third_party_scripts'), 'lazy_render' => get_option('berqwp_lazy_render'), 'img_lazyloading' => get_option('berqwp_image_lazyloading'), 'exclude_img_lazy_load' => get_option('berqwp_exclude_lazy_load_images', []), 'lazy_load_videos' => get_option('berqwp_lazy_load_videos'), 'youtube_lazyloading' => get_option('berqwp_lazyload_youtube_embed'), 'preload_yt_poster' => get_option('berqwp_preload_yt_poster'), 'js_mode' => get_option('berqwp_javascript_execution_mode'), 'key' => $key, // 'interaction_delay' => get_option('berqwp_interaction_delay'), 'use_cdn' => get_option('berqwp_enable_cdn'), 'opt_mode' => $optimization_mode, 'disable_webp' => !get_option('berqwp_enable_webp'), // 'js_css_exclude_urls' => get_option('berq_exclude_js_css', []), 'preload_fontfaces' => get_option('berqwp_preload_fontfaces'), 'enable_cwv' => get_option('berqwp_enable_cwv'), 'preload_cookiebanner' => get_option('berqwp_preload_cookiebanner'), 'css_optimization' => get_option('berq_css_optimization'), 'js_optimization' => get_option('berq_js_optimization'), 'exclude_cdn' => get_option('berq_exclude_cdn', []), 'webhook' => true, 'version' => BERQWP_VERSION ); if (!get_option('berqwp_can_use_fluid_images')) { $post_data['fluid_images'] = 0; } // if (defined('BERQ_STAGING')) { // $post_data['run_queue'] = 1; // $post_data['doing_queue'] = true; // } if ($page_url == home_url('/')) { $is_forced = true; } if ($is_forced) { $post_data['force'] = true; } return $post_data; } function bwp_pass_account_requirement() { global $berq_log; $berqWP = \berqWP::getInstance(); $license_key = berqwp_get_license_key(); if (empty($license_key)) { return false; } global $berq_log; // $berq_log->info("License key check from bwp_pass_account_requirement function."); $key_response = $berqWP->verify_license_key($license_key); if (empty($key_response->product_ref)) { return false; } if ($key_response->result !== 'success' || $key_response->status !== 'active') { // $berq_log->error("account requirement: license verification failed"); return false; } if ($key_response->product_ref == 'Free Account' && bwp_cached_pages_count() >= 10) { return false; } if ($key_response->product_ref == 'Starter' && bwp_cached_pages_count() >= 100) { return false; } return true; } function warmup_cache_by_url($page_url, $is_forced = false, $async = false) { if (!berqwp_can_use_cloud()) { return; } if (empty($page_url)) { return; } if (empty(berqwp_get_license_key())) { return; } if (berq_is_localhost() && !defined('BERQWP_ALLOW_LOCALHOST')) { return; } if (berq_is_localhost() && defined('BERQWP_ALLOW_LOCALHOST') && BERQWP_ALLOW_LOCALHOST === false) { return; } $page_url = strtolower($page_url); $parsed_site_url = wp_parse_url(home_url()); $parsed_page_url = wp_parse_url($page_url); if ($parsed_page_url['host'] !== $parsed_site_url['host']) { return; } // Avoid caching file URLs e.g .php // Allow .html if (berqwp_is_file_url($page_url)) { return; } // We don't want to cache page URL with query params if (strpos($page_url, '?') !== false) { return; } // Return if page url or page path (slug) is excluded if (!bwp_can_optimize_page_url($page_url)) { return; } global $berq_log; $berq_log->info('warming page: ' . $page_url); // Prepare post data for this page $post_data = berqwp_get_page_params($page_url, $is_forced); $berqwp = new BerqWP(get_option('berqwp_license_key'), null, optifer_cache); $timeout = 30; if ($async) { $timeout = 1; } $berqwp->request_cache($post_data, $timeout); } function bwp_is_home_cached() { $cache_directory = bwp_get_cache_dir(); $cache_file = $cache_directory . bwp_build_cache_path(bwp_admin_home_url('/')) . '/index.html.gz'; return file_exists($cache_file); } function bwp_cache_current_page() { global $bwp_current_page, $berq_log; // $berq_log->info('Shutdown hook fired.'); if (empty($bwp_current_page)) { return; } // Check if the current user is logged in or if it's a POST request if (is_user_logged_in() || $_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PURGE') { return; } if (is_admin()) { return; } if (defined('DOING_CRON') && DOING_CRON) { return; } if (defined('DOING_AJAX') && DOING_AJAX) { return; } if (defined('REST_REQUEST') && REST_REQUEST) { return; } if (php_sapi_name() === 'cli' || defined('WP_CLI')) { return; } if (!bwp_is_webpage()) { return; } if (!bwp_can_warmup_cache($bwp_current_page)) { return; } warmup_cache_by_url($bwp_current_page, false, false); $bwp_current_page = null; } function bwp_is_partial_cache($identifier) { $cache_directory = bwp_get_cache_dir(); $cache_key = md5($identifier); $cache_file = $cache_directory . $cache_key . '.html'; if (file_exists($cache_file)) { $buffer = file_get_contents($cache_file); if (!empty($buffer)) { $html = HtmlDomParser::str_get_html($buffer); if ($html !== false) { $style_tag = $html->find('style#berqwp-critical-css', 0); if ($style_tag === null) { return true; } } } } return false; } function berq_is_localhost() { $whitelist = array('127.0.0.1', '::1'); if (in_array($_SERVER['REMOTE_ADDR'], $whitelist)) { return true; } return false; } function berqwp_remove_ignore_params($slug) { // List of tracking parameters to remove $tracking_params = get_option('berq_ignore_urls_params', []); $tracking_params = apply_filters('berqwp_ignored_urls_params', $tracking_params); // Parse the provided slug $url_parts = parse_url($slug); // Get the current URL parameters $url_params = array(); if (isset($url_parts['query'])) { parse_str($url_parts['query'], $url_params); } // Remove specified tracking parameters from the URL foreach ($tracking_params as $param) { $param = trim($param); if (isset($url_params[$param])) { unset($url_params[$param]); } } // Build the new query string $new_query_string = http_build_query($url_params); // Reconstruct the URL with the new query string $updated_url = $url_parts['scheme'] . "://" . $url_parts['host'] . $url_parts['path']; if (!empty($new_query_string)) { $updated_url .= '?' . $new_query_string; } return $updated_url; } function berqwp_is_sub_dir_wp() { // // remove http // $site_url = explode('//', home_url())[1]; // $break_slash = explode('/', $site_url); // return count($break_slash) > 1; $site_url = site_url(); $home_url = home_url(); // Parse paths from URLs $site_path = @trim(parse_url($site_url, PHP_URL_PATH), '/'); $home_path = @trim(parse_url($home_url, PHP_URL_PATH), '/'); // Split paths into segments $site_segments = explode('/', $site_path); $home_segments = explode('/', $home_path); // Check if Site URL has any segments and is not empty if (!empty($site_path) && count($site_segments) > 0) { // If both paths are the same and contain at least one segment if ($site_path === $home_path && count($site_segments) > 0) { return true; // WordPress is in a subdirectory } } // Check if the Home URL has more segments than the Site URL if (count($home_segments) > 1) { return true; // Home URL indicates a subdirectory } return false; // Otherwise, it's likely not in a subdirectory } function berqwp_current_page_cache_file() { $slug_uri = $_SERVER['REQUEST_URI']; // if wordpress is installed in a sub directory if (berqwp_is_sub_dir_wp()) { // Parse strings to extract paths $path1 = explode('/', parse_url(home_url(), PHP_URL_PATH)); $path2 = explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)); // Find the common part of the paths $commonPath = implode('/', array_intersect($path1, $path2)); // Subtract the common part from the first string $slug_uri = str_replace($commonPath, '', $_SERVER['REQUEST_URI']); } // Return if page is excluded from cache $pages_to_exclude = get_option('berq_exclude_urls', []); if (in_array(get_site_url() . $slug_uri, $pages_to_exclude)) { return; } $slug = berqwp_remove_ignore_params($slug_uri); if (isset($_GET['creating_cache'])) { return; } if (get_option('berqwp_enable_sandbox') == 1 && isset($_GET['berqwp'])) { $slug = explode('?berqwp', $slug_uri)[0]; } elseif (get_option('berqwp_enable_sandbox') == 1 && !isset($_GET['creating_cache'])) { return; } // Attempt to retrieve the cached HTML from the cache directory $cache_directory = bwp_get_cache_dir(); // Generate a unique cache key based on the current page URL $cache_key = md5($slug); $cache_file = $cache_directory . $cache_key . '.html'; return $cache_file; } function berqwp_get_LCP_details($url, $device = 'mobile') { $google_pagespeed_api_url = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=$url&strategy=$device "; // Send a GET request to the Google PageSpeed Insights API // $response = wp_remote_get($google_pagespeed_api_url, array('timeout' => 60)); $response = bwp_wp_remote_get($google_pagespeed_api_url, array('timeout' => 60)); if (is_wp_error($response)) { return 'Error: ' . $response->get_error_message(); } // Convert the JSON response to a PHP array $body = wp_remote_retrieve_body($response); $output = json_decode($body, true); // Get the LCP data return $output['lighthouseResult']['audits']['largest-contentful-paint-element']['details']['items'][0]['items'][0]['node']; } function berqwp_enable_advanced_cache($status) { global $berq_log; // Get wp-config.php path $configFilePath = defined('BERQWP_WP_CONFIG') ? BERQWP_WP_CONFIG : ABSPATH . 'wp-config.php'; // Check if the file exists if (!file_exists($configFilePath)) { $berq_log->error("Error: wp-config.php does not exist."); return false; } // Check if the file is writable if (!is_writable($configFilePath)) { $berq_log->error("Error: wp-config.php is not writable. Check file permissions."); return false; } // Prepare the new WP_CACHE definition $newVal = sprintf("define( 'WP_CACHE', %s ); /* Added by BerqWP */\n", ($status ? "true" : "false")); $replacementVal = sprintf(" %s ", ($status ? "true" : "false")); // Read the file into an array of lines $lines = file($configFilePath); if ($lines === false || empty($lines)) { $berq_log->error("Error: Could not read wp-config.php or file is empty."); return false; } $wpCacheFound = false; $phpOpeningTagLine = false; // Process each line to update an existing WP_CACHE definition foreach ($lines as $lineIndex => &$line) { if (strpos($line, "") === false) { $phpOpeningTagLine = $lineIndex; } if (!$wpCacheFound && preg_match("/define\s*\(\s*['\"](.*?)['\"]\s*,(.*?)\)/", $line, $matches)) { if ($matches[1] === "WP_CACHE") { // Replace the existing WP_CACHE value with the new value $line = str_replace($matches[2], $replacementVal, $line); $wpCacheFound = true; } } // If we have found both the opening tag and WP_CACHE, we can stop processing further lines. if ($phpOpeningTagLine !== false && $wpCacheFound !== false) { break; } } unset($line); // If WP_CACHE was not found and we are enabling it, insert it after the PHP opening tag. if (!$wpCacheFound && $status) { if ($phpOpeningTagLine !== false) { array_splice($lines, $phpOpeningTagLine + 1, 0, [$newVal]); } else { // If no PHP opening tag is found, prepend a new one with the WP_CACHE definition. array_unshift($lines, "\n"); } } // Rebuild the file content $newContent = implode("", $lines); $tempFile = $configFilePath . '.tmp'; // Write to a temporary file first (atomic write) if (file_put_contents($tempFile, $newContent, LOCK_EX) === false) { $berq_log->error("Error: Could not write to temporary file: $tempFile"); return false; } // Rename the temporary file to wp-config.php if (!rename($tempFile, $configFilePath)) { $berq_log->error("Error: Could not rename temporary file to wp-config.php"); unlink($tempFile); return false; } $berq_log->info("wp-config.php updated successfully."); return true; } // Copied from Nginx Helper plugin // function berqwp_unlink_recursive($dir) // { // if (!is_dir($dir)) { // return; // } // $dh = opendir($dir); // if (!$dh) { // return; // } // // phpcs:ignore -- WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition -- Variable assignment required for recursion. // while (false !== ($obj = readdir($dh))) { // if ('.' === $obj || '..' === $obj) { // continue; // } // if (!@unlink($dir . '/' . $obj)) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged // berqwp_unlink_recursive($dir . '/' . $obj, false); // } // } // closedir($dh); // } function berqwp_unlink_recursive($dir) { if (!is_dir($dir)) { return false; } $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($files as $file) { if ($file->isFile()) { if (!unlink($file->getRealPath())) { error_log("Failed to delete file: " . $file->getRealPath()); } } elseif ($file->isDir()) { if (!rmdir($file->getRealPath())) { error_log("Failed to delete directory: " . $file->getRealPath()); } } } return rmdir($dir); // remove the root directory itself } function berqwp_get_last_modified_timestamp() { global $post; // Check if it's a single post or page if (is_singular()) { return get_the_modified_time('U', $post->ID); // 'U' format parameter returns Unix timestamp } // Check if it's a taxonomy term if (is_tax() || is_category() || is_tag()) { $term = get_queried_object(); // Get the current term object // For tags, get the last modified date of the most recent post associated with the tag if (is_tag()) { $args = array( 'tag_id' => $term->term_id, 'posts_per_page' => 1, 'orderby' => 'modified', 'order' => 'DESC', 'fields' => 'ids', // Return only post IDs to reduce overhead ); $posts = get_posts($args); if ($posts) { $latest_post_id = $posts[0]; return get_the_modified_time('U', $latest_post_id); // 'U' format parameter returns Unix timestamp } } // For category archives, get the last modified date of the most recent post within the category if (is_category()) { $args = array( 'category' => $term->term_id, 'posts_per_page' => 1, 'orderby' => 'modified', 'order' => 'DESC', 'fields' => 'ids', // Return only post IDs to reduce overhead ); $posts = get_posts($args); if ($posts) { $latest_post_id = $posts[0]; return get_the_modified_time('U', $latest_post_id); // 'U' format parameter returns Unix timestamp } } return strtotime($term->modified); // Convert modified date to timestamp } // Check if it's an archive if (is_archive()) { // For other archives $archive_id = get_queried_object_id(); // Get the ID of the current archive $archive = get_post($archive_id); // Get the archive post object return strtotime($archive->post_modified); // Convert modified date to timestamp } // For other cases (fallback) return false; } function bwp_is_gzip_supported() { return function_exists('gzencode') && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false; } // function bwp_cached_pages_count() // { // $cache_directory = bwp_get_cache_dir(); // $cache_files = glob($cache_directory . "*.gz"); // return is_array($cache_files) ? count($cache_files) : 0; // } function bwp_cached_pages_count() { $cache_directory = bwp_get_cache_dir(); if (!is_dir($cache_directory)) { return 0; } $count = 0; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($cache_directory, FilesystemIterator::SKIP_DOTS) ); foreach ($iterator as $file) { if ($file->isFile() && str_ends_with($file->getFilename(), '.gz')) { $count++; } } return $count; } function bwp_wp_remote_get($url, $args = array()) { // Default arguments $defaults = array( 'headers' => array( 'User-Agent' => 'BerqWP Bot', // Customize user agent if needed ), ); // Merge provided arguments with defaults $args = wp_parse_args($args, $defaults); if (empty($args['timeout'])) { $args['timeout'] = 30; } // Initialize cURL session $ch = curl_init(); // Set the URL curl_setopt($ch, CURLOPT_URL, $url); // Set to return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Set timeout in seconds curl_setopt($ch, CURLOPT_TIMEOUT, $args['timeout']); // Set the user-agent curl_setopt($ch, CURLOPT_USERAGENT, $args['headers']['User-Agent']); // Include header in the output curl_setopt($ch, CURLOPT_HEADER, true); // Execute the request $response = curl_exec($ch); // Check for errors if (curl_errno($ch)) { $error_message = curl_error($ch); curl_close($ch); return new WP_Error('curl_error', $error_message); } // Close cURL session curl_close($ch); // Separate headers and body list($headers, $body) = explode("\r\n\r\n", $response, 2); // Parse headers into array $header_lines = explode("\r\n", $headers); $headers = array(); foreach ($header_lines as $line) { $parts = explode(':', $line, 2); if (count($parts) == 2) { $headers[trim($parts[0])] = trim($parts[1]); } } // Construct response array similar to wp_remote_get $response = array( 'headers' => $headers, 'body' => $body, 'response' => array( 'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE), 'message' => curl_getinfo($ch, CURLINFO_HTTP_CODE), ), 'cookies' => array(), 'filename' => '', ); return $response; } function bwp_is_openlitespeed_server() { $is_litespeed = false; $is_litespeed = isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false; $headers = getallheaders(); foreach ($headers as $header => $value) { if (stripos($value, 'LiteSpeed') !== false) { $is_litespeed = true; } } return $is_litespeed; } function verify_request_origin($request) { // Check the referrer header to ensure the request is coming from the same site $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; $site_url = get_site_url(); // Optionally, check the origin header $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : ''; // Ensure the request comes from the same site if (strpos($referrer, $site_url) !== 0 && strpos($origin, $site_url) !== 0) { return new WP_Error('rest_forbidden', esc_html__('You cannot access this resource.', 'searchpro'), array('status' => 403)); } // Ensure the origin is a subdomain of berqwp.com if (!preg_match('/^https?:\/\/([a-z0-9-]+\.)?berqwp\.com$/', $origin)) { return new WP_Error('rest_forbidden', esc_html__('You cannot access this resource.', 'searchpro'), array('status' => 403)); } return true; } function berq_rest_permission_callback(WP_REST_Request $request) { // Get the nonce from the request $nonce = $request->get_header('X-WP-Nonce'); $hash = $request->get_header('X-berqwp-key-hash'); if ($hash == md5(berqwp_get_license_key())) { return true; } // Verify the nonce if (!wp_verify_nonce($nonce, 'wp_rest')) { return new WP_Error('rest_invalid_nonce', __('Invalid nonce', 'searchpro'), array('status' => 403)); } return true; // Return true to allow the request } function berq_rest_verify_license_callback(WP_REST_Request $request) { $license_key_hash = sanitize_text_field($request->get_param('license_key_hash')); $license_key = berqwp_get_license_key(); if (empty($license_key_hash) || empty($license_key) || $license_key_hash !== md5($license_key)) { global $berq_log; $berq_log->error("Exiting... Invalid license key."); return new WP_Error('rest_invalid_nonce', __('Invalid license key', 'searchpro'), array('status' => 403)); } return true; // Return true to allow the request } function bwp_dash_notification($msg = '', $status = 'warning') { ?>
' . esc_html($logs) . ''; exit; } } function bwp_cf_flush_all() { if (!empty(get_option('berqwp_cf_creden'))) { $email = get_option('berqwp_cf_creden')['email']; $apitoken = get_option('berqwp_cf_creden')['apitoken']; $zoneid = get_option('berqwp_cf_creden')['zoneid']; $berqCloudflareAPIHandler = new berqCloudflareAPIHandler($email, $apitoken, $zoneid); $berqCloudflareAPIHandler->purge_all_cache(); } } function bwp_cf_flush_page($url) { if (!empty(get_option('berqwp_cf_creden'))) { $email = get_option('berqwp_cf_creden')['email']; $apitoken = get_option('berqwp_cf_creden')['apitoken']; $zoneid = get_option('berqwp_cf_creden')['zoneid']; $berqCloudflareAPIHandler = new berqCloudflareAPIHandler($email, $apitoken, $zoneid); $berqCloudflareAPIHandler->flush_url($url); } } function bwp_cf_delete_rules() { if (!empty(get_option('berqwp_cf_creden'))) { $email = get_option('berqwp_cf_creden')['email']; $apitoken = get_option('berqwp_cf_creden')['apitoken']; $zoneid = get_option('berqwp_cf_creden')['zoneid']; $berqCloudflareAPIHandler = new berqCloudflareAPIHandler($email, $apitoken, $zoneid); $berqCloudflareAPIHandler->delete_rule_by_description('BerqWP cache rules'); } } function bwp_lock_cache_directory() { $cache_dir = optifer_cache; if (!file_exists($cache_dir)) { wp_mkdir_p($cache_dir); } $rules = <<