首页 / 应用软件 / 手把手教学,为WordPress集成智能化的网站死链检测与自动修复工具

手把手教学,为WordPress集成智能化的网站死链检测与自动修复工具

手把手教学:为WordPress集成智能化的网站死链检测与自动修复工具

引言:为什么WordPress网站需要死链检测与修复工具

在当今互联网时代,网站链接的完整性和可用性直接影响用户体验和搜索引擎排名。根据权威统计,一个拥有超过1000个页面的网站中,平均有5%-10%的链接可能失效或成为"死链"。对于使用WordPress构建的网站而言,随着内容不断积累和更新,死链问题会日益严重。

死链不仅导致访客无法访问目标内容,还会损害网站的专业形象,更重要的是,搜索引擎会将死链数量作为网站质量评估的指标之一,直接影响SEO排名。传统的手动检测方法耗时耗力,且难以实时发现新出现的死链问题。因此,为WordPress集成智能化的死链检测与自动修复工具显得尤为重要。

本文将详细介绍如何通过WordPress代码二次开发,实现一个功能完善的死链检测与自动修复系统,让您的网站始终保持链接健康状态。

第一章:准备工作与环境配置

1.1 开发环境要求

在开始开发之前,我们需要确保具备以下环境条件:

  • WordPress 5.0及以上版本
  • PHP 7.2及以上版本(推荐PHP 7.4+)
  • MySQL 5.6及以上版本
  • 服务器支持cURL扩展
  • 适当的服务器内存和CPU资源(检测过程可能消耗资源)

1.2 创建插件基础结构

首先,我们需要创建一个独立的WordPress插件来承载我们的死链检测功能:

  1. 在WordPress的wp-content/plugins/目录下创建新文件夹smart-link-checker
  2. 在该文件夹中创建主插件文件smart-link-checker.php
  3. 添加插件基本信息:
<?php
/**
 * Plugin Name: Smart Link Checker & Fixer
 * Plugin URI: https://yourwebsite.com/smart-link-checker
 * Description: 智能化的网站死链检测与自动修复工具
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL v2 or later
 * Text Domain: smart-link-checker
 */

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

// 定义插件常量
define('SLC_VERSION', '1.0.0');
define('SLC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SLC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('SLC_MAX_LINKS_PER_RUN', 100); // 每次运行检测的最大链接数
define('SLC_REQUEST_TIMEOUT', 15); // 请求超时时间(秒)

1.3 创建数据库表结构

我们需要创建数据库表来存储链接检测结果和历史记录:

// 在插件激活时创建数据库表
register_activation_hook(__FILE__, 'slc_create_database_tables');

function slc_create_database_tables() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    $table_name = $wpdb->prefix . 'slc_links';
    $history_table = $wpdb->prefix . 'slc_link_history';
    
    // 主链接表
    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        url varchar(1000) NOT NULL,
        source_id bigint(20) NOT NULL,
        source_type varchar(50) NOT NULL,
        last_checked datetime DEFAULT NULL,
        status_code int(4) DEFAULT NULL,
        status varchar(50) DEFAULT 'pending',
        redirect_to varchar(1000) DEFAULT NULL,
        error_message text,
        check_count int(11) DEFAULT 0,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY url_index (url(191)),
        KEY status_index (status),
        KEY source_index (source_type, source_id)
    ) $charset_collate;";
    
    // 历史记录表
    $sql2 = "CREATE TABLE IF NOT EXISTS $history_table (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        link_id bigint(20) NOT NULL,
        status_code int(4) DEFAULT NULL,
        response_time float DEFAULT NULL,
        checked_at datetime DEFAULT CURRENT_TIMESTAMP,
        notes text,
        PRIMARY KEY (id),
        KEY link_id_index (link_id)
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    dbDelta($sql2);
    
    // 添加默认选项
    add_option('slc_settings', array(
        'check_frequency' => 'daily',
        'auto_fix_redirects' => true,
        'send_notifications' => true,
        'notification_email' => get_option('admin_email'),
        'excluded_domains' => array(),
        'max_redirects' => 3
    ));
}

