set_404(); } status_header(404); nocache_headers(); return; } if (!get_query_var('aksrt_message_view') && is_page() && get_page_template_slug(get_queried_object_id()) === 'templates/pages/page-messages.php') { global $wp_query; if ($wp_query instanceof WP_Query) { $wp_query->set_404(); } status_header(404); nocache_headers(); return; } $resolved_path = aksrt_get_current_special_template_path(); if ($resolved_path === '') { return; } status_header(200); load_template($resolved_path, true); exit; }, 100); // /user/{tab} only accepts registered user-center tabs; former public /user/{slug} // addresses must not silently resolve to the user-center home. add_action('template_redirect', function () { if (is_admin() || wp_doing_ajax()) { return; } $tab = (string) get_query_var('aksrt_user_center_tab'); if ($tab === '') { return; } $tab = $tab === 'balance' ? 'credits' : sanitize_key($tab); $allowed = class_exists('\\AKSRT\\User\\Center') ? array_keys(\AKSRT\User\Center::get_instance()->get_dashboard_tabs()) : ['profile', 'level', 'creator', 'posts', 'follow', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'revenue', 'msg', 'settings']; if (!in_array($tab, $allowed, true)) { global $wp_query; if ($wp_query instanceof WP_Query) { $wp_query->set_404(); } status_header(404); nocache_headers(); } }, 1); add_action('init', function () { add_rewrite_tag('%aksrt_user_center%', '([^&]+)'); add_rewrite_tag('%aksrt_user_center_tab%', '([^/]+)'); add_rewrite_tag('%aksrt_author_identifier%', '([^/]+)'); add_rewrite_tag('%aksrt_message_view%', '(unread|posts|like|system)'); add_rewrite_rule('^message/?$', 'index.php?aksrt_message_view=unread', 'top'); add_rewrite_rule('^message/(posts|like|system)/?$', 'index.php?aksrt_message_view=$matches[1]', 'top'); add_rewrite_rule('^user/([a-z0-9_-]+)/?$', 'index.php?aksrt_user_center=1&aksrt_user_center_tab=$matches[1]', 'top'); add_rewrite_rule('^author/([^/]+)/?$', 'index.php?aksrt_author_identifier=$matches[1]', 'top'); }); // --- 3b. 统一模板拦截器(核心)--- // 拦截所有使用主题特殊模板的页面请求,确保正确加载 add_filter('template_include', function ($template) { $resolved_path = aksrt_get_current_special_template_path(); if ($resolved_path !== '') { return $resolved_path; } // A) /user/{昵称} even if special-path helper returned empty (user missing → 404). $identifier = (string) get_query_var('aksrt_author_identifier'); if ($identifier !== '') { $user = function_exists('aksrt_resolve_public_user') ? aksrt_resolve_public_user($identifier) : null; if ($user instanceof WP_User) { $tpl = aksrt_locate_template_file('templates/pages/page-user-home.php'); if ($tpl) { global $aksrt_profile_user; $aksrt_profile_user = $user; return $tpl; } } // Unknown nicename: force 404 instead of blank page. global $wp_query; if ($wp_query instanceof WP_Query) { $wp_query->set_404(); status_header(404); nocache_headers(); } $four = get_query_template('404'); return $four ?: $template; } // B) ordinary assigned page templates. if (is_page()) { $page_id = get_queried_object_id(); if ($page_id) { $slug = (string) get_post_field('post_name', $page_id); $page_template = get_post_meta($page_id, '_wp_page_template', true); if (is_string($page_template) && strpos($page_template, 'templates/pages/') === 0) { $tpl = aksrt_locate_template_file($page_template); if ($tpl) { return $tpl; } } } } return $template; }, 99); add_filter('template_include', function ($template) { $resolved_path = aksrt_get_current_special_template_path(); if ($resolved_path !== '') { return $resolved_path; } if (get_query_var('aksrt_user_center')) { $profile_template = aksrt_locate_template_file('templates/pages/page-profile.php'); if ($profile_template) { return $profile_template; } } 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 $template; }, 100); // ============================================================ // 四、自动维护 + flush // ============================================================ add_action('init', function () { global $_aksrt_special_templates; // 后台/AJAX:检查并创建缺失页面(含 profile 用户中心) $pages_bootstrapped = get_option('aksrt_template_pages_bootstrapped'); $requested_template_key = (!is_admin() && !wp_doing_ajax()) ? aksrt_get_requested_template_key() : ''; if (is_admin() || wp_doing_ajax() || $pages_bootstrapped !== AKSRT_VERSION) { foreach ($_aksrt_special_templates as $key => $cfg) { aksrt_ensure_template_page($key); } if ($pages_bootstrapped !== AKSRT_VERSION) { update_option('aksrt_template_pages_bootstrapped', AKSRT_VERSION); } } elseif ($requested_template_key !== '') { aksrt_ensure_template_page($requested_template_key); } // 统一 flush 检查 — bump when user-home rewrite / author override changes $rewrite_version = AKSRT_VERSION . ':message-routing-v1'; $flushed = get_option('aksrt_user_rules_flushed'); $rules = get_option('rewrite_rules'); $need_flush = ($flushed !== $rewrite_version) || !is_array($rules) || $rules === [] || !get_option('permalink_structure'); // Dev/plain installs often have empty permalink_structure → pretty /user/ 404s at Apache. // Force a usable structure so registered rewrite rules actually apply. if (!get_option('permalink_structure')) { update_option('permalink_structure', '/%postname%/'); $need_flush = true; } if ($need_flush) { flush_rewrite_rules(true); update_option('aksrt_user_rules_flushed', $rewrite_version); } }); // 页面变更时清缓存 add_action('save_post', function ($pid) { if (get_post_type($pid) === 'page') aksrt_clear_template_page_cache(); }); add_action('delete_post', function ($pid) { if (get_post_type($pid) === 'page') aksrt_clear_template_page_cache(); }); // ============================================================ // 六、作者链接改写 — 强制覆盖 WP 默认 /author/{slug}/ // ============================================================ add_filter('author_link', function ($link, $author_id) { $author_id = (int) $author_id; if ($author_id > 0 && function_exists('aksrt_get_user_home_url')) { return aksrt_get_user_home_url($author_id); } $user = get_userdata($author_id); $slug = $user ? $user->user_nicename : ('user-' . max(0, $author_id)); if (!get_option('permalink_structure')) { return add_query_arg('aksrt_author', rawurlencode($slug), home_url('/')); } return home_url('/author/' . trailingslashit($slug)); }, 99, 2); // Accept ?user_nicename= when pretty rewrites are unavailable. add_filter('request', function ($query_vars) { if (empty($query_vars['aksrt_author_identifier']) && !empty($_GET['aksrt_author'])) { $query_vars['aksrt_author_identifier'] = sanitize_text_field(wp_unslash((string) $_GET['aksrt_author'])); } if (empty($query_vars['aksrt_user_center']) && isset($_GET['aksrt_user_center'])) { $query_vars['aksrt_user_center'] = '1'; } return $query_vars; }); // Pretty-permalink author archives → public user home. add_action('template_redirect', function () { if (is_admin() || wp_doing_ajax() || is_feed() || is_embed()) { return; } if (!is_author()) { return; } $author_id = (int) get_queried_object_id(); if ($author_id <= 0) { $author_id = (int) get_query_var('author'); } if ($author_id <= 0) { return; } $target = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($author_id) : home_url('/user/'); if ($target === '' || $target === home_url('/')) { return; } wp_safe_redirect($target, 301); exit; }, 1); // Catch bare ?author=ID when is_author() did not fire. add_action('template_redirect', function () { if (is_admin() || wp_doing_ajax()) { return; } if (empty($_GET['author'])) { return; } if (get_query_var('aksrt_author_identifier') || get_query_var('aksrt_user_center')) { return; } if (is_author()) { return; // handled above } $author_id = (int) $_GET['author']; if ($author_id > 0 && function_exists('aksrt_get_user_home_url')) { wp_safe_redirect(aksrt_get_user_home_url($author_id), 301); exit; } }, 2); // ============================================================ // AJAX: 保存用户个人资料(显示名称、简介、联系方式)