self::get_php_info(), 'image' => self::get_image_support(), 'upload' => self::get_upload_limits(), 'memory' => self::get_memory_info(), 'formats' => self::get_format_support(), 'optimization' => self::get_optimization_support(), ); } /** * Get PHP information. * * @return array PHP version and configuration. * @since 1.1.0 */ public static function get_php_info() { return array( 'version' => PHP_VERSION, 'version_ok' => version_compare( PHP_VERSION, '7.4', '>=' ), 'sapi' => php_sapi_name(), 'os' => PHP_OS, 'architecture' => PHP_INT_SIZE * 8 . '-bit', ); } /** * Get image library support. * * @return array Image library availability and capabilities. * @since 1.1.0 */ public static function get_image_support() { $gd_available = extension_loaded( 'gd' ); $imagick_available = extension_loaded( 'imagick' ); $info = array( 'gd' => array( 'available' => $gd_available, 'version' => $gd_available ? self::get_gd_version() : null, 'info' => $gd_available ? gd_info() : array(), ), 'imagick' => array( 'available' => $imagick_available, 'version' => $imagick_available ? self::get_imagick_version() : null, ), ); // Determine primary library. if ( $imagick_available ) { $info['primary'] = 'imagick'; } elseif ( $gd_available ) { $info['primary'] = 'gd'; } else { $info['primary'] = 'none'; } return $info; } /** * Get GD library version. * * @return string|null GD version string. * @since 1.1.0 */ private static function get_gd_version() { if ( ! function_exists( 'gd_info' ) ) { return null; } $gd_info = gd_info(); if ( isset( $gd_info['GD Version'] ) ) { return $gd_info['GD Version']; } return null; } /** * Get ImageMagick version. * * @return string|null ImageMagick version string. * @since 1.1.0 */ private static function get_imagick_version() { if ( ! class_exists( 'Imagick' ) ) { return null; } $version = \Imagick::getVersion(); if ( isset( $version['versionString'] ) ) { return $version['versionString']; } return null; } /** * Get upload size limits. * * @return array Upload size limits from PHP and WordPress. * @since 1.1.0 */ public static function get_upload_limits() { $php_upload_max = self::parse_size( ini_get( 'upload_max_filesize' ) ); $php_post_max = self::parse_size( ini_get( 'post_max_size' ) ); $wp_max = wp_max_upload_size(); // Effective limit is the smallest of all limits. $effective_limit = min( $php_upload_max, $php_post_max, $wp_max ); return array( 'php_upload_max_filesize' => $php_upload_max, 'php_post_max_size' => $php_post_max, 'wp_max_upload_size' => $wp_max, 'effective_limit' => $effective_limit, 'effective_limit_mb' => round( $effective_limit / 1024 / 1024, 2 ), ); } /** * Get memory information. * * @return array Memory limits and usage. * @since 1.1.0 */ public static function get_memory_info() { $memory_limit = self::parse_size( ini_get( 'memory_limit' ) ); $wp_memory = self::parse_size( WP_MEMORY_LIMIT ); $wp_max = defined( 'WP_MAX_MEMORY_LIMIT' ) ? self::parse_size( WP_MAX_MEMORY_LIMIT ) : $wp_memory; return array( 'php_memory_limit' => $memory_limit, 'php_memory_mb' => round( $memory_limit / 1024 / 1024, 2 ), 'wp_memory_limit' => $wp_memory, 'wp_memory_mb' => round( $wp_memory / 1024 / 1024, 2 ), 'wp_max_memory' => $wp_max, 'wp_max_memory_mb' => round( $wp_max / 1024 / 1024, 2 ), 'current_usage' => memory_get_usage( true ), 'current_usage_mb' => round( memory_get_usage( true ) / 1024 / 1024, 2 ), ); } /** * Get format support information. * * @return array Supported image formats. * @since 1.1.0 */ public static function get_format_support() { $gd_info = function_exists( 'gd_info' ) ? gd_info() : array(); $imagick_available = extension_loaded( 'imagick' ); return array( 'jpeg' => array( 'supported' => isset( $gd_info['JPEG Support'] ) && $gd_info['JPEG Support'], 'library' => 'gd', ), 'png' => array( 'supported' => isset( $gd_info['PNG Support'] ) && $gd_info['PNG Support'], 'library' => 'gd', ), 'gif' => array( 'supported' => isset( $gd_info['GIF Create Support'] ) && $gd_info['GIF Create Support'], 'library' => 'gd', ), 'webp' => array( 'supported' => isset( $gd_info['WebP Support'] ) && $gd_info['WebP Support'], 'library' => 'gd', ), 'avif' => array( 'supported' => Format_Capabilities::supports_avif(), 'library' => ! empty( $gd_info['AVIF Support'] ) ? 'gd' : 'imagick', 'note' => 'Requires PHP 8.1+ with AVIF in GD, or ImageMagick with AVIF', ), 'heic' => array( 'supported' => $imagick_available, 'library' => 'imagick', 'note' => 'Requires ImageMagick extension', ), 'svg' => array( 'supported' => class_exists( 'DOMDocument' ), 'library' => 'dom', 'note' => 'Requires DOMDocument for sanitization', ), ); } /** * Get optimization capabilities. * * @return array Available optimization features. * @since 1.1.0 */ public static function get_optimization_support() { return array( 'compression' => self::can_compress_images(), 'format_conversion' => self::can_convert_formats(), 'transparency' => self::supports_transparency(), 'metadata' => self::can_process_metadata(), ); } /** * Check if server can compress images. * * @return array Compression capability details. * @since 1.1.0 */ private static function can_compress_images() { $gd_available = extension_loaded( 'gd' ); return array( 'supported' => $gd_available, 'method' => $gd_available ? 'GD Library' : 'none', 'quality_control' => $gd_available, ); } /** * Check if server can convert between formats. * * @return array Format conversion capabilities. * @since 1.1.0 */ private static function can_convert_formats() { $gd_info = function_exists( 'gd_info' ) ? gd_info() : array(); $can_convert = isset( $gd_info['JPEG Support'] ) && isset( $gd_info['PNG Support'] ); // Check AVIF support $avif_supported = isset( $gd_info['AVIF Support'] ) && $gd_info['AVIF Support']; if ( ! $avif_supported && extension_loaded( 'imagick' ) ) { try { $imagick = new \Imagick(); $formats = $imagick->queryFormats( 'AVIF' ); $avif_supported = ! empty( $formats ); $imagick->clear(); $imagick->destroy(); } catch ( \Exception $e ) { $avif_supported = false; } } return array( 'supported' => $can_convert, 'formats' => array( 'jpeg_to_png' => $can_convert, 'png_to_jpeg' => $can_convert, 'webp' => isset( $gd_info['WebP Support'] ) && $gd_info['WebP Support'], 'avif' => $avif_supported, ), ); } /** * Check if server supports image transparency. * * @return array Transparency support details. * @since 1.1.0 */ private static function supports_transparency() { $gd_info = function_exists( 'gd_info' ) ? gd_info() : array(); // Check AVIF support for transparency $avif_supported = isset( $gd_info['AVIF Support'] ) && $gd_info['AVIF Support']; if ( ! $avif_supported && extension_loaded( 'imagick' ) ) { try { $imagick = new \Imagick(); $formats = $imagick->queryFormats( 'AVIF' ); $avif_supported = ! empty( $formats ); $imagick->clear(); $imagick->destroy(); } catch ( \Exception $e ) { $avif_supported = false; } } return array( 'supported' => isset( $gd_info['PNG Support'] ) && $gd_info['PNG Support'], 'formats' => array( 'png' => isset( $gd_info['PNG Support'] ) && $gd_info['PNG Support'], 'gif' => isset( $gd_info['GIF Create Support'] ) && $gd_info['GIF Create Support'], 'webp' => isset( $gd_info['WebP Support'] ) && $gd_info['WebP Support'], 'avif' => $avif_supported, ), ); } /** * Check if server can process image metadata. * * @return array Metadata processing capabilities. * @since 1.1.0 */ private static function can_process_metadata() { return array( 'exif' => function_exists( 'exif_read_data' ), 'iptc' => function_exists( 'iptcparse' ), 'wp_meta' => true, // WordPress always supports its own metadata. ); } /** * Parse size string to bytes. * * Converts PHP size notation (e.g., '128M', '2G') to bytes. * * @param string $size Size string. * @return int Size in bytes. * @since 1.1.0 */ private static function parse_size( $size ) { $unit = strtolower( substr( $size, -1 ) ); $value = (int) $size; switch ( $unit ) { case 'g': $value *= 1024; // Fall through. case 'm': $value *= 1024; // Fall through. case 'k': $value *= 1024; } return $value; } /** * Get human-readable system status. * * @return array Status messages for display. * @since 1.1.0 */ public static function get_status_messages() { $info = self::get_all(); $messages = array(); // PHP version check. if ( ! $info['php']['version_ok'] ) { $messages[] = array( 'type' => 'error', 'message' => sprintf( 'PHP version %s is below the minimum required version 7.4.', $info['php']['version'] ), ); } // Image library check. if ( $info['image']['primary'] === 'none' ) { $messages[] = array( 'type' => 'error', 'message' => 'No image processing library found (GD or ImageMagick required).', ); } // Memory check. if ( $info['memory']['php_memory_mb'] < 128 ) { $messages[] = array( 'type' => 'warning', 'message' => sprintf( 'Memory limit is %dMB. Recommend at least 128MB for image processing.', $info['memory']['php_memory_mb'] ), ); } // Upload size check. if ( $info['upload']['effective_limit_mb'] < 2 ) { $messages[] = array( 'type' => 'warning', 'message' => sprintf( 'Upload size limit is %dMB. Users may have difficulty uploading images.', $info['upload']['effective_limit_mb'] ), ); } // All good! if ( empty( $messages ) ) { $messages[] = array( 'type' => 'success', 'message' => 'Server is properly configured for image optimization.', ); } return $messages; } /** * Get conversion mode support information. * * Returns which format conversion modes are available on this server. * * @return array Array of conversion modes and their availability. * @since 1.3.0 */ public static function get_conversion_mode_support() { return array( 'preserve' => array( 'supported' => true, 'label' => __( 'Preserve Original Format', 'gatewell' ), 'note' => __( 'Always available', 'gatewell' ), ), 'jpeg' => array( 'supported' => true, 'label' => __( 'Convert to JPEG', 'gatewell' ), 'note' => __( 'Always available', 'gatewell' ), ), 'webp' => array( 'supported' => Format_Capabilities::supports_webp(), 'label' => __( 'Convert to WebP', 'gatewell' ), 'note' => Format_Capabilities::supports_webp() ? __( 'Available', 'gatewell' ) : Format_Capabilities::get_format_requirements( 'webp' ), ), 'avif' => array( 'supported' => Format_Capabilities::supports_avif(), 'label' => __( 'Convert to AVIF', 'gatewell' ), 'note' => Format_Capabilities::supports_avif() ? __( 'Available', 'gatewell' ) : Format_Capabilities::get_format_requirements( 'avif' ), ), 'smart' => array( 'supported' => Format_Capabilities::supports_webp() || Format_Capabilities::supports_avif(), 'label' => __( 'Smart Conversion', 'gatewell' ), 'note' => ( Format_Capabilities::supports_webp() || Format_Capabilities::supports_avif() ) ? __( 'Available', 'gatewell' ) : __( 'Requires WebP or AVIF support', 'gatewell' ), ), ); } }