首页 / 教程文章 / 网络传媒WordPress多站点柔性内容同步管理插件开发教程

网络传媒WordPress多站点柔性内容同步管理插件开发教程

网络传媒WordPress多站点柔性内容同步管理插件开发教程

一、项目背景与需求分析

在当今网络传媒行业中,内容分发效率直接决定了信息传播的广度和深度。许多传媒机构使用WordPress多站点(Multisite)架构来管理多个子站点,但面临着一个共同挑战:如何在多个站点之间高效、灵活地同步和管理内容?

传统的内容同步方法存在诸多局限:

  • 手动复制粘贴效率低下且容易出错
  • 硬编码的同步规则缺乏灵活性
  • 无法根据不同内容类型和站点特性进行差异化同步
  • 缺乏版本控制和冲突解决机制

本教程将指导您开发一个"柔性内容同步管理插件",该插件能够:

  1. 根据预设规则自动同步指定内容
  2. 支持多种同步模式(实时、定时、手动)
  3. 允许自定义内容转换规则
  4. 提供冲突检测和解决机制
  5. 具备完整的日志和错误处理系统

二、插件架构设计

2.1 核心模块划分

<?php
/**
 * 柔性内容同步管理插件 - 主文件
 * Plugin Name: 柔性内容同步管理器
 * Plugin URI:  https://yourdomain.com/
 * Description: WordPress多站点内容同步管理解决方案
 * Version:     1.0.0
 * Author:      网络传媒技术团队
 * License:     GPL v2 or later
 */

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

// 定义插件常量
define('FCSM_VERSION', '1.0.0');
define('FCSM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FCSM_PLUGIN_URL', plugin_dir_url(__FILE__));

// 主控制器类
class Flexible_Content_Sync_Manager {
    
    private static $instance = null;
    private $sync_rules = array();
    private $scheduler;
    private $logger;
    
    // 单例模式
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->load_dependencies();
        $this->init_hooks();
    }
    
    // 加载依赖模块
    private function load_dependencies() {
        require_once FCSM_PLUGIN_DIR . 'includes/class-sync-scheduler.php';
        require_once FCSM_PLUGIN_DIR . 'includes/class-content-processor.php';
        require_once FCSM_PLUGIN_DIR . 'includes/class-conflict-resolver.php';
        require_once FCSM_PLUGIN_DIR . 'includes/class-logger.php';
        require_once FCSM_PLUGIN_DIR . 'includes/class-rule-manager.php';
        
        $this->scheduler = new FCSM_Sync_Scheduler();
        $this->logger = new FCSM_Logger();
    }
    
    // 初始化WordPress钩子
    private function init_hooks() {
        add_action('init', array($this, 'init'));
        add_action('admin_menu', array($this, 'add_admin_menu'));
        add_action('save_post', array($this, 'handle_post_save'), 10, 3);
    }
    
    // 初始化方法
    public function init() {
        // 加载同步规则
        $this->load_sync_rules();
    }
    
    // 加载同步规则
    private function load_sync_rules() {
        $rule_manager = new FCSM_Rule_Manager();
        $this->sync_rules = $rule_manager->get_active_rules();
    }
}
?>

2.2 数据库设计

<?php
/**
 * 数据库表创建与维护
 */
class FCSM_Database {
    
    // 创建插件所需的数据表
    public static function create_tables() {
        global $wpdb;
        
        $charset_collate = $wpdb->get_charset_collate();
        
        // 同步规则表
        $table_rules = $wpdb->prefix . 'fcsm_sync_rules';
        $sql_rules = "CREATE TABLE IF NOT EXISTS $table_rules (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            rule_name varchar(255) NOT NULL,
            source_site_id bigint(20) NOT NULL,
            target_site_ids text NOT NULL,
            post_types text NOT NULL,
            sync_conditions text NOT NULL,
            sync_mode varchar(50) DEFAULT 'manual',
            sync_schedule varchar(50) DEFAULT '',
            status tinyint(1) DEFAULT 1,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        // 同步日志表
        $table_logs = $wpdb->prefix . 'fcsm_sync_logs';
        $sql_logs = "CREATE TABLE IF NOT EXISTS $table_logs (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            rule_id mediumint(9) NOT NULL,
            source_post_id bigint(20) NOT NULL,
            target_post_id bigint(20) DEFAULT NULL,
            target_site_id bigint(20) NOT NULL,
            sync_status varchar(50) NOT NULL,
            sync_message text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY rule_id (rule_id),
            KEY source_post_id (source_post_id)
        ) $charset_collate;";
        