第二章:核心功能模块开发

2.1 链接提取器模块

首先,我们需要从WordPress内容中提取所有链接:

class SLC_Link_Extractor {
    
    /**
     * 从所有文章和页面中提取链接
     */
    public static function extract_all_links() {
        global $wpdb;
        
        $links = array();
        
        // 从文章内容中提取链接
        $posts = $wpdb->get_results("SELECT ID, post_content FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type IN ('post', 'page')");
        
        foreach ($posts as $post) {
            $post_links = self::extract_from_content($post->post_content);
            
            foreach ($post_links as $link) {
                $links[] = array(
                    'url' => $link,
                    'source_id' => $post->ID,
                    'source_type' => 'post'
                );
            }
        }
        
        // 从评论中提取链接
        $comments = $wpdb->get_results("SELECT comment_ID, comment_content FROM {$wpdb->comments} WHERE comment_approved = '1'");
        
        foreach ($comments as $comment) {
            $comment_links = self::extract_from_content($comment->comment_content);
            
            foreach ($comment_links as $link) {
                $links[] = array(
                    'url' => $link,
                    'source_id' => $comment->comment_ID,
                    'source_type' => 'comment'
                );
            }
        }
        
        return $links;
    }
    
    /**
     * 从文本内容中提取URL
     */
    private static function extract_from_content($content) {
        $pattern = '/https?://[^s'"<>]+/i';
        preg_match_all($pattern, $content, $matches);
        
        $urls = array();
        if (!empty($matches[0])) {
            foreach ($matches[0] as $url) {
                // 清理URL
                $url = rtrim($url, '.,;:!?');
                $url = html_entity_decode($url);
                
                // 排除站内链接(可选)
                if (!self::is_internal_link($url)) {
                    $urls[] = $url;
                }
            }
        }
        
        return array_unique($urls);
    }
    
    /**
     * 判断是否为站内链接
     */
    private static function is_internal_link($url) {
        $site_url = site_url();
        $parsed_url = parse_url($url);
        $parsed_site = parse_url($site_url);
        
        if (!isset($parsed_url['host'])) {
            return false;
        }
        
        return $parsed_url['host'] === $parsed_site['host'];
    }
}

2.2 链接检测器模块

接下来,我们创建链接检测的核心功能:

class SLC_Link_Checker {
    
    private $timeout;
    private $user_agent;
    
    public function __construct() {
        $this->timeout = SLC_REQUEST_TIMEOUT;
        $this->user_agent = 'Mozilla/5.0 (compatible; SmartLinkChecker/1.0; +' . site_url() . ')';
    }
    
    /**
     * 检测单个链接的状态
     */
    public function check_single_link($url) {
        $start_time = microtime(true);
        
        // 初始化cURL
        $ch = curl_init();
        
        curl_setopt_array($ch, array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 5,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_USERAGENT => $this->user_agent,
            CURLOPT_HEADER => true,
            CURLOPT_NOBODY => true, // 只获取头部信息,提高速度
        ));
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $total_time = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
        $effective_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
        $redirect_count = curl_getinfo($ch, CURLINFO_REDIRECT_COUNT);
        
        $error = curl_error($ch);
        curl_close($ch);
        
        $response_time = microtime(true) - $start_time;
        
        // 分析结果
        $result = array(
            'url' => $url,
            'http_code' => $http_code,
            'response_time' => $response_time,
            'effective_url' => $effective_url,
            'redirect_count' => $redirect_count,
            'error' => $error,
            'status' => $this->determine_status($http_code, $error)
        );
        
