Move 288 types from global AKSRT_* + inc/classes manual requires into
namespace AKSRT\{Domain} under src/AKSRT/, wire composer.json psr-4,
and slim bootstrap to helpers/modules/hooks only. Split multi-class
widget/gateway files, update admin contract audit paths, and document
the layout in ADR/README.
286 lines
9.7 KiB
PHP
286 lines
9.7 KiB
PHP
<?php
|
||
/**
|
||
* @package AKSRT
|
||
*/
|
||
|
||
namespace AKSRT\Core;
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
trait ScriptsPart2 {
|
||
|
||
|
||
/**
|
||
* 前端 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\Admin::enqueue_admin_assets() 负责加载
|
||
}
|
||
|
||
/**
|
||
* 输出运行时 CSS 变量覆盖
|
||
*
|
||
* 仅注入用户可在后台配置的覆盖值(logo / favicon / primary),
|
||
* 主体宽度统一使用固定 token:1280 / 1080 / 300。
|
||
*/
|
||
public function inline_css_vars(): void {
|
||
(new \AKSRT\Frontend\InlineStyleBuilder())->output();
|
||
}
|
||
|
||
/**
|
||
* 输出自定义头部/底部代码
|
||
*/
|
||
public function output_custom_codes(): void {
|
||
(new \AKSRT\Frontend\CustomCodeRenderer())->output_header();
|
||
}
|
||
|
||
public function output_loading_overlay(): void {
|
||
(new \AKSRT\Frontend\LoadingOverlayRenderer())->output();
|
||
}
|
||
|
||
/**
|
||
* 输出自定义底部代码
|
||
*/
|
||
public function output_custom_footer_codes(): void {
|
||
(new \AKSRT\Frontend\CustomCodeRenderer())->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';
|
||
}
|
||
|
||
// Zibll site-layout-1/2/3 (no sidebar / right / left).
|
||
if (function_exists('aksrt_body_layout_classes')) {
|
||
foreach (aksrt_body_layout_classes() as $layout_class) {
|
||
$classes[] = $layout_class;
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|