A cup of coffee
A heart set free

开源共享:Auto WebP Image Optimizer v1.1.0 更新说明

#WordPress

🆕 新增功能

1. 自动文件重命名功能

功能描述

  • 上传的图片文件会自动重命名为基于当前日期时间的格式
  • 命名规则:YYYY-MM-DD-HHMMSS (例:2025-09-18-195314)
  • 如果同一秒内上传多个文件,会自动添加微秒后缀确保唯一性

示例

上传文件: "大神.png"
重命名后: "2025-09-18-195314.png"

上传文件: "产品图片.jpg"  
重命名后: "2025-09-18-195315.jpg"

同一秒上传第二个文件:
重命名后: "2025-09-18-195315-123456.jpg"

设置选项

设置 > WebP Optimizer 中新增:

  • 自动重命名文件: 可开启/关闭此功能

file

2. 扩展图片格式支持

支持的格式大幅增加

原支持格式: JPEG, PNG, GIF
新支持格式: JPEG, JPG, PNG, GIF, BMP, WebP, TIFF, TIF, SVG, ICO

file

格式处理策略

格式 重命名 WebP转换 说明
JPEG/JPG 完全支持
PNG 保持透明度
GIF 动画会变为静态
BMP 转换为更小的WebP
TIFF/TIF 使用Imagick处理
WebP 重新压缩优化
SVG 矢量图不需要转换
ICO 图标文件不转换

🔧 技术实现

文件重命名机制

// 使用wp_handle_upload_prefilter钩子
add_filter('wp_handle_upload_prefilter', array($this, 'rename_uploaded_file'));

// 生成时间戳文件名
$date_time = date('Y-m-d-His'); // 2025-09-18-195314

唯一性保证

  • 检查同名文件是否存在
  • 如存在则添加微秒后缀
  • 确保文件名100%唯一

格式识别

  • 支持MIME类型识别
  • 自动推断文件扩展名
  • 处理无扩展名的情况

📈 优化效果

文件管理优势

  • 统一命名规范: 所有上传文件按时间顺序命名
  • 避免中文乱码: 解决中文文件名在某些服务器环境下的问题
  • 便于批量管理: 按时间顺序排列,便于查找和管理

SEO友好

  • 避免特殊字符对URL的影响
  • 统一的命名规范有利于搜索引擎索引
  • 减少因文件名问题导致的404错误

🛠️ 使用方法

启用新功能

  1. 进入 WordPress后台 > 设置 > WebP Optimizer
  2. 勾选 "自动重命名文件" 选项
  3. 点击 "保存设置"

批量处理现有文件

# WP-CLI命令保持不变
wp awio convert --limit=100

验证功能

  1. 上传一个图片文件(任意格式)
  2. 检查媒体库中的文件名是否变为时间格式
  3. 确认文件正常显示且已转换为WebP(如适用)

📊 设置建议

推荐配置

启用WebP转换: ✅
自动重命名文件: ✅  (新功能)
删除原文件: ✅
跳过小文件: ✅
备份原文件: ❌ (节省空间)

质量设置保持不变

小文件质量: 85%
中等文件质量: 80%
大文件质量: 75%
超大文件质量: 70%

⚠️ 注意事项

兼容性

  • 新功能向下兼容,不影响现有文件
  • 现有上传的文件名不会被更改
  • 只对新上传的文件生效

文件名变化

  • 上传后无法通过原文件名搜索
  • 建议通过媒体库的标题、说明等字段记录原始信息
  • 可以在上传时填写图片的Alt文本和描述

性能影响

  • 文件重命名操作几乎无性能影响
  • 新格式支持可能略微增加处理时间
  • 整体性能提升仍然显著

🔍 故障排除

常见问题

Q: 重命名功能不生效?
A:

  1. 检查设置页面是否启用了"自动重命名文件"
  2. 确认上传的是支持的图片格式
  3. 检查文件权限是否正确

