true, 'emergency_disable' => false, 'delete_data_on_uninstall' => false, // Cache. 'page_cache_enabled' => true, 'page_cache_ttl' => 3600, 'cache_warming_enabled' => false, 'cache_warming_concurrency' => 2, 'cache_exclusions' => array( 'urls' => array(), 'patterns' => array( '/cart/*', '/checkout/*', '/my-account/*', '/wp-admin/*', '/wp-login.php' ), 'cookies' => array( 'wordpress_logged_in_', 'woocommerce_cart_hash', 'woocommerce_items_in_cart' ), 'query' => array(), ), // CSS. 'css_minify' => false, 'css_combine' => false, 'css_critical' => false, 'css_async' => true, 'css_remove_unused' => false, 'css_remove_unused_mode' => 'safe', 'css_exclusions' => array(), // JavaScript. 'js_minify' => false, 'js_combine' => false, 'js_defer' => true, 'js_delay' => true, 'js_delay_timeout' => 3, 'js_delay_trigger' => 'interaction', 'js_move_to_footer' => false, 'js_exclusions' => array( 'jquery', 'jquery-core', 'jquery-migrate', ), 'js_auto_exclusions' => array( 'wc-checkout', 'wc-cart', 'wc-add-to-cart', 'stripe', 'razorpay', 'paypal', 'ppcp', 'recaptcha', 'google-recaptcha', 'elementor-frontend', ), // HTML. 'html_minify' => true, // Images. 'lazy_load_images' => true, 'lazy_load_iframes' => true, 'lazy_load_videos' => true, 'add_missing_dimensions' => true, 'image_compression' => true, 'image_quality' => 82, 'webp_conversion' => true, 'avif_conversion' => false, 'lcp_image_preload' => true, 'lcp_image_url' => '', 'image_exclusions' => array(), // Fonts. 'font_display_swap' => true, 'google_fonts_local' => false, 'preload_fonts' => false, 'preload_font_urls' => array(), // WordPress. 'disable_emojis' => true, 'disable_embeds' => true, 'disable_xmlrpc' => false, 'remove_wp_version' => true, 'remove_generator_meta' => true, 'disable_feeds' => false, 'disable_pingbacks' => false, 'remove_shortlinks' => false, 'remove_discovery_links' => false, 'heartbeat_frontend' => 'default', 'heartbeat_admin' => 'default', 'heartbeat_editor' => 'default', // Third-party. 'delay_analytics' => true, 'delay_gtm' => true, 'delay_facebook_pixel' => true, 'delay_clarity' => true, 'lazy_load_youtube' => true, 'lazy_load_vimeo' => true, 'lazy_load_google_maps' => true, // Cloudflare. 'cloudflare_enabled' => false, 'cloudflare_api_token' => '', 'cloudflare_zone_id' => '', 'cloudflare_auto_purge' => false, // CDN. 'cdn_enabled' => false, 'cdn_url' => '', 'cdn_purge_endpoint' => '', 'cdn_api_key' => '', // Server. 'browser_cache_htaccess' => true, 'compression_htaccess' => true, // Diagnostics. 'pagespeed_api_key' => '', // Conflicts. 'dismissed_conflicts' => array(), 'locked_features' => array(), ); } /** * Get plugin settings. * * @param string|null $key Optional key. * @param mixed $default Default value. * @return mixed */ function wpsco_get_setting( $key = null, $default = null ) { $settings = get_option( 'wpsco_settings', wpsco_get_default_settings() ); $defaults = wpsco_get_default_settings(); $settings = wp_parse_args( $settings, $defaults ); if ( null === $key ) { return $settings; } return isset( $settings[ $key ] ) ? $settings[ $key ] : $default; } /** * Update a plugin setting. * * @param string $key Setting key. * @param mixed $value Setting value. * @return bool */ function wpsco_update_setting( $key, $value ) { $settings = wpsco_get_setting(); $settings[ $key ] = $value; return update_option( 'wpsco_settings', $settings ); } /** * Check if current user can manage the plugin. * * @return bool */ function wpsco_current_user_can() { return current_user_can( WPSCO_CAPABILITY ) || current_user_can( 'manage_options' ); } /** * Get plugin cache directory inside wp_upload_dir(), dynamically resolved at runtime. * * @param string $sub Optional subdirectory or relative file path. * @return string Normalized absolute path. */ function wpsco_get_cache_dir( $sub = '' ) { $upload_dir = wp_upload_dir(); $basedir = ! empty( $upload_dir['basedir'] ) ? $upload_dir['basedir'] : WP_CONTENT_DIR . '/uploads'; $base = wp_normalize_path( trailingslashit( $basedir ) . 'speednest/' ); return $sub ? $base . ltrim( $sub, '/' ) : $base; } /** * Get plugin cache directory URL inside wp_upload_dir(), dynamically resolved at runtime. * * @param string $sub Optional subdirectory or relative file path. * @return string Cache URL. */ function wpsco_get_cache_url( $sub = '' ) { $upload_dir = wp_upload_dir(); $baseurl = ! empty( $upload_dir['baseurl'] ) ? $upload_dir['baseurl'] : content_url( 'uploads' ); $base = trailingslashit( $baseurl ) . 'speednest/'; return $sub ? $base . ltrim( $sub, '/' ) : $base; } /** * Safely write content to a file in the uploads cache directory using the WordPress Filesystem API. * * @param string $file_path Absolute path to the destination file. * @param string $content Data content to write. * @param bool $append Whether to append to the file if it exists. * @return bool True on success, false on failure. */ function wpsco_write_file( $file_path, $content, $append = false ) { $base_dir = wp_normalize_path( wpsco_get_cache_dir() ); $norm_path = wp_normalize_path( $file_path ); // Ensure target path is strictly within the plugin's uploads directory. if ( strpos( $norm_path, $base_dir ) !== 0 ) { return false; } $dir = dirname( $norm_path ); if ( ! is_dir( $dir ) ) { wp_mkdir_p( $dir ); } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { if ( ! function_exists( 'WP_Filesystem' ) && defined( 'ABSPATH' ) && file_exists( ABSPATH . 'wp-admin/includes/file.php' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } if ( function_exists( 'WP_Filesystem' ) ) { WP_Filesystem(); } } if ( $wp_filesystem && is_object( $wp_filesystem ) ) { if ( $append && $wp_filesystem->exists( $norm_path ) ) { $existing = $wp_filesystem->get_contents( $norm_path ); return $wp_filesystem->put_contents( $norm_path, $existing . $content, FS_CHMOD_FILE ); } return $wp_filesystem->put_contents( $norm_path, $content, FS_CHMOD_FILE ); } // Fallback if WP_Filesystem could not be initialized. // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents return false !== @file_put_contents( $norm_path, $content, $append ? ( FILE_APPEND | LOCK_EX ) : LOCK_EX ); } /** * Safely read content from a file using the WordPress Filesystem API. * * @param string $file_path Absolute path to the file. * @return string|false File contents or false on failure. */ function wpsco_read_file( $file_path ) { if ( ! file_exists( $file_path ) ) { return false; } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { if ( ! function_exists( 'WP_Filesystem' ) && defined( 'ABSPATH' ) && file_exists( ABSPATH . 'wp-admin/includes/file.php' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } if ( function_exists( 'WP_Filesystem' ) ) { WP_Filesystem(); } } if ( $wp_filesystem && is_object( $wp_filesystem ) ) { return $wp_filesystem->get_contents( $file_path ); } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents return @file_get_contents( $file_path ); } /** * Log a message. * * @param string $message Log message. * @param string $level Log level (info, warning, error). */ function wpsco_log( $message, $level = 'info' ) { $log_dir = wpsco_get_cache_dir( 'logs/' ); $log_file = $log_dir . gmdate( 'Y-m-d' ) . '.log'; $timestamp = gmdate( 'Y-m-d H:i:s' ); $entry = sprintf( "[%s] [%s] %s\n", $timestamp, strtoupper( $level ), $message ); wpsco_write_file( $log_file, $entry, true ); } /** * Get cache version string. * * @return string */ function wpsco_get_cache_version() { return get_option( 'wpsco_cache_version', md5( WPSCO_VERSION ) ); } /** * Increment cache version (invalidates all generated assets). */ function wpsco_increment_cache_version() { update_option( 'wpsco_cache_version', md5( microtime( true ) . wp_rand() ) ); } /** * Get human-readable file size. * * @param int $bytes Size in bytes. * @return string */ function wpsco_format_size( $bytes ) { if ( $bytes >= 1073741824 ) { return number_format( $bytes / 1073741824, 2 ) . ' GB'; } elseif ( $bytes >= 1048576 ) { return number_format( $bytes / 1048576, 2 ) . ' MB'; } elseif ( $bytes >= 1024 ) { return number_format( $bytes / 1024, 2 ) . ' KB'; } else { return $bytes . ' bytes'; } } /** * Get directory size recursively. * * @param string $dir Directory path. * @return int Size in bytes. */ function wpsco_get_dir_size( $dir ) { $size = 0; if ( ! is_dir( $dir ) ) { return $size; } $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir, RecursiveDirectoryIterator::SKIP_DOTS ) ); foreach ( $iterator as $file ) { if ( $file->isFile() ) { $size += $file->getSize(); } } return $size; } /** * Delete directory contents recursively. * * @param string $dir Directory path. * @param bool $delete Whether to delete the directory itself. * @return bool */ function wpsco_delete_dir_contents( $dir, $delete = false ) { if ( ! is_dir( $dir ) ) { return false; } $norm_dir = function_exists( 'wp_normalize_path' ) ? wp_normalize_path( $dir ) : str_replace( '\\', '/', $dir ); // Safety check: The directory MUST contain 'wp-speed-optimizer' or 'speednest' to ensure we never touch any outside directory. if ( false === strpos( $norm_dir, 'wp-speed-optimizer' ) && false === strpos( $norm_dir, 'speednest' ) ) { wpsco_log( 'Refused to delete directory outside plugin cache: ' . $dir, 'error' ); return false; } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { if ( ! function_exists( 'WP_Filesystem' ) && defined( 'ABSPATH' ) && file_exists( ABSPATH . 'wp-admin/includes/file.php' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } if ( function_exists( 'WP_Filesystem' ) ) { WP_Filesystem(); } } $cache_root = function_exists( 'wpsco_get_cache_dir' ) ? wpsco_get_cache_dir() : ( defined( 'WPSCO_CACHE_DIR' ) ? WPSCO_CACHE_DIR : '' ); $root_norm = function_exists( 'wp_normalize_path' ) ? wp_normalize_path( $cache_root ) : str_replace( '\\', '/', $cache_root ); $is_root = ( rtrim( $norm_dir, '/' ) === rtrim( $root_norm, '/' ) ); $files = @scandir( $dir ); if ( is_array( $files ) ) { foreach ( $files as $file ) { if ( '.' === $file || '..' === $file ) { continue; } // Always preserve root security files. if ( $is_root && in_array( $file, array( '.htaccess', 'index.php' ), true ) ) { continue; } $item_path = rtrim( $dir, '/' ) . '/' . $file; if ( is_dir( $item_path ) ) { wpsco_delete_dir_contents( $item_path, true ); } else { wp_delete_file( $item_path ); } } } if ( $delete && ! $is_root && is_dir( $dir ) ) { if ( ! empty( $wp_filesystem ) ) { $wp_filesystem->delete( $dir ); } } clearstatcache(); return true; } /** * Check if WooCommerce is active. * * @return bool */ function wpsco_is_woocommerce_active() { return class_exists( 'WooCommerce' ); } /** * Check if Elementor is active. * * @return bool */ function wpsco_is_elementor_active() { return defined( 'ELEMENTOR_VERSION' ); } /** * Check if this is a WooCommerce page that should not be cached. * * @return bool */ function wpsco_is_woocommerce_nocache_page() { if ( ! wpsco_is_woocommerce_active() ) { return false; } if ( function_exists( 'is_cart' ) && is_cart() ) { return true; } if ( function_exists( 'is_checkout' ) && is_checkout() ) { return true; } if ( function_exists( 'is_account_page' ) && is_account_page() ) { return true; } return false; } /** * Check if current request should be excluded from caching. * * @return bool */ function wpsco_is_cache_excluded() { // Never cache admin. if ( is_admin() ) { return true; } $req_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; // Never cache login page. if ( strpos( $req_uri, 'wp-login.php' ) !== false ) { return true; } // Never cache previews, editor sessions, or explicit nocache requests. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only inspection of preview and cache bypass query parameters. if ( isset( $_GET['preview'] ) || isset( $_GET['elementor-preview'] ) || isset( $_GET['nocache'] ) || isset( $_GET['purge'] ) || isset( $_GET['preview_id'] ) ) { return true; } // Never cache logged-in users (check both WordPress function and cookie). if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) { return true; } if ( ! empty( $_COOKIE ) ) { foreach ( $_COOKIE as $cookie_name => $cookie_val ) { if ( strpos( $cookie_name, 'wordpress_logged_in_' ) === 0 || strpos( $cookie_name, 'comment_author_' ) === 0 ) { return true; } } } // Never cache POST requests. $request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : ''; if ( 'POST' === $request_method ) { return true; } // Never cache AJAX requests. if ( wp_doing_ajax() ) { return true; } // Never cache REST API. if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return true; } // Never cache cron. if ( wp_doing_cron() ) { return true; } // Never cache XML-RPC. if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { return true; } // Check for WooCommerce cookies. $wc_cookies = array( 'woocommerce_cart_hash', 'woocommerce_items_in_cart', 'wp_woocommerce_session_' ); foreach ( $wc_cookies as $cookie ) { foreach ( $_COOKIE as $cookie_name => $cookie_value ) { if ( strpos( $cookie_name, $cookie ) === 0 && ! empty( $cookie_value ) ) { return true; } } } // Check URL exclusions. $settings = wpsco_get_setting(); $exclusions = isset( $settings['cache_exclusions'] ) ? $settings['cache_exclusions'] : array(); $request = $req_uri; // URL patterns. if ( ! empty( $exclusions['patterns'] ) ) { foreach ( $exclusions['patterns'] as $pattern ) { $regex = '#^' . str_replace( array( '*', '#' ), array( '.*', '\\#' ), $pattern ) . '$#i'; if ( preg_match( $regex, $request ) ) { return true; } } } // Exact URLs. if ( ! empty( $exclusions['urls'] ) ) { foreach ( $exclusions['urls'] as $url ) { if ( trailingslashit( $request ) === trailingslashit( $url ) ) { return true; } } } // Cookie exclusions. if ( ! empty( $exclusions['cookies'] ) ) { foreach ( $exclusions['cookies'] as $cookie ) { foreach ( $_COOKIE as $cookie_name => $cookie_value ) { if ( strpos( $cookie_name, $cookie ) === 0 ) { return true; } } } } return false; } /** * Get server type. * * @return string */ function wpsco_get_server_type() { $server_software = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : ''; if ( stripos( $server_software, 'litespeed' ) !== false ) { if ( stripos( $server_software, 'openlitespeed' ) !== false ) { return 'openlitespeed'; } return 'litespeed'; } if ( stripos( $server_software, 'nginx' ) !== false ) { return 'nginx'; } if ( stripos( $server_software, 'apache' ) !== false ) { return 'apache'; } if ( stripos( $server_software, 'cloudflare' ) !== false ) { return 'cloudflare'; } return 'unknown'; } /** * Get OPcache status. * * @return array */ function wpsco_get_opcache_status() { $status = array( 'enabled' => false, 'available' => false, 'memory_usage' => null, 'statistics' => null, 'can_reset' => false, 'reason' => '', ); if ( ! function_exists( 'opcache_get_status' ) ) { $status['reason'] = __( 'OPcache extension is not installed.', 'speednest' ); return $status; } $status['available'] = true; $opcache_status = @opcache_get_status( false ); if ( false === $opcache_status ) { $status['reason'] = __( 'OPcache is installed but disabled.', 'speednest' ); return $status; } $status['enabled'] = ! empty( $opcache_status['opcache_enabled'] ); if ( isset( $opcache_status['memory_usage'] ) ) { $status['memory_usage'] = $opcache_status['memory_usage']; } if ( isset( $opcache_status['opcache_statistics'] ) ) { $status['statistics'] = $opcache_status['opcache_statistics']; } $status['can_reset'] = function_exists( 'opcache_reset' ) && $status['enabled'] && ! ini_get( 'opcache.restrict_api' ); if ( ! $status['can_reset'] && $status['enabled'] ) { $restrict = ini_get( 'opcache.restrict_api' ); if ( $restrict ) { $status['reason'] = sprintf( /* translators: %s: opcache.restrict_api value */ __( 'OPcache reset is restricted by opcache.restrict_api (%s).', 'speednest' ), $restrict ); } } return $status; } /** * Sanitize a URL path for use in file operations. * * @param string $path URL path. * @return string Sanitized path. */ function wpsco_sanitize_cache_path( $path ) { // Remove dangerous characters. $path = preg_replace( '/[^a-zA-Z0-9\/_\-\.]/', '', $path ); // Remove directory traversal. $path = str_replace( '..', '', $path ); // Remove leading/trailing slashes. $path = trim( $path, '/' ); return $path; } /** * Check if the request has query parameters that affect caching. * * @return bool */ function wpsco_has_query_string() { $query = isset( $_SERVER['QUERY_STRING'] ) ? sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) : ''; if ( empty( $query ) ) { return false; } // Common analytics/tracking params to ignore. $ignore = array( 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'msclkid', 'mc_cid', 'mc_eid', ); parse_str( $query, $params ); $remaining = array_diff_key( $params, array_flip( $ignore ) ); return ! empty( $remaining ); } /** * Convert a URL or relative path to a local absolute filesystem path. * Strips query strings (?ver=...) and hash fragments (#...) so file_exists() succeeds. * * @param string $url URL to convert. * @return string|false File path or false if not resolvable. */ function wpsco_url_to_path( $url ) { if ( empty( $url ) || ! is_string( $url ) ) { return false; } // Strip query strings and hash anchors (e.g. ?ver=6.4, #svg). $url = strtok( $url, '?#' ); // Handle protocol-relative URLs. if ( strpos( $url, '//' ) === 0 ) { $url = 'https:' . $url; } // Handle root-relative paths (/wp-content/...). if ( strpos( $url, '/' ) === 0 && strpos( $url, '//' ) !== 0 ) { $candidate = ABSPATH . ltrim( $url, '/' ); if ( file_exists( $candidate ) ) { return $candidate; } // Check if relative to WP_CONTENT_DIR. if ( defined( 'WP_CONTENT_DIR' ) ) { $content_folder = basename( WP_CONTENT_DIR ); if ( strpos( $url, '/' . $content_folder . '/' ) === 0 ) { $sub = substr( $url, strlen( '/' . $content_folder . '/' ) ); $cand2 = WP_CONTENT_DIR . '/' . $sub; if ( file_exists( $cand2 ) ) { return $cand2; } } } } // Check uploads directory. $uploads = wp_get_upload_dir(); if ( ! empty( $uploads['baseurl'] ) && strpos( $url, $uploads['baseurl'] ) === 0 ) { $rel = substr( $url, strlen( $uploads['baseurl'] ) ); return $uploads['basedir'] . $rel; } // Check wp-content URL. $content_url = content_url(); if ( strpos( $url, $content_url ) === 0 ) { $rel = ltrim( substr( $url, strlen( $content_url ) ), '/' ); return WP_CONTENT_DIR . '/' . $rel; } // Check site URL. $site_url = site_url(); if ( strpos( $url, $site_url ) === 0 ) { $rel = ltrim( substr( $url, strlen( $site_url ) ), '/' ); return ABSPATH . $rel; } // Check home URL. $home_url = home_url(); if ( $home_url !== $site_url && strpos( $url, $home_url ) === 0 ) { $rel = ltrim( substr( $url, strlen( $home_url ) ), '/' ); return ABSPATH . $rel; } return false; }