首页 / 教程文章 / WordPress网络传媒柔性内容多渠道同步插件开发教程

WordPress网络传媒柔性内容多渠道同步插件开发教程

WordPress网络传媒柔性内容多渠道同步插件开发教程

一、插件开发背景与需求分析

在当今数字化媒体时代,网络传媒机构需要在多个平台同步发布内容,包括微信公众号、微博、头条号、知乎等多个渠道。手动同步不仅效率低下,还容易出错。本教程将指导您开发一个WordPress柔性内容多渠道同步插件,实现一键发布到多个平台。

核心需求:

  1. 支持自定义内容转换规则,适应不同平台的内容格式要求
  2. 可配置的发布渠道管理
  3. 定时发布和即时发布两种模式
  4. 发布状态跟踪和错误处理
  5. 支持图片等媒体资源的自动处理

二、插件基础结构搭建

首先,我们需要创建插件的基本文件结构:

<?php
/**
 * Plugin Name: 柔性内容多渠道同步插件
 * Plugin URI: https://yourwebsite.com/
 * Description: 实现WordPress内容一键同步到多个媒体平台
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 */

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

// 定义插件常量
define('FLEX_SYNC_VERSION', '1.0.0');
define('FLEX_SYNC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FLEX_SYNC_PLUGIN_URL', plugin_dir_url(__FILE__));

// 初始化插件
class FlexContentSync {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // 激活/停用插件时的操作
        register_activation_hook(__FILE__, array($this, 'activate'));
        register_deactivation_hook(__FILE__, array($this, 'deactivate'));
        
        // 初始化
        add_action('plugins_loaded', array($this, 'init'));
        
        // 添加管理菜单
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // 保存文章时触发同步
        add_action('save_post', array($this, 'on_save_post'), 10, 3);
    }
    
    public function activate() {
        // 创建必要的数据库表
        $this->create_tables();
        
        // 设置默认选项
        $this->set_default_options();
    }
    
    public function deactivate() {
        // 清理临时数据
        // 注意:这里不清除配置数据,以便重新激活时保留设置
    }
    
    public function init() {
        // 加载文本域
        load_plugin_textdomain('flex-sync', false, dirname(plugin_basename(__FILE__)) . '/languages');
        
        // 加载必要的类
        $this->load_dependencies();
    }
    
    // 其他方法将在后续章节实现
}

// 启动插件
FlexContentSync::get_instance();
?>

三、数据库设计与渠道管理

我们需要设计数据库表来存储渠道配置和同步记录:

<?php
// 在FlexContentSync类中添加以下方法

private function create_tables() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    $table_name_channels = $wpdb->prefix . 'flex_sync_channels';
    $table_name_logs = $wpdb->prefix . 'flex_sync_logs';
    
    // 渠道配置表
    $sql_channels = "CREATE TABLE IF NOT EXISTS $table_name_channels (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        channel_name varchar(100) NOT NULL,
        channel_type varchar(50) NOT NULL,
        api_config text NOT NULL,
        is_active tinyint(1) DEFAULT 1,
        content_rules text,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id)
    ) $charset_collate;";
    
    // 同步日志表
    $sql_logs = "CREATE TABLE IF NOT EXISTS $table_name_logs (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        post_id bigint(20) NOT NULL,
        channel_id mediumint(9) NOT NULL,
        status varchar(20) NOT NULL,
        response text,
        published_url varchar(500),
        published_at datetime,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY post_id (post_id),
        KEY channel_id (channel_id)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql_channels);
    dbDelta($sql_logs);
}

// 渠道管理类
class ChannelManager {
    
    public static function get_channels($active_only = true) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'flex_sync_channels';
        
        $where = $active_only ? "WHERE is_active = 1" : "";
        $query = "SELECT * FROM $table_name $where ORDER BY channel_name";
        