        return $result;
    }
    
    /**
     * 根据HTTP状态码确定链接状态
     */
    private function determine_status($http_code, $error) {
        if (!empty($error)) {
            return 'error';
        }
        
        if ($http_code >= 200 && $http_code < 300) {
            return 'working';
        } elseif ($http_code >= 300 && $http_code < 400) {
            return 'redirect';
        } elseif ($http_code == 404) {
            return 'broken';
        } elseif ($http_code >= 400 && $http_code < 500) {
            return 'client_error';
        } elseif ($http_code >= 500) {
            return 'server_error';
        } else {
            return 'unknown';
        }
    }
    
    /**
     * 批量检测链接
     */
    public function check_batch_links($links, $batch_size = 10) {
        $results = array();
        $batches = array_chunk($links, $batch_size);
        
        foreach ($batches as $batch) {
            $batch_results = $this->check_batch_concurrently($batch);
            $results = array_merge($results, $batch_results);
            
            // 避免对目标服务器造成过大压力
            sleep(1);
        }
        
        return $results;
    }
    
    /**
     * 并发检测(使用curl_multi)
     */
    private function check_batch_concurrently($links) {
        $mh = curl_multi_init();
        $channels = array();
        
        foreach ($links as $i => $link) {
            $ch = curl_init();
            
            curl_setopt_array($ch, array(
                CURLOPT_URL => $link['url'],
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 3,
                CURLOPT_TIMEOUT => $this->timeout,
                CURLOPT_CONNECTTIMEOUT => 5,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_USERAGENT => $this->user_agent,
                CURLOPT_HEADER => true,
                CURLOPT_NOBODY => true,
            ));
            
            curl_multi_add_handle($mh, $ch);
            $channels[$i] = array(
                'channel' => $ch,
                'link' => $link
            );
        }
        
        // 执行并发请求
        $active = null;
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        
        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mh) != -1) {
                do {
                    $mrc = curl_multi_exec($mh, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            }
        }
        
        // 收集结果
        $results = array();
        foreach ($channels as $i => $channel) {
            $ch = $channel['channel'];
            $link = $channel['link'];
            
            $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $effective_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
            $error = curl_error($ch);
            
            $results[] = array_merge($link, array(
                'http_code' => $http_code,
                'effective_url' => $effective_url,
                'error' => $error,
                'status' => $this->determine_status($http_code, $error)
            ));
            
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }
        
        curl_multi_close($mh);
        return $results;
    }
}

2.3 智能修复模块

检测到死链后,我们需要尝试自动修复:

class SLC_Link_Fixer {
    
    /**
     * 尝试自动修复死链
     */
    public static function try_auto_fix($link_data) {
        $url = $link_data['url'];
        $source_id = $link_data['source_id'];
        $source_type = $link_data['source_type'];
        
        // 检查是否为404错误
        if ($link_data['http_code'] != 404) {
            return false;
        }
        
        // 尝试常见的修复策略
        $fixed_url = self::try_fix_strategies($url);
        
        if ($fixed_url && $fixed_url !== $url) {
            // 验证修复后的链接是否有效
            $checker = new SLC_Link_Checker();
            $check_result = $checker->check_single_link($fixed_url);
            
            if ($check_result['status'] === 'working') {
                // 更新数据库中的链接
                self::update_link_in_database($link_data['id'], $fixed_url, $check_result['http_code']);
                
                // 更新内容中的链接
                self::update_link_in_content($source_id, $source_type, $url, $fixed_url);
                
                return array(
                    'original_url' => $url,
                    'fixed_url' => $fixed_url,
                    'http_code' => $check_result['http_code'],
                    'success' => true
                );
            }
        }
        
        return false;
    }
    
