Files
kate522andClaude Opus 5 35bb96e82f refactor: rename the theme brand and every identifier from AKSRT to Jio
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>
2026-11-01 20:05:04 +08:00

354 lines
10 KiB
PHP

<?php
/**
* User template registry + template utils
*
* @package Jio
*/
defined('ABSPATH') || exit;
// ============================================================
// 一、模板注册表 — 所有特殊页面的"身份证"
// 修改此处即可增删模板页面,无需改动其他逻辑
// ============================================================
// Only true fixed template pages live in the registry.
$_jio_special_templates = [
'sign' => [
'file' => 'templates/pages/page-sign.php',
'slug' => 'sign',
'title' => '登录/注册',
'fallback' => '/sign/',
],
'categories' => [
'file' => 'templates/pages/page-categories.php',
'slug' => 'categories',
'title' => '分类目录',
'fallback' => '/categories/',
],
'friends' => [
'file' => 'templates/pages/page-friends.php',
'slug' => 'friends',
'title' => '友情链接',
'fallback' => '/friends/',
],
'profile' => [
'file' => 'templates/pages/page-profile.php',
'slug' => 'profile',
'title' => '个人中心',
'fallback' => '/profile/',
],
'submit' => [
'file' => 'templates/pages/page-submit.php',
'slug' => 'submit',
'title' => '发布文章',
'fallback' => '/submit/',
],
];
/** @var array 缓存 key=模板文件路径 => value=WP_Post|null */
$_jio_template_page_cache = [];
// ============================================================
// 二、核心工具函数
// ============================================================
/**
* 查找使用指定模板文件的页面(按模板匹配,自适应任意 slug)
*
* @param string $template_file 相对于主题的模板路径
* @return WP_Post|null
*/
function jio_find_template_page(string $template_file) {
global $_jio_template_page_cache;
if (isset($_jio_template_page_cache[$template_file])) {
return $_jio_template_page_cache[$template_file];
}
$page = null;
$pages = get_pages([
'meta_key' => '_wp_page_template',
'meta_value' => $template_file,
'number' => 1,
'post_status' => 'publish',
]);
if (!empty($pages)) {
$page = $pages[0];
}
$_jio_template_page_cache[$template_file] = $page;
return $page;
}
/**
* 获取使用指定模板的页面 URL
*
* @param string $key 注册表 key(当前仅 profile 使用)
* @return string 页面 URL 或回退地址
*/
function jio_get_template_url(string $key): string {
global $_jio_special_templates;
if (!isset($_jio_special_templates[$key])) {
return home_url('/');
}
$cfg = $_jio_special_templates[$key];
$page = jio_find_template_page($cfg['file']);
if (!$page) {
jio_ensure_template_page($key);
$page = jio_find_template_page($cfg['file']);
}
if ($page) {
return get_permalink($page->ID);
}
return home_url($cfg['fallback']);
}
/**
* 定位模板文件的绝对路径
*
* @param string $template_file 相对于主题的路径
* @return string|false 文件绝对路径或 false
*/
function jio_locate_template_file(string $template_file) {
$path = locate_template([$template_file]);
if ($path) return $path;
$full = JIO_DIR . '/' . $template_file;
return file_exists($full) ? $full : false;
}
/**
* Resolve a public-facing page template file from stored meta or page slug.
*/
function jio_resolve_page_template_file(string $template_file = '', string $post_slug = ''): string {
$template_file = ltrim($template_file, '/\\');
$post_slug = sanitize_title($post_slug);
if ($template_file !== '') {
if ($template_file === 'templates/pages/page-messages.php') {
return '';
}
if ($template_file === 'templates/pages/page-sign.php') {
return $template_file;
}
if (strpos($template_file, 'templates/pages/') === 0 && jio_locate_template_file($template_file)) {
return $template_file;
}
}
if ($post_slug !== '') {
if ($post_slug === 'sign') {
return 'templates/pages/page-sign.php';
}
$slug_map = [
'categories' => 'templates/pages/page-categories.php',
'friends' => 'templates/pages/page-friends.php',
'profile' => 'templates/pages/page-profile.php',
];
if (!empty($slug_map[$post_slug]) && jio_locate_template_file($slug_map[$post_slug])) {
return $slug_map[$post_slug];
}
}
return '';
}
/**
* Normalize auth view keys used by the unified sign page.
*/
function jio_normalize_auth_tab(string $tab): string {
$tab = sanitize_key($tab);
switch ($tab) {
case 'signin':
return 'signin';
case 'signup':
return 'signup';
case 'bind':
return 'bind';
case 'resetpassword':
return 'resetpassword';
case 'oauth':
return 'oauth';
default:
return 'signin';
}
}
/**
* 清除模板页面缓存
*/
function jio_clear_template_page_cache(): void {
global $_jio_template_page_cache;
$_jio_template_page_cache = [];
}
/**
* Prepare the public user-home template context and return its template path.
*/
function jio_get_user_home_template_path(): string {
global $_jio_special_templates, $jio_profile_user;
$identifier = (string) get_query_var('jio_author_identifier');
if ($identifier === '') {
return '';
}
$user = function_exists('jio_resolve_public_user') ? jio_resolve_public_user($identifier) : null;
if (!$user instanceof WP_User) {
return '';
}
$template_path = jio_locate_template_file('templates/pages/page-user-home.php');
if (!$template_path) {
return '';
}
$jio_profile_user = $user;
return $template_path;
}
/**
* Resolve the active special-page template path for the current request.
*/
function jio_get_current_special_template_path(): string {
if (get_query_var('jio_message_view')) {
$message_template = jio_locate_template_file('templates/pages/page-messages.php');
return $message_template ?: '';
}
if (get_query_var('jio_author_identifier')) {
return jio_get_user_home_template_path();
}
if (get_query_var('jio_user_center')) {
$profile_template = jio_locate_template_file('templates/pages/page-profile.php');
return $profile_template ?: '';
}
if (get_query_var('jio_sign')) {
$auth_template_path = jio_locate_template_file('templates/pages/page-sign.php');
return $auth_template_path ?: '';
}
if (is_page()) {
$page_id = get_queried_object_id();
if ($page_id > 0) {
$page_template = get_post_meta($page_id, '_wp_page_template', true);
$resolved_template = jio_resolve_page_template_file(
is_string($page_template) ? $page_template : '',
(string) get_post_field('post_name', $page_id)
);
if ($resolved_template !== '') {
$resolved_path = jio_locate_template_file($resolved_template);
if ($resolved_path) {
return $resolved_path;
}
}
}
}
return '';
}
/**
* 根据当前请求路径识别系统模板页 key。
*
* 用于前台直接访问固定 slug 时的自动补页。
*/
function jio_get_requested_template_key(): string {
global $_jio_special_templates;
$request_uri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : '';
if ($request_uri === '') {
return '';
}
$request_path = wp_parse_url($request_uri, PHP_URL_PATH);
if (!is_string($request_path) || $request_path === '') {
return '';
}
$home_path = (string) wp_parse_url(home_url('/'), PHP_URL_PATH);
if ($home_path !== '' && str_starts_with($request_path, $home_path)) {
$request_path = (string) substr($request_path, strlen($home_path));
}
$request_slug = trim($request_path, '/');
if ($request_slug === '') {
return '';
}
foreach ($_jio_special_templates as $key => $cfg) {
$slug = isset($cfg['slug']) ? sanitize_title((string) $cfg['slug']) : '';
if ($slug !== '' && $slug === $request_slug) {
return (string) $key;
}
}
return '';
}
/**
* 确保使用指定模板的页面存在,缺失则自动创建
*
* @param string $key 注册表 key
*/
function jio_ensure_template_page(string $key): void {
global $_jio_special_templates;
if (!isset($_jio_special_templates[$key])) return;
$cfg = $_jio_special_templates[$key];
if (array_key_exists('auto_create', $cfg) && empty($cfg['auto_create'])) {
return;
}
$desired_slug = sanitize_title($cfg['slug'] ?? $key);
// 已有页面使用此模板?仍校验模板 meta,避免空白默认页。
$found_page = jio_find_template_page($cfg['file']);
if ($found_page instanceof WP_Post) {
$current_tpl = get_post_meta((int) $found_page->ID, '_wp_page_template', true);
if ($current_tpl !== $cfg['file']) {
update_post_meta((int) $found_page->ID, '_wp_page_template', $cfg['file']);
jio_clear_template_page_cache();
}
return;
}
if ($desired_slug !== '') {
$existing_page = get_page_by_path($desired_slug, OBJECT, 'page');
if ($existing_page instanceof WP_Post) {
// Slug collisions belong to the administrator. System pages are
// created only when the slug is completely free.
return;
}
}
// 自动创建
$page_id = wp_insert_post([
'post_title' => $cfg['title'],
'post_content' => '',
'post_status' => 'publish',
'post_type' => 'page',
'post_name' => $desired_slug !== '' ? $desired_slug : $key,
'comment_status' => 'closed',
'ping_status' => 'closed',
]);
if (!is_wp_error($page_id) && $page_id > 0) {
update_post_meta($page_id, '_wp_page_template', $cfg['file']);
update_post_meta($page_id, '_jio_managed_template_page', (string) $key);
jio_clear_template_page_cache();
}
}