        return $wpdb->get_results($query);
    }
    
    public static function add_channel($data) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'flex_sync_channels';
        
        $defaults = array(
            'is_active' => 1,
            'content_rules' => json_encode(array(
                'max_length' => 0,
                'image_count' => 0,
                'format' => 'html'
            ))
        );
        
        $data = wp_parse_args($data, $defaults);
        
        return $wpdb->insert($table_name, $data);
    }
    
    public static function update_channel($id, $data) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'flex_sync_channels';
        
        return $wpdb->update($table_name, $data, array('id' => $id));
    }
    
    public static function delete_channel($id) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'flex_sync_channels';
        
        return $wpdb->delete($table_name, array('id' => $id));
    }
}
?>

四、内容转换引擎开发

不同平台对内容格式有不同的要求,我们需要开发一个灵活的内容转换引擎:

<?php
class ContentTransformer {
    
    private $post;
    private $channel_rules;
    
    public function __construct($post_id, $channel_rules) {
        $this->post = get_post($post_id);
        $this->channel_rules = is_string($channel_rules) ? 
            json_decode($channel_rules, true) : $channel_rules;
    }
    
    /**
     * 转换内容为适合目标平台的格式
     */
    public function transform() {
        $content = $this->post->post_content;
        
        // 应用转换规则
        $content = $this->apply_rules($content);
        
        // 处理图片
        $content = $this->process_images($content);
        
        // 处理长度限制
        $content = $this->handle_length_limit($content);
        
        return array(
            'title' => $this->transform_title(),
            'content' => $content,
            'excerpt' => $this->transform_excerpt(),
            'images' => $this->extract_images()
        );
    }
    
    private function apply_rules($content) {
        $rules = $this->channel_rules;
        
        // 移除短代码
        if (isset($rules['remove_shortcodes']) && $rules['remove_shortcodes']) {
            $content = strip_shortcodes($content);
        }
        
        // 转换HTML标签
        if (isset($rules['format']) && $rules['format'] === 'plaintext') {
            $content = wp_strip_all_tags($content);
        } elseif (isset($rules['format']) && $rules['format'] === 'markdown') {
            $content = $this->html_to_markdown($content);
        }
        
        // 添加来源声明
        if (isset($rules['add_source']) && $rules['add_source']) {
            $content .= "nn来源: " . get_bloginfo('name');
        }
        
        return $content;
    }
    
    private function process_images($content) {
        // 提取内容中的图片
        preg_match_all('/<img[^>]+>/i', $content, $img_matches);
        
        foreach ($img_matches[0] as $img_tag) {
            // 根据渠道规则处理图片
            // 这里可以添加图片上传到图床、压缩等逻辑
            if (isset($this->channel_rules['upload_images']) && 
                $this->channel_rules['upload_images']) {
                // 上传图片到指定图床
                $new_img_tag = $this->upload_and_replace_image($img_tag);
                $content = str_replace($img_tag, $new_img_tag, $content);
            }
        }
        
        return $content;
    }
    
    private function handle_length_limit($content) {
        if (isset($this->channel_rules['max_length']) && 
            $this->channel_rules['max_length'] > 0) {
            
            $max_length = intval($this->channel_rules['max_length']);
            
            if (mb_strlen($content) > $max_length) {
                $content = mb_substr($content, 0, $max_length - 3) . '...';
            }
        }
        
        return $content;
    }
    
    private function transform_title() {
        $title = $this->post->post_title;
        
        // 这里可以添加标题转换规则
        if (isset($this->channel_rules['title_prefix'])) {
            $title = $this->channel_rules['title_prefix'] . $title;
        }
        
        return $title;
    }
    
    private function extract_images() {
        $images = array();
        $content = $this->post->post_content;
        
        preg_match_all('/<img[^>]+src="([^">]+)"/i', $content, $matches);
        
        if (!empty($matches[1])) {
            $images = $matches[1];
            
            // 限制图片数量
            if (isset($this->channel_rules['image_count']) && 
                $this->channel_rules['image_count'] > 0) {
                $max_images = intval($this->channel_rules['image_count']);
                $images = array_slice($images, 0, $max_images);
            }
        }
        
        return $images;
    }
    
    // 其他辅助方法...
}
?>

五、平台API集成与发布器

接下来,我们实现不同平台的API集成:

<?php
// 发布器基类
abstract class PlatformPublisher {
    
    protected $api_config;
    protected $channel_id;
    