    /**
     * 尝试多种修复策略
     */
    private static function try_fix_strategies($url) {
        $strategies = array(
            'remove_www' => function($url) {
                return preg_replace('/^(https?://)www./i', '$1', $url);
            },
            'add_www' => function($url) {
                $parsed = parse_url($url);
                if (!preg_match('/^www./i', $parsed['host'])) {
                    $parsed['host'] = 'www.' . $parsed['host'];
                    return self::build_url($parsed);
                }
                return $url;
            },
            'force_https' => function($url) {
                return preg_replace('/^http:/i', 'https:', $url);
            },
            'force_http' => function($url) {
                return preg_replace('/^https:/i', 'http:', $url);
            },
            'remove_trailing_slash' => function($url) {
                return rtrim($url, '/');
            },
            'add_trailing_slash' => function($url) {
                $parsed = parse_url($url);
                if (!isset($parsed['path']) || substr($parsed['path'], -1) !== '/') {
                    $parsed['path'] = ($parsed['path'] ?? '') . '/';
                    return self::build_url($parsed);
                }
                return $url;
            }
        );
        
        foreach ($strategies as $strategy) {
            $fixed_url = $strategy($url);
            if ($fixed_url !== $url) {
                // 简单验证URL格式
                if (filter_var($fixed_url, FILTER_VALIDATE_URL)) {
                    return $fixed_url;
                }
            }
        }
        
        return false;
    }
    
    /**
     * 从解析的URL部分重建完整URL
     */
    private static function build_url($parts) {
        $scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : '';
        $host = $parts['host'] ?? '';
        $port = isset($parts['port']) ? ':' . $parts['port'] : '';
        $path = $parts['path'] ?? '';
        $query = isset($parts['query']) ? '?' . $parts['query'] : '';
        $fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
        
        return $scheme . $host . $port . $path . $query . $fragment;
    }
    
    /**
     * 更新数据库中的链接记录
     */
    private static function update_link_in_database($link_id, $new_url, $http_code) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'slc_links';
        
        $wpdb->update(
            $table_name,
            array(
                'url' => $new_url,
                'status_code' => $http_code,
            'status' => 'fixed',
            'last_checked' => current_time('mysql')
        ),
        array('id' => $link_id),
        array('%s', '%d', '%s', '%s'),
        array('%d')
    );
    
    // 记录修复历史
    $history_table = $wpdb->prefix . 'slc_link_history';
    $wpdb->insert(
        $history_table,
        array(
            'link_id' => $link_id,
            'status_code' => $http_code,
            'checked_at' => current_time('mysql'),
            'notes' => '自动修复: ' . $new_url
        )
    );
}

/**
 * 更新内容中的链接
 */
private static function update_link_in_content($source_id, $source_type, $old_url, $new_url) {
    if ($source_type === 'post') {
        $post = get_post($source_id);
        if ($post) {
            $new_content = str_replace($old_url, $new_url, $post->post_content);
            
            wp_update_post(array(
                'ID' => $source_id,
                'post_content' => $new_content
            ));
        }
    } elseif ($source_type === 'comment') {
        $comment = get_comment($source_id);
        if ($comment) {
            $new_content = str_replace($old_url, $new_url, $comment->comment_content);
            
            wp_update_comment(array(
                'comment_ID' => $source_id,
                'comment_content' => $new_content
            ));
        }
    }
}

/**
 * 查找可能的替代链接(通过搜索引擎API)
 */
public static function find_alternative_url($url, $title = '') {
    // 这里可以集成搜索引擎API来查找替代链接
    // 由于API需要密钥,这里仅提供框架代码
    
    $parsed = parse_url($url);
    $domain = $parsed['host'] ?? '';
    $path = $parsed['path'] ?? '';
    
    // 尝试通过Wayback Machine查找存档
    $wayback_url = "https://archive.org/wayback/available?url=" . urlencode($url);
    
    $response = wp_remote_get($wayback_url, array('timeout' => 10));
    
    if (!is_wp_error($response)) {
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (isset($data['archived_snapshots']['closest']['url'])) {
            return $data['archived_snapshots']['closest']['url'];
        }
    }
    
    return false;
}

}


## 第三章:后台管理与用户界面

### 3.1 创建管理菜单和页面

