前言
本工具为心猿社自主开发插件,用来辅助我社滴动态更新机制,现在你看到的是V1.5.1测试版本,修复了当关键词中文字重叠时,长关键词不生效的bug。
V1.5版本实现了CSV(表格)文件的一键导入和导出!由于使用了新的代码设计,虽然目前测试已没有问题,但本版本可能并不稳定,如果出现问题,可以先使用V1.4版本。
开发前瞻(V1.6规划)
- 前端UI优化
- 增加前端修改和检索功能
- 增加链接分类和开关,该功能主要用于管理并方便CSV文件筛选
- 指定文章黑名单(待定)
- 制定文章白名单(待定)
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版本更新! | 原创开发论坛 | 心猿社频道 | 心猿社](https://xysai.top/wp-content/smush-webp/2025/02/image.png.webp)
支援文档(使用教程)
需要的话请在评论区留言。
旧版本代码
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);
}
没有回复内容