    public function __construct($api_config, $channel_id) {
        $this->api_config = $api_config;
        $this->channel_id = $channel_id;
    }
    
    abstract public function publish($transformed_content);
    abstract public function test_connection();
    
    protected function log_result($post_id, $status, $response, $published_url = '') {
        global $wpdb;
        $table_name = $wpdb->prefix . 'flex_sync_logs';
        
        $data = array(
            'post_id' => $post_id,
            'channel_id' => $this->channel_id,
            'status' => $status,
            'response' => is_array($response) ? json_encode($response) : $response,
            'published_url' => $published_url,
            'published_at' => current_time('mysql')
        );
        
        return $wpdb->insert($table_name, $data);
    }
}

// 微信公众号发布器
class WeChatPublisher extends PlatformPublisher {
    
    public function publish($transformed_content) {
        // 微信公众号API实现
        $api_url = 'https://api.weixin.qq.com/cgi-bin/material/add_news';
        
        $data = array(
            'articles' => array(
                array(
                    'title' => $transformed_content['title'],
                    'content' => $transformed_content['content'],
                    'digest' => $transformed_content['excerpt'],
                    'thumb_media_id' => $this->upload_cover_image($transformed_content['images'])
                )
            )
        );
        
        // 获取访问令牌
        $access_token = $this->get_access_token();
        
        // 发送请求
        $response = wp_remote_post($api_url . '?access_token=' . $access_token, array(
            'body' => json_encode($data, JSON_UNESCAPED_UNICODE),
            'headers' => array('Content-Type' => 'application/json')
        ));
        
        if (is_wp_error($response)) {
            $this->log_result(
                $transformed_content['post_id'], 
                'error', 
                $response->get_error_message()
            );
            return false;
        }
        
        $body = json_decode(wp_remote_retrieve_body($response), true);
        
        if (isset($body['media_id'])) {
            $this->log_result(
                $transformed_content['post_id'], 
                'success', 
                $body,
                'https://mp.weixin.qq.com/s/' . $body['media_id']
            );
            return true;
        } else {
            $this->log_result(
                $transformed_content['post_id'], 
                'error', 
                $body
            );
            return false;
        }
    }
    
    private function get_access_token() {
        // 实现获取access_token的逻辑
        // 这里应该包含缓存机制,避免频繁请求
        return 'your_access_token';
    }
    
    private function upload_cover_image($images) {
        // 上传封面图片到微信服务器
        if (!empty($images)) {
            // 实现图片上传逻辑
            return 'thumb_media_id';
        }
        return '';
    }
    
    public function test_connection() {
        // 测试API连接
        return array('success' => true, 'message' => '连接成功');
    }
}

// 发布器工厂
class PublisherFactory {
    
    public static function create($channel_type, $api_config, $channel_id) {
        switch ($channel_type) {
            case 'wechat':
                return new WeChatPublisher($api_config, $channel_id);
            case 'weibo':
                // 返回微博发布器实例
                // return new WeiboPublisher($api_config, $channel_id);
            case 'zhihu':
                // 返回知乎发布器实例
                // return new ZhihuPublisher($api_config, $channel_id);
            default:
                throw new Exception('不支持的渠道类型: ' . $channel_type);
        }
    }
}
?>

六、管理界面与配置页面

最后,我们创建插件的管理界面:

<?php
// 在FlexContentSync类中添加管理菜单方法

public function add_admin_menu() {
    // 主菜单
    add_menu_page(
        '多渠道同步',
        '内容同步',
        'manage_options',
        'flex-sync',
        array($this, 'render_main_page'),
        'dashicons-share',
        30
    );
    
    // 子菜单
    add_submenu_page(
        'flex-sync',
        '渠道管理',
        '渠道管理',
        'manage_options',
        'flex-sync-channels',
        array($this, 'render_channels_page')
    );
    
    add_submenu_page(
        'flex-sync',
        '同步日志',
        '同步日志',
        'manage_options',
        'flex-sync-logs',
        array($this, 'render_logs_page')
    );
    
    add_submenu_page(
        'flex-sync',
        '设置',
        '设置',
        'manage_options',
        'flex-sync-settings',
        array($this, 'render_settings_page')
    );
}

