settings = maple_performance()->settings; $this->determine_enabled_plugins(); $this->init_hooks(); } /** * Determine which plugins should have compatibility rules applied */ private function determine_enabled_plugins() { // If auto-detect is enabled, detect plugins if ( ! empty( $this->settings['compat_auto_detect'] ) ) { $this->detect_plugins(); $this->enabled = $this->detected; } else { // Use manual selection $manual = $this->settings['compat_plugins'] ?? array(); foreach ( $manual as $plugin ) { $this->enabled[ $plugin ] = true; } } } /** * Detect active plugins (used when auto-detect is enabled) */ private function detect_plugins() { // WooCommerce if ( class_exists( 'WooCommerce' ) || defined( 'WC_PLUGIN_FILE' ) ) { $this->detected['woocommerce'] = true; } // LearnDash if ( defined( 'LEARNDASH_VERSION' ) || class_exists( 'SFWD_LMS' ) ) { $this->detected['learndash'] = true; } // WPForms if ( defined( 'WPFORMS_VERSION' ) || class_exists( 'WPForms' ) ) { $this->detected['wpforms'] = true; } // Wordfence if ( defined( 'WORDFENCE_VERSION' ) || class_exists( 'wordfence' ) ) { $this->detected['wordfence'] = true; } // Gutenberg FSE / Block Themes if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) { $this->detected['gutenberg_fse'] = true; } // Gravity Forms if ( class_exists( 'GFForms' ) || defined( 'GF_MIN_WP_VERSION' ) ) { $this->detected['gravityforms'] = true; } // Contact Form 7 if ( defined( 'WPCF7_VERSION' ) || class_exists( 'WPCF7' ) ) { $this->detected['cf7'] = true; } // Elementor if ( defined( 'ELEMENTOR_VERSION' ) ) { $this->detected['elementor'] = true; } // === Caching plugin conflict detection === // WP Rocket if ( defined( 'WP_ROCKET_VERSION' ) ) { $this->detected['wp_rocket'] = true; } // W3 Total Cache if ( defined( 'W3TC' ) || class_exists( 'W3_Plugin_TotalCache' ) ) { $this->detected['w3tc'] = true; } // LiteSpeed Cache if ( defined( 'LSCWP_V' ) || class_exists( 'LiteSpeed_Cache' ) ) { $this->detected['litespeed'] = true; } // WP Super Cache if ( defined( 'WPCACHEHOME' ) || function_exists( 'wp_cache_phase2' ) ) { $this->detected['wp_super_cache'] = true; } // WP Fastest Cache if ( class_exists( 'WpFastestCache' ) || defined( 'WPFC_WP_CONTENT_BASENAME' ) ) { $this->detected['wp_fastest_cache'] = true; } // Autoptimize if ( class_exists( 'autoptimizeMain' ) || defined( 'AUTOPTIMIZE_PLUGIN_VERSION' ) ) { $this->detected['autoptimize'] = true; } // Cache Enabler if ( class_exists( 'Cache_Enabler' ) || defined( 'CACHE_ENABLER_VERSION' ) ) { $this->detected['cache_enabler'] = true; } // Hummingbird if ( class_exists( 'WP_Hummingbird' ) || defined( 'WPHB_VERSION' ) ) { $this->detected['hummingbird'] = true; } // Breeze (Cloudways) if ( class_exists( 'Breeze_Admin' ) || defined( 'BREEZE_VERSION' ) ) { $this->detected['breeze'] = true; } // SG Optimizer (SiteGround) if ( class_exists( 'SiteGround_Optimizer' ) || defined( 'SG_OPTIMIZER_VERSION' ) ) { $this->detected['sg_optimizer'] = true; } // Swift Performance if ( class_exists( 'Swift_Performance' ) || defined( 'FLAVOR_FLAVOR' ) ) { $this->detected['swift_performance'] = true; } // Comet Cache if ( class_exists( 'WebSharks\\CometCache\\Classes\\Plugin' ) || defined( 'COMET_CACHE_VERSION' ) ) { $this->detected['comet_cache'] = true; } // Powered Cache if ( defined( 'POWERED_CACHE_VERSION' ) ) { $this->detected['powered_cache'] = true; } // Perfmatters if ( class_exists( 'Perfmatters' ) || defined( 'PERFMATTERS_VERSION' ) ) { $this->detected['perfmatters'] = true; } } /** * Initialize hooks */ private function init_hooks() { // Only apply filters if at least one plugin is enabled if ( empty( $this->enabled ) ) { // Still check for caching conflicts in admin add_action( 'admin_notices', array( $this, 'conflict_notices' ) ); return; } // Filter exclusions based on enabled plugins add_filter( 'maple_performance_js_exclusions', array( $this, 'add_js_exclusions' ) ); add_filter( 'maple_performance_css_exclusions', array( $this, 'add_css_exclusions' ) ); add_filter( 'maple_performance_path_exclusions', array( $this, 'add_path_exclusions' ) ); add_filter( 'maple_performance_cookie_exclusions', array( $this, 'add_cookie_exclusions' ) ); // Add admin notice for conflicts add_action( 'admin_notices', array( $this, 'conflict_notices' ) ); // WooCommerce specific hooks if ( $this->is_enabled( 'woocommerce' ) ) { $this->init_woocommerce_compat(); } // LearnDash specific hooks if ( $this->is_enabled( 'learndash' ) ) { $this->init_learndash_compat(); } // WPForms specific hooks if ( $this->is_enabled( 'wpforms' ) ) { $this->init_wpforms_compat(); } // Wordfence specific hooks if ( $this->is_enabled( 'wordfence' ) ) { $this->init_wordfence_compat(); } // Gutenberg FSE specific hooks if ( $this->is_enabled( 'gutenberg_fse' ) ) { $this->init_gutenberg_fse_compat(); } } /** * Check if plugin compatibility is enabled (either via auto-detect or manual) */ public function is_enabled( $plugin ) { return ! empty( $this->enabled[ $plugin ] ); } /** * Check if plugin was detected (for display purposes) */ public function is_detected( $plugin ) { return ! empty( $this->detected[ $plugin ] ); } /** * Get all detected plugins */ public function get_detected() { // Always run detection for display in admin if ( empty( $this->detected ) ) { $this->detect_plugins(); } return $this->detected; } /** * Get all enabled plugins */ public function get_enabled() { return $this->enabled; } /** * Add JS exclusions for enabled plugins */ public function add_js_exclusions( $exclusions ) { // WooCommerce if ( $this->is_enabled( 'woocommerce' ) ) { $exclusions = array_merge( $exclusions, array( 'woocommerce', 'wc-', 'wc_', 'jquery-blockui', 'selectWoo', 'select2', 'js-cookie', 'cart-fragments', 'checkout', 'add-to-cart', 'payment', 'stripe', 'paypal', 'square', 'braintree', ) ); } // LearnDash if ( $this->is_enabled( 'learndash' ) ) { $exclusions = array_merge( $exclusions, array( 'learndash', 'sfwd-', 'sfwd_', 'ld-', 'ld_', 'ldlms', 'quiz', 'wpProQuiz', ) ); } // WPForms if ( $this->is_enabled( 'wpforms' ) ) { $exclusions = array_merge( $exclusions, array( 'wpforms', 'wpforms-', 'jquery-validation', 'mailcheck', 'inputmask', ) ); } // Wordfence if ( $this->is_enabled( 'wordfence' ) ) { $exclusions = array_merge( $exclusions, array( 'wordfence', 'wf-', 'wfls-', ) ); } // Gutenberg FSE / Block Themes if ( $this->is_enabled( 'gutenberg_fse' ) ) { $exclusions = array_merge( $exclusions, array( 'wp-block-', 'wp-edit-', ) ); } // Gravity Forms if ( $this->is_enabled( 'gravityforms' ) ) { $exclusions = array_merge( $exclusions, array( 'gform', 'gravityforms', 'gf_', ) ); } // Contact Form 7 if ( $this->is_enabled( 'cf7' ) ) { $exclusions = array_merge( $exclusions, array( 'contact-form-7', 'wpcf7', ) ); } // Elementor if ( $this->is_enabled( 'elementor' ) ) { $exclusions = array_merge( $exclusions, array( 'elementor-', 'elementor_', ) ); } return array_unique( $exclusions ); } /** * Add CSS exclusions for enabled plugins */ public function add_css_exclusions( $exclusions ) { // LearnDash - Focus Mode CSS should load normally if ( $this->is_enabled( 'learndash' ) ) { $exclusions = array_merge( $exclusions, array( 'learndash-front', 'sfwd-', ) ); } // WPForms if ( $this->is_enabled( 'wpforms' ) ) { $exclusions = array_merge( $exclusions, array( 'wpforms', ) ); } // Gutenberg FSE / Block Themes - protect global styles if ( $this->is_enabled( 'gutenberg_fse' ) ) { $exclusions = array_merge( $exclusions, array( 'global-styles', 'wp-block-', 'core-block-', ) ); } return array_unique( $exclusions ); } /** * Add path exclusions for enabled plugins */ public function add_path_exclusions( $exclusions ) { // WooCommerce if ( $this->is_enabled( 'woocommerce' ) ) { $exclusions = array_merge( $exclusions, array( '/cart/', '/cart', '/checkout/', '/checkout', '/my-account/', '/my-account', '/wc-api/', '/order-received/', '/order-pay/', '/view-order/', '/add-to-cart=', '?add-to-cart=', '?remove_item=', '?removed_item=', ) ); } // LearnDash if ( $this->is_enabled( 'learndash' ) ) { $exclusions = array_merge( $exclusions, array( '/lessons/', '/topic/', '/quiz/', '/quizzes/', '/certificates/', '/sfwd-', ) ); } // Wordfence if ( $this->is_enabled( 'wordfence' ) ) { $exclusions = array_merge( $exclusions, array( '/wp-login.php', '?wfls-', ) ); } return array_unique( $exclusions ); } /** * Add cookie exclusions for enabled plugins */ public function add_cookie_exclusions( $exclusions ) { // WooCommerce if ( $this->is_enabled( 'woocommerce' ) ) { $exclusions = array_merge( $exclusions, array( 'woocommerce_items_in_cart', 'woocommerce_cart_hash', 'wp_woocommerce_session_', 'woocommerce_recently_viewed', ) ); } // Wordfence if ( $this->is_enabled( 'wordfence' ) ) { $exclusions = array_merge( $exclusions, array( 'wfCBLBypass', 'wf_loginalerted_', ) ); } return array_unique( $exclusions ); } /** * Initialize WooCommerce compatibility */ private function init_woocommerce_compat() { // Don't cache cart fragments AJAX add_action( 'wc_ajax_get_refreshed_fragments', array( $this, 'disable_caching' ), 1 ); add_action( 'wc_ajax_add_to_cart', array( $this, 'disable_caching' ), 1 ); add_action( 'wc_ajax_remove_from_cart', array( $this, 'disable_caching' ), 1 ); add_action( 'wc_ajax_apply_coupon', array( $this, 'disable_caching' ), 1 ); add_action( 'wc_ajax_remove_coupon', array( $this, 'disable_caching' ), 1 ); add_action( 'wc_ajax_update_shipping_method', array( $this, 'disable_caching' ), 1 ); add_action( 'wc_ajax_checkout', array( $this, 'disable_caching' ), 1 ); // Clear cache on stock changes add_action( 'woocommerce_product_set_stock', array( $this, 'clear_product_cache' ) ); add_action( 'woocommerce_variation_set_stock', array( $this, 'clear_product_cache' ) ); // Clear cache on order status changes (affects stock) add_action( 'woocommerce_order_status_changed', array( $this, 'clear_on_order_status' ), 10, 3 ); // Exclude WooCommerce pages from optimization add_filter( 'maple_performance_exclude_optimization', array( $this, 'exclude_woo_pages' ) ); } /** * Initialize LearnDash compatibility */ private function init_learndash_compat() { // Don't cache any LearnDash AJAX add_action( 'wp_ajax_learndash_mark_complete', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_ld_adv_quiz_result', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_wpProQuiz_admin_ajax', array( $this, 'disable_caching' ), 1 ); // Clear cache on course enrollment/completion add_action( 'learndash_course_completed', array( $this, 'clear_learndash_user_cache' ), 10, 1 ); add_action( 'learndash_lesson_completed', array( $this, 'clear_learndash_user_cache' ), 10, 1 ); add_action( 'learndash_topic_completed', array( $this, 'clear_learndash_user_cache' ), 10, 1 ); add_action( 'learndash_quiz_completed', array( $this, 'clear_learndash_user_cache' ), 10, 2 ); // Clear cache when user is enrolled add_action( 'learndash_update_course_access', array( $this, 'clear_course_cache' ), 10, 4 ); } /** * Initialize WPForms compatibility */ private function init_wpforms_compat() { // WPForms AJAX is generally fine, but ensure it's not cached add_action( 'wp_ajax_wpforms_submit', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_nopriv_wpforms_submit', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_wpforms_file_upload_speed_test', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_nopriv_wpforms_file_upload_speed_test', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_wpforms_restricted_email', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_nopriv_wpforms_restricted_email', array( $this, 'disable_caching' ), 1 ); } /** * Initialize Wordfence compatibility */ private function init_wordfence_compat() { // Don't interfere with Wordfence login security add_action( 'wp_ajax_nopriv_wordfence_ls_authenticate', array( $this, 'disable_caching' ), 1 ); add_action( 'wp_ajax_wordfence_ls_authenticate', array( $this, 'disable_caching' ), 1 ); // Don't cache Wordfence blocked pages if ( defined( 'WORDFENCE_BLOCKED' ) && WORDFENCE_BLOCKED ) { add_filter( 'maple_performance_should_cache', '__return_false' ); } // Respect Wordfence's caching headers add_filter( 'maple_performance_should_cache', array( $this, 'check_wordfence_bypass' ) ); } /** * Initialize Gutenberg FSE / Block Theme compatibility */ private function init_gutenberg_fse_compat() { // Don't aggregate global styles inline CSS add_filter( 'maple_performance_aggregate_inline_css', '__return_false' ); // Protect block editor assets on frontend add_filter( 'maple_performance_exclude_optimization', array( $this, 'exclude_block_editor_frontend' ) ); } /** * Exclude block editor frontend from aggressive optimization */ public function exclude_block_editor_frontend( $exclude ) { // If viewing a page with blocks that need JS interaction // This is conservative - most block content is static return $exclude; } /** * Disable caching for current request */ public function disable_caching() { if ( ! defined( 'DONOTCACHEPAGE' ) ) { define( 'DONOTCACHEPAGE', true ); } } /** * Clear product cache */ public function clear_product_cache( $product ) { if ( ! class_exists( 'Maple_Performance_Cache' ) ) { return; } $product_id = is_numeric( $product ) ? $product : $product->get_id(); $url = get_permalink( $product_id ); if ( $url ) { $cache = Maple_Performance_Cache::get_instance(); $cache->clear_url_cache( $url ); } // Also clear shop page $shop_url = function_exists( 'wc_get_page_permalink' ) ? wc_get_page_permalink( 'shop' ) : ''; if ( $shop_url ) { $cache->clear_url_cache( $shop_url ); } } /** * Clear cache on order status change */ public function clear_on_order_status( $order_id, $old_status, $new_status ) { // Only clear when status changes might affect stock $stock_statuses = array( 'completed', 'processing', 'cancelled', 'refunded' ); if ( in_array( $new_status, $stock_statuses ) || in_array( $old_status, $stock_statuses ) ) { $order = wc_get_order( $order_id ); if ( $order ) { foreach ( $order->get_items() as $item ) { $product_id = $item->get_product_id(); $this->clear_product_cache( $product_id ); } } } } /** * Exclude WooCommerce pages from JS/CSS optimization */ public function exclude_woo_pages( $exclude ) { 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 $exclude; } /** * Clear LearnDash user-related cache */ public function clear_learndash_user_cache( $data ) { // LearnDash pages are user-specific and already excluded for logged-in users // But we can clear the course archive pages if ( ! class_exists( 'Maple_Performance_Cache' ) ) { return; } $cache = Maple_Performance_Cache::get_instance(); // Clear course archive $course_archive = get_post_type_archive_link( 'sfwd-courses' ); if ( $course_archive ) { $cache->clear_url_cache( $course_archive ); } // Clear home page (might show course counts) $cache->clear_url_cache( home_url( '/' ) ); } /** * Clear course cache when enrollment changes */ public function clear_course_cache( $user_id, $course_id, $access_list, $remove ) { if ( ! class_exists( 'Maple_Performance_Cache' ) ) { return; } $cache = Maple_Performance_Cache::get_instance(); // Clear the course page (might show enrollment count) $course_url = get_permalink( $course_id ); if ( $course_url ) { $cache->clear_url_cache( $course_url ); } } /** * Check Wordfence bypass */ public function check_wordfence_bypass( $should_cache ) { // If Wordfence has set bypass cookie, don't cache if ( isset( $_COOKIE['wfCBLBypass'] ) ) { return false; } return $should_cache; } /** * Show admin notices for plugin conflicts */ public function conflict_notices() { // Build list of conflicting caching plugins $caching_conflicts = $this->get_caching_conflicts(); // Show caching conflict warning on all admin pages (dismissible) if ( ! empty( $caching_conflicts ) && ! get_transient( 'maple_perf_conflict_dismissed' ) ) { $this->show_conflict_warning( $caching_conflicts ); } // Show detailed info only on Maple Performance settings page $screen = get_current_screen(); if ( ! $screen || $screen->id !== 'settings_page_maple-performance' ) { return; } // If conflicts exist but were dismissed, show a subtle reminder on settings page if ( ! empty( $caching_conflicts ) && get_transient( 'maple_perf_conflict_dismissed' ) ) { echo '
' . esc_html__( 'Reminder:', 'maple-performance' ) . ' ';
echo sprintf(
esc_html__( 'Other caching plugin(s) detected: %s. For best results, use only one caching solution.', 'maple-performance' ),
'' . implode( ', ', array_map( 'esc_html', $caching_conflicts ) ) . ''
);
echo '
' . esc_html__( 'Maple Performance - Detected Plugins:', 'maple-performance' ) . ' ';
echo sprintf(
esc_html__( 'Compatibility rules available for: %s. Enable them in the Plugin Compatibility section below.', 'maple-performance' ),
'' . implode( ', ', array_map( 'esc_html', $compatible ) ) . ''
);
echo '
' . esc_html__( '⚠️ Maple Performance - Caching Conflict Detected', 'maple-performance' ) . '
'; echo '' . sprintf( esc_html__( 'The following caching/optimization plugin(s) are also active: %s', 'maple-performance' ), '' . implode( ', ', array_map( 'esc_html', $conflicts ) ) . '' ) . '
'; echo '' . esc_html__( 'Running multiple caching plugins simultaneously can cause:', 'maple-performance' ) . '
'; echo '' . esc_html__( 'Recommended action:', 'maple-performance' ) . ' '; echo esc_html__( 'Deactivate the other caching plugin(s), or deactivate Maple Performance if you prefer to keep your existing solution.', 'maple-performance' ); echo '
'; echo ''; echo '' . esc_html__( 'Go to Plugins', 'maple-performance' ) . ' '; echo '' . esc_html__( 'Dismiss for 7 days', 'maple-performance' ) . ''; echo '
'; echo '