Files
wordpress-plugins/AI SEO 助手/ai-seo-generator.php
Snowz 1ae6823bd5 feat: 新增AI SEO助手插件,支持自动生成SEO内容和导航主题适配
添加完整的AI SEO助手WordPress插件,主要功能包括:
- 集成Dify API自动生成SEO优化的标题、描述和关键词
- 支持导航主题的自定义字段适配
- 提供管理界面设置API和文章类型支持
- 包含前端SEO标签自动应用功能
- 添加详细的测试和调试功能
2025-08-13 18:52:35 +08:00

503 lines
18 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: AI SEO 助手
* Plugin URI: https://ckk.photo8.site/Photo8/wordpress-plugins
* Description: 使用AI自动生成SEO TDK内容的WordPress插件集成Dify API
* Version: 1.0.7
* Author: SnowZ
* License: GPL v2 or later
* Text Domain: ai-seo-generator
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('AI_SEO_PLUGIN_URL', plugin_dir_url(__FILE__));
define('AI_SEO_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('AI_SEO_VERSION', '1.0.0');
// 加载安装脚本
require_once AI_SEO_PLUGIN_PATH . 'install.php';
// 加载测试功能(仅在管理后台)
if (is_admin()) {
require_once AI_SEO_PLUGIN_PATH . 'test/api-test.php';
}
/**
* 主插件类
*/
class AiSeoGenerator {
/**
* 构造函数 - 初始化插件
*/
public function __construct() {
add_action('init', array($this, 'init'));
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
}
/**
* 插件初始化
*/
public function init() {
// 加载文本域
load_plugin_textdomain('ai-seo-generator', false, dirname(plugin_basename(__FILE__)) . '/languages');
// 添加管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 添加编辑页面的meta box
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
// 保存文章时的钩子
add_action('save_post', array($this, 'save_post_meta'));
// 添加AJAX处理
add_action('wp_ajax_generate_seo_content', array($this, 'ajax_generate_seo_content'));
// 加载管理页面样式和脚本
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
// 前端钩子 - 修改页面标题和meta标签
add_filter('wp_title', array($this, 'custom_wp_title'), 10, 2);
add_action('wp_head', array($this, 'add_meta_tags'));
}
/**
* 插件激活时执行
*/
public function activate() {
// 创建数据库表或设置默认选项
$this->create_options();
}
/**
* 插件停用时执行
*/
public function deactivate() {
// 清理工作
}
/**
* 创建默认选项
*/
private function create_options() {
add_option('ai_seo_api_key', '');
add_option('ai_seo_api_url', '');
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_options_page(
'AI SEO Generator 设置',
'AI SEO Generator',
'manage_options',
'ai-seo-generator',
array($this, 'admin_page')
);
// 添加测试页面子菜单
add_submenu_page(
'options-general.php',
'AI SEO 测试',
'AI SEO 测试',
'manage_options',
'ai-seo-test',
array($this, 'test_page')
);
}
/**
* 管理页面内容
* 处理设置保存包括API配置和支持的文章类型
*/
public function admin_page() {
if (isset($_POST['submit'])) {
// 保存API设置
update_option('ai_seo_api_key', sanitize_text_field($_POST['api_key']));
update_option('ai_seo_api_url', esc_url_raw($_POST['api_url']));
// 保存支持的文章类型设置
$supported_post_types = array();
if (isset($_POST['supported_post_types']) && is_array($_POST['supported_post_types'])) {
// 获取所有公开的post类型进行验证
$all_post_types = get_post_types(array('public' => true), 'names');
foreach ($_POST['supported_post_types'] as $post_type) {
$post_type = sanitize_text_field($post_type);
// 只保存有效的公开post类型
if (in_array($post_type, $all_post_types)) {
$supported_post_types[] = $post_type;
}
}
}
// 如果没有选择任何类型默认支持post和page
if (empty($supported_post_types)) {
$supported_post_types = array('post', 'page');
}
update_option('ai_seo_supported_post_types', $supported_post_types);
echo '<div class="notice notice-success"><p>设置已保存!支持的文章类型:' . implode(', ', $supported_post_types) . '</p></div>';
}
$api_key = get_option('ai_seo_api_key', '');
$api_url = get_option('ai_seo_api_url', '');
include AI_SEO_PLUGIN_PATH . 'admin/settings.php';
}
/**
* 测试页面内容
*/
public function test_page() {
if (!class_exists('AiSeoApiTest')) {
echo '<div class="wrap"><h1>测试功能不可用</h1><p>测试类未加载。</p></div>';
return;
}
echo '<div class="wrap">';
echo '<h1>🧪 AI SEO Generator 测试</h1>';
echo '<p>此页面用于测试API连接和功能验证。</p>';
if (isset($_POST['run_test'])) {
$tester = new AiSeoApiTest();
echo $tester->generate_test_report();
} else {
echo '<form method="post">';
echo '<p><button type="submit" name="run_test" class="button button-primary">🚀 运行测试</button></p>';
echo '</form>';
echo '<div class="ai-seo-test-info">';
echo '<h3>测试内容包括:</h3>';
echo '<ul>';
echo '<li>✅ API连接测试</li>';
echo '<li>✅ SEO内容生成测试</li>';
echo '<li>✅ 系统环境检查</li>';
echo '<li>✅ 插件配置验证</li>';
echo '</ul>';
echo '</div>';
}
echo '</div>';
}
/**
* 添加meta boxes到编辑页面
* 支持所有公开的post类型包括自定义post类型
*/
public function add_meta_boxes() {
// 获取所有公开的post类型
$post_types = get_post_types(array('public' => true), 'names');
// 从设置中获取支持的post类型如果没有设置则使用所有公开类型
$supported_post_types = get_option('ai_seo_supported_post_types', $post_types);
// 确保支持的类型都是公开的
$supported_post_types = array_intersect($supported_post_types, $post_types);
// 为每个支持的post类型添加meta box
foreach ($supported_post_types as $post_type) {
add_meta_box(
'ai-seo-generator',
'AI SEO Generator',
array($this, 'meta_box_callback'),
$post_type,
'normal',
'high'
);
}
}
/**
* Meta box回调函数
*/
public function meta_box_callback($post) {
wp_nonce_field('ai_seo_meta_box', 'ai_seo_meta_box_nonce');
$seo_title = get_post_meta($post->ID, '_ai_seo_title', true);
$seo_description = get_post_meta($post->ID, '_ai_seo_description', true);
$seo_keywords = get_post_meta($post->ID, '_ai_seo_keywords', true);
include AI_SEO_PLUGIN_PATH . 'admin/meta-box.php';
}
/**
* 保存文章meta数据
*/
public function save_post_meta($post_id) {
if (!isset($_POST['ai_seo_meta_box_nonce']) || !wp_verify_nonce($_POST['ai_seo_meta_box_nonce'], 'ai_seo_meta_box')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (isset($_POST['ai_seo_title'])) {
update_post_meta($post_id, '_ai_seo_title', sanitize_text_field($_POST['ai_seo_title']));
}
if (isset($_POST['ai_seo_description'])) {
update_post_meta($post_id, '_ai_seo_description', sanitize_textarea_field($_POST['ai_seo_description']));
}
if (isset($_POST['ai_seo_keywords'])) {
update_post_meta($post_id, '_ai_seo_keywords', sanitize_text_field($_POST['ai_seo_keywords']));
}
}
/**
* 加载管理页面脚本和样式
*/
public function enqueue_admin_scripts($hook) {
if ('post.php' == $hook || 'post-new.php' == $hook || 'settings_page_ai-seo-generator' == $hook) {
wp_enqueue_script('ai-seo-admin', AI_SEO_PLUGIN_URL . 'assets/admin.js', array('jquery'), AI_SEO_VERSION, true);
wp_enqueue_style('ai-seo-admin', AI_SEO_PLUGIN_URL . 'assets/admin.css', array(), AI_SEO_VERSION);
wp_localize_script('ai-seo-admin', 'aiSeoAjax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('ai_seo_nonce')
));
}
}
/**
* AJAX处理生成SEO内容
* 增强错误处理和调试信息
*/
public function ajax_generate_seo_content() {
// 增加PHP执行时间限制防止长时间AI生成被中断
set_time_limit(180); // 设置为3分钟
check_ajax_referer('ai_seo_nonce', 'nonce');
$post_id = intval($_POST['post_id']);
$post = get_post($post_id);
if (!$post) {
wp_send_json_error('文章不存在');
return;
}
$content = $post->post_content;
$title = $post->post_title;
// 读取导航主题的自定义字段
$sites_link = get_post_meta($post_id, '_sites_link', true);
$sites_describe = get_post_meta($post_id, '_sites_sescribe', true);
// 构建完整的内容信息,包含自定义字段
$full_content = $content;
if (!empty($sites_link)) {
$full_content .= "\n\n网站链接: " . $sites_link;
}
if (!empty($sites_describe)) {
$full_content .= "\n\n网站描述: " . $sites_describe;
}
// 记录请求信息
error_log('AI SEO Request - Post ID: ' . $post_id . ', Title: ' . $title . ', Sites Link: ' . $sites_link . ', Sites Describe: ' . $sites_describe);
// 调用AI API生成SEO内容
$seo_data = $this->generate_seo_with_ai($title, $full_content);
if ($seo_data && is_array($seo_data)) {
// 记录成功信息
error_log('AI SEO Success: ' . json_encode($seo_data));
wp_send_json_success($seo_data);
} else {
// 记录失败信息
error_log('AI SEO Failed: seo_data = ' . var_export($seo_data, true));
wp_send_json_error('生成SEO内容失败请查看错误日志获取详细信息');
}
}
/**
* 调用AI API生成SEO内容
* 增强调试和错误处理功能
*/
private function generate_seo_with_ai($title, $content) {
$api_key = get_option('ai_seo_api_key');
$api_url = get_option('ai_seo_api_url');
// 记录配置信息
error_log('AI SEO Config - API URL: ' . $api_url . ', API Key: ' . (empty($api_key) ? 'Empty' : 'Set'));
if (empty($api_key) || empty($api_url)) {
error_log('AI SEO Error: API Key or URL not configured');
return false;
}
// 检测是否包含导航网站信息
$is_navigation_site = (strpos($content, '网站链接:') !== false || strpos($content, '网站描述:') !== false);
if ($is_navigation_site) {
$prompt = "请根据以下导航网站信息生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)。这是一个网站导航页面,请重点关注网站的功能、特色和用途:\n\n标题:{$title}\n\n内容:" . wp_strip_all_tags($content) . "\n\n请针对导航类网站的特点生成吸引用户点击的SEO内容。以JSON格式返回包含title、description、keywords字段。";
} else {
$prompt = "请根据以下文章标题和内容生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)\n\n标题:{$title}\n\n内容:" . wp_strip_all_tags($content) . "\n\n请以JSON格式返回包含title、description、keywords字段。";
}
$request_body = array(
'inputs' => array(),
'query' => $prompt,
'response_mode' => 'blocking',
'user' => 'wordpress-user'
);
// 记录请求信息
error_log('AI SEO Request Body: ' . json_encode($request_body));
$response = wp_remote_post($api_url . '/chat-messages', array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json'
),
'body' => json_encode($request_body),
'timeout' => 120 // 增加超时时间到120秒2分钟
));
if (is_wp_error($response)) {
error_log('AI SEO WP Error: ' . $response->get_error_message());
return false;
}
$response_code = wp_remote_retrieve_response_code($response);
error_log('AI SEO Response Code: ' . $response_code);
$body = wp_remote_retrieve_body($response);
// 记录原始响应
error_log('AI SEO Raw Response: ' . $body);
if (empty($body)) {
error_log('AI SEO Error: Empty response body');
return false;
}
$data = json_decode($body, true);
$json_error = json_last_error();
if ($json_error !== JSON_ERROR_NONE) {
error_log('AI SEO JSON Error: ' . json_last_error_msg());
return false;
}
error_log('AI SEO Parsed Data: ' . json_encode($data));
// 方法1: 检查是否直接返回了SEO数据结构
if (isset($data['title'], $data['description'], $data['keywords'])) {
error_log('AI SEO: Found direct SEO data structure');
return array(
'title' => $data['title'],
'description' => $data['description'],
'keywords' => $data['keywords']
);
}
// 方法2: 检查answer字段中的JSON数据
if (isset($data['answer'])) {
$answer = $data['answer'];
error_log('AI SEO: Found answer field: ' . $answer);
// 尝试直接解析answer作为JSON
$seo_data = json_decode($answer, true);
if ($seo_data && isset($seo_data['title'], $seo_data['description'], $seo_data['keywords'])) {
error_log('AI SEO: Successfully parsed answer as JSON');
return $seo_data;
}
// 尝试从answer中提取JSON字符串
preg_match('/\{.*\}/s', $answer, $matches);
if (!empty($matches[0])) {
error_log('AI SEO: Extracted JSON from answer: ' . $matches[0]);
$seo_data = json_decode($matches[0], true);
if ($seo_data && isset($seo_data['title'], $seo_data['description'], $seo_data['keywords'])) {
error_log('AI SEO: Successfully parsed extracted JSON');
return $seo_data;
}
}
}
// 方法3: 检查data字段中的内容
if (isset($data['data'])) {
$data_content = $data['data'];
error_log('AI SEO: Found data field: ' . json_encode($data_content));
if (is_array($data_content) && isset($data_content['title'], $data_content['description'], $data_content['keywords'])) {
error_log('AI SEO: Successfully found SEO data in data field');
return $data_content;
}
}
error_log('AI SEO: No valid SEO data found in response');
return false;
}
/**
* 自定义页面标题
*/
public function custom_wp_title($title, $sep) {
if (is_single() || is_page()) {
global $post;
$custom_title = get_post_meta($post->ID, '_ai_seo_title', true);
if (!empty($custom_title)) {
return $custom_title;
}
}
return $title;
}
/**
* 添加meta标签到页面头部
* 使用Open Graph标签避免与WordPress默认meta标签冲突
*/
public function add_meta_tags() {
if (is_single() || is_page()) {
global $post;
$seo_title = get_post_meta($post->ID, '_ai_seo_title', true);
$description = get_post_meta($post->ID, '_ai_seo_description', true);
$keywords = get_post_meta($post->ID, '_ai_seo_keywords', true);
// 输出Open Graph标题
if (!empty($seo_title)) {
echo '<meta property="og:title" content="' . esc_attr($seo_title) . '">' . "\n";
}
// 输出Open Graph描述
if (!empty($description)) {
echo '<meta property="og:description" content="' . esc_attr($description) . '">' . "\n";
}
// 保留keywords标签Open Graph没有对应标签
if (!empty($keywords)) {
echo '<meta name="keywords" content="' . esc_attr($keywords) . '">' . "\n";
}
// 添加其他常用的Open Graph标签
echo '<meta property="og:type" content="article">' . "\n";
echo '<meta property="og:url" content="' . esc_url(get_permalink($post->ID)) . '">' . "\n";
// 如果文章有特色图片添加og:image
if (has_post_thumbnail($post->ID)) {
$thumbnail_url = get_the_post_thumbnail_url($post->ID, 'large');
echo '<meta property="og:image" content="' . esc_url($thumbnail_url) . '">' . "\n";
}
}
}
}
// 初始化插件
new AiSeoGenerator();
?>