Move ~94 root class shells and root *-traits into domain directories (core, auth, user, credits, content, payment/gateways, forum, shop, sms, ai, messages, extensions, widgets, settings, admin). Update bootstrap require paths, co-locate traits with owners, fix forum/user relative requires, drop duplicate shop controller requires, and wire home-modules load. Path-only; class names and init order unchanged.
238 lines
7.9 KiB
PHP
238 lines
7.9 KiB
PHP
<?php
|
|
/**
|
|
* AKSRT Search Push Service
|
|
*
|
|
* 提供搜索引擎主动推送能力。当前支持百度推送。
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class AKSRT_Search_Push {
|
|
|
|
private static $instance = null;
|
|
|
|
public static function get_instance(): self {
|
|
if (null === self::$instance) self::$instance = new self();
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* 绑定运行时钩子:发布/更新主动推送 + 前台自动推送 JS。
|
|
*/
|
|
public function init(): void {
|
|
add_action('transition_post_status', [$this, 'on_transition_post_status'], 10, 3);
|
|
add_action('wp_footer', [$this, 'output_auto_push_script'], 99);
|
|
}
|
|
|
|
/**
|
|
* 文章发布/更新时主动推送链接到百度。
|
|
*
|
|
* @param string $new_status 新状态。
|
|
* @param string $old_status 旧状态。
|
|
* @param WP_Post $post 文章对象。
|
|
*/
|
|
public function on_transition_post_status(string $new_status, string $old_status, $post): void {
|
|
if (!($post instanceof WP_Post)) {
|
|
return;
|
|
}
|
|
if ($new_status !== 'publish') {
|
|
return;
|
|
}
|
|
if (wp_is_post_revision($post->ID) || wp_is_post_autosave($post->ID)) {
|
|
return;
|
|
}
|
|
// 仅推送公开可索引的内容类型。
|
|
$allowed = function_exists('aksrt_searchable_post_types')
|
|
? aksrt_searchable_post_types()
|
|
: ['post'];
|
|
if (!in_array($post->post_type, $allowed, true)) {
|
|
return;
|
|
}
|
|
|
|
$config = $this->get_config();
|
|
if (empty($config['baidu_push_enabled'])) {
|
|
return;
|
|
}
|
|
|
|
$is_new = $old_status !== 'publish';
|
|
if ($is_new && empty($config['baidu_push_on_publish'])) {
|
|
return;
|
|
}
|
|
if (!$is_new && empty($config['baidu_push_on_update'])) {
|
|
return;
|
|
}
|
|
|
|
$this->push_url((string) get_permalink($post));
|
|
}
|
|
|
|
/**
|
|
* 前台输出百度自动推送 JS(由 wp_footer 调用)。
|
|
*/
|
|
public function output_auto_push_script(): void {
|
|
if (is_admin()) {
|
|
return;
|
|
}
|
|
$script = $this->get_auto_push_script();
|
|
if ($script !== '') {
|
|
echo $script; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped — 固定常量脚本,无用户输入
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 推送单条 URL 到百度
|
|
*
|
|
* @param string $url 待推送的完整 URL
|
|
* @return array{success: bool, message: string, result: array}
|
|
*/
|
|
public function push_url(string $url): array {
|
|
$config = $this->get_config();
|
|
|
|
if (empty($config['baidu_push_enabled'])) {
|
|
return ['success' => false, 'message' => __('百度推送未启用', 'aksrt'), 'result' => []];
|
|
}
|
|
|
|
$token = (string) ($config['baidu_push_token'] ?? '');
|
|
if ($token === '') {
|
|
return ['success' => false, 'message' => __('推送 Token 未配置', 'aksrt'), 'result' => []];
|
|
}
|
|
|
|
$api_url = "http://data.zz.baidu.com/urls?site=" . rawurlencode(home_url('/')) . "&token={$token}";
|
|
|
|
$response = wp_remote_post($api_url, [
|
|
'timeout' => 10,
|
|
'headers' => ['Content-Type' => 'text/plain'],
|
|
'body' => $url,
|
|
]);
|
|
|
|
if (is_wp_error($response)) {
|
|
$this->log('error', $url, $response->get_error_message());
|
|
return ['success' => false, 'message' => $response->get_error_message(), 'result' => []];
|
|
}
|
|
|
|
$body = json_decode(wp_remote_retrieve_body($response), true);
|
|
$status = wp_remote_retrieve_response_code($response);
|
|
|
|
if ($status === 200 && isset($body['success'])) {
|
|
$this->log('success', $url, wp_json_encode($body));
|
|
return ['success' => true, 'message' => __('推送成功', 'aksrt'), 'result' => $body];
|
|
}
|
|
|
|
$err_msg = $body['message'] ?? ($body['error'] ?? sprintf('HTTP %d', $status));
|
|
$this->log('error', $url, $err_msg);
|
|
return ['success' => false, 'message' => $err_msg, 'result' => $body ?? []];
|
|
}
|
|
|
|
/**
|
|
* 批量推送 URL
|
|
*
|
|
* @param string[] $urls
|
|
* @return array{success: int, failed: int, results: array}
|
|
*/
|
|
public function push_batch(array $urls): array {
|
|
$config = $this->get_config();
|
|
$batch_size = max(1, min(500, (int) ($config['baidu_push_batch_size'] ?? 50)));
|
|
$success = 0;
|
|
$failed = 0;
|
|
$results = [];
|
|
|
|
$chunks = array_chunk($urls, $batch_size);
|
|
foreach ($chunks as $chunk) {
|
|
$token = (string) ($config['baidu_push_token'] ?? '');
|
|
$api_url = "http://data.zz.baidu.com/urls?site=" . rawurlencode(home_url('/')) . "&token={$token}";
|
|
$body_str = implode("\n", $chunk);
|
|
|
|
$response = wp_remote_post($api_url, [
|
|
'timeout' => 15,
|
|
'headers' => ['Content-Type' => 'text/plain'],
|
|
'body' => $body_str,
|
|
]);
|
|
|
|
if (is_wp_error($response)) {
|
|
$failed += count($chunk);
|
|
$results[] = ['error' => $response->get_error_message()];
|
|
continue;
|
|
}
|
|
|
|
$body = json_decode(wp_remote_retrieve_body($response), true);
|
|
if (isset($body['success'])) {
|
|
$success += (int) ($body['success'] ?? 0);
|
|
$failed += (int) ($body['not_same_site'] ?? 0) + (int) ($body['not_valid'] ?? 0);
|
|
} else {
|
|
$failed += count($chunk);
|
|
}
|
|
$results[] = $body ?? [];
|
|
}
|
|
|
|
return ['success' => $success, 'failed' => $failed, 'results' => $results];
|
|
}
|
|
|
|
/**
|
|
* 获取自动推送 JS 代码
|
|
*/
|
|
public function get_auto_push_script(): string {
|
|
$config = $this->get_config();
|
|
if (empty($config['baidu_push_enabled']) || empty($config['baidu_push_auto'])) {
|
|
return '';
|
|
}
|
|
|
|
$site_url = home_url('/');
|
|
return <<<SCRIPT
|
|
<script>
|
|
(function(){
|
|
var bp = document.createElement('script');
|
|
var curProtocol = window.location.protocol.split(':')[0];
|
|
if (curProtocol === 'https') {
|
|
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
|
|
} else {
|
|
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
|
|
}
|
|
var s = document.getElementsByTagName("script")[0];
|
|
s.parentNode.insertBefore(bp, s);
|
|
})();
|
|
</script>
|
|
SCRIPT;
|
|
}
|
|
|
|
/**
|
|
* 获取服务运行时状态
|
|
*/
|
|
public function get_status(): array {
|
|
$config = $this->get_config();
|
|
$enabled = !empty($config['baidu_push_enabled']);
|
|
$token = (string) ($config['baidu_push_token'] ?? '');
|
|
|
|
$missing = [];
|
|
if ($enabled && $token === '') {
|
|
$missing[] = 'baidu_push_token';
|
|
}
|
|
|
|
return [
|
|
'enabled' => $enabled,
|
|
'provider' => 'baidu',
|
|
'configured' => $enabled && $token !== '',
|
|
'available' => $enabled && $token !== '',
|
|
'verified' => !empty($config['baidu_push_verified']),
|
|
'transport' => 'http_api',
|
|
'missing_fields' => $missing,
|
|
'auto_push' => !empty($config['baidu_push_auto']),
|
|
'on_publish' => !empty($config['baidu_push_on_publish']),
|
|
'on_update' => !empty($config['baidu_push_on_update']),
|
|
'batch_size' => max(1, (int) ($config['baidu_push_batch_size'] ?? 50)),
|
|
];
|
|
}
|
|
|
|
private function get_config(): array {
|
|
if (class_exists('AKSRT_Settings')) {
|
|
return AKSRT_Settings::get_search_push_settings();
|
|
}
|
|
return ['baidu_push_enabled' => false];
|
|
}
|
|
|
|
private function log(string $level, string $url, string $message): void {
|
|
if (!defined('WP_DEBUG') || !WP_DEBUG) return;
|
|
error_log(sprintf('[AKSRT Search Push] [%s] URL: %s — %s', $level, $url, $message));
|
|
}
|
|
}
|