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

352 lines
10 KiB
PHP

<?php
/**
* User template registry + template utils
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
// ============================================================
// 一、模板注册表 — 所有特殊页面的"身份证"
// 修改此处即可增删模板页面,无需改动其他逻辑
// ============================================================
// Only true fixed template pages live in the registry.
$_aksrt_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/',
],
'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);
if ($template_file !== '') {
if ($template_file === 'templates/pages/page-sign.php') {
return $template_file;
}
if (strpos($template_file, 'templates/pages/') === 0 && aksrt_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]) && 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':
return 'signin';
case 'signup':
return 'signup';
case 'bind':
return 'bind';
case 'resetpassword':
return 'resetpassword';
case 'oauth':
return 'oauth';
default:
return 'signin';
}
}
/**
* 清除模板页面缓存
*/
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;
$identifier = (string) get_query_var('aksrt_author_identifier');
if ($identifier === '') {
return '';
}
$user = function_exists('aksrt_resolve_public_user') ? aksrt_resolve_public_user($identifier) : null;
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('aksrt_author_identifier')) {
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_sign')) {
$auth_template_path = aksrt_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 = 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();
}
}