public function render_main_page() {
    ?>
    <div class="wrap">
        <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
        
        <div class="card">
            <h2>快速发布</h2>
            <form method="post" action="">
                <?php wp_nonce_field('flex_sync_quick_publish', 'flex_sync_nonce'); ?>
                
                <table class="form-table">
                    <tr>
                        <th scope="row">选择文章</th>
                        <td>
                            <select name="post_id" required>
                                <option value="">选择要发布的文章</option>
                                <?php
                                $args = array(
                                    'post_type' => 'post',
                                    'post_status' => 'publish',
                                    'posts_per_page' => 50
                                );
                                $posts = get_posts($args);
                                foreach ($posts as $post) {
                                    echo '<option value="' . $post->ID . '">' . 
                                         esc_html($post->post_title) . '</option>';
                                }
                                ?>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <th scope="row">选择渠道</th>
                        <td>
                            <?php
                            $channels = ChannelManager::get_channels();
                            foreach ($channels as $channel) {
                                echo '<label>';
                                echo '<input type="checkbox" name="channels[]" value="' . 
                                     $channel->id . '"> ';
                                echo esc_html($channel->channel_name);
                                echo '</label><br>';
                            }
                            ?>
                        </td>
                    </tr>
                </table>
                
                <p class="submit">
                    <input type="submit" name="submit" class="button button-primary" 
                           value="立即发布">
                    <input type="submit" name="schedule" class="button" 
                           value="定时发布">
                </p>
            </form>
        </div>
        
        <div class="card">
            <h2>发布统计</h2>
            <p>最近7天发布情况统计图将显示在这里</p>
            <!-- 这里可以添加统计图表 -->
        </div>
    </div>
    <?php
}

// 处理发布请求
public function handle_publish_request() {

publish', 'flex_sync_nonce')) {

    $post_id = intval($_POST['post_id']);
    $channels = isset($_POST['channels']) ? array_map('intval', $_POST['channels']) : array();
    
    if ($post_id && !empty($channels)) {
        $this->sync_to_channels($post_id, $channels);
        
        // 显示成功消息
        add_settings_error(
            'flex_sync_messages',
            'flex_sync_message',
            '内容已开始同步到选定的渠道',
            'success'
        );
    }
}

}
?>


## 七、文章编辑界面集成

为了让用户在编辑文章时就能同步,我们在文章编辑页面添加元框:

<?php
class PostMetaBox {


public static function init() {
    add_action('add_meta_boxes', array(__CLASS__, 'add_meta_box'));
    add_action('save_post', array(__CLASS__, 'save_meta_box'), 10, 2);
    add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'));
}

public static function add_meta_box() {
    add_meta_box(
        'flex_sync_meta_box',
        '多渠道同步',
        array(__CLASS__, 'render_meta_box'),
        'post',
        'side',
        'high'
    );
}

public static function render_meta_box($post) {
    wp_nonce_field('flex_sync_meta_box', 'flex_sync_meta_box_nonce');
    
    // 获取已配置的渠道
    $channels = ChannelManager::get_channels();
    
    // 获取该文章已同步的渠道
    $synced_channels = self::get_synced_channels($post->ID);
    
    ?>
    <div id="flex-sync-meta-box">
        <p><strong>选择要同步的渠道:</strong></p>
        
        <?php if (empty($channels)): ?>
            <p class="description">请先在<a href="<?php echo admin_url('admin.php?page=flex-sync-channels'); ?>">渠道管理</a>中添加渠道。</p>
        <?php else: ?>
            <div class="channel-list">
                <?php foreach ($channels as $channel): ?>
                    <label>
                        <input type="checkbox" 
                               name="flex_sync_channels[]" 
                               value="<?php echo esc_attr($channel->id); ?>"
                               <?php checked(in_array($channel->id, $synced_channels)); ?>>
                        <?php echo esc_html($channel->channel_name); ?>
                        
                        <?php if (in_array($channel->id, $synced_channels)): ?>
                            <span class="dashicons dashicons-yes" style="color: #46b450;"></span>
                        <?php endif; ?>
                    </label><br>
                <?php endforeach; ?>
            </div>
            
            <div style="margin-top: 15px;">
                <label>
                    <input type="checkbox" name="flex_sync_immediate" value="1">
                    发布时立即同步
                </label>
            </div>
            
            <div style="margin-top: 10px;">
                <button type="button" id="flex-sync-test" class="button button-secondary">
                    测试所选渠道
                </button>
                <button type="button" id="flex-sync-preview" class="button button-secondary">
                    内容预览
                </button>
            </div>
            
            <div id="flex-sync-status" style="margin-top: 10px; display: none;">
                <!-- 同步状态将在这里显示 -->
            </div>
        <?php endif; ?>
    </div>
    
    <script type="text/javascript">
    jQuery(document).ready(function($) {
        $('#flex-sync-test').on('click', function() {
            var channels = [];
            $('input[name="flex_sync_channels[]"]:checked').each(function() {
                channels.push($(this).val());
            });
            
            if (channels.length === 0) {
                alert('请至少选择一个渠道');
                return;
            }
            
            $('#flex-sync-status').html('<p>测试中...</p>').show();
            
            $.post(ajaxurl, {
                action: 'flex_sync_test_channels',
                post_id: <?php echo $post->ID; ?>,
                channels: channels,
                nonce: '<?php echo wp_create_nonce("flex_sync_test"); ?>'
            }, function(response) {
                $('#flex-sync-status').html(response.data);
            });
        });
        
        $('#flex-sync-preview').on('click', function() {
            var channels = [];
            $('input[name="flex_sync_channels[]"]:checked').each(function() {
                channels.push($(this).val());
            });
            
            if (channels.length === 0) {
                alert('请至少选择一个渠道');
                return;
            }
            
            // 打开预览窗口
            window.open('<?php echo admin_url("admin-ajax.php?action=flex_sync_preview&post_id=" . $post->ID); ?>&channels=' + channels.join(','), 
                      'preview', 'width=800,height=600');
        });
    });
    </script>
    <?php
}

public static function save_meta_box($post_id, $post) {
    // 验证nonce
    if (!isset($_POST['flex_sync_meta_box_nonce']) || 
        !wp_verify_nonce($_POST['flex_sync_meta_box_nonce'], 'flex_sync_meta_box')) {
        return;
    }
    
    // 检查自动保存
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
    
    // 检查权限
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }
    
    // 保存选择的渠道
    if (isset($_POST['flex_sync_channels'])) {
        $channels = array_map('intval', $_POST['flex_sync_channels']);
        update_post_meta($post_id, '_flex_sync_channels', $channels);
    } else {
        delete_post_meta($post_id, '_flex_sync_channels');
    }
    
    // 如果勾选了立即同步,并且文章已发布
    if (isset($_POST['flex_sync_immediate']) && $post->post_status === 'publish') {
        $channels = isset($_POST['flex_sync_channels']) ? 
                   array_map('intval', $_POST['flex_sync_channels']) : array();
        
        if (!empty($channels)) {
            // 异步执行同步,避免阻塞保存过程
            wp_schedule_single_event(time() + 5, 'flex_sync_async_publish', array($post_id, $channels));
        }
    }
}

public static function get_synced_channels($post_id) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'flex_sync_logs';
    
    $query = $wpdb->prepare(
        "SELECT DISTINCT channel_id FROM $table_name WHERE post_id = %d AND status = 'success'",
        $post_id
    );
    
    $results = $wpdb->get_col($query);
    return $results ? array_map('intval', $results) : array();
}

public static function enqueue_scripts($hook) {
    if ('post.php' === $hook || 'post-new.php' === $hook) {
        wp_enqueue_script(
            'flex-sync-admin',
            FLEX_SYNC_PLUGIN_URL . 'assets/js/admin.js',
            array('jquery'),
            FLEX_SYNC_VERSION,
            true
        );
        
        wp_localize_script('flex-sync-admin', 'flexSync', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('flex_sync_ajax')
        ));
    }
}

}

// 初始化元框
PostMetaBox::init();
?>