class SLC_Admin {


public function __construct() {
    add_action('admin_menu', array($this, 'add_admin_menu'));
    add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    add_action('wp_ajax_slc_start_scan', array($this, 'ajax_start_scan'));
    add_action('wp_ajax_slc_get_stats', array($this, 'ajax_get_stats'));
    add_action('wp_ajax_slc_fix_link', array($this, 'ajax_fix_link'));
}

/**
 * 添加管理菜单
 */
public function add_admin_menu() {
    add_menu_page(
        '智能死链检测',
        '死链检测',
        'manage_options',
        'smart-link-checker',
        array($this, 'render_main_page'),
        'dashicons-admin-links',
        30
    );
    
    add_submenu_page(
        'smart-link-checker',
        '检测设置',
        '设置',
        'manage_options',
        'slc-settings',
        array($this, 'render_settings_page')
    );
    
    add_submenu_page(
        'smart-link-checker',
        '检测报告',
        '报告',
        'manage_options',
        'slc-reports',
        array($this, 'render_reports_page')
    );
}

/**
 * 渲染主页面
 */
public function render_main_page() {
    ?>
    <div class="wrap slc-admin">
        <h1>智能死链检测与修复</h1>
        
        <div class="slc-dashboard">
            <div class="slc-stats-cards">
                <div class="card">
                    <h3>总链接数</h3>
                    <p class="stat-number" id="total-links">0</p>
                </div>
                <div class="card">
                    <h3>正常链接</h3>
                    <p class="stat-number" id="working-links">0</p>
                </div>
                <div class="card">
                    <h3>死链数</h3>
                    <p class="stat-number" id="broken-links">0</p>
                </div>
                <div class="card">
                    <h3>已修复</h3>
                    <p class="stat-number" id="fixed-links">0</p>
                </div>
            </div>
            
            <div class="slc-controls">
                <button id="start-scan" class="button button-primary button-large">
                    <span class="dashicons dashicons-search"></span>
                    开始检测
                </button>
                <button id="stop-scan" class="button button-secondary button-large" disabled>
                    <span class="dashicons dashicons-controls-pause"></span>
                    停止检测
                </button>
                <button id="export-report" class="button button-secondary">
                    <span class="dashicons dashicons-download"></span>
                    导出报告
                </button>
            </div>
            
            <div class="slc-progress-container" style="display: none;">
                <h3>检测进度</h3>
                <div class="progress-bar">
                    <div class="progress-fill" id="scan-progress" style="width: 0%"></div>
                </div>
                <p class="progress-text" id="progress-text">准备开始...</p>
            </div>
            
            <div class="slc-results">
                <h2>检测结果</h2>
                <div class="tablenav top">
                    <div class="alignleft actions">
                        <select id="status-filter">
                            <option value="all">所有状态</option>
                            <option value="broken">死链</option>
                            <option value="working">正常</option>
                            <option value="redirect">重定向</option>
                            <option value="error">错误</option>
                        </select>
                        <button id="apply-filter" class="button">筛选</button>
                    </div>
                    <div class="tablenav-pages">
                        <span class="displaying-num" id="displaying-num">0个项目</span>
                        <div class="pagination">
                            <button class="button" id="prev-page" disabled>上一页</button>
                            <span id="current-page">1</span> / <span id="total-pages">1</span>
                            <button class="button" id="next-page" disabled>下一页</button>
                        </div>
                    </div>
                </div>
                
                <table class="wp-list-table widefat fixed striped" id="links-table">
                    <thead>
                        <tr>
                            <th width="5%">ID</th>
                            <th width="30%">URL</th>
                            <th width="10%">状态码</th>
                            <th width="15%">状态</th>
                            <th width="20%">来源</th>
                            <th width="15%">最后检测</th>
                            <th width="15%">操作</th>
                        </tr>
                    </thead>
                    <tbody id="links-tbody">
                        <!-- 动态加载数据 -->
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    <?php
}

/**
 * 渲染设置页面
 */
public function render_settings_page() {
    $settings = get_option('slc_settings', array());
    ?>
    <div class="wrap">
        <h1>死链检测设置</h1>
        
        <form method="post" action="options.php">
            <?php settings_fields('slc_settings_group'); ?>
            
            <table class="form-table">
                <tr>
                    <th scope="row">检测频率</th>
                    <td>
                        <select name="slc_settings[check_frequency]">
                            <option value="hourly" <?php selected($settings['check_frequency'], 'hourly'); ?>>每小时</option>
                            <option value="twicedaily" <?php selected($settings['check_frequency'], 'twicedaily'); ?>>每天两次</option>
                            <option value="daily" <?php selected($settings['check_frequency'], 'daily'); ?>>每天</option>
                            <option value="weekly" <?php selected($settings['check_frequency'], 'weekly'); ?>>每周</option>
                            <option value="monthly" <?php selected($settings['check_frequency'], 'monthly'); ?>>每月</option>
                        </select>
                        <p class="description">自动检测死链的频率</p>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">自动修复</th>
                    <td>
                        <label>
                            <input type="checkbox" name="slc_settings[auto_fix_redirects]" value="1" 
                                <?php checked($settings['auto_fix_redirects'], true); ?>>
                            自动尝试修复重定向和简单错误
                        </label>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">邮件通知</th>
                    <td>
                        <label>
                            <input type="checkbox" name="slc_settings[send_notifications]" value="1" 
                                <?php checked($settings['send_notifications'], true); ?>>
                            检测到死链时发送邮件通知
                        </label>
                        <p class="description">
                            <input type="email" name="slc_settings[notification_email]" 
                                value="<?php echo esc_attr($settings['notification_email']); ?>" 
                                placeholder="通知邮箱地址">
                        </p>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">排除域名</th>
                    <td>
                        <textarea name="slc_settings[excluded_domains]" rows="5" cols="50" 
                            placeholder="每行一个域名,例如:example.com"><?php 
                            echo esc_textarea(implode("n", $settings['excluded_domains'] ?? array())); 
                        ?></textarea>
                        <p class="description">不检测这些域名的链接</p>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">最大重定向次数</th>
                    <td>
                        <input type="number" name="slc_settings[max_redirects]" 
                            value="<?php echo esc_attr($settings['max_redirects']); ?>" min="1" max="10">
                        <p class="description">检测时允许的最大重定向次数</p>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">请求超时时间</th>
                    <td>
                        <input type="number" name="slc_settings[request_timeout]" 
                            value="<?php echo esc_attr($settings['request_timeout'] ?? SLC_REQUEST_TIMEOUT); ?>" min="5" max="60">
                        <span>秒</span>
                        <p class="description">检测单个链接的最大等待时间</p>
                    </td>
                </tr>
            </table>
            
            <?php submit_button(); ?>
        </form>
    </div>
    <?php
}

/**
 * 注册设置
 */
public function register_settings() {
    register_setting('slc_settings_group', 'slc_settings', array(
        'sanitize_callback' => array($this, 'sanitize_settings')
    ));
}

/**
 * 清理设置数据
 */
public function sanitize_settings($input) {
    $sanitized = array();
    
    $sanitized['check_frequency'] = sanitize_text_field($input['check_frequency']);
    $sanitized['auto_fix_redirects'] = isset($input['auto_fix_redirects']);
    $sanitized['send_notifications'] = isset($input['send_notifications']);
    $sanitized['notification_email'] = sanitize_email($input['notification_email']);
    
    // 处理排除域名
    $excluded_domains = explode("n", $input['excluded_domains']);
    $sanitized['excluded_domains'] = array_map('trim', $excluded_domains);
    $sanitized['excluded_domains'] = array_filter($sanitized['excluded_domains']);
    
    $sanitized['max_redirects'] = absint($input['max_redirects']);
    if ($sanitized['max_redirects'] < 1 || $sanitized['max_redirects'] > 10) {
        $sanitized['max_redirects'] = 3;
    }
    
    $sanitized['request_timeout'] = absint($input['request_timeout']);
    if ($sanitized['request_timeout'] < 5 || $sanitized['request_timeout'] > 60) {
        $sanitized['request_timeout'] = SLC_REQUEST_TIMEOUT;
    }
    
    return $sanitized;
}

}