        // 冲突记录表
        $table_conflicts = $wpdb->prefix . 'fcsm_conflicts';
        $sql_conflicts = "CREATE TABLE IF NOT EXISTS $table_conflicts (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            post_id bigint(20) NOT NULL,
            site_id bigint(20) NOT NULL,
            conflict_type varchar(100) NOT NULL,
            conflict_data text NOT NULL,
            resolution varchar(50) DEFAULT 'pending',
            resolved_by bigint(20) DEFAULT NULL,
            resolved_at datetime DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql_rules);
        dbDelta($sql_logs);
        dbDelta($sql_conflicts);
    }
}
?>

三、核心功能实现

3.1 内容处理器开发

<?php
/**
 * 内容处理器 - 负责内容的转换和同步
 */
class FCSM_Content_Processor {
    
    /**
     * 同步单篇文章到目标站点
     * 
     * @param int $post_id 源文章ID
     * @param int $target_site_id 目标站点ID
     * @param array $rule 同步规则
     * @return array 同步结果
     */
    public function sync_post_to_site($post_id, $target_site_id, $rule) {
        
        // 切换到源站点获取文章数据
        switch_to_blog($rule['source_site_id']);
        $source_post = get_post($post_id, ARRAY_A);
        
        if (!$source_post) {
            restore_current_blog();
            return array(
                'success' => false,
                'message' => '源文章不存在'
            );
        }
        
        // 获取文章元数据
        $post_meta = get_post_meta($post_id);
        
        // 获取分类和标签
        $categories = wp_get_post_categories($post_id, array('fields' => 'ids'));
        $tags = wp_get_post_tags($post_id, array('fields' => 'ids'));
        
        // 获取特色图片
        $thumbnail_id = get_post_thumbnail_id($post_id);
        
        restore_current_blog();
        
        // 切换到目标站点
        switch_to_blog($target_site_id);
        
        // 检查文章是否已存在
        $existing_post_id = $this->find_existing_post($source_post, $target_site_id);
        
        // 准备文章数据
        $post_data = $this->prepare_post_data($source_post, $rule);
        
        if ($existing_post_id) {
            // 更新现有文章
            $post_data['ID'] = $existing_post_id;
            $new_post_id = wp_update_post($post_data, true);
            $action = 'updated';
        } else {
            // 创建新文章
            $new_post_id = wp_insert_post($post_data, true);
            $action = 'created';
        }
        
        if (is_wp_error($new_post_id)) {
            restore_current_blog();
            return array(
                'success' => false,
                'message' => $new_post_id->get_error_message()
            );
        }
        
        // 同步元数据
        $this->sync_post_meta($new_post_id, $post_meta, $rule);
        
        // 同步分类和标签
        $this->sync_taxonomies($new_post_id, $categories, $tags, $rule);
        
        // 同步特色图片
        if ($thumbnail_id) {
            $this->sync_featured_image($new_post_id, $thumbnail_id, $rule);
        }
        
        restore_current_blog();
        
        return array(
            'success' => true,
            'post_id' => $new_post_id,
            'action' => $action,
            'message' => '文章同步成功'
        );
    }
    
    /**
     * 准备文章数据
     */
    private function prepare_post_data($source_post, $rule) {
        // 基础字段映射
        $post_data = array(
            'post_title'   => $source_post['post_title'],
            'post_content' => $source_post['post_content'],
            'post_excerpt' => $source_post['post_excerpt'],
            'post_status'  => $this->map_post_status($source_post['post_status'], $rule),
            'post_type'    => $source_post['post_type'],
            'post_author'  => $this->map_author($source_post['post_author'], $rule),
            'post_date'    => $source_post['post_date'],
            'post_date_gmt' => $source_post['post_date_gmt']
        );
        
        // 应用内容转换规则
        if (!empty($rule['content_transform'])) {
            $post_data = $this->apply_content_transform($post_data, $rule['content_transform']);
        }
        
        return $post_data;
    }
    