## 八、AJAX处理与异步任务

处理前端AJAX请求和后台异步任务:

<?php
class AjaxHandler {


public static function init() {
    // 测试渠道连接
    add_action('wp_ajax_flex_sync_test_channels', array(__CLASS__, 'test_channels'));
    
    // 内容预览
    add_action('wp_ajax_flex_sync_preview', array(__CLASS__, 'preview_content'));
    
    // 手动触发同步
    add_action('wp_ajax_flex_sync_manual', array(__CLASS__, 'manual_sync'));
    
    // 获取同步状态
    add_action('wp_ajax_flex_sync_status', array(__CLASS__, 'get_sync_status'));
    
    // 异步发布任务
    add_action('flex_sync_async_publish', array(__CLASS__, 'async_publish'), 10, 2);
}

public static function test_channels() {
    check_ajax_referer('flex_sync_test', 'nonce');
    
    $post_id = intval($_POST['post_id']);
    $channel_ids = isset($_POST['channels']) ? array_map('intval', $_POST['channels']) : array();
    
    if (empty($channel_ids)) {
        wp_send_json_error('请选择要测试的渠道');
    }
    
    $results = array();
    foreach ($channel_ids as $channel_id) {
        $channel = self::get_channel_by_id($channel_id);
        if ($channel) {
            try {
                $publisher = PublisherFactory::create(
                    $channel->channel_type,
                    json_decode($channel->api_config, true),
                    $channel_id
                );
                
                $test_result = $publisher->test_connection();
                $results[] = array(
                    'channel' => $channel->channel_name,
                    'success' => $test_result['success'],
                    'message' => $test_result['message']
                );
            } catch (Exception $e) {
                $results[] = array(
                    'channel' => $channel->channel_name,
                    'success' => false,
                    'message' => $e->getMessage()
                );
            }
        }
    }
    
    ob_start();
    ?>
    <div class="test-results">
        <h4>渠道连接测试结果:</h4>
        <ul>
            <?php foreach ($results as $result): ?>
                <li>
                    <strong><?php echo esc_html($result['channel']); ?>:</strong>
                    <?php if ($result['success']): ?>
                        <span style="color: green;">✓ <?php echo esc_html($result['message']); ?></span>
                    <?php else: ?>
                        <span style="color: red;">✗ <?php echo esc_html($result['message']); ?></span>
                    <?php endif; ?>
                </li>
            <?php endforeach; ?>
        </ul>
    </div>
    <?php
    $html = ob_get_clean();
    
    wp_send_json_success($html);
}

public static function preview_content() {
    $post_id = intval($_GET['post_id']);
    $channel_ids = isset($_GET['channels']) ? 
                  array_map('intval', explode(',', $_GET['channels'])) : array();
    
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <title>内容预览</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 20px; }
            .preview-container { max-width: 800px; margin: 0 auto; }
            .channel-preview { margin-bottom: 40px; border: 1px solid #ddd; padding: 20px; }
            .channel-name { background: #f1f1f1; padding: 10px; margin: -20px -20px 20px -20px; }
            .content-preview { line-height: 1.6; }
            .image-preview { max-width: 100%; height: auto; margin: 10px 0; }
        </style>
    </head>
    <body>
        <div class="preview-container">
            <h1>内容预览</h1>
            
            <?php foreach ($channel_ids as $channel_id): 
                $channel = self::get_channel_by_id($channel_id);
                if (!$channel) continue;
                
                $transformer = new ContentTransformer($post_id, $channel->content_rules);
                $transformed = $transformer->transform();
            ?>
                <div class="channel-preview">
                    <div class="channel-name">
                        <h2><?php echo esc_html($channel->channel_name); ?></h2>
                    </div>
                    
                    <div class="content-preview">
                        <h3><?php echo esc_html($transformed['title']); ?></h3>
                        <div><?php echo wpautop($transformed['content']); ?></div>
                        
                        <?php if (!empty($transformed['images'])): ?>
                            <h4>包含的图片:</h4>
                            <?php foreach ($transformed['images'] as $image): ?>
                                <img src="<?php echo esc_url($image); ?>" class="image-preview">
                            <?php endforeach; ?>
                        <?php endif; ?>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
    </body>
    </html>
    <?php
    exit;
}

public static function async_publish($post_id, $channels) {
    // 这里调用同步方法
    $flex_sync = FlexContentSync::get_instance();
    $flex_sync->sync_to_channels($post_id, $channels);
}

private static function get_channel_by_id($channel_id) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'flex_sync_channels';
    
    return $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM $table_name WHERE id = %d",
        $channel_id
    ));
}

}