### 3.2 AJAX处理与前端交互

// 继续SLC_Admin类中的方法

/**
 * AJAX开始扫描
 */
public function ajax_start_scan() {
    check_ajax_referer('slc_ajax_nonce', 'nonce');
    
    if (!current_user_can('manage_options')) {
        wp_die('权限不足');
    }
    
    // 获取所有链接
    $links = SLC_Link_Extractor::extract_all_links();
    
    // 保存到数据库
    $this->save_links_to_db($links);
    
    // 开始后台处理
    wp_schedule_single_event(time() + 1, 'slc_process_batch');
    
    wp_send_json_success(array(
        'message' => '扫描已开始',
        'total_links' => count($links)
    ));
}

/**
 * 保存链接到数据库
 */
private function save_links_to_db($links) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'slc_links';
    
    // 清空旧数据
    $wpdb->query("TRUNCATE TABLE $table_name");
    
    // 批量插入新数据
    $values = array();
    $placeholders = array();
    
    foreach ($links as $link) {
        array_push(
            $values,
            $link['url'],
            $link['source_id'],
            $link['source_type']
        );
        $placeholders[] = "(%s, %d, %s, 'pending')";
    }
    
    if (!empty($values)) {
        $query = "INSERT INTO $table_name (url, source_id, source_type, status) VALUES ";
        $query .= implode(', ', $placeholders);
        
        $wpdb->query($wpdb->prepare($query, $values));
    }
}

