'ShortPixel Image Optimizer', 'slug' => 'shortpixel', 'handles_compression' => true, 'handles_format_conversion' => true, 'supports_avif' => true, 'supports_webp' => true, 'cdn_based' => false, 'cloud_service' => true, ); } // Imagify. if ( defined( 'IMAGIFY_VERSION' ) || class_exists( 'Imagify' ) ) { $optimization_plugins[] = array( 'name' => 'Imagify', 'slug' => 'imagify', 'handles_compression' => true, 'handles_format_conversion' => true, 'supports_avif' => false, 'supports_webp' => true, 'cdn_based' => false, 'cloud_service' => true, ); } // Smush. if ( defined( 'WP_SMUSH_VERSION' ) || class_exists( 'WP_Smush' ) || class_exists( 'Smush\Core\Core' ) ) { $optimization_plugins[] = array( 'name' => 'Smush', 'slug' => 'smush', 'handles_compression' => true, 'handles_format_conversion' => true, 'supports_avif' => false, 'supports_webp' => true, 'cdn_based' => false, 'cloud_service' => false, ); } // EWWW Image Optimizer. if ( defined( 'EWWW_IMAGE_OPTIMIZER_VERSION' ) || class_exists( 'EWWW_Image_Optimizer' ) ) { $optimization_plugins[] = array( 'name' => 'EWWW Image Optimizer', 'slug' => 'ewww', 'handles_compression' => true, 'handles_format_conversion' => true, 'supports_avif' => true, 'supports_webp' => true, 'cdn_based' => false, 'cloud_service' => true, ); } // Optimole. if ( defined( 'OPTIMOLE_VERSION' ) || class_exists( 'Optml_Main' ) ) { $optimization_plugins[] = array( 'name' => 'Optimole', 'slug' => 'optimole', 'handles_compression' => false, 'handles_format_conversion' => false, 'supports_avif' => true, 'supports_webp' => true, 'cdn_based' => true, 'cloud_service' => true, ); } // TinyPNG / Compress JPEG & PNG images. if ( defined( 'TINYPNG_VERSION' ) || class_exists( 'Tiny_Settings' ) || class_exists( 'Tiny_Plugin' ) ) { $optimization_plugins[] = array( 'name' => 'TinyPNG', 'slug' => 'tinypng', 'handles_compression' => true, 'handles_format_conversion' => false, 'supports_avif' => false, 'supports_webp' => true, 'cdn_based' => false, 'cloud_service' => true, ); } // Jetpack (Photon / Site Accelerator). if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'is_module_active' ) ) { if ( \Jetpack::is_module_active( 'photon' ) || \Jetpack::is_module_active( 'photon-cdn' ) ) { $optimization_plugins[] = array( 'name' => 'Jetpack (Site Accelerator)', 'slug' => 'jetpack', 'handles_compression' => false, 'handles_format_conversion' => false, 'supports_avif' => false, 'supports_webp' => true, 'cdn_based' => true, 'cloud_service' => true, ); } } // Cache the results. self::$detected_plugins = $optimization_plugins; return $optimization_plugins; } /** * Check if any optimization plugin is active. * * @return bool True if at least one optimization plugin is detected. * @since 1.3.0 */ public static function has_optimization_plugin() { return ! empty( self::get_active_optimization_plugins() ); } /** * Check if an active plugin can handle format conversion. * * @param string $format Target format (webp, avif). * @return bool True if an external plugin can handle this format. * @since 1.3.0 */ public static function external_plugin_handles_format( $format ) { $plugins = self::get_active_optimization_plugins(); foreach ( $plugins as $plugin ) { if ( $format === 'webp' && ! empty( $plugin['supports_webp'] ) && $plugin['handles_format_conversion'] ) { return true; } if ( $format === 'avif' && ! empty( $plugin['supports_avif'] ) && $plugin['handles_format_conversion'] ) { return true; } } return false; } /** * Get recommended cooperation mode based on detected plugins and server capabilities. * * @return string Recommended mode ('gatewell_primary', 'external_primary', 'both', or 'auto'). * @since 1.3.0 */ public static function get_recommended_mode() { $plugins = self::get_active_optimization_plugins(); if ( empty( $plugins ) ) { return 'gatewell_primary'; // No competition, Gatewell is in charge. } foreach ( $plugins as $plugin ) { // CDN-based plugins don't conflict - Gatewell can be primary. if ( ! empty( $plugin['cdn_based'] ) ) { continue; } // If external plugin supports AVIF and server doesn't, recommend external. if ( $plugin['supports_avif'] && ! Format_Capabilities::supports_avif() && $plugin['handles_format_conversion'] ) { return 'external_primary'; } // If external plugin supports WebP and server doesn't, recommend external. if ( $plugin['supports_webp'] && ! Format_Capabilities::supports_webp() && $plugin['handles_format_conversion'] ) { return 'external_primary'; } // If external plugin has cloud service and server has limited capabilities. if ( ! empty( $plugin['cloud_service'] ) && $plugin['handles_compression'] ) { // Server has both compression plugins - let user decide. return 'auto'; } } // Default: Gatewell primary. return 'gatewell_primary'; } /** * Get recommendations and warnings based on active plugins. * * @return array Array of recommendation/warning messages. * @since 1.3.0 */ public static function get_recommendations() { $plugins = self::get_active_optimization_plugins(); $recommendations = array(); if ( empty( $plugins ) ) { return $recommendations; } $recommended_mode = self::get_recommended_mode(); foreach ( $plugins as $plugin ) { // CDN-based plugins play nicely. if ( ! empty( $plugin['cdn_based'] ) ) { $recommendations[] = array( 'type' => 'info', 'message' => sprintf( /* translators: %s: plugin name */ __( '%s detected: This CDN-based plugin works alongside Gatewell without conflicts. Both can remain active.', 'gatewell' ), '' . $plugin['name'] . '' ), 'action' => 'none', ); continue; } // External plugin has better format support. if ( $recommended_mode === 'external_primary' ) { if ( $plugin['supports_avif'] && ! Format_Capabilities::supports_avif() ) { $recommendations[] = array( 'type' => 'warning', 'message' => sprintf( /* translators: %s: plugin name */ __( '%s can create AVIF images (your server cannot). We recommend setting cooperation mode to "External Plugin Primary" to use this capability.', 'gatewell' ), '' . $plugin['name'] . '' ), 'action' => 'set_external_primary', ); continue; } } // Compression conflict warning. if ( $plugin['handles_compression'] && ! $plugin['cdn_based'] ) { $recommendations[] = array( 'type' => 'warning', 'message' => sprintf( /* translators: %s: plugin name */ __( '%s detected: This plugin compresses images. To avoid double processing, choose a cooperation mode below.', 'gatewell' ), '' . $plugin['name'] . '' ), 'action' => 'choose_mode', ); } } return $recommendations; } /** * Get a user-friendly explanation of what each cooperation mode does. * * @return array Array of mode explanations. * @since 1.3.0 */ public static function get_mode_explanations() { $plugins = self::get_active_optimization_plugins(); $plugin_name = ! empty( $plugins[0]['name'] ) ? $plugins[0]['name'] : __( 'external plugin', 'gatewell' ); return array( 'auto' => array( 'label' => __( 'Auto (Recommended)', 'gatewell' ), 'description' => __( 'Automatically choose the best mode based on your server capabilities and installed plugins. Gatewell will coordinate intelligently.', 'gatewell' ), ), 'gatewell_primary' => array( 'label' => __( 'Gatewell Primary', 'gatewell' ), 'description' => sprintf( /* translators: %s: plugin name */ __( 'Gatewell handles compression and format conversion. %s will skip processing or only optimize thumbnails.', 'gatewell' ), $plugin_name ), ), 'external_primary' => array( 'label' => __( 'External Plugin Primary', 'gatewell' ), 'description' => sprintf( /* translators: %s: plugin name */ __( 'Gatewell collects metadata (alt text, captions) only. %s handles all compression and format conversion.', 'gatewell' ), $plugin_name ), ), 'both' => array( 'label' => __( 'Both (Advanced)', 'gatewell' ), 'description' => sprintf( /* translators: %s: plugin name */ __( 'Both Gatewell and %s process images. May result in better compression but risks quality loss from double processing. Use with caution.', 'gatewell' ), $plugin_name ), ), ); } /** * Get the effective cooperation mode (resolves 'auto' to actual mode). * * @return string Effective mode ('gatewell_primary', 'external_primary', or 'both'). * @since 1.3.0 */ public static function get_effective_mode() { $mode = get_option( 'gatewell_plugin_cooperation', 'auto' ); if ( $mode === 'auto' ) { // Auto mode: use recommendation logic. $recommended = self::get_recommended_mode(); return $recommended === 'auto' ? 'gatewell_primary' : $recommended; } return $mode; } /** * Check if Gatewell should process compression. * * @return bool True if Gatewell should compress images. * @since 1.3.0 */ public static function should_gatewell_compress() { $mode = self::get_effective_mode(); // External primary: skip compression. if ( $mode === 'external_primary' ) { return false; } // Gatewell primary or Both: compress. return true; } /** * Check if Gatewell should process format conversion. * * @return bool True if Gatewell should convert formats. * @since 1.3.0 */ public static function should_gatewell_convert() { $mode = self::get_effective_mode(); // External primary: skip conversion. if ( $mode === 'external_primary' ) { return false; } // Gatewell primary or Both: convert. return true; } }