    /**
     * 同步文章元数据
     */
    private function sync_post_meta($post_id, $source_meta, $rule) {
        $meta_blacklist = array('_edit_lock', '_edit_last');
        $meta_whitelist = isset($rule['meta_whitelist']) ? $rule['meta_whitelist'] : array();
        
        foreach ($source_meta as $meta_key => $meta_values) {
            // 跳过黑名单中的元数据
            if (in_array($meta_key, $meta_blacklist)) {
                continue;
            }
            
            // 如果设置了白名单,只同步白名单中的元数据
            if (!empty($meta_whitelist) && !in_array($meta_key, $meta_whitelist)) {
                continue;
            }
            
            // 删除旧的元数据
            delete_post_meta($post_id, $meta_key);
            
            // 添加新的元数据
            foreach ($meta_values as $meta_value) {
                // 处理序列化数据
                $meta_value = maybe_unserialize($meta_value);
                add_post_meta($post_id, $meta_key, $meta_value);
            }
        }
    }
}
?>

3.2 冲突解决器实现

<?php
/**
 * 冲突解决器 - 处理内容同步中的冲突
 */
class FCSM_Conflict_Resolver {
    
    /**
     * 检测并处理冲突
     */
    public function detect_and_resolve_conflicts($source_post_id, $target_site_id, $rule) {
        $conflicts = array();
        
        // 检测标题冲突
        $title_conflict = $this->detect_title_conflict($source_post_id, $target_site_id);
        if ($title_conflict) {
            $conflicts[] = $title_conflict;
        }
        
        // 检测内容冲突
        $content_conflict = $this->detect_content_conflict($source_post_id, $target_site_id);
        if ($content_conflict) {
            $conflicts[] = $content_conflict;
        }
        
        // 根据规则自动解决冲突
        if (!empty($conflicts) && isset($rule['auto_resolve_conflicts'])) {
            foreach ($conflicts as $conflict) {
                $this->auto_resolve_conflict($conflict, $rule);
            }
        }
        
        return $conflicts;
    }
    
    /**
     * 检测标题冲突
     */
    private function detect_title_conflict($source_post_id, $target_site_id) {
        global $wpdb;
        
        switch_to_blog($target_site_id);
        
        $source_title = get_the_title($source_post_id);
        
        // 查找是否有相同标题的文章
        $query = $wpdb->prepare(
            "SELECT ID, post_title FROM {$wpdb->posts} 
             WHERE post_title = %s AND post_type = 'post' 
             AND post_status IN ('publish', 'draft', 'pending')",
            $source_title
        );
        
        $existing_posts = $wpdb->get_results($query);
        
        restore_current_blog();
        
        if (!empty($existing_posts)) {
            return array(
                'type' => 'title_duplicate',
                'source_post_id' => $source_post_id,
                'target_site_id' => $target_site_id,
                'conflicting_posts' => $existing_posts,
                'message' => '存在标题相同的文章'
            );
        }
        
        return false;
    }
    
    /**
     * 自动解决冲突
     */
    private function auto_resolve_conflict($conflict, $rule) {
        switch ($conflict['type']) {
            case 'title_duplicate':
                $this->resolve_title_conflict($conflict, $rule);
                break;
            case 'content_duplicate':
                $this->resolve_content_conflict($conflict, $rule);
                break;
        }
    }
    
    /**
     * 解决标题冲突
     */
    private function resolve_title_conflict($conflict, $rule) {
        $resolution_strategy = isset($rule['conflict_resolution']['title']) 
            ? $rule['conflict_resolution']['title'] 
            : 'rename';
        
        switch ($resolution_strategy) {
            case 'rename':
                // 在标题后添加时间戳
                $new_title = get_the_title($conflict['source_post_id']) . ' - ' . current_time('Y-m-d H:i:s');
                wp_update_post(array(
                    'ID' => $conflict['source_post_id'],
                    'post_title' => $new_title
                ));
                break;
                
            case 'skip':
                // 跳过同步
                return false;
                
            case 'overwrite':
                // 覆盖现有文章(需要额外处理)
                break;
        }
        
        return true;
    }
}
?>

四、管理界面开发

4.1 规则管理界面

<?php
/**
 * 规则管理界面
 */
class FCSM_Admin_Interface {
    
