Files
wordpress-theme-aksrt/inc/modules/user-parts/template-registry.php
T

544 lines
16 KiB
PHP

<?php
/**
* User template registry + template utils
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
// ============================================================
// 一、模板注册表 — 所有特殊页面的"身份证"
// 修改此处即可增删模板页面,无需改动其他逻辑
// ============================================================
$_aksrt_special_templates = [
'login' => [
'file' => 'templates/pages/page-login.php',
'slug' => 'login',
'title' => '登录',
'fallback' => '/login/',
],
'register' => [
'file' => 'templates/pages/page-register.php',
'slug' => 'register',
'title' => '注册',
'fallback' => '/register/',
],
'bind' => [
'file' => 'templates/pages/page-bind-account.php',
'slug' => 'bind-account',
'title' => '绑定账号',
'fallback' => '/bind-account/',
],
'reset-password' => [
'file' => 'templates/pages/page-reset-password.php',
'slug' => 'reset-password',
'title' => '重置密码',
'fallback' => '/reset-password/',
],
'verify-email' => [
'file' => 'templates/pages/page-verify-email.php',
'slug' => 'verify-email',
'title' => '邮箱验证',
'fallback' => '/verify-email/',
],
'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' => '/',
],
];
// Zibll-style v2 routing keeps only true fixed template pages in the registry.
$_aksrt_special_templates = [
'sign' => [
'file' => 'templates/pages/page-sign.php',
'slug' => 'sign',
'title' => '登录/注册',
'fallback' => '/sign/',
],
'bind' => [
'file' => 'templates/pages/page-bind-account.php',
'slug' => 'bind-account',
'title' => '绑定账号',
'fallback' => '/bind-account/',
],
'reset-password' => [
'file' => 'templates/pages/page-reset-password.php',
'slug' => 'reset-password',
'title' => '重置密码',
'fallback' => '/reset-password/',
],
'verify-email' => [
'file' => 'templates/pages/page-verify-email.php',
'slug' => 'verify-email',
'title' => '邮箱验证',
'fallback' => '/verify-email/',
],
'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/',
],
// Commerce center pages (权益与消费 / 购物车 / 收益)
'orders' => [
'file' => 'templates/pages/page-orders.php',
'slug' => 'orders',
'title' => '我的订单',
'fallback' => '/orders/',
],
'cart' => [
'file' => 'templates/pages/page-cart.php',
'slug' => 'cart',
'title' => '购物车',
'fallback' => '/cart/',
],
'revenue' => [
'file' => 'templates/pages/page-revenue.php',
'slug' => 'revenue',
'title' => '收益中心',
'fallback' => '/revenue/',
],
'messages' => [
'file' => 'templates/pages/page-messages.php',
'slug' => 'messages',
'title' => '消息中心',
'fallback' => '/messages/',
],
'submit' => [
'file' => 'templates/pages/page-submit.php',
'slug' => 'submit',
'title' => '发布文章',
'fallback' => '/submit/',
],
];
/** @var array 缓存 key=模板文件路径 => value=WP_Post|null */
$_aksrt_template_page_cache = [];
// ============================================================
// 二、核心工具函数
// ============================================================
/**
* 查找使用指定模板文件的页面(按模板匹配,自适应任意 slug)
*
* @param string $template_file 相对于主题的模板路径
* @return WP_Post|null
*/
function aksrt_find_template_page(string $template_file) {
global $_aksrt_template_page_cache;
if (isset($_aksrt_template_page_cache[$template_file])) {
return $_aksrt_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];
}
$_aksrt_template_page_cache[$template_file] = $page;
return $page;
}
/**
* 获取使用指定模板的页面 URL
*
* @param string $key 注册表 key(当前仅 profile 使用)
* @return string 页面 URL 或回退地址
*/
function aksrt_get_template_url(string $key): string {
global $_aksrt_special_templates;
if (!isset($_aksrt_special_templates[$key])) {
return home_url('/');
}
$cfg = $_aksrt_special_templates[$key];
$page = aksrt_find_template_page($cfg['file']);
if (!$page) {
aksrt_ensure_template_page($key);
$page = aksrt_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 aksrt_locate_template_file(string $template_file) {
$path = locate_template([$template_file]);
if ($path) return $path;
$full = AKSRT_DIR . '/' . $template_file;
return file_exists($full) ? $full : false;
}
/**
* Resolve a public-facing page template file from stored meta or page slug.
*/
function aksrt_resolve_page_template_file(string $template_file = '', string $post_slug = ''): string {
$template_file = ltrim($template_file, '/\\');
$post_slug = sanitize_title($post_slug);
$legacy_auth_templates = [
'templates/pages/page-login.php' => 'login',
'templates/pages/page-register.php' => 'register',
'templates/pages/page-bind-account.php' => 'bind',
'templates/pages/page-reset-password.php' => 'reset-password',
'templates/pages/page-verify-email.php' => 'verify-email',
];
if ($template_file !== '') {
if ($template_file === 'templates/pages/page-sign.php') {
return aksrt_get_auth_template_file(aksrt_get_auth_tab(), true);
}
if (!empty($legacy_auth_templates[$template_file])) {
return aksrt_get_auth_template_file((string) $legacy_auth_templates[$template_file], true);
}
if (strpos($template_file, 'templates/pages/') === 0 && aksrt_locate_template_file($template_file)) {
return $template_file;
}
}
if ($post_slug !== '') {
$auth_slug_map = [
'sign' => aksrt_get_auth_tab(),
'login' => 'login',
'register' => 'register',
'bind-account' => 'bind',
'reset-password' => 'reset-password',
'verify-email' => 'verify-email',
];
if (!empty($auth_slug_map[$post_slug])) {
return aksrt_get_auth_template_file((string) $auth_slug_map[$post_slug], true);
}
$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]) && aksrt_locate_template_file($slug_map[$post_slug])) {
return $slug_map[$post_slug];
}
}
return '';
}
/**
* Normalize auth view keys used by the unified sign page.
*/
function aksrt_normalize_auth_tab(string $tab): string {
$tab = sanitize_key($tab);
switch ($tab) {
case 'signin':
case 'login':
return 'login';
case 'signup':
case 'register':
return 'register';
case 'bind':
case 'bind-account':
return 'bind';
case 'reset':
case 'lostpassword':
case 'reset-password':
return 'reset-password';
case 'verify':
case 'verify-email':
return 'verify-email';
default:
return 'login';
}
}
/**
* Whether an auth tab should be rendered by the unified sign page.
*/
function aksrt_auth_tab_uses_unified_sign_page(string $tab): bool {
return in_array(
aksrt_normalize_auth_tab($tab),
['login', 'register'],
true
);
}
/**
* Resolve the auth template file, preferring the unified sign page when present.
*/
function aksrt_get_auth_template_file(string $tab = 'login', bool $prefer_sign_page = true): string {
$normalized_tab = aksrt_normalize_auth_tab($tab);
$sign_template = 'templates/pages/page-sign.php';
if (
$prefer_sign_page
&& aksrt_auth_tab_uses_unified_sign_page($normalized_tab)
&& aksrt_locate_template_file($sign_template)
) {
return $sign_template;
}
switch ($normalized_tab) {
case 'register':
return 'templates/pages/page-register.php';
case 'bind':
return 'templates/pages/page-bind-account.php';
case 'reset-password':
return 'templates/pages/page-reset-password.php';
case 'verify-email':
return 'templates/pages/page-verify-email.php';
default:
return 'templates/pages/page-login.php';
}
}
/**
* Return the active auth view for sign routes and the sign page template.
*/
function aksrt_get_auth_tab(): string {
$query_tab = get_query_var('aksrt_auth_tab');
if (is_string($query_tab) && $query_tab !== '') {
return aksrt_normalize_auth_tab($query_tab);
}
if (!empty($_GET['tab'])) {
return aksrt_normalize_auth_tab((string) wp_unslash($_GET['tab']));
}
$post = get_queried_object();
if ($post instanceof WP_Post) {
return aksrt_normalize_auth_tab((string) $post->post_name);
}
return 'login';
}
/**
* 清除模板页面缓存
*/
function aksrt_clear_template_page_cache(): void {
global $_aksrt_template_page_cache;
$_aksrt_template_page_cache = [];
}
/**
* Prepare the public user-home template context and return its template path.
*/
function aksrt_get_user_home_template_path(): string {
global $_aksrt_special_templates, $aksrt_profile_user;
$nicename = (string) get_query_var('user_nicename');
if ($nicename === '') {
return '';
}
$user = get_user_by('slug', $nicename);
if (!$user instanceof WP_User) {
return '';
}
$template_path = aksrt_locate_template_file('templates/pages/page-user-home.php');
if (!$template_path) {
return '';
}
$aksrt_profile_user = $user;
return $template_path;
}
/**
* Resolve the active special-page template path for the current request.
*/
function aksrt_get_current_special_template_path(): string {
if (get_query_var('user_nicename')) {
return aksrt_get_user_home_template_path();
}
if (get_query_var('aksrt_user_center')) {
$profile_template = aksrt_locate_template_file('templates/pages/page-profile.php');
return $profile_template ?: '';
}
if (get_query_var('aksrt_orders')) {
$orders_template = aksrt_locate_template_file('templates/pages/page-orders.php');
return $orders_template ?: '';
}
if (get_query_var('aksrt_cart')) {
$cart_template = aksrt_locate_template_file('templates/pages/page-cart.php');
return $cart_template ?: '';
}
if (get_query_var('aksrt_revenue')) {
$revenue_template = aksrt_locate_template_file('templates/pages/page-revenue.php');
return $revenue_template ?: '';
}
if (get_query_var('aksrt_sign')) {
$auth_template = aksrt_get_auth_template_file((string) get_query_var('aksrt_auth_tab'), true);
$auth_template_path = aksrt_locate_template_file($auth_template);
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 = aksrt_resolve_page_template_file(
is_string($page_template) ? $page_template : '',
(string) get_post_field('post_name', $page_id)
);
if ($resolved_template !== '') {
$resolved_path = aksrt_locate_template_file($resolved_template);
if ($resolved_path) {
return $resolved_path;
}
}
}
}
return '';
}
/**
* 根据当前请求路径识别系统模板页 key。
*
* 用于前台直接访问固定 slug 时的自动补页。
*/
function aksrt_get_requested_template_key(): string {
global $_aksrt_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 ($_aksrt_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 aksrt_ensure_template_page(string $key): void {
global $_aksrt_special_templates;
if (!isset($_aksrt_special_templates[$key])) return;
$cfg = $_aksrt_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 = aksrt_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']);
aksrt_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, '_aksrt_managed_template_page', (string) $key);
aksrt_clear_template_page_cache();
}
}