Files
wordpress-theme-aksrt/inc/classes/scripts-traits/trait-aksrt-scripts-part-2.php
T

273 lines
9.4 KiB
PHP
Raw 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
defined('ABSPATH') || exit;
trait AKSRT_Scripts_Part_2 {
/**
* 前端 debug 上报入口(仅在 WP_DEBUG 模式下写日志)
*/
public function handle_frontend_debug(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
if (!defined('WP_DEBUG') || !WP_DEBUG) {
wp_send_json_success(['ignored' => true]);
}
$ctx = [
'source' => isset($_POST['source']) ? sanitize_text_field(wp_unslash($_POST['source'])) : 'frontend',
'event' => isset($_POST['event']) ? sanitize_text_field(wp_unslash($_POST['event'])) : 'unknown',
'page' => isset($_POST['page']) ? esc_url_raw(wp_unslash($_POST['page'])) : '',
'text' => isset($_POST['text']) ? sanitize_text_field(wp_unslash($_POST['text'])) : '',
'size' => isset($_POST['size']) ? (int) wp_unslash($_POST['size']) : 0,
'error' => isset($_POST['error']) ? sanitize_text_field(wp_unslash($_POST['error'])) : '',
];
$this->debug_log('frontend debug event', $ctx);
wp_send_json_success(['logged' => true]);
}
/**
* Passive event listener polyfill — 全局加载,消除 Chrome Violation 警告
*/
public function enqueue_passive_polyfill(): void {
wp_enqueue_script(
'aksrt-passive-events',
get_template_directory_uri() . '/assets/js/passive-events.js',
[],
AKSRT_VERSION,
false
);
}
/**
* 加载后台资源 — 仅在 AKSRT 设置页面加载(与前端样式完全隔离)
*/
public function enqueue_admin($hook): void {
// 只在 AKSRT 设置页面 (SPA 容器) 加载
$screen = get_current_screen();
if (!$screen || $screen->base !== 'toplevel_page_aksrt-settings') {
return;
}
// Admin 专用面板样式 — 独立于前端,不受前端 CSS 影响
wp_enqueue_style(
'aksrt-admin-panel',
AKSRT_URI . '/assets/css/admin/admin-panel.css',
[], // 无依赖,不加载任何前端样式
AKSRT_VERSION
);
// 注意: SPA 主资源 (Vue3 build) 由 AKSRT_Admin::enqueue_admin_assets() 负责加载
}
/**
* 输出运行时 CSS 变量覆盖
*
* 仅注入用户可在后台配置的覆盖值(logo / favicon / primary),
* 主体宽度统一使用固定 token:1280 / 1080 / 300。
*/
public function inline_css_vars(): void {
(new AKSRT_Inline_Style_Builder())->output();
}
/**
* 输出自定义头部/底部代码
*/
public function output_custom_codes(): void {
(new AKSRT_Custom_Code_Renderer())->output_header();
}
public function output_loading_overlay(): void {
(new AKSRT_Loading_Overlay_Renderer())->output();
}
/**
* 输出自定义底部代码
*/
public function output_custom_footer_codes(): void {
(new AKSRT_Custom_Code_Renderer())->output_footer();
}
/**
* Body 类增强
*/
public function body_classes(array $classes): array {
if (is_front_page()) {
$classes[] = 'front-page';
}
if (function_exists('aksrt_is_fixed_homepage_request') && aksrt_is_fixed_homepage_request()) {
$classes[] = 'aksrt-homepage-layout';
$classes[] = 'aksrt-homepage-active';
}
if (is_singular()) {
$classes[] = 'single-post-' . get_the_ID();
}
if (is_archive()) {
$classes[] = 'archive-page';
}
if ((function_exists('aksrt_is_user_center_page') && aksrt_is_user_center_page())
|| (function_exists('aksrt_is_user_home_page') && aksrt_is_user_home_page())
|| get_query_var('user_nicename')) {
$classes[] = 'aksrt-profile';
}
// 区分本人中心与公开主页的 body class
if (function_exists('aksrt_is_user_center_page') && aksrt_is_user_center_page()) {
$classes[] = 'aksrt-user-center';
}
if (function_exists('aksrt_is_user_home_page') && aksrt_is_user_home_page()) {
$classes[] = 'aksrt-user-home';
}
if (function_exists('aksrt_is_auth_page_request') && aksrt_is_auth_page_request()) {
$classes[] = 'auth-page';
}
return $classes;
}
/**
* 搜索历史同步(登录用户)
*/
public function handle_search_history(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
$user_id = get_current_user_id();
if (!$user_id) {
wp_send_json_error(['message' => '未登录'], 401);
}
$mode = isset($_POST['mode']) ? sanitize_key(wp_unslash($_POST['mode'])) : 'get';
$meta_key = 'aksrt_search_history';
if ($mode === 'save') {
$raw = isset($_POST['items']) ? wp_unslash($_POST['items']) : '[]';
$items = json_decode($raw, true);
if (!is_array($items)) {
$items = [];
}
$clean = [];
foreach (array_slice($items, 0, 20) as $item) {
if (!is_array($item) || empty($item['keyword'])) {
continue;
}
$clean[] = [
'keyword' => sanitize_text_field($item['keyword']),
'type' => sanitize_key($item['type'] ?? 'post'),
];
}
update_user_meta($user_id, $meta_key, $clean);
wp_send_json_success(['items' => $clean]);
}
$saved = get_user_meta($user_id, $meta_key, true);
wp_send_json_success(['items' => is_array($saved) ? $saved : []]);
}
/**
* 搜索建议(实时搜索提示)
*/
public function handle_search_suggestions(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
$q = isset($_POST['q']) ? sanitize_text_field(wp_unslash($_POST['q'])) : '';
$type = isset($_POST['type']) ? sanitize_key(wp_unslash($_POST['type'])) : 'post';
if (mb_strlen($q) < 2) {
wp_send_json_success(['items' => []]);
}
$items = [];
if ($type === 'post' || $type === '') {
$posts = get_posts([
'post_type' => 'post',
'post_status' => 'publish',
's' => $q,
'posts_per_page' => 6,
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
]);
foreach ($posts as $p) {
$items[] = [
'title' => $p->post_title,
'url' => get_permalink($p),
'meta' => get_the_date('', $p),
];
}
} elseif ($type === 'category') {
$terms = get_terms([
'taxonomy' => 'category',
'search' => $q,
'number' => 6,
'hide_empty' => true,
]);
if (!is_wp_error($terms)) {
foreach ($terms as $t) {
$items[] = [
'title' => $t->name,
'url' => get_term_link($t),
'meta' => sprintf(__('%d 篇文章', 'aksrt'), $t->count),
];
}
}
} elseif ($type === 'tag') {
$terms = get_terms([
'taxonomy' => 'post_tag',
'search' => $q,
'number' => 6,
'hide_empty' => true,
]);
if (!is_wp_error($terms)) {
foreach ($terms as $t) {
$items[] = [
'title' => $t->name,
'url' => get_term_link($t),
'meta' => sprintf(__('%d 篇文章', 'aksrt'), $t->count),
];
}
}
}
wp_send_json_success(['items' => $items]);
}
private function debug_log(string $message, array $context = []): void {
if (!defined('WP_DEBUG') || !WP_DEBUG) {
return;
}
$payload = '[AKSRT Scripts] ' . $message;
if (!empty($context)) {
$json = wp_json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (false !== $json) {
$payload .= ' ' . $json;
}
}
error_log($payload);
}
/**
* Resolve public route URLs from the rebuilt mainline ownership.
*
* @return array<string, string>
*/
private function resolve_frontend_routes(): array {
return [
'cart' => $this->resolve_template_page_url('templates/pages/page-cart.php', '/cart/'),
'orders' => $this->resolve_template_page_url('templates/pages/page-orders.php', '/orders/'),
'resources' => home_url('/resources/'),
];
}
/**
* Resolve the permalink for a template-owned page with a stable fallback.
*/
private function resolve_template_page_url(string $template_file, string $fallback): string {
if (function_exists('aksrt_find_template_page')) {
$page = aksrt_find_template_page($template_file);
if ($page instanceof WP_Post) {
return get_permalink($page);
}
}
return home_url($fallback);
}
}