    /**
     * 添加管理菜单
     */
    public function add_admin_menu() {
        add_menu_page(
            '柔性内容同步管理',
            '内容同步',
            'manage_options',
            'fcsm-dashboard',
            array($this, 'render_dashboard'),
            'dashicons-update',
            30
        );
        
        add_submenu_page(
            'fcsm-dashboard',
            '同步规则',
            '同步规则',
            'manage_options',
            'fcsm-rules',
            array($this, 'render_rules_page')
        );
        
        add_submenu_page(
            'fcsm-dashboard',
            '同步日志',
            '同步日志',
            'manage_options',
            'fcsm-logs',
            array($this, 'render_logs_page')
        );
        
        add_submenu_page(
            'fcsm-dashboard',
            '冲突管理',
            '冲突管理',
            'manage_options',
            'fcsm-conflicts',
            array($this, 'render_conflicts_page')
        );
    }
    
    /**
     * 渲染规则管理页面
     */
    public function render_rules_page() {
        ?>
        <div class="wrap">
            <h1 class="wp-heading-inline">同步规则管理</h1>
            <a href="<?php echo admin_url('admin.php?page=fcsm-rules&action=add'); ?>" class="page-title-action">
                添加新规则
            </a>
            
            <hr class="wp-header-end">
            
            <div id="fcsm-rules-container">
                <?php
                $rules_table = new FCSM_Rules_Table();
                $rules_table->prepare_items();
                $rules_table->display();
                ?>
            </div>
            
            <!-- 规则编辑表单 -->
            <div id="fcsm-rule-form" style="display: none;">
                <form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
                    <input type="hidden" name="action" value="fcsm_save_rule">
                    <?php wp_nonce_field('fcsm_save_rule_nonce'); ?>
                    
                    <table class="form-table">
                        <tr>
                            <th scope="row"><label for="rule_name">规则名称</label></th>
                            <td><input type="text" id="rule_name" name="rule_name" class="regular-text" required></td>
                        </tr>
                        
                        <tr>
                            <th scope="row"><label for="source_site">源站点</label></th>
                            <td>
                                <select id="source_site" name="source_site_id" required>
                                    <option value="">选择源站点</option>
                                    <?php
                                    $sites = get_sites();
                                    foreach ($sites as $site) {
                                        echo '<option value="' . $site->blog_id . '">' . get_blog_details($site->blog_id)->blogname . '</option>';
                                    }
                                    ?>
                                </select>
                            </td>
                        </tr>
                        
                        <tr>

4.2 规则配置界面(续)

<tr>
    <th scope="row"><label for="target_sites">目标站点</label></th>
    <td>
        <select id="target_sites" name="target_site_ids[]" multiple="multiple" class="fcsm-select2" style="width: 100%;" required>
            <?php
            $sites = get_sites();
            foreach ($sites as $site) {
                echo '<option value="' . $site->blog_id . '">' . get_blog_details($site->blog_id)->blogname . '</option>';
            }
            ?>
        </select>
        <p class="description">按住Ctrl键可多选</p>
    </td>
</tr>

<tr>
    <th scope="row"><label for="post_types">内容类型</label></th>
    <td>
        <select id="post_types" name="post_types[]" multiple="multiple" class="fcsm-select2" style="width: 100%;" required>
            <?php
            $post_types = get_post_types(array('public' => true), 'objects');
            foreach ($post_types as $post_type) {
                echo '<option value="' . $post_type->name . '">' . $post_type->label . '</option>';
            }
            ?>
        </select>
    </td>
</tr>

<tr>
    <th scope="row"><label for="sync_mode">同步模式</label></th>
    <td>
        <select id="sync_mode" name="sync_mode" onchange="toggleScheduleField()">
            <option value="manual">手动同步</option>
            <option value="auto">自动同步</option>
            <option value="scheduled">定时同步</option>
        </select>
    </td>
</tr>

<tr id="schedule_field" style="display: none;">
    <th scope="row"><label for="sync_schedule">同步计划</label></th>
    <td>
        <select id="sync_schedule" name="sync_schedule">
            <option value="hourly">每小时</option>
            <option value="twicedaily">每12小时</option>
            <option value="daily">每天</option>
            <option value="weekly">每周</option>
            <option value="custom">自定义</option>
        </select>
        <div id="custom_schedule" style="display: none; margin-top: 10px;">
            <input type="text" name="custom_cron_expression" placeholder="Cron表达式,如: 0 2 * * *" class="regular-text">
            <p class="description">使用标准的Cron表达式格式</p>
        </div>
    </td>
</tr>

<tr>
    <th scope="row"><label for="sync_conditions">同步条件</label></th>
    <td>
        <textarea id="sync_conditions" name="sync_conditions" rows="5" cols="50" placeholder='例如: {"post_status": "publish", "categories": [1,2]}'></textarea>
        <p class="description">JSON格式的条件表达式</p>
    </td>
</tr>

<tr>
    <th scope="row"><label for="content_transform">内容转换规则</label></th>
    <td>
        <textarea id="content_transform" name="content_transform" rows="5" cols="50" placeholder='例如: {"replace": [["旧关键词", "新关键词"]], "append": "版权声明"}'></textarea>
        <p class="description">JSON格式的转换规则</p>
    </td>
</tr>

<tr>
    <th scope="row"><label>冲突解决策略</label></th>
    <td>
        <fieldset>
            <legend class="screen-reader-text">冲突解决策略</legend>
            <label>
                <input type="radio" name="conflict_resolution[title]" value="rename" checked>
                重命名标题
            </label><br>
            <label>
                <input type="radio" name="conflict_resolution[title]" value="skip">
                跳过同步
            </label><br>
            <label>
                <input type="radio" name="conflict_resolution[title]" value="overwrite">
                覆盖内容
            </label>
        </fieldset>
    </td>
</tr>

<tr>
    <th scope="row"><label for="meta_whitelist">元数据白名单</label></th>
    <td>
        <input type="text" id="meta_whitelist" name="meta_whitelist" class="large-text" placeholder="_thumbnail_id, _custom_field1, _custom_field2">
        <p class="description">逗号分隔的元数据键名,留空则同步所有元数据</p>
    </td>
</tr>
</table>

<p class="submit">
    <input type="submit" name="submit" id="submit" class="button button-primary" value="保存规则">
    <a href="<?php echo admin_url('admin.php?page=fcsm-rules'); ?>" class="button">取消</a>
</p>
</form>
</div>

<script>
jQuery(document).ready(function($) {
    // 初始化Select2
    $('.fcsm-select2').select2();
    
    // 显示/隐藏计划字段
    window.toggleScheduleField = function() {
        var mode = $('#sync_mode').val();
        if (mode === 'scheduled') {
            $('#schedule_field').show();
        } else {
            $('#schedule_field').hide();
        }
    }
    
    // 显示/隐藏自定义计划字段
    $('#sync_schedule').change(function() {
        if ($(this).val() === 'custom') {
            $('#custom_schedule').show();
        } else {
            $('#custom_schedule').hide();
        }
    });
    
    // 表单验证
    $('form').submit(function(e) {
        var ruleName = $('#rule_name').val();
        if (!ruleName.trim()) {
            alert('请输入规则名称');
            e.preventDefault();
            return false;
        }
        
        // 验证JSON格式
        try {
            var conditions = $('#sync_conditions').val();
            if (conditions.trim()) {
                JSON.parse(conditions);
            }
            
            var transform = $('#content_transform').val();
            if (transform.trim()) {
                JSON.parse(transform);
            }
        } catch (err) {
            alert('JSON格式错误: ' + err.message);
            e.preventDefault();
            return false;
        }
    });
});
</script>
<?php
    }
    
