【WP自动内链/发布页】自定义关键词自动链接!V1.5.1版本更新! | 原创开发论坛 | 心猿社频道 | 心猿社

【WP自动内链/发布页】自定义关键词自动链接!V1.5.1版本更新!

前言

本工具为心猿社自主开发插件,用来辅助我社滴动态更新机制,现在你看到的是V1.5.1测试版本,修复了当关键词中文字重叠时,长关键词不生效的bug。

V1.5版本实现了CSV(表格)文件的一键导入和导出!由于使用了新的代码设计,虽然目前测试已没有问题,但本版本可能并不稳定,如果出现问题,可以先使用V1.4版本。

开发前瞻(V1.6规划)

  1. 前端UI优化
  2. 增加前端修改和检索功能
  3. 增加链接分类和开关,该功能主要用于管理并方便CSV文件筛选
  4. 指定文章黑名单(待定)
  5. 制定文章白名单(待定)

V1.5.1最新版本代码

<?php
/**
 * Plugin Name: 关键词自动链接
 * Plugin URI:  https://xysai.top/forum-post/148635.html/
 * Description: 通过表格文件导入/导出关键词链接,并自动将文章中的关键词替换为链接
 * Version:     1.5.1
 * Author:      心猿社
 * Author URI:  https://xysai.top
 */

class Keyword_Auto_Linker {
    public function __construct() {
        add_action('admin_menu', array($this, 'add_admin_menu'));
        add_action('admin_init', array($this, 'handle_form_submit'));
        register_activation_hook(__FILE__, array($this, 'activate'));
        
        // 仅在前端注册内容过滤器
        if (!is_admin()) {
            add_filter('the_content', array($this, 'replace_keywords'), 9);
        }
    }

    // 插件激活时初始化
    public function activate() {
        if (!get_option('keyword_auto_linker_data')) {
            update_option('keyword_auto_linker_data', array());
        }
    }

    // 添加管理菜单
    public function add_admin_menu() {
        add_options_page(
            '关键词自动链接设置',
            '关键词自动链接', 
            'manage_options',
            'keyword-auto-linker',
            array($this, 'render_admin_page')
        );
    }