Q: 某些格式无法转换?
A:

  1. TIFF格式需要Imagick扩展支持
  2. BMP格式在某些环境下可能不支持
  3. SVG和ICO格式只重命名,不转换WebP

Q: 文件名包含微秒后缀?
A: 这表示同一秒内上传了多个文件,属于正常现象

调试方法

// 在wp-config.php中启用调试
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);

// 查看日志文件
tail -f /wp-content/debug.log

📚 更新历史

v1.1.0 (当前版本)

  • ✅ 新增自动文件重命名功能
  • ✅ 支持11种图片格式
  • ✅ 改进管理界面显示
  • ✅ 优化文件处理逻辑

v1.0.0 (初始版本)

  • ✅ 基础WebP转换功能
  • ✅ 智能质量控制
  • ✅ 统计报告功能
  • ✅ WP-CLI支持

🎯 下个版本预告 (v1.2.0)

计划中的新功能:

  • AVIF格式支持: 下一代图像格式
  • 批量重命名工具: 对现有文件应用新的命名规则
  • 自定义命名模板: 支持更多命名格式选择
  • 图片水印功能: 自动添加网站水印

升级建议: 建议所有用户升级到v1.1.0,享受更强大的文件管理功能和更广泛的格式支持。

插件源代码:

<?php
/**
 * Plugin Name: Auto WebP Image Optimizer
 * Plugin URI: https://yourwebsite.com
 * Description: 自动压缩上传的图片并转换为WebP格式,完成后删除原文件
 * Version: 1.1.0
 * Author: Your Name
 * Author URI: https://yourwebsite.com
 * License: GPL v2 or later
 * Text Domain: auto-webp-optimizer
 * Domain Path: /languages
 * 
 * Requires at least: 5.8
 * Tested up to: 6.6
 * Requires PHP: 7.4
 * 
 * 更新说明:
 * v1.1.0 - 添加自动文件重命名功能,支持更多图片格式
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

// 定义插件常量
define('AWIO_VERSION', '1.1.0');
define('AWIO_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('AWIO_PLUGIN_URL', plugin_dir_url(__FILE__));

class AutoWebPImageOptimizer {

    private $options;

    public function __construct() {
        // 插件激活和停用钩子
        register_activation_hook(__FILE__, array($this, 'activate'));
        register_deactivation_hook(__FILE__, array($this, 'deactivate'));

        // 初始化插件
        add_action('init', array($this, 'init'));

        // 管理员界面
        if (is_admin()) {
            add_action('admin_menu', array($this, 'add_admin_menu'));
            add_action('admin_init', array($this, 'admin_init'));
        }

        // 文件名重命名钩子 - 在文件上传前修改文件名
        add_filter('wp_handle_upload_prefilter', array($this, 'rename_uploaded_file'));

        // 主要功能钩子 - 使用wp_generate_attachment_metadata确保所有图片尺寸都已生成
        add_filter('wp_generate_attachment_metadata', array($this, 'process_uploaded_image'), 10, 2);

        // 加载选项
        $this->options = get_option('awio_options', $this->get_default_options());
    }

    /**
     * 检查是否支持转换为WebP格式
     */
    private function is_supported_for_webp_conversion($mime_type) {
        $webp_supported_types = array(
            'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 
            'image/bmp', 'image/webp', 'image/tiff', 'image/tif'
        );
        return in_array($mime_type, $webp_supported_types);
    }

    /**
     * 重命名上传的文件
     */
    public function rename_uploaded_file($file) {
        // 检查是否启用文件重命名
        if (!$this->options['rename_files']) {
            return $file;
        }

        // 检查是否为支持的图片格式
        if (!$this->is_supported_image_type($file['type'])) {
            return $file;
        }

        // 获取文件扩展名
        $file_info = pathinfo($file['name']);
        $extension = isset($file_info['extension']) ? strtolower($file_info['extension']) : '';

        // 如果没有扩展名,尝试从MIME类型推断
        if (empty($extension)) {
            $extension = $this->get_extension_from_mime($file['type']);
        }

        // 生成基于当前时间的文件名
        $date_time = date('Y-m-d-His'); // 格式:2015-09-18-195314

        // 确保文件名唯一性,如果存在同名文件则添加微秒
        $new_filename = $date_time;
        if (!empty($extension)) {
            $new_filename .= '.' . $extension;
        }

        // 检查文件是否已存在,如果存在则添加微秒确保唯一性
        $upload_dir = wp_upload_dir();
        $target_path = $upload_dir['path'] . '/' . $new_filename;

        if (file_exists($target_path)) {
            $microtime = microtime(true);
            $microseconds = sprintf("%06d", ($microtime - floor($microtime)) * 1000000);
            $new_filename = $date_time . '-' . $microseconds;
            if (!empty($extension)) {
                $new_filename .= '.' . $extension;
            }
        }

        // 更新文件名
        $file['name'] = $new_filename;

        return $file;
    }

    /**
     * 检查是否为支持的图片类型
     */
    private function is_supported_image_type($mime_type) {
        return in_array($mime_type, $this->options['supported_types']);
    }

    /**
     * 从MIME类型获取文件扩展名
     */
    private function get_extension_from_mime($mime_type) {
        $mime_to_ext = array(
            'image/jpeg' => 'jpg',
            'image/jpg' => 'jpg',
            'image/png' => 'png',
            'image/gif' => 'gif',
            'image/bmp' => 'bmp',
            'image/webp' => 'webp',
            'image/tiff' => 'tiff',
            'image/tif' => 'tif',
            'image/svg+xml' => 'svg',
            'image/x-icon' => 'ico',
            'image/vnd.microsoft.icon' => 'ico'
        );

        return isset($mime_to_ext[$mime_type]) ? $mime_to_ext[$mime_type] : '';
    }

    /**
     * 插件激活时执行
     */
    public function activate() {
        // 检查系统要求
        if (!$this->check_requirements()) {
            deactivate_plugins(plugin_basename(__FILE__));
            wp_die('Auto WebP Image Optimizer requires GD or Imagick extension with WebP support.');
        }

        // 初始化选项
        add_option('awio_options', $this->get_default_options());
    }

    /**
     * 插件停用时执行
     */
    public function deactivate() {
        // 清理任务(如有需要)
    }

    /**
     * 初始化插件
     */
    public function init() {
        // 加载文本域
        load_plugin_textdomain('auto-webp-optimizer', false, dirname(plugin_basename(__FILE__)) . '/languages');
    }

    /**
     * 检查系统要求
     */
    private function check_requirements() {
        // 检查GD扩展
        if (extension_loaded('gd')) {
            $gd_info = gd_info();
            if (isset($gd_info['WebP Support']) && $gd_info['WebP Support']) {
                return true;
            }
        }

        // 检查Imagick扩展
        if (extension_loaded('imagick')) {
            $imagick = new Imagick();
            $formats = $imagick->queryFormats('WEBP');
            if (!empty($formats)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取默认选项
     */
    private function get_default_options() {
        return array(
            'enable_conversion' => 1,
            'quality_small' => 85,      // 小于200KB图片质量
            'quality_medium' => 80,     // 200KB-1MB图片质量  
            'quality_large' => 75,      // 1MB-2.5MB图片质量
            'quality_xlarge' => 70,     // 大于2.5MB图片质量
            'delete_originals' => 1,    // 删除原文件
            'max_width' => 2048,        // 最大宽度
            'max_height' => 2048,       // 最大高度
            'supported_types' => array(
                'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 
                'image/bmp', 'image/webp', 'image/tiff', 'image/tif',
                'image/svg+xml', 'image/x-icon', 'image/vnd.microsoft.icon'
            ),
            'rename_files' => 1,        // 是否重命名上传的文件
            'skip_small_files' => 1,    // 跳过小于10KB的文件
            'backup_originals' => 0,    // 是否备份原文件
        );
    }

    /**
     * 处理上传的图片
     */
    public function process_uploaded_image($metadata, $attachment_id) {
        // 检查是否启用转换
        if (!$this->options['enable_conversion']) {
            return $metadata;
        }

        $file_path = get_attached_file($attachment_id);
        if (!file_exists($file_path)) {
            return $metadata;
        }

        // 获取文件信息
        $file_info = pathinfo($file_path);
        $mime_type = get_post_mime_type($attachment_id);

        // 检查是否为支持的图片类型(排除SVG和ICO,这些不需要转换为WebP)
        if (!$this->is_supported_for_webp_conversion($mime_type)) {
            return $metadata;
        }

        // 获取文件大小
        $file_size = filesize($file_path);

        // 跳过过小的文件
        if ($this->options['skip_small_files'] && $file_size < 10240) { // 10KB
            return $metadata;
        }

        try {
            // 备份原文件(如果启用)
            if ($this->options['backup_originals']) {
                $this->backup_original($file_path);
            }

            // 处理主图片
            $webp_path = $this->convert_to_webp($file_path, $file_size);

            if ($webp_path) {
                // 更新附件文件路径
                update_attached_file($attachment_id, $webp_path);

                // 处理所有缩略图尺寸
                if (isset($metadata['sizes']) && is_array($metadata['sizes'])) {
                    $upload_dir = wp_upload_dir();
                    $base_dir = dirname($file_path);

                    foreach ($metadata['sizes'] as $size => &$size_data) {
                        $thumb_path = $base_dir . '/' . $size_data['file'];
                        if (file_exists($thumb_path)) {
                            $thumb_size = filesize($thumb_path);
                            $thumb_webp_path = $this->convert_to_webp($thumb_path, $thumb_size);

                            if ($thumb_webp_path) {
                                $size_data['file'] = basename($thumb_webp_path);
                                $size_data['mime-type'] = 'image/webp';

                                // 删除原缩略图
                                if ($this->options['delete_originals']) {
                                    @unlink($thumb_path);
                                }
                            }
                        }
                    }
                }

                // 更新元数据
                $metadata['file'] = str_replace($upload_dir['basedir'] . '/', '', $webp_path);

                // 删除原主图片
                if ($this->options['delete_originals']) {
                    @unlink($file_path);
                }

                // 记录转换信息
                add_post_meta($attachment_id, '_awio_converted', 1);
                add_post_meta($attachment_id, '_awio_original_size', $file_size);
                add_post_meta($attachment_id, '_awio_webp_size', filesize($webp_path));
            }

        } catch (Exception $e) {
            // 记录错误日志
            error_log('Auto WebP Optimizer Error: ' . $e->getMessage());
        }

        return $metadata;
    }

    /**
     * 转换图片为WebP格式
     */
    private function convert_to_webp($source_path, $file_size) {
        $path_info = pathinfo($source_path);
        $webp_path = $path_info['dirname'] . '/' . $path_info['filename'] . '.webp';

        // 根据文件大小确定质量
        $quality = $this->get_quality_by_size($file_size);

        // 尝试使用GD库
        if ($this->convert_with_gd($source_path, $webp_path, $quality)) {
            return $webp_path;
        }

        // 尝试使用Imagick
        if ($this->convert_with_imagick($source_path, $webp_path, $quality)) {
            return $webp_path;
        }

        return false;
    }

    /**
     * 使用GD库转换
     */
    private function convert_with_gd($source_path, $webp_path, $quality) {
        if (!function_exists('imagewebp')) {
            return false;
        }

        $mime_type = mime_content_type($source_path);
        $image = false;

        switch ($mime_type) {
            case 'image/jpeg':
            case 'image/jpg':
                $image = imagecreatefromjpeg($source_path);
                break;
            case 'image/png':
                $image = imagecreatefrompng($source_path);
                // 保持透明度
                imagepalettetotruecolor($image);
                imagealphablending($image, true);
                imagesavealpha($image, true);
                break;
            case 'image/gif':
                $image = imagecreatefromgif($source_path);
                break;
            case 'image/bmp':
                if (function_exists('imagecreatefrombmp')) {
                    $image = imagecreatefrombmp($source_path);
                } else {
                    // 如果GD不支持BMP,尝试转换
                    return false;
                }
                break;
            case 'image/webp':
                if (function_exists('imagecreatefromwebp')) {
                    $image = imagecreatefromwebp($source_path);
                }
                break;
            case 'image/tiff':
            case 'image/tif':
                // GD通常不直接支持TIFF,返回false让Imagick处理
                return false;
                break;
        }

        if (!$image) {
            return false;
        }

        // 调整尺寸(如果需要)
        $image = $this->resize_image($image);

        // 转换为WebP
        $result = imagewebp($image, $webp_path, $quality);
        imagedestroy($image);

        return $result;
    }

    /**
     * 使用Imagick转换
     */
    private function convert_with_imagick($source_path, $webp_path, $quality) {
        if (!class_exists('Imagick')) {
            return false;
        }

        try {
            $imagick = new Imagick($source_path);

            // 调整尺寸(如果需要)
            $this->resize_imagick($imagick);

            // 设置WebP格式和质量
            $imagick->setImageFormat('webp');
            $imagick->setImageCompressionQuality($quality);
            $imagick->stripImage(); // 移除EXIF数据

            // 写入文件
            $result = $imagick->writeImage($webp_path);
            $imagick->destroy();

            return $result;

        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * 根据文件大小获取质量参数
     */
    private function get_quality_by_size($file_size) {
        $size_mb = $file_size / (1024 * 1024);

        if ($size_mb > 2.5) {
            return $this->options['quality_xlarge'];
        } elseif ($size_mb > 1) {
            return $this->options['quality_large'];
        } elseif ($size_mb > 0.2) {
            return $this->options['quality_medium'];
        } else {
            return $this->options['quality_small'];
        }
    }

    /**
     * 调整GD图片尺寸
     */
    private function resize_image($image) {
        $width = imagesx($image);
        $height = imagesy($image);

        $max_width = $this->options['max_width'];
        $max_height = $this->options['max_height'];

        if ($width <= $max_width && $height <= $max_height) {
            return $image;
        }

        // 计算新尺寸
        $ratio = min($max_width / $width, $max_height / $height);
        $new_width = (int)($width * $ratio);
        $new_height = (int)($height * $ratio);

        // 创建新图片
        $new_image = imagecreatetruecolor($new_width, $new_height);

        // 保持透明度(PNG)
        imagealphablending($new_image, false);
        imagesavealpha($new_image, true);
        $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
        imagefilledrectangle($new_image, 0, 0, $new_width, $new_height, $transparent);

        // 调整尺寸
        imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
        imagedestroy($image);

        return $new_image;
    }

    /**
     * 调整Imagick图片尺寸
     */
    private function resize_imagick($imagick) {
        $width = $imagick->getImageWidth();
        $height = $imagick->getImageHeight();

        $max_width = $this->options['max_width'];
        $max_height = $this->options['max_height'];

        if ($width <= $max_width && $height <= $max_height) {
            return;
        }

        // 计算新尺寸
        $ratio = min($max_width / $width, $max_height / $height);
        $new_width = (int)($width * $ratio);
        $new_height = (int)($height * $ratio);

        $imagick->resizeImage($new_width, $new_height, Imagick::FILTER_LANCZOS, 1);
    }

    /**
     * 备份原文件
     */
    private function backup_original($file_path) {
        $backup_dir = dirname($file_path) . '/awio_backup';
        if (!is_dir($backup_dir)) {
            wp_mkdir_p($backup_dir);
        }

        $backup_path = $backup_dir . '/' . basename($file_path);
        copy($file_path, $backup_path);
    }

    /**
     * 添加管理菜单
     */
    public function add_admin_menu() {
        add_options_page(
            'Auto WebP Optimizer Settings',
            'WebP Optimizer',
            'manage_options',
            'auto-webp-optimizer',
            array($this, 'admin_page')
        );
    }

    /**
     * 初始化管理设置
     */
    public function admin_init() {
        register_setting(
            'awio_settings',
            'awio_options',
            array($this, 'sanitize_options')
        );

        // 基本设置区块
        add_settings_section(
            'awio_basic_settings',
            '基本设置',
            array($this, 'basic_settings_callback'),
            'awio_settings'
        );

        // 质量设置区块
        add_settings_section(
            'awio_quality_settings',
            '质量设置',
            array($this, 'quality_settings_callback'),
            'awio_settings'
        );

        // 添加设置字段
        $this->add_settings_fields();
    }

    /**
     * 添加设置字段
     */
    private function add_settings_fields() {
        // 基本设置字段
        add_settings_field(
            'enable_conversion',
            '启用WebP转换',
            array($this, 'checkbox_field_callback'),
            'awio_settings',
            'awio_basic_settings',
            array('name' => 'enable_conversion')
        );

        add_settings_field(
            'rename_files',
            '自动重命名文件',
            array($this, 'checkbox_field_callback'),
            'awio_settings',
            'awio_basic_settings',
            array('name' => 'rename_files', 'description' => '上传时自动将文件名改为日期时间格式')
        );

        add_settings_field(
            'delete_originals',
            '删除原文件',
            array($this, 'checkbox_field_callback'),
            'awio_settings',
            'awio_basic_settings',
            array('name' => 'delete_originals')
        );

        add_settings_field(
            'skip_small_files',
            '跳过小文件(<10KB)',
            array($this, 'checkbox_field_callback'),
            'awio_settings',
            'awio_basic_settings',
            array('name' => 'skip_small_files')
        );

        add_settings_field(
            'backup_originals',
            '备份原文件',
            array($this, 'checkbox_field_callback'),
            'awio_settings',
            'awio_basic_settings',
            array('name' => 'backup_originals')
        );

        // 质量设置字段
        add_settings_field(
            'quality_small',
            '小文件质量(<200KB)',
            array($this, 'number_field_callback'),
            'awio_settings',
            'awio_quality_settings',
            array('name' => 'quality_small', 'min' => 1, 'max' => 100)
        );

        add_settings_field(
            'quality_medium',
            '中等文件质量(200KB-1MB)',
            array($this, 'number_field_callback'),
            'awio_settings',
            'awio_quality_settings',
            array('name' => 'quality_medium', 'min' => 1, 'max' => 100)
        );

        add_settings_field(
            'quality_large',
            '大文件质量(1MB-2.5MB)',
            array($this, 'number_field_callback'),
            'awio_settings',
            'awio_quality_settings',
            array('name' => 'quality_large', 'min' => 1, 'max' => 100)
        );

        add_settings_field(
            'quality_xlarge',
            '超大文件质量(>2.5MB)',
            array($this, 'number_field_callback'),
            'awio_settings',
            'awio_quality_settings',
            array('name' => 'quality_xlarge', 'min' => 1, 'max' => 100)
        );

        add_settings_field(
            'max_width',
            '最大宽度(像素)',
            array($this, 'number_field_callback'),
            'awio_settings',
            'awio_quality_settings',
            array('name' => 'max_width', 'min' => 100, 'max' => 5000)
        );

        add_settings_field(
            'max_height',
            '最大高度(像素)',
            array($this, 'number_field_callback'),
            'awio_settings',
            'awio_quality_settings',
            array('name' => 'max_height', 'min' => 100, 'max' => 5000)
        );
    }

    /**
     * 管理页面
     */
    public function admin_page() {
        ?>
        <div class="wrap">
            <h1>Auto WebP Image Optimizer 设置</h1>

            <?php if (!$this->check_requirements()): ?>
            <div class="notice notice-error">
                <p><strong>警告:</strong>您的服务器不支持WebP格式。请确保GD或Imagick扩展已安装并支持WebP。</p>
            </div>
            <?php endif; ?>

            <form method="post" action="options.php">
                <?php
                settings_fields('awio_settings');
                do_settings_sections('awio_settings');
                submit_button('保存设置');
                ?>
            </form>

            <div class="awio-stats">
                <h3>统计信息</h3>
                <?php $this->display_stats(); ?>
            </div>

            <div class="awio-info">
                <h3>支持的图片格式</h3>
                <p><strong>可重命名的格式:</strong> JPEG, JPG, PNG, GIF, BMP, WebP, TIFF, TIF, SVG, ICO</p>
                <p><strong>可转换为WebP的格式:</strong> JPEG, JPG, PNG, GIF, BMP, TIFF, TIF, WebP</p>
                <p><strong>文件命名格式:</strong> YYYY-MM-DD-HHMMSS (如: 2025-09-18-195314.jpg)</p>
            </div>
        </div>

        <style>
        .awio-stats, .awio-info {
            margin-top: 30px;
            padding: 15px;
            background: #f1f1f1;
            border-radius: 5px;
        }
        .awio-info {
            background: #e7f3ff;
            border-left: 4px solid #2196f3;
        }
        .description {
            font-style: italic;
            color: #666;
            margin-top: 5px;
        }
        </style>
        <?php
    }

    /**
     * 显示统计信息
     */
    private function display_stats() {
        global $wpdb;

        $converted_count = $wpdb->get_var("
            SELECT COUNT(*) 
            FROM {$wpdb->postmeta} 
            WHERE meta_key = '_awio_converted'
        ");

        $total_original_size = $wpdb->get_var("
            SELECT SUM(meta_value) 
            FROM {$wpdb->postmeta} 
            WHERE meta_key = '_awio_original_size'
        ");

        $total_webp_size = $wpdb->get_var("
            SELECT SUM(meta_value) 
            FROM {$wpdb->postmeta} 
            WHERE meta_key = '_awio_webp_size'
        ");

        $saved_bytes = $total_original_size - $total_webp_size;
        $saved_percentage = $total_original_size > 0 ? round(($saved_bytes / $total_original_size) * 100, 1) : 0;

        echo "<p><strong>已转换图片:</strong> {$converted_count} 张</p>";
        echo "<p><strong>原始大小:</strong> " . size_format($total_original_size) . "</p>";
        echo "<p><strong>压缩后大小:</strong> " . size_format($total_webp_size) . "</p>";
        echo "<p><strong>节省空间:</strong> " . size_format($saved_bytes) . " ({$saved_percentage}%)</p>";
    }

    /**
     * 设置区块回调
     */
    public function basic_settings_callback() {
        echo '<p>配置WebP转换的基本选项</p>';
    }

    public function quality_settings_callback() {
        echo '<p>根据文件大小设置不同的压缩质量</p>';
    }

    /**
     * 复选框字段回调
     */
    public function checkbox_field_callback($args) {
        $name = $args['name'];
        $value = isset($this->options[$name]) ? $this->options[$name] : 0;
        $description = isset($args['description']) ? $args['description'] : '';

        echo "<input type='checkbox' name='awio_options[{$name}]' value='1' " . checked(1, $value, false) . " />";

        if (!empty($description)) {
            echo "<p class='description'>{$description}</p>";
        }
    }

    /**
     * 数字字段回调
     */
    public function number_field_callback($args) {
        $name = $args['name'];
        $value = isset($this->options[$name]) ? $this->options[$name] : '';
        $min = isset($args['min']) ? $args['min'] : 1;
        $max = isset($args['max']) ? $args['max'] : 100;

        echo "<input type='number' name='awio_options[{$name}]' value='{$value}' min='{$min}' max='{$max}' />";
    }

    /**
     * 选项验证
     */
    public function sanitize_options($input) {
        $sanitized = array();

        // 布尔值字段
        $bool_fields = array('enable_conversion', 'delete_originals', 'skip_small_files', 'backup_originals', 'rename_files');
        foreach ($bool_fields as $field) {
            $sanitized[$field] = isset($input[$field]) ? 1 : 0;
        }

        // 数字字段
        $number_fields = array(
            'quality_small' => array('min' => 1, 'max' => 100),
            'quality_medium' => array('min' => 1, 'max' => 100),
            'quality_large' => array('min' => 1, 'max' => 100),
            'quality_xlarge' => array('min' => 1, 'max' => 100),
            'max_width' => array('min' => 100, 'max' => 5000),
            'max_height' => array('min' => 100, 'max' => 5000),
        );

        foreach ($number_fields as $field => $limits) {
            $value = isset($input[$field]) ? intval($input[$field]) : $this->options[$field];
            $sanitized[$field] = max($limits['min'], min($limits['max'], $value));
        }

        // 保持其他选项
        $sanitized['supported_types'] = $this->options['supported_types'];

        return $sanitized;
    }
}

// 初始化插件
new AutoWebPImageOptimizer();

// 批量转换现有图片的WP-CLI命令(可选)
if (defined('WP_CLI') && WP_CLI) {
    class AWIO_CLI_Command {

        /**
         * 批量转换现有图片为WebP格式
         *
         * ## OPTIONS
         *
         * [--limit=<number>]
         * : 限制处理图片数量
         *
         * [--force]
         * : 强制转换已转换的图片
         *
         * ## EXAMPLES
         *
         *     wp awio convert --limit=100
         *     wp awio convert --force
         */
        public function convert($args, $assoc_args) {
            $limit = isset($assoc_args['limit']) ? intval($assoc_args['limit']) : 50;
            $force = isset($assoc_args['force']);

            global $wpdb;

            // 查询图片附件
            $meta_query = '';
            if (!$force) {
                $meta_query = "AND p.ID NOT IN (
                    SELECT post_id FROM {$wpdb->postmeta} 
                    WHERE meta_key = '_awio_converted'
                )";
            }

            $attachments = $wpdb->get_results($wpdb->prepare("
                SELECT p.ID 
                FROM {$wpdb->posts} p 
                WHERE p.post_type = 'attachment' 
                AND p.post_mime_type IN ('image/jpeg', 'image/png', 'image/gif')
                {$meta_query}
                LIMIT %d
            ", $limit));

            if (empty($attachments)) {
                WP_CLI::success('没有找到需要转换的图片。');
                return;
            }

            $optimizer = new AutoWebPImageOptimizer();
            $progress = WP_CLI\Utils\make_progress_bar('Converting images', count($attachments));

            foreach ($attachments as $attachment) {
                $metadata = wp_get_attachment_metadata($attachment->ID);
                if ($metadata) {
                    // 使用私有方法处理图片
                    $reflection = new ReflectionClass($optimizer);
                    $method = $reflection->getMethod('process_uploaded_image');
                    $method->setAccessible(true);
                    $method->invoke($optimizer, $metadata, $attachment->ID);
                }
                $progress->tick();
            }

            $progress->finish();
            WP_CLI::success(sprintf('成功处理 %d 张图片。', count($attachments)));
        }
    }

    WP_CLI::add_command('awio', 'AWIO_CLI_Command');
}
赞(0) 打赏
未经允许不得转载:大神网 - 币圈投资与科技生活博客 » 开源共享:Auto WebP Image Optimizer v1.1.0 更新说明

评论 抢沙发

评论前必须登录!

 

登录

找回密码

注册