    /**
     * 渲染日志页面
     */
    public function render_logs_page() {
        ?>
        <div class="wrap">
            <h1>同步日志</h1>
            
            <div class="fcsm-filters">
                <form method="get">
                    <input type="hidden" name="page" value="fcsm-logs">
                    
                    <label for="filter_rule">规则:</label>
                    <select name="rule_id" id="filter_rule">
                        <option value="">所有规则</option>
                        <?php
                        global $wpdb;
                        $rules = $wpdb->get_results("SELECT id, rule_name FROM {$wpdb->prefix}fcsm_sync_rules");
                        foreach ($rules as $rule) {
                            $selected = isset($_GET['rule_id']) && $_GET['rule_id'] == $rule->id ? 'selected' : '';
                            echo '<option value="' . $rule->id . '" ' . $selected . '>' . $rule->rule_name . '</option>';
                        }
                        ?>
                    </select>
                    
                    <label for="filter_status">状态:</label>
                    <select name="status" id="filter_status">
                        <option value="">所有状态</option>
                        <option value="success" <?php echo isset($_GET['status']) && $_GET['status'] == 'success' ? 'selected' : ''; ?>>成功</option>
                        <option value="failed" <?php echo isset($_GET['status']) && $_GET['status'] == 'failed' ? 'selected' : ''; ?>>失败</option>
                        <option value="partial" <?php echo isset($_GET['status']) && $_GET['status'] == 'partial' ? 'selected' : ''; ?>>部分成功</option>
                    </select>
                    
                    <label for="filter_date">日期:</label>
                    <input type="date" name="date" id="filter_date" value="<?php echo isset($_GET['date']) ? $_GET['date'] : ''; ?>">
                    
                    <input type="submit" class="button" value="筛选">
                    <a href="<?php echo admin_url('admin.php?page=fcsm-logs'); ?>" class="button">重置</a>
                </form>
            </div>
            
            <?php
            $logs_table = new FCSM_Logs_Table();
            $logs_table->prepare_items();
            $logs_table->display();
            ?>
            
            <div class="fcsm-log-actions">
                <form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
                    <input type="hidden" name="action" value="fcsm_export_logs">
                    <?php wp_nonce_field('fcsm_export_logs_nonce'); ?>
                    <input type="submit" class="button" value="导出日志">
                </form>
                
                <form method="post" action="<?php echo admin_url('admin-post.php'); ?>" onsubmit="return confirm('确定要清空所有日志吗?此操作不可恢复。');">
                    <input type="hidden" name="action" value="fcsm_clear_logs">
                    <?php wp_nonce_field('fcsm_clear_logs_nonce'); ?>
                    <input type="submit" class="button button-secondary" value="清空日志">
                </form>
            </div>
        </div>
        <?php
    }
}
?>

