$server, 'is_nginx' => $is_ng, 'exists' => $exists, 'writable' => $write, 'supported' => ! $is_ng && $exists, 'active' => $browser_active, 'page_cache_active' => $page_cache_active, 'webp_active' => $webp_active, ); } /** * Build Apache / LiteSpeed static asset caching & deflate rules. */ public static function get_rules() { return array( '', ' ExpiresActive On', ' ExpiresDefault "access plus 1 month"', ' ExpiresByType text/html "access plus 0 seconds"', ' ExpiresByType text/xml "access plus 0 seconds"', ' ExpiresByType application/xml "access plus 0 seconds"', ' ExpiresByType application/json "access plus 0 seconds"', ' ExpiresByType text/css "access plus 1 year"', ' ExpiresByType text/javascript "access plus 1 year"', ' ExpiresByType application/javascript "access plus 1 year"', ' ExpiresByType application/x-javascript "access plus 1 year"', ' ExpiresByType image/jpeg "access plus 1 year"', ' ExpiresByType image/png "access plus 1 year"', ' ExpiresByType image/gif "access plus 1 year"', ' ExpiresByType image/webp "access plus 1 year"', ' ExpiresByType image/avif "access plus 1 year"', ' ExpiresByType image/svg+xml "access plus 1 year"', ' ExpiresByType image/x-icon "access plus 1 year"', ' ExpiresByType font/woff2 "access plus 1 year"', ' ExpiresByType font/woff "access plus 1 year"', ' ExpiresByType font/ttf "access plus 1 year"', ' ExpiresByType font/otf "access plus 1 year"', ' ExpiresByType application/font-woff2 "access plus 1 year"', ' ExpiresByType application/font-woff "access plus 1 year"', '', '', ' ', ' Header set Cache-Control "public, max-age=31536000"', ' ', ' Header append Vary Accept-Encoding', '', '', ' AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript application/json application/xml application/rss+xml image/svg+xml font/ttf font/otf', '', ); } /** * Build Zero-PHP Direct Disk Page Cache mod_rewrite block (must precede # BEGIN WordPress). */ public static function build_page_cache_block( $options = null ) { if ( ! is_array( $options ) ) { $options = get_option( 'aio_options', array() ); } $upload_dir = wp_upload_dir(); $norm_abspath = trailingslashit( wp_normalize_path( ABSPATH ) ); $norm_cache = trailingslashit( wp_normalize_path( $upload_dir['basedir'] ) ) . 'aio-cache'; if ( strpos( $norm_cache, $norm_abspath ) !== 0 ) { return ''; } $rel_cache = ltrim( substr( $norm_cache, strlen( $norm_abspath ) ), '/' ); $home_sub = trim( (string) wp_parse_url( home_url(), PHP_URL_PATH ), '/' ); $uri_base = $home_sub !== '' ? '/' . preg_replace( '/[^A-Za-z0-9\/_.-]/', '', $home_sub ) : ''; $ignore_tracking = ! isset( $options['optCacheIgnoreTracking'] ) || ! empty( $options['optCacheIgnoreTracking'] ); $qs_cond = $ignore_tracking ? ' RewriteCond %{QUERY_STRING} ^(?:&*(?:utm_(?:source|medium|campaign|term|content|id)|fbclid|gclid|dclid|msclkid|ttclid|twclid|yclid|zarsrc|_ga|_gl|mc_cid|mc_eid)=[^&]*)*$ [NC]' : ' RewriteCond %{QUERY_STRING} ^$'; $cookies = array( 'wordpress_logged_in_', 'wp-postpass_', 'woocommerce_items_in_cart', 'wp_woocommerce_session_', 'aio_maint_bypass', 'comment_author_', ); if ( ! empty( $options['optCacheExcludeCookies'] ) ) { foreach ( preg_split( '/[\r\n]+/', (string) $options['optCacheExcludeCookies'] ) as $c ) { $clean_c = preg_replace( '/[^A-Za-z0-9_-]/', '', trim( $c ) ); if ( $clean_c !== '' ) { $cookies[] = $clean_c; } } } $cookie_cond = ' RewriteCond %{HTTP_COOKIE} !(' . implode( '|', array_unique( $cookies ) ) . ') [NC]'; $uri_exclude_lines = array(); if ( ! empty( $options['optCacheExcludeUrls'] ) ) { foreach ( preg_split( '/[\r\n]+/', (string) $options['optCacheExcludeUrls'] ) as $u ) { $clean_u = preg_replace( '/[^A-Za-z0-9\/_.-]/', '', trim( $u ) ); if ( $clean_u !== '' ) { $uri_exclude_lines[] = ' RewriteCond %{REQUEST_URI} !' . preg_quote( $clean_u, '#' ) . ' [NC]'; } } } $common_conds = array_merge( array( ' RewriteCond %{REQUEST_METHOD} ^GET$', $qs_cond, $cookie_cond, ), $uri_exclude_lines ); $lines = array( '# BEGIN ' . self::PAGE_CACHE_MARKER, '', ' RewriteEngine On', ' # Serve pre-compressed HTTPS .html.gz directly from disk (0ms PHP)', ' RewriteCond %{HTTPS} =on [OR]', ' RewriteCond %{HTTP:X-Forwarded-Proto} =https', ); $lines = array_merge( $lines, $common_conds, array( ' RewriteCond %{HTTP:Accept-Encoding} gzip [NC]', ' RewriteCond "' . $norm_cache . '/https-%{HTTP_HOST}' . $uri_base . '/$1/index.html.gz" -f', ' RewriteRule ^(.*?)/?$ ' . $rel_cache . '/https-%{HTTP_HOST}' . $uri_base . '/$1/index.html.gz [L,E=AIO_HIT:SERVER-GZIP]', '', ' # Serve pre-compressed HTTP .html.gz directly from disk (0ms PHP)', ' RewriteCond %{HTTPS} !=on', ' RewriteCond %{HTTP:X-Forwarded-Proto} !=https', ), $common_conds, array( ' RewriteCond %{HTTP:Accept-Encoding} gzip [NC]', ' RewriteCond "' . $norm_cache . '/http-%{HTTP_HOST}' . $uri_base . '/$1/index.html.gz" -f', ' RewriteRule ^(.*?)/?$ ' . $rel_cache . '/http-%{HTTP_HOST}' . $uri_base . '/$1/index.html.gz [L,E=AIO_HIT:SERVER-GZIP]', '', ' # Serve static HTTPS .html directly from disk', ' RewriteCond %{HTTPS} =on [OR]', ' RewriteCond %{HTTP:X-Forwarded-Proto} =https', ), $common_conds, array( ' RewriteCond "' . $norm_cache . '/https-%{HTTP_HOST}' . $uri_base . '/$1/index.html" -f', ' RewriteRule ^(.*?)/?$ ' . $rel_cache . '/https-%{HTTP_HOST}' . $uri_base . '/$1/index.html [L,E=AIO_HIT:SERVER]', '', ' # Serve static HTTP .html directly from disk', ' RewriteCond %{HTTPS} !=on', ' RewriteCond %{HTTP:X-Forwarded-Proto} !=https', ), $common_conds, array( ' RewriteCond "' . $norm_cache . '/http-%{HTTP_HOST}' . $uri_base . '/$1/index.html" -f', ' RewriteRule ^(.*?)/?$ ' . $rel_cache . '/http-%{HTTP_HOST}' . $uri_base . '/$1/index.html [L,E=AIO_HIT:SERVER]', '', '', ' Header set X-AIO-Cache "HIT-SERVER-GZIP" env=REDIRECT_AIO_HIT', ' Header set X-AIO-Cache "HIT-SERVER-GZIP" env=AIO_HIT', '', '# END ' . self::PAGE_CACHE_MARKER, ) ); return implode( "\n", $lines ); } /** * Build transparent WebP delivery mod_rewrite block for uploads directory. * Works even when original .jpg/.png files were removed after WebP conversion! */ public static function build_webp_block() { $upload_dir = wp_upload_dir(); $norm_abspath = trailingslashit( wp_normalize_path( ABSPATH ) ); $norm_uploads = untrailingslashit( wp_normalize_path( $upload_dir['basedir'] ) ); if ( strpos( $norm_uploads, $norm_abspath ) !== 0 ) { return ''; } $rel_uploads = ltrim( substr( $norm_uploads, strlen( $norm_abspath ) ), '/' ); $rel_uploads_rx = str_replace( '.', '\.', $rel_uploads ); $lines = array( '# BEGIN ' . self::WEBP_MARKER, '', ' RewriteEngine On', ' RewriteCond %{DOCUMENT_ROOT}/' . $rel_uploads . '/$1.webp -f [OR]', ' RewriteCond "' . $norm_uploads . '/$1.webp" -f', ' RewriteRule ^' . $rel_uploads_rx . '/(.+)\.(?:jpe?g|png)$ ' . $rel_uploads . '/$1.webp [T=image/webp,E=AIO_WEBP:1,L]', '', ' # Prevent missing static media in uploads from booting WordPress / MySQL 404 queries', ' RewriteCond %{REQUEST_FILENAME} !-f', ' RewriteRule ^' . $rel_uploads_rx . '/.+\.(?:jpe?g|png|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|css|js)$ - [R=404,L]', '', '', ' Header append Vary Accept env=REDIRECT_AIO_WEBP', ' Header append Vary Accept env=AIO_WEBP', '', '', ' AddType image/webp .webp', '', '# END ' . self::WEBP_MARKER, ); return implode( "\n", $lines ); } /** * Prepend or remove # BEGIN AIO Tools Page Cache block above # BEGIN WordPress in .htaccess. */ public static function sync_page_cache( $enabled, $options = null ) { $path = self::get_htaccess_path(); if ( ! file_exists( $path ) || ! is_readable( $path ) || ! is_writable( $path ) ) { return false; } $server = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : ''; if ( stripos( $server, 'nginx' ) !== false ) { return false; } $contents = (string) @file_get_contents( $path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged $pattern = '/# BEGIN ' . preg_quote( self::PAGE_CACHE_MARKER, '/' ) . '.*?# END ' . preg_quote( self::PAGE_CACHE_MARKER, '/' ) . '\r?\n*/s'; $cleaned = preg_replace( $pattern, '', $contents ); if ( ! is_string( $cleaned ) ) { return false; } if ( $enabled ) { $block = self::build_page_cache_block( $options ); if ( $block !== '' ) { $cleaned = $block . "\n\n" . ltrim( $cleaned ); } } if ( $cleaned === $contents ) { return true; } return (bool) @file_put_contents( $path, $cleaned, LOCK_EX ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged } /** * Prepend or remove # BEGIN AIO Tools WebP Delivery block above # BEGIN WordPress in .htaccess. */ public static function sync_webp_rewrite( $enabled ) { $path = self::get_htaccess_path(); if ( ! file_exists( $path ) || ! is_readable( $path ) || ! is_writable( $path ) ) { return false; } $server = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : ''; if ( stripos( $server, 'nginx' ) !== false ) { return false; } $contents = (string) @file_get_contents( $path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged $pattern = '/# BEGIN ' . preg_quote( self::WEBP_MARKER, '/' ) . '.*?# END ' . preg_quote( self::WEBP_MARKER, '/' ) . '\r?\n*/s'; $cleaned = preg_replace( $pattern, '', $contents ); if ( ! is_string( $cleaned ) ) { return false; } if ( $enabled ) { $block = self::build_webp_block(); if ( $block !== '' ) { // Place right before # BEGIN WordPress if present, otherwise prepend if ( strpos( $cleaned, '# BEGIN WordPress' ) !== false ) { $cleaned = str_replace( '# BEGIN WordPress', $block . "\n\n# BEGIN WordPress", $cleaned ); } else { $cleaned = $block . "\n\n" . ltrim( $cleaned ); } } } if ( $cleaned === $contents ) { return true; } return (bool) @file_put_contents( $path, $cleaned, LOCK_EX ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged } /** * Synchronize Browser Cache & Static Gzip rules with plugin setting. * * @param bool $enabled Whether browser cache rules should be present. * @return bool */ public static function sync( $enabled ) { $path = self::get_htaccess_path(); if ( ! file_exists( $path ) || ! is_writable( $path ) ) { return false; } if ( ! function_exists( 'insert_with_markers' ) && file_exists( ABSPATH . 'wp-admin/includes/misc.php' ) ) { require_once ABSPATH . 'wp-admin/includes/misc.php'; } if ( ! function_exists( 'insert_with_markers' ) ) { return false; } $lines = $enabled ? self::get_rules() : array(); return (bool) insert_with_markers( $path, self::MARKER, $lines ); } /** * Generate a copy-paste Nginx server {} block snippet for Zero-PHP Page Cache & WebP delivery. */ public static function get_nginx_config_snippet() { $upload_dir = wp_upload_dir(); $uploads_url = (string) wp_parse_url( $upload_dir['baseurl'], PHP_URL_PATH ); $rel_uploads = '/' . trim( $uploads_url !== '' ? $uploads_url : '/wp-content/uploads', '/' ); $rel_cache = $rel_uploads . '/aio-cache'; $lines = array( '# === AIO Tools Zero-PHP Nginx Page Cache & WebP Rules ===', 'set $aio_cache_bypass 0;', 'if ($request_method != GET) { set $aio_cache_bypass 1; }', 'if ($query_string !~* "^(?:&*(?:utm_(?:source|medium|campaign|term|content|id)|fbclid|gclid|dclid|msclkid|ttclid|twclid|yclid|zarsrc|_ga|_gl|mc_cid|mc_eid)=[^&]*)*$") {', ' set $aio_cache_bypass 1;', '}', 'if ($http_cookie ~* "(wordpress_logged_in_|wp-postpass_|woocommerce_items_in_cart|wp_woocommerce_session_|aio_maint_bypass|comment_author_)") {', ' set $aio_cache_bypass 1;', '}', 'set $aio_cache_uri $uri;', 'if ($aio_cache_bypass = 1) { set $aio_cache_uri "/__aio_bypass__"; }', '', '# 1. Zero-PHP Full-Page Cache (serves pre-compressed .html.gz via gzip_static)', 'location / {', ' gzip_static on;', ' add_header X-AIO-Cache "HIT-NGINX" always;', ' try_files ' . $rel_cache . '/$scheme-$host$aio_cache_uri/index.html $uri $uri/ /index.php?$args;', '}', '', '# 2. Transparent WebP Delivery & 1-Year Static Browser Cache', 'location ~* ^(' . $rel_uploads . '/.+)\.(?:jpe?g|png)$ {', ' add_header Vary Accept;', ' expires 365d;', ' try_files $1.webp $uri =404;', '}', 'location ~* \.(?:css|js|webp|avif|gif|svg|ico|woff2?|ttf|otf)$ {', ' expires 365d;', ' add_header Cache-Control "public, max-age=31536000, immutable";', '}', ); return implode( "\n", $lines ); } /** * Remove all AIO Tools Page Cache, WebP Delivery, and Browser Cache rules from root .htaccess. */ public static function remove() { self::sync_page_cache( false ); self::sync_webp_rewrite( false ); return self::sync( false ); } }