    // 渲染管理页面 - 整合所有功能
    public function render_admin_page() {
        $keywords = get_option('keyword_auto_linker_data', array());
        $per_page = 10;
        $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
        $total = count($keywords);
        $total_pages = ceil($total / $per_page);
        $offset = ($current_page - 1) * $per_page;
        $current_keywords = array_slice($keywords, $offset, $per_page);
        ?>
        <div class="wrap">
            <h1>自动内链·<a href="https://xysai.top/" target="_blank">心猿社</a></h1>
            
            <!-- 手动添加关键词表单 -->
            <h2>添加单个关键词</h2>
            <form method="post">
                <?php wp_nonce_field('kal_save_keywords'); ?>
                <table class="form-table">
                    <tr>
                        <th><label for="keyword">关键词</label></th>
                        <td><input type="text" name="keyword" required></td>
                    </tr>
                    <tr>
                        <th><label for="url">链接</label></th>
                        <td><input type="url" name="url" required></td>
                    </tr>
                    <tr>
                        <th>选项</th>
                        <td>
                            <label><input type="checkbox" name="newtab" value="1"> 新标签页打开</label>
                            <label><input type="checkbox" name="nofollow" value="1"> 添加nofollow</label>
                        </td>
                    </tr>
                </table>
                <input type="submit" name="submit_single" class="button button-primary" value="添加关键词">
            </form>

            <!-- 批量添加关键词表单 -->
            <h2>批量添加关键词</h2>
            <form method="post">
                <?php wp_nonce_field('kal_bulk_save_keywords'); ?>
                <textarea name="bulk_keywords" rows="5" style="width:100%" placeholder="每行格式: 关键词,链接,新标签(0/1),nofollow(0/1)"></textarea>
                <p class="description">每行一组关键词,用逗号分隔各字段</p>
                <input type="submit" name="submit_bulk" class="button button-primary" value="批量添加">
            </form>

            <!-- 导入CSV表单 -->
            <h2>导入关键词(CSV)</h2>
            <form method="post" enctype="multipart/form-data">
                <input type="hidden" name="action" value="import_csv">
                <?php wp_nonce_field('keyword_import_action', 'keyword_import_nonce'); ?>
                <input type="file" name="keywords_file" accept=".csv" required>
                <p class="description">CSV格式:关键词,链接,新标签(0/1),nofollow(0/1)</p>
                <input type="submit" class="button button-primary" value="导入CSV">
            </form>
            
            <!-- 导出CSV表单 -->
            <h2>导出关键词</h2>
            <form method="post">
                <input type="hidden" name="action" value="export_csv">
                <?php wp_nonce_field('keyword_export_action', 'keyword_export_nonce'); ?>
                <input type="submit" class="button" value="导出为CSV">
            </form>

            <!-- 一键删除所有关键词 -->
            <h2>危险操作</h2>
            <form method="post" onsubmit="return confirm('确定要删除所有关键词吗?此操作不可恢复!');">
                <?php wp_nonce_field('kal_delete_all_keywords'); ?>
                <input type="hidden" name="action" value="delete_all">
                <input type="submit" class="button button-delete" value="删除所有关键词">
            </form>

            <!-- 关键词列表 -->
            <h2>当前关键词列表 (共<?php echo $total; ?>条)</h2>
            <?php if ($total_pages > 1): ?>
                <div class="tablenav top">
                    <div class="tablenav-pages">
                        <?php echo paginate_links(array(
                            'base' => add_query_arg('paged', '%#%'),
                            'format' => '',
                            'prev_text' => '«',
                            'next_text' => '»',
                            'total' => $total_pages,
                            'current' => $current_page
                        )); ?>
                    </div>
                </div>
            <?php endif; ?>
            
            <table class="wp-list-table widefat fixed striped">
                <thead>
                    <tr>
                        <th>关键词</th>
                        <th>链接</th>
                        <th>新标签</th>
                        <th>nofollow</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (empty($current_keywords)) : ?>
                        <tr>
                            <td colspan="5">暂无关键词数据</td>
                        </tr>
                    <?php else : ?>
                        <?php foreach ($current_keywords as $index => $item) : ?>
                            <tr>
                                <td><?php echo esc_html($item['keyword']); ?></td>
                                <td><?php echo esc_url($item['url']); ?></td>
                                <td><?php echo $item['newtab'] ? '是' : '否'; ?></td>
                                <td><?php echo $item['nofollow'] ? '是' : '否'; ?></td>
                                <td>
                                    <a href="<?php echo wp_nonce_url(
                                        add_query_arg(array(
                                            'action' => 'delete',
                                            'index' => $offset + $index
                                        )), 
                                        'kal_delete_keyword'
                                    ); ?>" class="submitdelete">删除</a>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
        <?php
    }

    // 处理表单提交 - 整合所有操作
    public function handle_form_submit() {
        // 处理单个关键词添加
        if (isset($_POST['submit_single'])) {
            $this->add_single_keyword();
        }
        
        // 处理批量添加
        if (isset($_POST['submit_bulk'])) {
            $this->add_bulk_keywords();
        }
        
        // 处理CSV导入
        if (isset($_POST['action']) && $_POST['action'] === 'import_csv') {
            $this->import_csv();
        }
        
        // 处理CSV导出
        if (isset($_POST['action']) && $_POST['action'] === 'export_csv') {
            $this->export_csv();
        }
        
        // 处理删除单个关键词
        if (isset($_GET['action']) && $_GET['action'] === 'delete') {
            $this->delete_keyword();
        }
        
        // 处理删除所有关键词
        if (isset($_POST['action']) && $_POST['action'] === 'delete_all') {
            $this->delete_all_keywords();
        }
    }

    // 添加单个关键词
    private function add_single_keyword() {
        check_admin_referer('kal_save_keywords');
        
        $new_keyword = array(
            'keyword'  => sanitize_text_field($_POST['keyword']),
            'url'      => esc_url_raw($_POST['url']),
            'newtab'   => isset($_POST['newtab']) ? 1 : 0,
            'nofollow' => isset($_POST['nofollow']) ? 1 : 0,
        );
        
        $keywords = get_option('keyword_auto_linker_data');
        $keywords[] = $new_keyword;
        update_option('keyword_auto_linker_data', $keywords);
        
        $this->redirect_with_pagination();
    }

    // 批量添加关键词
    private function add_bulk_keywords() {
        check_admin_referer('kal_bulk_save_keywords');
        
        $bulk_data = sanitize_textarea_field($_POST['bulk_keywords']);
        $lines = array_filter(array_map('trim', explode("\n", $bulk_data)));
        $keywords = get_option('keyword_auto_linker_data');
        $results = array(
            'success' => 0,
            'errors' => array()
        );

        foreach ($lines as $line_number => $line) {
            $columns = str_getcsv($line, ',', '"');
            if (count($columns) < 2) {
                $results['errors'][] = sprintf('第%d行:缺少必要参数', $line_number+1);
                continue;
            }

            // 参数处理
            $keyword = sanitize_text_field(trim($columns[0]));
            $url = esc_url_raw(trim($columns[1]));
            $newtab = isset($columns[2]) ? (int)$columns[2] : 0;
            $nofollow = isset($columns[3]) ? (int)$columns[3] : 0;

            // 有效性验证
            if (empty($keyword)) {
                $results['errors'][] = sprintf('第%d行:关键词不能为空', $line_number+1);
                continue;
            }

            if (!filter_var($url, FILTER_VALIDATE_URL)) {
                $results['errors'][] = sprintf('第%d行:URL格式无效', $line_number+1);
                continue;
            }

            $keywords[] = array(
                'keyword'  => $keyword,
                'url'      => $url,
                'newtab'   => $newtab ? 1 : 0,
                'nofollow' => $nofollow ? 1 : 0,
            );
            $results['success']++;
        }

        update_option('keyword_auto_linker_data', $keywords);

        // 显示处理结果
        if ($results['success'] > 0) {
            add_settings_error('keyword_auto_linker', 'bulk_success', '成功导入 '.$results['success'].' 条记录', 'updated');
        }
        if (!empty($results['errors'])) {
            add_settings_error('keyword_auto_linker', 'bulk_error', implode('<br>', $results['errors']), 'error');
        }
        
        $this->redirect_with_pagination();
    }

    // 删除单个关键词
    private function delete_keyword() {
        check_admin_referer('kal_delete_keyword');
        
        $index = intval($_GET['index']);
        $keywords = get_option('keyword_auto_linker_data');
        if (isset($keywords[$index])) {
            unset($keywords[$index]);
            update_option('keyword_auto_linker_data', array_values($keywords));
        }
        
        $this->redirect_with_pagination();
    }

    // 删除所有关键词
    private function delete_all_keywords() {
        check_admin_referer('kal_delete_all_keywords');
        update_option('keyword_auto_linker_data', array());
        $this->redirect_with_pagination();
    }

    // 带分页的重定向
    private function redirect_with_pagination() {
        $redirect_url = admin_url('options-general.php?page=keyword-auto-linker');
        $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
        wp_redirect(add_query_arg('paged', $paged, $redirect_url));
        exit;
    }

    // 导入CSV文件
    private function import_csv() {
        if (!current_user_can('manage_options') || 
            !wp_verify_nonce($_POST['keyword_import_nonce'], 'keyword_import_action')) {
            wp_die('无权限操作');
        }

        if (!empty($_FILES['keywords_file']['tmp_name'])) {
            $file = $_FILES['keywords_file']['tmp_name'];
            $keywords = array();
            
            // 读取文件内容并转换为UTF-8
            $content = file_get_contents($file);
            if (substr($content, 0, 3) == "\xEF\xBB\xBF") {
                $content = substr($content, 3); // 移除BOM头
            }
            $content = mb_convert_encoding($content, 'UTF-8', 'auto');
            
            // 将内容按行分割
            $lines = explode("\n", $content);
            
            foreach ($lines as $line) {
                $line = trim($line);
                if (empty($line)) continue;
                
                // 使用str_getcsv解析CSV行
                $data = str_getcsv($line);
                if (count($data) >= 2) {
                    $keywords[] = array(
                        'keyword' => trim($data[0]),
                        'url' => trim($data[1]),
                        'newtab' => isset($data[2]) ? (int)$data[2] : 0,
                        'nofollow' => isset($data[3]) ? (int)$data[3] : 0
                    );
                }
            }
            
            update_option('keyword_auto_linker_data', $keywords);
            add_settings_error('keyword_auto_linker', 'import_success', 'CSV导入成功', 'updated');
        }
    }

    // 导出CSV文件
    private function export_csv() {
        if (!current_user_can('manage_options') || 
            !wp_verify_nonce($_POST['keyword_export_nonce'], 'keyword_export_action')) {
            wp_die('无权限操作');
        }

        $keywords = get_option('keyword_auto_linker_data', array());
        
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="keywords_' . date('Ymd') . '.csv"');
        
        $output = fopen('php://output', 'w');
        // 添加UTF-8 BOM头
        fwrite($output, "\xEF\xBB\xBF");
        // 添加CSV标题行
        fputcsv($output, array('关键词', '链接', '新标签', 'nofollow'));
        foreach ($keywords as $item) {
            fputcsv($output, array(
                $item['keyword'],
                $item['url'],
                $item['newtab'] ?? 0,
                $item['nofollow'] ?? 0
            ));
        }
        fclose($output);
        exit;
    }

    // 替换内容中的关键词
    public function replace_keywords($content) {
        $keywords = get_option('keyword_auto_linker_data', array());
        if (empty($keywords)) return $content;

        // 按长度降序排序
        usort($keywords, function($a, $b) {
            return mb_strlen($b['keyword']) - mb_strlen($a['keyword']);
        });

        // 创建临时存储已替换的内容
        $replacedContent = array();
        
        foreach ($keywords as $item) {
            if (empty($item['keyword']) || empty($item['url'])) continue;
            
            // 跳过已经被替换的内容
            $skip = false;
            foreach ($replacedContent as $replaced) {
                if (strpos($replaced, $item['keyword']) !== false) {
                    $skip = true;
                    break;
                }
            }
            if ($skip) continue;

            $pattern = '/'.preg_quote($item['keyword'], '/').'/u';
            $attrs = 'href="' . esc_url($item['url']) . '"';
            if ($item['newtab'] != 0) $attrs .= ' target="_blank"';
            if ($item['nofollow']) $attrs .= ' rel="nofollow"';

            $content = preg_replace_callback(
                $pattern,
                function($matches) use ($attrs, &$replacedContent) {
                    $replacedContent[] = $matches[0];
                    return '<a ' . $attrs . '>'.$matches[0].'</a>';
                },
                $content,
                -1
            );
        }
        
        return $content;
    }
}