五、高级功能实现

5.1 智能内容转换引擎

<?php
/**
 * 智能内容转换引擎
 */
class FCSM_Content_Transformer {
    
    /**
     * 应用内容转换规则
     */
    public function transform_content($content, $transform_rules) {
        if (empty($transform_rules) || !is_array($transform_rules)) {
            return $content;
        }
        
        // 文本替换
        if (isset($transform_rules['replace']) && is_array($transform_rules['replace'])) {
            foreach ($transform_rules['replace'] as $replacement) {
                if (is_array($replacement) && count($replacement) >= 2) {
                    $content = str_replace($replacement[0], $replacement[1], $content);
                }
            }
        }
        
        // 正则表达式替换
        if (isset($transform_rules['regex_replace']) && is_array($transform_rules['regex_replace'])) {
            foreach ($transform_rules['regex_replace'] as $pattern => $replacement) {
                $content = preg_replace($pattern, $replacement, $content);
            }
        }
        
        // 添加前缀/后缀
        if (isset($transform_rules['prepend'])) {
            $content = $transform_rules['prepend'] . $content;
        }
        
        if (isset($transform_rules['append'])) {
            $content .= $transform_rules['append'];
        }
        
        // 图片URL重写
        if (isset($transform_rules['rewrite_image_urls'])) {
            $content = $this->rewrite_image_urls($content, $transform_rules['rewrite_image_urls']);
        }
        
        // 自定义转换函数
        if (isset($transform_rules['custom_callback']) && is_callable($transform_rules['custom_callback'])) {
            $content = call_user_func($transform_rules['custom_callback'], $content);
        }
        
        return $content;
    }
    
    /**
     * 重写图片URL
     */
    private function rewrite_image_urls($content, $config) {
        $source_domain = isset($config['source_domain']) ? $config['source_domain'] : '';
        $target_domain = isset($config['target_domain']) ? $config['target_domain'] : '';
        
        if (empty($source_domain) || empty($target_domain)) {
            return $content;
        }
        
        // 匹配图片标签
        $pattern = '/<img[^>]+src="([^"]*' . preg_quote($source_domain, '/') . '[^"]*)"[^>]*>/i';
        $content = preg_replace_callback($pattern, function($matches) use ($source_domain, $target_domain) {
            $new_src = str_replace($source_domain, $target_domain, $matches[1]);
            return str_replace($matches[1], $new_src, $matches[0]);
        }, $content);
        
        // 匹配背景图片
        $pattern = '/background(-image)?:s*url(["']?([^"')]*' . preg_quote($source_domain, '/') . '[^"')]*)["']?)/i';
        $content = preg_replace_callback($pattern, function($matches) use ($source_domain, $target_domain) {
            $new_url = str_replace($source_domain, $target_domain, $matches[2]);
            return str_replace($matches[2], $new_url, $matches[0]);
        }, $content);
        
