Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.
Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)
Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
(dropped 3 stale entries, added the 17 missing ones)
Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
when it is empty
Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.
Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
278 lines
9.5 KiB
PHP
278 lines
9.5 KiB
PHP
<?php
|
||
/**
|
||
* @package Jio
|
||
*/
|
||
|
||
namespace Jio\Core;
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
trait ScriptsPart2 {
|
||
|
||
|
||
/**
|
||
* 前端 debug 上报入口(仅在 WP_DEBUG 模式下写日志)
|
||
*/
|
||
public function handle_frontend_debug(): void {
|
||
check_ajax_referer('jio_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]);
|
||
}
|
||
|
||
/**
|
||
* 加载后台资源 — 仅在 Jio 设置页面加载(与前端样式完全隔离)
|
||
*/
|
||
public function enqueue_admin($hook): void {
|
||
// 只在 Jio 设置页面 (SPA 容器) 加载
|
||
$screen = get_current_screen();
|
||
if (!$screen || $screen->base !== 'toplevel_page_jio-settings') {
|
||
return;
|
||
}
|
||
|
||
// Admin 专用面板样式 — 独立于前端,不受前端 CSS 影响
|
||
wp_enqueue_style(
|
||
'jio-admin-panel',
|
||
JIO_URI . '/assets/css/admin/admin-panel.css',
|
||
[], // 无依赖,不加载任何前端样式
|
||
JIO_VERSION
|
||
);
|
||
|
||
// 注意: SPA 主资源 (Vue3 build) 由 \Jio\Admin\Admin::enqueue_admin_assets() 负责加载
|
||
}
|
||
|
||
/**
|
||
* 输出运行时 CSS 变量覆盖
|
||
*
|
||
* 仅注入用户可在后台配置的覆盖值(logo / favicon / primary),
|
||
* 主体宽度统一使用固定 token:1280 / 1080 / 300。
|
||
*/
|
||
public function inline_css_vars(): void {
|
||
(new \Jio\Frontend\InlineStyleBuilder())->output();
|
||
}
|
||
|
||
/**
|
||
* 输出自定义头部/底部代码
|
||
*/
|
||
public function output_custom_codes(): void {
|
||
(new \Jio\Frontend\CustomCodeRenderer())->output_header();
|
||
}
|
||
|
||
public function output_loading_overlay(): void {
|
||
(new \Jio\Frontend\LoadingOverlayRenderer())->output();
|
||
}
|
||
|
||
/**
|
||
* 输出自定义底部代码
|
||
*/
|
||
public function output_custom_footer_codes(): void {
|
||
(new \Jio\Frontend\CustomCodeRenderer())->output_footer();
|
||
}
|
||
|
||
/**
|
||
* Body 类增强
|
||
*/
|
||
public function body_classes(array $classes): array {
|
||
if (is_front_page()) {
|
||
$classes[] = 'front-page';
|
||
}
|
||
if (function_exists('jio_is_fixed_homepage_request') && jio_is_fixed_homepage_request()) {
|
||
$classes[] = 'jio-homepage-layout';
|
||
$classes[] = 'jio-homepage-active';
|
||
}
|
||
if (is_singular()) {
|
||
$classes[] = 'single-post-' . get_the_ID();
|
||
}
|
||
if (is_archive()) {
|
||
$classes[] = 'archive-page';
|
||
}
|
||
if ((function_exists('jio_is_user_center_page') && jio_is_user_center_page())
|
||
|| (function_exists('jio_is_user_home_page') && jio_is_user_home_page())
|
||
|| get_query_var('jio_author_identifier')) {
|
||
$classes[] = 'jio-profile';
|
||
}
|
||
// 区分本人中心与公开主页的 body class
|
||
if (function_exists('jio_is_user_center_page') && jio_is_user_center_page()) {
|
||
$classes[] = 'jio-user-center';
|
||
}
|
||
if (function_exists('jio_is_user_home_page') && jio_is_user_home_page()) {
|
||
$classes[] = 'jio-user-home';
|
||
}
|
||
if (function_exists('jio_is_auth_page_request') && jio_is_auth_page_request()) {
|
||
$classes[] = 'auth-page';
|
||
}
|
||
|
||
// 对齐参考主题 close_backdrop:fps-accelerat 由 main.css 统一关闭 backdrop-filter。
|
||
if (class_exists('\Jio\Settings\Settings') && \Jio\Settings\Settings::close_backdrop()) {
|
||
$classes[] = 'fps-accelerat';
|
||
}
|
||
|
||
// legacy site-layout-1/2/3 (no sidebar / right / left).
|
||
if (function_exists('jio_body_layout_classes')) {
|
||
foreach (jio_body_layout_classes() as $layout_class) {
|
||
$classes[] = $layout_class;
|
||
}
|
||
}
|
||
|
||
return $classes;
|
||
}
|
||
|
||
/**
|
||
* 搜索历史同步(登录用户)
|
||
*/
|
||
public function handle_search_history(): void {
|
||
check_ajax_referer('jio_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 = 'jio_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('jio_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 篇文章', 'jio'), $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 篇文章', 'jio'), $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 = '[Jio 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 [
|
||
'orders' => function_exists('jio_get_user_center_tab_url') ? jio_get_user_center_tab_url('orders') : home_url('/user/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('jio_find_template_page')) {
|
||
$page = jio_find_template_page($template_file);
|
||
if ($page instanceof \WP_Post) {
|
||
return get_permalink($page);
|
||
}
|
||
}
|
||
|
||
return home_url($fallback);
|
||
}
|
||
}
|