// 始终初始化插件(管理功能需要)
new Keyword_Auto_Linker();

后端预览

图片[1] | 【WP自动内链/发布页】自定义关键词自动链接!V1.5.1版本更新! | 原创开发论坛 | 心猿社频道 | 心猿社

支援文档(使用教程)

需要的话请在评论区留言。

旧版本代码

V1.4版本:新增分页功能,提升操作体验~

<?php
/*
Plugin Name: Keyword Auto Linker
Description: 自动为内容中的关键词添加内部链接
Version: 1.4
Author: 心猿社
*/

// 安全检测
defined('ABSPATH') || exit;

// 激活时初始化选项
register_activation_hook(__FILE__, 'kal_activate');
function kal_activate() {
    if (!get_option('keyword_links')) {
        update_option('keyword_links', array());
    }
}

// 添加管理菜单
add_action('admin_menu', 'kal_add_admin_menu');
function kal_add_admin_menu() {
    add_options_page(
        '关键词链接设置',
        '关键词自动链接',
        'manage_options',
        'keyword-auto-linker',
        'kal_settings_page'
    );
}

// 设置页面内容
function kal_settings_page() {
    if (!current_user_can('manage_options')) return;
    
    // 处理表单提交
    if (isset($_POST['submit_single'])) {
        check_admin_referer('kal_save_keywords');
        
        $new_keyword = array(
            'keyword'  => sanitize_text_field($_POST['keyword']),
            'url'      => esc_url_raw($_POST['url']),
            'newtab'   => isset($_POST['newtab']) ? 1 : 0,
            'nofollow' => isset($_POST['nofollow']) ? 1 : 0,
        );
        
        $keywords = get_option('keyword_links');
        $keywords[] = $new_keyword;
        update_option('keyword_links', $keywords);
        
        // 重定向防止重复提交
        $redirect_url = admin_url('options-general.php?page=keyword-auto-linker');
        if (isset($_GET['paged'])) {
            $redirect_url = add_query_arg('paged', intval($_GET['paged']), $redirect_url);
        }
        wp_redirect($redirect_url);
        exit;
    }
    
    // 处理删除操作
    if (isset($_GET['action']) && $_GET['action'] === 'delete') {
        check_admin_referer('kal_delete_keyword');
        
        $index = intval($_GET['index']);
        $keywords = get_option('keyword_links');
        if (isset($keywords[$index])) {
            unset($keywords[$index]);
            update_option('keyword_links', array_values($keywords));
        }
        // 重定向回当前分页
        $redirect_url = admin_url('options-general.php?page=keyword-auto-linker');
        $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
        $redirect_url = add_query_arg('paged', $paged, $redirect_url);
        wp_redirect($redirect_url);
        exit;
    }
    
    // 处理批量添加
    if (isset($_POST['bulk_keywords']) && isset($_POST['submit_bulk'])) {
        check_admin_referer('kal_bulk_save_keywords');
        
        $bulk_data = sanitize_textarea_field($_POST['bulk_keywords']);
        $lines = array_filter(array_map('trim', explode("\n", $bulk_data)));
        $keywords = get_option('keyword_links');
        $results = array(
            'success' => 0,
            'errors' => array()
        );

        foreach ($lines as $line_number => $line) {
            $columns = str_getcsv($line, ',', '"');
            if (count($columns) < 2) {
                $results['errors'][] = sprintf('第%d行:缺少必要参数', $line_number+1);
                continue;
            }

            // 参数处理
            $keyword = sanitize_text_field(trim($columns[0]));
            $url = esc_url_raw(trim($columns[1]));
            $newtab = isset($columns[2]) ? (int)$columns[2] : 0;
            $nofollow = isset($columns[3]) ? (int)$columns[3] : 0;

            // 有效性验证
            if (empty($keyword)) {
                $results['errors'][] = sprintf('第%d行:关键词不能为空', $line_number+1);
                continue;
            }

            if (!filter_var($url, FILTER_VALIDATE_URL)) {
                $results['errors'][] = sprintf('第%d行:URL格式无效', $line_number+1);
                continue;
            }

            $keywords[] = array(
                'keyword'  => $keyword,
                'url'      => $url,
                'newtab'   => $newtab ? 1 : 0,
                'nofollow' => $nofollow ? 1 : 0,
            );
            $results['success']++;
        }

        update_option('keyword_links', $keywords);

        // 显示处理结果
        if ($results['success'] > 0) {
            echo '<div class="notice notice-success"><p>成功导入 '.$results['success'].' 条记录</p></div>';
        }
        if (!empty($results['errors'])) {
            echo '<div class="notice notice-error"><p>'.implode('<br>', $results['errors']).'</p></div>';
        }
        
        // 重定向防止重复提交
        $redirect_url = admin_url('options-general.php?page=keyword-auto-linker');
        if (isset($_GET['paged'])) {
            $redirect_url = add_query_arg('paged', intval($_GET['paged']), $redirect_url);
        }
        wp_redirect($redirect_url);
        exit;
    }
    
    // 显示设置界面
    $keywords = get_option('keyword_links', array());
    $per_page = 10;
    $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
    $total = count($keywords);
    $total_pages = ceil($total / $per_page);
    $offset = ($current_page - 1) * $per_page;
    $current_keywords = array_slice($keywords, $offset, $per_page);
    ?>
    <div class="wrap">
        <h1>自动内链·心猿社</h1>
        
        <!-- 添加关键词表单 -->
        <form method="post">
            <?php wp_nonce_field('kal_save_keywords'); ?>
            <table class="form-table">
                <tr>
                    <th><label for="keyword">关键词</label></th>
                    <td><input type="text" name="keyword" required></td>
                </tr>
                <tr>
                    <th><label for="url">目标URL</label></th>
                    <td><input type="url" name="url" required></td>
                </tr>
                <tr>
                    <th>选项</th>
                    <td>
                        <label><input type="checkbox" name="newtab"> 新窗口打开</label><br>
                        <label><input type="checkbox" name="nofollow"> 添加nofollow</label>
                    </td>
                </tr>
            </table>
            <?php submit_button('添加关键词', 'primary', 'submit_single'); ?>
        </form>

        <!-- 批量添加关键词表单 -->
        <h2>批量添加关键词</h2>
        <form method="post">
            <?php wp_nonce_field('kal_bulk_save_keywords'); ?>
            <table class="form-table">
                <tr>
                    <th><label>批量添加格式</label></th>
                    <td>
                        <textarea 
                            name="bulk_keywords" 
                            rows="10" 
                            cols="50"
                            placeholder="每行格式:关键词,URL,新窗口(0/1),nofollow(0/1)"
                        ></textarea>
                        <p class="description">
                            示例:<br>
                            WordPress插件,https://example.com/plugins,1,0<br>
                            SEO优化,https://example.com/seo,0,1<br>
                            * 说明:后两个参数可选,默认0(0=否,1=是)
                        </p>
                    </td>
                </tr>
            </table>
            <?php submit_button('批量导入', 'primary', 'submit_bulk'); ?>
        </form>

        <!-- 现有关键词列表 -->
        <h2>已有关键词</h2>
        <?php if ($total > 0) : ?>
            <div class="tablenav top">
                <div class="tablenav-pages">
                    <span class="displaying-num"><?php printf('显示 %d - %d 共 %d 项', $offset + 1, min($offset + $per_page, $total), $total); ?></span>
                    <?php
                    echo paginate_links(array(
                        'base' => add_query_arg('paged', '%#%'),
                        'format' => '',
                        'prev_text' => '« 上一页',
                        'next_text' => '下一页 »',
                        'total' => $total_pages,
                        'current' => $current_page
                    ));
                    ?>
                </div>
            </div>
        <?php endif; ?>
        
        <table class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th>关键词</th>
                    <th>URL</th>
                    <th>选项</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($current_keywords as $original_index => $keyword): ?>
                <tr>
                    <td><?= esc_html($keyword['keyword']) ?></td>
                    <td><?= esc_url($keyword['url']) ?></td>
                    <td>
                        <?= $keyword['newtab'] ? '新窗口' : '' ?>
                        <?= $keyword['nofollow'] ? 'nofollow' : '' ?>
                    </td>
                    <td>
                        <a href="<?= wp_nonce_url(
                            admin_url('options-general.php?page=keyword-auto-linker&action=delete&index=' . $original_index . '&paged=' . $current_page),
                            'kal_delete_keyword'
                        ) ?>">删除</a>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>

        <?php if ($total > 0) : ?>
            <div class="tablenav bottom">
                <div class="tablenav-pages">
                    <span class="displaying-num"><?php printf('显示 %d - %d 共 %d 项', $offset + 1, min($offset + $per_page, $total), $total); ?></span>
                    <?php
                    echo paginate_links(array(
                        'base' => add_query_arg('paged', '%#%'),
                        'format' => '',
                        'prev_text' => '« 上一页',
                        'next_text' => '下一页 »',
                        'total' => $total_pages,
                        'current' => $current_page
                    ));
                    ?>
                </div>
            </div>
        <?php endif; ?>
        
        <!-- 添加作者介绍 -->
        <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd;">
            <h3>自动内链·心猿社V1.4</h3>
            <p>本插件由 <a href="https://xysai.top/" target="_blank">心猿社</a> 开发和维护。新增分页功能,提升操作体验~</p>
        </div>
    </div>
    <?php
}