/**
 * AJAX获取统计信息
 */
public function ajax_get_stats() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'slc_links';
    
    $stats = array(
        'total' => $wpdb->get_var("SELECT COUNT(*) FROM $table_name"),
        'working' => $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status = 'working'"),
        'broken' => $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status = 'broken'"),
        'fixed' => $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status = 'fixed'"),
        'pending' => $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status = 'pending'")
    );
    
    wp_send_json_success($stats);
}

/**
 * AJAX修复链接
 */
public function ajax_fix_link() {
    check_ajax_referer('slc_ajax_nonce', 'nonce');
    
    if (!current_user_can('manage_options')) {
        wp_die('权限不足');
    }
    
    $link_id = intval($_POST['link_id']);
    $fix_type = sanitize_text_field($_POST['fix_type']);
    
    global $wpdb;
    $table_name = $wpdb->prefix . 'slc_links';
    
    $link = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM $table_name WHERE id = %d", $link_id
    ));
    
    if (!$link) {
        wp_send_json_error('链接不存在');
    }
    
    $result = false;
    
    switch ($fix_type) {
        case 'auto':
            $result = SLC_Link_Fixer::try_auto_fix((array)$link);
            break;
            
        case 'manual':
            $new_url = sanitize_text_field($_POST['new_url']);
            if ($new_url && filter_var($new_url, FILTER_VALIDATE_URL)) {
                $result = SLC_Link_Fixer::update_link_in_content(
                    $link->source_id,
                    $link->source_type,
                    $link->url,
                    $new_url
                );
            }
            break;
            
        case 'remove':
            // 从内容中移除链接
            $result = SLC_Link_Fixer::update_link_in_content(
                $link->source_id,
                $link->source_type,
                $link->url,
                ''
            );
            break;
    }
    
    if ($result) {
        wp_send_json_success(array(
            'message' => '修复成功',
            'link_id' => $link_id
        ));
    } else {
        wp_send_json_error('修复失败');
    }
}

/**
 * 加载管理脚本和样式
 */
public function enqueue_admin_scripts($hook) {
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5276.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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