        return $content;
    }
    
    /**
     * 智能分类映射
     */
    public function map_categories($source_categories, $mapping_rules) {
        $mapped_categories = array();
        
        if (empty($mapping_rules) || !is_array($mapping_rules)) {
            return $source_categories;
        }
        
        foreach ($source_categories as $source_cat_id) {
            // 直接映射
            if (isset($mapping_rules['direct'][$source_cat_id])) {
                $mapped_categories[] = $mapping_rules['direct'][$source_cat_id];
                continue;
            }
            
            // 名称匹配映射
            $source_cat = get_category($source_cat_id);
            if ($source_cat && isset($mapping_rules['by_name'][$source_cat->name])) {
                $mapped_categories[] = $mapping_rules['by_name'][$source_cat->name];
                continue;
            }
            
            // 默认映射
            if (isset($mapping_rules['default'])) {
                $mapped_categories[] = $mapping_rules['default'];
            }
        }
        
        return array_unique($mapped_categories);
    }
}
?>

5.2 批量同步处理器

<?php
/**
 * 批量同步处理器
 */
class FCSM_Batch_Sync_Processor {
    
    private $batch_size = 10;
    private $max_retries = 3;
    
    /**
     * 执行批量同步
     */
    public function process_batch_sync($rule_id, $post_ids = array()) {
        $rule = $this->get_rule($rule_id);
        if (!$rule) {
            return array(
                'success' => false,
                'message' => '规则不存在'
            );
        }
        
        // 如果没有指定文章ID,根据规则获取文章
        if (empty($post_ids)) {
            $post_ids = $this->get_posts_by_rule($rule);
        }
        
        // 分批处理
        $batches = array_chunk($post_ids, $this->batch_size);
        $results = array(
            'total' => count($post_ids),
            'success' => 0,
            'failed' => 0,
            'details' => array()
        );
        
        foreach ($batches as $batch_index => $batch) {
            $batch_result = $this->process_single_batch($batch, $rule);
            
            $results['success'] += $batch_result['success'];
            $results['failed'] += $batch_result['failed'];
            $results['details'][] = $batch_result;
            
            // 记录进度
            $this->update_batch_progress($rule_id, $batch_index + 1, count($batches));
            
            // 防止超时,每批处理完后休息一下
            if (count($batches) > 1 && $batch_index < count($batches) - 1) {
                sleep(1);
            }
        }
        
        return $results;
    }
    
    /**
     * 处理单批文章
     */
    private function process_single_batch($post_ids, $rule) {
        $batch_result = array(
            'success' => 0,
            'failed' => 0,
            'posts' => array()
        );
        
        $content_processor = new FCSM_Content_Processor();
        $conflict_resolver = new FCSM_Conflict_Resolver();
        
        foreach ($post_ids as $post_id) {
            $post_result = array(
                'post_id' => $post_id,
                'sync_results' => array()
            );
            
            // 处理每个目标站点
            foreach ($rule['target_site_ids'] as $target_site_id) {
                // 检测冲突
                $conflicts = $conflict_resolver->detect_and_resolve_conflicts(
                    $post_id, 
                    $target_site_id, 
                    $rule
                );
                
                // 执行同步
                $sync_result = $content_processor->sync_post_to_site(
                    $post_id,
                    $target_site_id,
                    $rule
                );
                
                // 记录结果
                $post_result['sync_results'][$target_site_id] = array(
                    'success' => $sync_result['success'],
                    'message' => $sync_result['message'],
                    'conflicts' => $conflicts,
                    'new_post_id' => isset($sync_result['post_id']) ? $sync_result['post_id'] : null
                );
                
                if ($sync_result['success']) {
                    $batch_result['success']++;
                } else {
                    $batch_result['failed']++;
                }
                
                // 记录日志
                $this->log_sync_result($rule['id'], $post_id, $target_site_id, $sync_result);
            }
            
            $batch_result['posts'][] = $post_result;
        }
        
        return $batch_result;
    }
    
    /**
     * 根据规则获取文章
     */
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/6491.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部