// 内容替换逻辑(保持不变)
add_filter('the_content', 'kal_replace_keywords');
function kal_replace_keywords($content) {
    $keywords = get_option('keyword_links');
    if (empty($keywords)) return $content;

    usort($keywords, function($a, $b) {
        return strlen($b['keyword']) - strlen($a['keyword']);
    });

    $parts = preg_split('/(<[^>]+>)/', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
    
    foreach ($parts as &$part) {
        if (preg_match('/^<.+>$/', $part)) continue;
        
        foreach ($keywords as $item) {
            $pattern = '/(' . preg_quote($item['keyword'], '/') . ')(?![^<]*<\/a>)/iu';
            $attrs = 'href="' . esc_url($item['url']) . '"';
            $attrs .= $item['newtab'] ? ' target="_blank"' : '';
            $attrs .= $item['nofollow'] ? ' rel="nofollow"' : '';
            
            $part = preg_replace(
                $pattern,
                '<a ' . $attrs . '>$1</a>',
                $part
            );
        }
    }
    
    return implode('', $parts);
}

V1.3版本:

<?php
/*
Plugin Name: Keyword Auto Linker
Description: 自动为内容中的关键词添加内部链接
Version: 1.3
Author: 心猿社
*/

// 安全检测
defined('ABSPATH') || exit;

// 激活时初始化选项
register_activation_hook(__FILE__, 'kal_activate');
function kal_activate() {
    if (!get_option('keyword_links')) {
        update_option('keyword_links', array());
    }
}

// 添加管理菜单
add_action('admin_menu', 'kal_add_admin_menu');
function kal_add_admin_menu() {
    add_options_page(
        '关键词链接设置',
        '关键词自动链接',
        'manage_options',
        'keyword-auto-linker',
        'kal_settings_page'
    );
}

// 设置页面内容
function kal_settings_page() {
    if (!current_user_can('manage_options')) return;
    
    // 处理表单提交
    if (isset($_POST['submit_single'])) {
        check_admin_referer('kal_save_keywords');
        
        $new_keyword = array(
            'keyword'  => sanitize_text_field($_POST['keyword']),
            'url'      => esc_url_raw($_POST['url']),
            'newtab'   => isset($_POST['newtab']) ? 1 : 0,
            'nofollow' => isset($_POST['nofollow']) ? 1 : 0,
        );
        
        $keywords = get_option('keyword_links');
        $keywords[] = $new_keyword;
        update_option('keyword_links', $keywords);
    }
    
    // 处理删除操作
    if (isset($_GET['action']) && $_GET['action'] === 'delete') {
        check_admin_referer('kal_delete_keyword');
        
        $index = intval($_GET['index']);
        $keywords = get_option('keyword_links');
        if (isset($keywords[$index])) {
            unset($keywords[$index]);
            update_option('keyword_links', array_values($keywords));
        }
    }
    
    // 处理批量添加
    if (isset($_POST['bulk_keywords']) && isset($_POST['submit_bulk'])) {
        check_admin_referer('kal_bulk_save_keywords');
        
        $bulk_data = sanitize_textarea_field($_POST['bulk_keywords']);
        $lines = array_filter(array_map('trim', explode("\n", $bulk_data)));
        $keywords = get_option('keyword_links');
        $results = array(
            'success' => 0,
            'errors' => array()
        );

        foreach ($lines as $line_number => $line) {
            $columns = str_getcsv($line, ',', '"');
            if (count($columns) < 2) {
                $results['errors'][] = sprintf('第%d行:缺少必要参数', $line_number+1);
                continue;
            }

            // 参数处理
            $keyword = sanitize_text_field(trim($columns[0]));
            $url = esc_url_raw(trim($columns[1]));
            $newtab = isset($columns[2]) ? (int)$columns[2] : 0;
            $nofollow = isset($columns[3]) ? (int)$columns[3] : 0;

            // 有效性验证
            if (empty($keyword)) {
                $results['errors'][] = sprintf('第%d行:关键词不能为空', $line_number+1);
                continue;
            }

            if (!filter_var($url, FILTER_VALIDATE_URL)) {
                $results['errors'][] = sprintf('第%d行:URL格式无效', $line_number+1);
                continue;
            }

            $keywords[] = array(
                'keyword'  => $keyword,
                'url'      => $url,
                'newtab'   => $newtab ? 1 : 0,
                'nofollow' => $nofollow ? 1 : 0,
            );
            $results['success']++;
        }

        update_option('keyword_links', $keywords);

        // 显示处理结果
        if ($results['success'] > 0) {
            echo '<div class="notice notice-success"><p>成功导入 '.$results['success'].' 条记录</p></div>';
        }
        if (!empty($results['errors'])) {
            echo '<div class="notice notice-error"><p>'.implode('<br>', $results['errors']).'</p></div>';
        }
    }
    
    // 显示设置界面
    ?>
    <div class="wrap">
        <h1>关键词链接·心猿社</h1>
        
        <!-- 添加关键词表单 -->
        <form method="post">
            <?php wp_nonce_field('kal_save_keywords'); ?>
            <table class="form-table">
                <tr>
                    <th><label for="keyword">关键词</label></th>
                    <td><input type="text" name="keyword" required></td>
                </tr>
                <tr>
                    <th><label for="url">目标URL</label></th>
                    <td><input type="url" name="url" required></td>
                </tr>
                <tr>
                    <th>选项</th>
                    <td>
                        <label><input type="checkbox" name="newtab"> 新窗口打开</label><br>
                        <label><input type="checkbox" name="nofollow"> 添加nofollow</label>
                    </td>
                </tr>
            </table>
            <?php submit_button('添加关键词', 'primary', 'submit_single'); ?>
        </form>

        <!-- 批量添加关键词表单 -->
        <h2>批量添加关键词</h2>
        <form method="post">
            <?php wp_nonce_field('kal_bulk_save_keywords'); ?>
            <table class="form-table">
                <tr>
                    <th><label>批量添加格式</label></th>
                    <td>
                        <textarea 
                            name="bulk_keywords" 
                            rows="10" 
                            cols="50"
                            placeholder="每行格式:关键词,URL,新窗口(0/1),nofollow(0/1)"
                        ></textarea>
                        <p class="description">
                            示例:<br>
                            WordPress插件,https://example.com/plugins,1,0<br>
                            SEO优化,https://example.com/seo,0,1<br>
                            * 说明:后两个参数可选,默认0(0=否,1=是)
                        </p>
                    </td>
                </tr>
            </table>
            <?php submit_button('批量导入', 'primary', 'submit_bulk'); ?>
        </form>

        <!-- 现有关键词列表 -->
        <h2>已有关键词</h2>
        <table class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th>关键词</th>
                    <th>URL</th>
                    <th>选项</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach (get_option('keyword_links', array()) as $index => $keyword): ?>
                <tr>
                    <td><?= esc_html($keyword['keyword']) ?></td>
                    <td><?= esc_url($keyword['url']) ?></td>
                    <td>
                        <?= $keyword['newtab'] ? '新窗口' : '' ?>
                        <?= $keyword['nofollow'] ? 'nofollow' : '' ?>
                    </td>
                    <td>
                        <a href="<?= wp_nonce_url(
                            admin_url('options-general.php?page=keyword-auto-linker&action=delete&index='.$index),
                            'kal_delete_keyword'
                        ) ?>">删除</a>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        
        <!-- 添加作者介绍 -->
        <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd;">
            <h3>关键词链接·心猿社V1.3</h3>
            <p>本插件由 <a href="https://xysai.top/" target="_blank">心猿社</a> 开发和维护。您可以点击 <a href="https://xysai.top/" target="_blank">插件维护面板</a> 查阅日志~</p>
        </div>
    </div>
    <?php
}

// 内容替换逻辑
add_filter('the_content', 'kal_replace_keywords');
function kal_replace_keywords($content) {
    $keywords = get_option('keyword_links');
    if (empty($keywords)) return $content;

    // 按关键词长度排序(从长到短)
    usort($keywords, function($a, $b) {
        return strlen($b['keyword']) - strlen($a['keyword']);
    });

    // 分割内容为HTML标签和文本
    $parts = preg_split('/(<[^>]+>)/', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
    
    foreach ($parts as &$part) {
        // 跳过HTML标签
        if (preg_match('/^<.+>$/', $part)) continue;
        
        // 替换每个关键词
        foreach ($keywords as $item) {
            $pattern = '/(' . preg_quote($item['keyword'], '/') . ')(?![^<]*<\/a>)/iu';
            $attrs = 'href="' . esc_url($item['url']) . '"';
            $attrs .= $item['newtab'] ? ' target="_blank"' : '';
            $attrs .= $item['nofollow'] ? ' rel="nofollow"' : '';
            
            $part = preg_replace(
                $pattern,
                '<a ' . $attrs . '>$1</a>',
                $part
            );
        }
    }
    
    return implode('', $parts);
}

请登录后发表评论

    没有回复内容