| @@ -224,8 +224,9 @@ | ||
| 224 | 224 | "/embed", |
| 225 | 225 | "/view-order/", |
| 226 | 226 | "/redirect/", |
| 227 | 227 | "/elementskit-content/", |
| 228 | + "/checkout/", | |
| 228 | 229 | ]; |
| 229 | 230 | |
| 230 | 231 | $exclude_items = apply_filters('berqwp_exclude_slug_match', $exclude_items); |
| 231 | 232 | |
| @@ -237,8 +238,52 @@ | ||
| 237 | 238 | |
| 238 | 239 | return false; |
| 239 | 240 | } |
| 240 | 241 | |
| 242 | + | |
| 243 | +function berqwp_home_url() { | |
| 244 | + return untrailingslashit(apply_filters('berqwp_site_url', home_url())); | |
| 245 | +} | |
| 246 | + | |
| 247 | +function bwp_canonicalize_page_url($url) { | |
| 248 | + $permalink_structure = get_option('permalink_structure'); | |
| 249 | + | |
| 250 | + if (!$permalink_structure) { | |
| 251 | + return $url; | |
| 252 | + } | |
| 253 | + | |
| 254 | + $path = parse_url($url, PHP_URL_PATH) ?? '/'; | |
| 255 | + | |
| 256 | + if ($path === '/') { | |
| 257 | + return $url; | |
| 258 | + } | |
| 259 | + | |
| 260 | + $uses_trailing_slash = substr(rtrim($permalink_structure), -1) === '/'; | |
| 261 | + $has_trailing_slash = substr($path, -1) === '/'; | |
| 262 | + | |
| 263 | + if ($uses_trailing_slash && !$has_trailing_slash) { | |
| 264 | + return trailingslashit($url); | |
| 265 | + } | |
| 266 | + | |
| 267 | + if (!$uses_trailing_slash && $has_trailing_slash) { | |
| 268 | + return untrailingslashit($url); | |
| 269 | + } | |
| 270 | + | |
| 271 | + return $url; | |
| 272 | +} | |
| 273 | + | |
| 274 | +function bwp_sync_permalink_config() { | |
| 275 | + $permalink_structure = get_option('permalink_structure'); | |
| 276 | + $trailing_slash = empty($permalink_structure) ? null : (substr(rtrim($permalink_structure), -1) === '/'); | |
| 277 | + | |
| 278 | + $berqconfigs = berqConfigs::getInstance(); | |
| 279 | + $current = $berqconfigs->get_configs(); | |
| 280 | + | |
| 281 | + if ($current === false || !array_key_exists('permalink_trailing_slash', $current) || $current['permalink_trailing_slash'] !== $trailing_slash) { | |
| 282 | + $berqconfigs->update_configs(['permalink_trailing_slash' => $trailing_slash]); | |
| 283 | + } | |
| 284 | +} | |
| 285 | + | |
| 241 | 286 | function berqwp_get_page_params($page_url, $is_forced = false) |
| 242 | 287 | { |
| 243 | 288 | |
| 244 | 289 | if (empty($page_url)) { |
| @@ -261,8 +306,10 @@ | ||
| 261 | 306 | } elseif ($optimization_mode == 1) { |
| 262 | 307 | $optimization_mode = 'basic'; |
| 263 | 308 | } |
| 264 | 309 | |
| 310 | + $home_url = berqwp_home_url(); | |
| 311 | + | |
| 265 | 312 | // Data to send as POST parameters |
| 266 | 313 | $post_data = array( |
| 267 | 314 | 'site_id' => $berqwp_configs['site_id'], |
| 268 | 315 | 'license_key' => berqwp_get_license_key(), |
| @@ -267,13 +314,14 @@ | ||
| 267 | 314 | 'site_id' => $berqwp_configs['site_id'], |
| 268 | 315 | 'license_key' => berqwp_get_license_key(), |
| 269 | 316 | 'page_url' => $page_url, |
| 270 | 317 | 'page_slug' => $page_slug, |
| 271 | - 'site_url' => home_url(), | |
| 318 | + 'site_url' => $home_url, | |
| 272 | 319 | 'webp_max_width' => (int) get_option('berqwp_webp_max_width'), |
| 273 | 320 | 'webp_quality' => (int) get_option('berqwp_webp_quality'), |
| 274 | 321 | 'fluid_images' => get_option('berqwp_fluid_images'), |
| 275 | 322 | 'enable_critical_css' => get_option('berqwp_enable_critical_css'), |
| 323 | + 'enable_used_css' => get_option('berqwp_enable_used_css'), | |
| 276 | 324 | 'force_include_critical_css'=> get_option('berqwp_force_include_critical_css', []), |
| 277 | 325 | 'exclude_css' => get_option('berqwp_exclude_css', []), |
| 278 | 326 | 'exclude_js' => get_option('berqwp_exclude_js', []), |
| 279 | 327 | 'exclude_third_party_js' => get_option('berqwp_exclude_third_party_js', []), |
| @@ -1300,9 +1348,9 @@ | ||
| 1300 | 1348 | |
| 1301 | 1349 | function bwp_sluguri_into_path($slug_uri) |
| 1302 | 1350 | { |
| 1303 | 1351 | $is_multisite = function_exists('is_multisite') && is_multisite(); |
| 1304 | - $home_path = parse_url(home_url(), PHP_URL_PATH); | |
| 1352 | + $home_path = parse_url(berqwp_home_url(), PHP_URL_PATH); | |
| 1305 | 1353 | |
| 1306 | 1354 | // if (berqwp_is_sub_dir_wp() && !$is_multisite) { |
| 1307 | 1355 | if (!$is_multisite && $home_path !== null) { |
| 1308 | 1356 | // Parse strings to extract paths |
| @@ -1323,9 +1371,9 @@ | ||
| 1323 | 1371 | { |
| 1324 | 1372 | $parsed_url = parse_url($url); |
| 1325 | 1373 | $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; |
| 1326 | 1374 | $query = isset($parsed_url['query']) ? $parsed_url['query'] : ''; |
| 1327 | - $homeurl = home_url(); | |
| 1375 | + $homeurl = berqwp_home_url(); | |
| 1328 | 1376 | |
| 1329 | 1377 | if (!empty($query)) { |
| 1330 | 1378 | $path = $path . '?' . $query; |
| 1331 | 1379 | } |
| @@ -1449,9 +1497,9 @@ | ||
| 1449 | 1497 | // Set the number of posts per batch to handle |
| 1450 | 1498 | $posts_per_page = 10000; // Adjust this based on server capacity |
| 1451 | 1499 | |
| 1452 | 1500 | // Get current page from query string (for pagination) |
| 1453 | - $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1; | |
| 1501 | + $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1; | |
| 1454 | 1502 | |
| 1455 | 1503 | // Build the query arguments with pagination |
| 1456 | 1504 | $args = array( |
| 1457 | 1505 | 'post_type' => $post_types, |
| @@ -1880,8 +1928,16 @@ | ||
| 1880 | 1928 | if (!file_exists($cache_dir)) { |
| 1881 | 1929 | wp_mkdir_p($cache_dir); |
| 1882 | 1930 | } |
| 1883 | 1931 | |
| 1932 | + if (!function_exists('got_mod_rewrite')) { | |
| 1933 | + require_once ABSPATH . 'wp-admin/includes/misc.php'; | |
| 1934 | + } | |
| 1935 | + | |
| 1936 | + if (!got_mod_rewrite()) { | |
| 1937 | + return; | |
| 1938 | + } | |
| 1939 | + | |
| 1884 | 1940 | $rules = <<<HTACCESS |
| 1885 | 1941 | Order allow,deny |
| 1886 | 1942 | Deny from all |
| 1887 | 1943 | |
| @@ -1907,10 +1963,31 @@ | ||
| 1907 | 1963 | $index_stub = $cache_dir . 'index.php'; |
| 1908 | 1964 | if (!file_exists($index_stub)) { |
| 1909 | 1965 | file_put_contents($index_stub, '<?php // Silence is golden'); |
| 1910 | 1966 | } |
| 1967 | + | |
| 1911 | 1968 | } |
| 1912 | 1969 | |
| 1970 | +function bwp_delete_php_files_in_cache() | |
| 1971 | +{ | |
| 1972 | + $cache_dir = optifer_cache; | |
| 1973 | + if (!is_dir($cache_dir)) { | |
| 1974 | + return; | |
| 1975 | + } | |
| 1976 | + | |
| 1977 | + $php_extensions = ['php', 'php3', 'php4', 'php5', 'php7', 'php8', 'phtml', 'phar']; | |
| 1978 | + | |
| 1979 | + $iterator = new RecursiveIteratorIterator( | |
| 1980 | + new RecursiveDirectoryIterator($cache_dir, RecursiveDirectoryIterator::SKIP_DOTS) | |
| 1981 | + ); | |
| 1982 | + | |
| 1983 | + foreach ($iterator as $file) { | |
| 1984 | + if ($file->isFile() && in_array(strtolower($file->getExtension()), $php_extensions, true)) { | |
| 1985 | + @unlink($file->getRealPath()); | |
| 1986 | + } | |
| 1987 | + } | |
| 1988 | +} | |
| 1989 | + | |
| 1913 | 1990 | function bwp_write_htaccess_rules($ignore_sandbox = false) |
| 1914 | 1991 | { |
| 1915 | 1992 | if (!got_mod_rewrite() || bwp_is_openlitespeed_server()) { |
| 1916 | 1993 | return; |
| @@ -1920,9 +1997,20 @@ | ||
| 1920 | 1997 | return; |
| 1921 | 1998 | } |
| 1922 | 1999 | |
| 1923 | 2000 | $htaccess = get_home_path() . '.htaccess'; |
| 1924 | - $rules = [ | |
| 2001 | + $cache_tag_host = parse_url(home_url(), PHP_URL_HOST); | |
| 2002 | + | |
| 2003 | + // Match the cache-serving RewriteCond to the site's actual permalink convention, | |
| 2004 | + // so caching works whether the site uses trailing slashes or not. | |
| 2005 | + $permalink_structure = get_option('permalink_structure'); | |
| 2006 | + $uses_trailing_slash = empty($permalink_structure) || substr(rtrim($permalink_structure), -1) === '/'; | |
| 2007 | + | |
| 2008 | + $slash_conds = $uses_trailing_slash | |
| 2009 | + ? [' RewriteCond %{REQUEST_URI} /$'] | |
| 2010 | + : [' RewriteCond %{REQUEST_URI} ^/$ [OR]', ' RewriteCond %{REQUEST_URI} !/$']; | |
| 2011 | + | |
| 2012 | + $rules = array_merge([ | |
| 1925 | 2013 | '<IfModule mod_rewrite.c>', |
| 1926 | 2014 | ' RewriteEngine On', |
| 1927 | 2015 | ' RewriteCond %{REQUEST_METHOD} !POST', |
| 1928 | 2016 | ' RewriteCond %{QUERY_STRING} ^$', |
| @@ -1927,8 +2015,9 @@ | ||
| 1927 | 2015 | ' RewriteCond %{REQUEST_METHOD} !POST', |
| 1928 | 2016 | ' RewriteCond %{QUERY_STRING} ^$', |
| 1929 | 2017 | ' RewriteCond %{HTTP_COOKIE} !(wp\-postpass|wordpress_logged_in|comment_author|woocommerce_cart_hash|edd_items_in_cart) [NC]', |
| 1930 | 2018 | ' RewriteCond %{HTTP_USER_AGENT} !(Googlebot|Google-InspectionTool|Bingbot|Slurp|DuckDuckBot|Baiduspider|YandexBot|Sogou|Exabot|facebookexternalhit|Twitterbot|LinkedInBot|WhatsApp|TelegramBot|Applebot|AhrefsBot|SemrushBot|MJ12bot|DotBot|PetalBot|BLEXBot|archive\.org_bot|UptimeRobot|Pingdom|ChatGPT-User|GPTBot|ClaudeBot|Bytespider) [NC]', |
| 2019 | + ], $slash_conds, [ | |
| 1931 | 2020 | ' RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/berqwp/html/%{HTTP_HOST}%{REQUEST_URI}/index.html.gz -f', |
| 1932 | 2021 | ' RewriteRule .* /wp-content/cache/berqwp/html/%{HTTP_HOST}%{REQUEST_URI}/index.html.gz [L]', |
| 1933 | 2022 | '</IfModule>', |
| 1934 | 2023 | '<IfModule mod_mime.c>', |
| @@ -1934,8 +2023,9 @@ | ||
| 1934 | 2023 | '<IfModule mod_mime.c>', |
| 1935 | 2024 | ' <FilesMatch "index\.html\.gz$">', |
| 1936 | 2025 | ' ForceType text/html', |
| 1937 | 2026 | ' AddEncoding gzip .gz', |
| 2027 | + ' AddDefaultCharset utf-8', | |
| 1938 | 2028 | ' </FilesMatch>', |
| 1939 | 2029 | '</IfModule>', |
| 1940 | 2030 | '<IfModule mod_headers.c>', |
| 1941 | 2031 | ' <FilesMatch "index\.html\.gz$">', |
| @@ -1944,9 +2034,9 @@ | ||
| 1944 | 2034 | ' Header set Content-Encoding "gzip"', |
| 1945 | 2035 | ' Header set Vary "Accept-Encoding, Cookie"', |
| 1946 | 2036 | ' Header set CDN-Cache-Control "max-age=2592000"', |
| 1947 | 2037 | ' Header set Cache-Control "public, max-age=600, s-maxage=2592000, stale-while-revalidate=86400"', |
| 1948 | - ' Header set Cache-Tag "%{HTTP_HOST}e"', | |
| 2038 | + ' Header set Cache-Tag "' . $cache_tag_host . '"', | |
| 1949 | 2039 | ' Header set X-Content-Type-Options "nosniff"', |
| 1950 | 2040 | ' </FilesMatch>', |
| 1951 | 2041 | '</IfModule>', |
| 1952 | 2042 | '<IfModule mod_expires.c>', |
| @@ -1979,9 +2069,9 @@ | ||
| 1979 | 2069 | ' Header set Cache-Control "public, max-age=31536000, immutable"', |
| 1980 | 2070 | ' Header set Access-Control-Allow-Origin "*"', |
| 1981 | 2071 | ' </FilesMatch>', |
| 1982 | 2072 | '</IfModule>', |
| 1983 | - ]; | |
| 2073 | + ]); | |
| 1984 | 2074 | |
| 1985 | 2075 | // Must appear before the WordPress block so Apache processes it first |
| 1986 | 2076 | $marker = 'BerqWP Cache'; |
| 1987 | 2077 | $start = "# BEGIN $marker"; |
| @@ -2157,8 +2247,40 @@ | ||
| 2157 | 2247 | // Fallback: no <head> tag found, return unchanged |
| 2158 | 2248 | return $buffer; |
| 2159 | 2249 | } |
| 2160 | 2250 | |
| 2251 | +function berqwp_earlyHeadHtml($buffer, $htmlToInsert) | |
| 2252 | +{ | |
| 2253 | + // Locate <head> opening tag | |
| 2254 | + if (!preg_match('/<head(\s[^>]*)?>/i', $buffer, $headMatch, PREG_OFFSET_CAPTURE)) { | |
| 2255 | + return berqwp_prependHtmlToHead($buffer, $htmlToInsert); | |
| 2256 | + } | |
| 2257 | + | |
| 2258 | + $headStart = $headMatch[0][1] + strlen($headMatch[0][0]); | |
| 2259 | + | |
| 2260 | + // Bound the search to content inside <head>...</head> | |
| 2261 | + $headEndPos = stripos($buffer, '</head>', $headStart); | |
| 2262 | + if ($headEndPos === false) { | |
| 2263 | + return berqwp_prependHtmlToHead($buffer, $htmlToInsert); | |
| 2264 | + } | |
| 2265 | + | |
| 2266 | + $headContent = substr($buffer, $headStart, $headEndPos - $headStart); | |
| 2267 | + | |
| 2268 | + // Find first <script, <link, or <style in the head | |
| 2269 | + // if (preg_match('/<(script|link|style)[\s>\/]/i', $headContent, $tagMatch, PREG_OFFSET_CAPTURE)) { | |
| 2270 | + | |
| 2271 | + $regex = "/<(script|link[^>]+rel=['\"]+(modulepreload|stylesheet|preload)['\"]|style)[\s>\/]/i"; | |
| 2272 | + | |
| 2273 | + if (preg_match($regex, $headContent, $tagMatch, PREG_OFFSET_CAPTURE)) { | |
| 2274 | + $insertPos = $headStart + $tagMatch[0][1]; | |
| 2275 | + return substr_replace($buffer, $htmlToInsert . PHP_EOL, $insertPos, 0); | |
| 2276 | + } | |
| 2277 | + | |
| 2278 | + // Fallback: no matching tag in head | |
| 2279 | + return berqwp_prependHtmlToHead($buffer, $htmlToInsert); | |
| 2280 | +} | |
| 2281 | + | |
| 2282 | + | |
| 2161 | 2283 | function berqwp_setup_dropin() |
| 2162 | 2284 | { |
| 2163 | 2285 | if (defined('BERQWP_ADVANCED_CACHE_PATH')) { |
| 2164 | 2286 | $adv_cache_path = BERQWP_ADVANCED_CACHE_PATH; |
| @@ -2330,9 +2452,9 @@ | ||
| 2330 | 2452 | } |
| 2331 | 2453 | |
| 2332 | 2454 | function bwp_remove_recently_optimized_entry($page_url) |
| 2333 | 2455 | { |
| 2334 | - if (empty($page_url)) return; | |
| 2456 | + if (empty($page_url)) return; | |
| 2335 | 2457 | |
| 2336 | 2458 | $log = json_decode(get_option('berqwp_recently_optimized', '[]'), true); |
| 2337 | 2459 | if (!is_array($log)) return; |
| 2338 | 2460 | |
| @@ -2345,5 +2467,12 @@ | ||
| 2345 | 2467 | $configs = $berqconfigs->get_configs(); |
| 2346 | 2468 | $license_key = berqwp_get_license_key(); |
| 2347 | 2469 | |
| 2348 | 2470 | return !empty($configs['site_id']) && !empty($configs['secret']) && !empty($configs['optimization_method']) && $configs['optimization_method'] == 'cloud' && !empty($license_key); |
| 2471 | +} | |
| 2472 | + | |
| 2473 | +function berqwp_generate_site_id() { | |
| 2474 | + $blog_id = get_current_blog_id(); | |
| 2475 | + $network_id = function_exists('get_current_network_id') ? get_current_network_id() : 1; | |
| 2476 | + $siteurl = get_option('siteurl'); | |
| 2477 | + return md5("berqwp|$network_id|$blog_id|$siteurl"); | |
| 2349 | 2478 | } |