// 初始化AJAX处理器
AjaxHandler::init();
?>


## 九、定时任务与批量处理

实现定时同步和批量处理功能:

<?php
class BatchProcessor {


public static function init() {
    // 注册定时任务
    add_filter('cron_schedules', array(__CLASS__, 'add_cron_schedules'));
    add_action('flex_sync_batch_process', array(__CLASS__, 'process_batch'));
    
    // 激活插件时安排定时任务
    register_activation_hook(__FILE__, array(__CLASS__, 'schedule_cron'));
    register_deactivation_hook(__FILE__, array(__CLASS__, 'unschedule_cron'));
}

public static function add_cron_schedules($schedules) {
    $schedules['flex_sync_5min'] = array(
        'interval' => 300,
        'display'  => __('每5分钟', 'flex-sync')
    );
    
    $schedules['flex_sync_hourly'] = array(
        'interval' => 3600,
        'display'  => __('每小时', 'flex-sync')
    );
    
    return $schedules;
}

public static function schedule_cron() {
    if (!wp_next_scheduled('flex_sync_batch_process')) {
        wp_schedule_event(time(), 'flex_sync_hourly', 'flex_sync_batch_process');
    }
}

public static function unschedule_cron() {
    $timestamp = wp_next_scheduled('flex_sync_batch_process');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'flex_sync_batch_process');
    }
}

public static function process_batch() {
    // 获取需要定时发布的文章
    $pending_posts = self::get_pending_posts();
    
    foreach ($pending_posts as $post) {
        // 获取该文章需要同步的渠道
        $channels = get_post_meta($post->ID, '_flex_sync_scheduled', true);
        
        if ($channels && is_array($channels)) {
            $flex_sync = FlexContentSync::get_instance();
            $flex_sync->sync_to_channels($post->ID, $channels);
            
            // 清除定时标记
            delete_post_meta($post->ID, '_flex_sync_scheduled');
        }
    }
    
    // 清理旧的同步日志(保留30天)
    self::cleanup_old_logs();
}

private static function get_pending_posts() {
    global $wpdb;
    
    $query = "
        SELECT p.ID, p.post_title 
        FROM {$wpdb->posts} p 
        INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id 
        WHERE p.post_status = 'publish' 
        AND pm.meta_key = '_flex_sync_scheduled' 
        AND pm.meta_value != ''
        ORDER BY p.post_date DESC 
        LIMIT 20
    ";
    
    return $wpdb->get_results($query);
}

private static function cleanup_old_logs() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'flex_sync_logs';
    
    $thirty_days_ago = date('Y-m-d H:i:s', strtotime('-30 days'));
    
    $wpdb->query($wpdb->prepare(
        "DELETE FROM $table_name WHERE created_at < %s",
        $thirty_days_ago
    ));
}

/**
 * 批量同步多篇文章到多个渠道
 */
public static function batch_sync($post_ids, $channel_ids) {
    $results = array();
    
    foreach ($post_ids as $post_id) {
        foreach ($channel_ids as $channel_id) {
            try {
                $flex_sync = FlexContentSync::get_instance();
                $success = $flex_sync->sync_to_channel($post_id, $channel_id);
                
                $results[] = array(
                    'post_id' => $post_id,
                    'channel_id' => $channel_id,
                    'success' => $success,
                    'message' => $success ? '同步成功' : '同步失败'
                );
            } catch (Exception $e) {
                $results[] = array(
                    'post_id' => $post_id,
                    'channel_id' => $channel_id,
                    'success' => false,
                    'message' => $e->getMessage()
                );
            }
        }
    }
    
    return $results;
}

}

本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5867.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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