Merge pull request 'fix(user): show IP city on home/center and force /user + profile templates' (#297) from worktree-ip-location-display into main
Reviewed-on: CYL/wordpress-theme-aksrt#297
This commit is contained in:
commit
8c2901fcbb
6 files changed
+163
-49
No files matched your search
@@ -46,13 +46,35 @@ if (!function_exists('aksrt_ip_geo_display_enabled')) :
|
|||||||
if (!aksrt_ip_geo_master_enabled()) {
|
if (!aksrt_ip_geo_master_enabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$location = sanitize_key($location);
|
||||||
$c = aksrt_get_ip_geo_config();
|
$c = aksrt_get_ip_geo_config();
|
||||||
$display = $c['ip_geo_display'] ?? [];
|
$display = $c['ip_geo_display'] ?? [];
|
||||||
if (!is_array($display)) {
|
if (!is_array($display)) {
|
||||||
$display = [$display];
|
$display = [$display];
|
||||||
}
|
}
|
||||||
$display = array_map('sanitize_key', $display);
|
$display = array_values(array_unique(array_filter(array_map('sanitize_key', $display))));
|
||||||
return in_array(sanitize_key($location), $display, true);
|
|
||||||
|
// Legacy saves only had "comment". When master is on, expand so user/post
|
||||||
|
// surfaces work without forcing a re-save of the checkbox group.
|
||||||
|
if ($display === [] || $display === ['comment']) {
|
||||||
|
$display = ['comment', 'user_home', 'user_center', 'post'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zibll: user home/center are gated by user_city_s, not a separate surface list.
|
||||||
|
// Still honour an explicit opt-out if the admin removed them from the list after upgrade.
|
||||||
|
if (in_array($location, ['user_home', 'user_center'], true)) {
|
||||||
|
if (!aksrt_user_city_enabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// If list explicitly includes any user surface, require membership; else allow.
|
||||||
|
$has_user_keys = (bool) array_intersect($display, ['user_home', 'user_center']);
|
||||||
|
if ($has_user_keys) {
|
||||||
|
return in_array($location, $display, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($location, $display, true);
|
||||||
}
|
}
|
||||||
endif;
|
endif;
|
||||||
|
|
||||||
@@ -72,9 +94,13 @@ if (!function_exists('aksrt_user_city_enabled')) :
|
|||||||
*/
|
*/
|
||||||
function aksrt_user_city_enabled(): bool {
|
function aksrt_user_city_enabled(): bool {
|
||||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||||
return false;
|
return true; // zibll default on
|
||||||
}
|
}
|
||||||
$all = \AKSRT\Settings\Settings::get_all();
|
$all = \AKSRT\Settings\Settings::get_all();
|
||||||
|
// Unset → on (zibll _pz default true). Explicit false turns off.
|
||||||
|
if (!array_key_exists('user_city_s', $all)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return !empty($all['user_city_s']);
|
return !empty($all['user_city_s']);
|
||||||
}
|
}
|
||||||
endif;
|
endif;
|
||||||
@@ -238,7 +264,36 @@ if (!function_exists('aksrt_get_user_addr')) :
|
|||||||
if ((!is_array($raw) || empty($raw)) && metadata_exists('user', $user_id, 'user_addr')) {
|
if ((!is_array($raw) || empty($raw)) && metadata_exists('user', $user_id, 'user_addr')) {
|
||||||
$raw = get_user_meta($user_id, 'user_addr', true);
|
$raw = get_user_meta($user_id, 'user_addr', true);
|
||||||
}
|
}
|
||||||
return aksrt_normalize_geo_addr($raw);
|
$addr = aksrt_normalize_geo_addr($raw);
|
||||||
|
if ($addr['country'] !== '' || $addr['province'] !== '' || $addr['city'] !== '') {
|
||||||
|
return $addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazy backfill from stored IPs so pages work before next login.
|
||||||
|
$ips = [];
|
||||||
|
foreach (['aksrt_register_ip', 'register_ip'] as $k) {
|
||||||
|
$v = trim((string) get_user_meta($user_id, $k, true));
|
||||||
|
if ($v !== '') {
|
||||||
|
$ips[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Own profile: refresh from current client IP (zibll updates on login; this covers open sessions).
|
||||||
|
if ((int) get_current_user_id() === $user_id) {
|
||||||
|
$cur = function_exists('aksrt_get_client_ip') ? (string) aksrt_get_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? '');
|
||||||
|
$cur = trim($cur);
|
||||||
|
if ($cur !== '') {
|
||||||
|
array_unshift($ips, $cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ips = array_values(array_unique(array_filter($ips)));
|
||||||
|
foreach ($ips as $ip) {
|
||||||
|
$looked = aksrt_lookup_geo_for_ip($ip);
|
||||||
|
if ($looked['country'] !== '' || $looked['province'] !== '' || $looked['city'] !== '') {
|
||||||
|
update_user_meta($user_id, 'aksrt_user_addr', $looked);
|
||||||
|
return $looked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $addr;
|
||||||
}
|
}
|
||||||
endif;
|
endif;
|
||||||
|
|
||||||
@@ -251,9 +306,10 @@ if (!function_exists('aksrt_get_user_city_badge_html')) :
|
|||||||
* @param string $class CSS.
|
* @param string $class CSS.
|
||||||
*/
|
*/
|
||||||
function aksrt_get_user_city_badge_html(int $user_id, string $location = 'user_home', string $class = 'badg'): string {
|
function aksrt_get_user_city_badge_html(int $user_id, string $location = 'user_home', string $class = 'badg'): string {
|
||||||
if ($user_id <= 0 || !aksrt_user_city_enabled()) {
|
if ($user_id <= 0) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
// aksrt_ip_geo_display_enabled already enforces master + user_city for user surfaces.
|
||||||
if (!aksrt_ip_geo_display_enabled($location)) {
|
if (!aksrt_ip_geo_display_enabled($location)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ if (!function_exists('aksrt_single_render_author_card')) :
|
|||||||
if ($author_id <= 0) {
|
if ($author_id <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$author_url = get_author_posts_url($author_id);
|
$author_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($author_id) : get_author_posts_url($author_id);
|
||||||
$author_name = get_the_author();
|
$author_name = get_the_author();
|
||||||
$bio = trim((string) get_the_author_meta('description'));
|
$bio = trim((string) get_the_author_meta('description'));
|
||||||
$name_html = function_exists('aksrt_get_user_name')
|
$name_html = function_exists('aksrt_get_user_name')
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ if (!function_exists('aksrt_get_comments_user_name_html')) :
|
|||||||
if ($user_id > 0) {
|
if ($user_id > 0) {
|
||||||
$user = get_userdata($user_id);
|
$user = get_userdata($user_id);
|
||||||
$display = $user instanceof WP_User ? $user->display_name : get_comment_author($comment);
|
$display = $user instanceof WP_User ? $user->display_name : get_comment_author($comment);
|
||||||
$url = get_author_posts_url($user_id);
|
$url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id);
|
||||||
$name = '<a class="text-ellipsis font-bold aksrt-comment__author" href="' . esc_url($url) . '">' . esc_html($display) . '</a>';
|
$name = '<a class="text-ellipsis font-bold aksrt-comment__author" href="' . esc_url($url) . '">' . esc_html($display) . '</a>';
|
||||||
if (function_exists('aksrt_render_user_identity_chips')) {
|
if (function_exists('aksrt_render_user_identity_chips')) {
|
||||||
$name .= aksrt_render_user_identity_chips($user_id, 'comment');
|
$name .= aksrt_render_user_identity_chips($user_id, 'comment');
|
||||||
|
|||||||
@@ -58,37 +58,46 @@ add_filter('template_include', function ($template) {
|
|||||||
return $resolved_path;
|
return $resolved_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $template;
|
// A) /user/{昵称} even if special-path helper returned empty (user missing → 404).
|
||||||
|
$nicename = (string) get_query_var('user_nicename');
|
||||||
global $_aksrt_special_templates;
|
if ($nicename !== '') {
|
||||||
|
|
||||||
// A) /user/{昵称} 路由 → 加载公开主页模板
|
|
||||||
$nicename = get_query_var('user_nicename');
|
|
||||||
if (!empty($nicename)) {
|
|
||||||
$user = get_user_by('slug', $nicename);
|
$user = get_user_by('slug', $nicename);
|
||||||
if (!$user) return $template; // 不存在的用户 → 默认 404
|
if ($user instanceof WP_User) {
|
||||||
|
$tpl = aksrt_locate_template_file('templates/pages/page-user-home.php');
|
||||||
$tpl = aksrt_locate_template_file('templates/pages/page-user-home.php');
|
if ($tpl) {
|
||||||
if (!$tpl) {
|
global $aksrt_profile_user;
|
||||||
// 兜底:如果新模板不存在,回退到旧 profile 模板
|
$aksrt_profile_user = $user;
|
||||||
$tpl = aksrt_locate_template_file($_aksrt_special_templates['profile']['file']);
|
return $tpl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!$tpl) return $template;
|
// Unknown nicename: force 404 instead of blank page.
|
||||||
|
global $wp_query;
|
||||||
global $aksrt_profile_user;
|
if ($wp_query instanceof WP_Query) {
|
||||||
$aksrt_profile_user = $user;
|
$wp_query->set_404();
|
||||||
return $tpl;
|
status_header(404);
|
||||||
|
nocache_headers();
|
||||||
|
}
|
||||||
|
$four = get_query_template('404');
|
||||||
|
return $four ?: $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
// B) 普通页面 → 检测是否使用了我们的特殊模板,确保加载正确的模板文件
|
// B) profile slug page without rewrite var (permalink edge).
|
||||||
// (防止 WP 在某些情况下未能正确解析自定义页面模板)
|
|
||||||
if (is_page()) {
|
if (is_page()) {
|
||||||
$page_id = get_queried_object_id();
|
$page_id = get_queried_object_id();
|
||||||
if ($page_id) {
|
if ($page_id) {
|
||||||
|
$slug = (string) get_post_field('post_name', $page_id);
|
||||||
$page_template = get_post_meta($page_id, '_wp_page_template', true);
|
$page_template = get_post_meta($page_id, '_wp_page_template', true);
|
||||||
if ($page_template && strpos($page_template, 'templates/pages/') === 0) {
|
if ($slug === 'profile' || $page_template === 'templates/pages/page-profile.php') {
|
||||||
|
$tpl = aksrt_locate_template_file('templates/pages/page-profile.php');
|
||||||
|
if ($tpl) {
|
||||||
|
return $tpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_string($page_template) && strpos($page_template, 'templates/pages/') === 0) {
|
||||||
$tpl = aksrt_locate_template_file($page_template);
|
$tpl = aksrt_locate_template_file($page_template);
|
||||||
if ($tpl) return $tpl;
|
if ($tpl) {
|
||||||
|
return $tpl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,26 +145,28 @@ add_filter('template_include', function ($template) {
|
|||||||
add_action('init', function () {
|
add_action('init', function () {
|
||||||
global $_aksrt_special_templates;
|
global $_aksrt_special_templates;
|
||||||
|
|
||||||
// 后台/AJAX:检查并创建缺失页面
|
// 后台/AJAX:检查并创建缺失页面(含 profile 用户中心)
|
||||||
$pages_bootstrapped = get_option('aksrt_template_pages_bootstrapped');
|
$pages_bootstrapped = get_option('aksrt_template_pages_bootstrapped');
|
||||||
$requested_template_key = (!is_admin() && !wp_doing_ajax()) ? aksrt_get_requested_template_key() : '';
|
$requested_template_key = (!is_admin() && !wp_doing_ajax()) ? aksrt_get_requested_template_key() : '';
|
||||||
if (is_admin() || wp_doing_ajax() || $pages_bootstrapped !== AKSRT_VERSION) {
|
if (is_admin() || wp_doing_ajax() || $pages_bootstrapped !== AKSRT_VERSION) {
|
||||||
foreach ($_aksrt_special_templates as $key => $cfg) {
|
foreach ($_aksrt_special_templates as $key => $cfg) {
|
||||||
if ($key === 'profile') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
aksrt_ensure_template_page($key);
|
aksrt_ensure_template_page($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($pages_bootstrapped !== AKSRT_VERSION) {
|
if ($pages_bootstrapped !== AKSRT_VERSION) {
|
||||||
update_option('aksrt_template_pages_bootstrapped', AKSRT_VERSION);
|
update_option('aksrt_template_pages_bootstrapped', AKSRT_VERSION);
|
||||||
}
|
}
|
||||||
} elseif ($requested_template_key !== '' && $requested_template_key !== 'profile') {
|
} elseif ($requested_template_key !== '') {
|
||||||
aksrt_ensure_template_page($requested_template_key);
|
aksrt_ensure_template_page($requested_template_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统一 flush 检查
|
// Always re-assert profile page template (blank WP page with slug profile is common).
|
||||||
$rewrite_version = AKSRT_VERSION . ':orders-cart-revenue-routing-v1';
|
if (function_exists('aksrt_ensure_template_page')) {
|
||||||
|
aksrt_ensure_template_page('profile');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一 flush 检查 — bump when user-home rewrite / author override changes
|
||||||
|
$rewrite_version = AKSRT_VERSION . ':user-home-profile-routing-v2';
|
||||||
$flushed = get_option('aksrt_user_rules_flushed');
|
$flushed = get_option('aksrt_user_rules_flushed');
|
||||||
if ($flushed !== $rewrite_version) {
|
if ($flushed !== $rewrite_version) {
|
||||||
flush_rewrite_rules(false);
|
flush_rewrite_rules(false);
|
||||||
@@ -168,24 +179,63 @@ add_action('save_post', function ($pid) { if (get_post_type($pid) === 'page') ak
|
|||||||
add_action('delete_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) {
|
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);
|
$user = get_userdata($author_id);
|
||||||
$slug = $user ? $user->user_nicename : 'user-' . $author_id;
|
$slug = $user ? $user->user_nicename : ('user-' . max(0, $author_id));
|
||||||
return home_url('/user/' . trailingslashit($slug));
|
return home_url('/user/' . trailingslashit($slug));
|
||||||
}, 10, 2);
|
}, 99, 2);
|
||||||
|
|
||||||
|
// Pretty-permalink author archives → public user home.
|
||||||
add_action('template_redirect', function () {
|
add_action('template_redirect', function () {
|
||||||
if (!is_author()) return;
|
if (is_admin() || wp_doing_ajax() || is_feed() || is_embed()) {
|
||||||
$author_id = get_queried_object_id();
|
return;
|
||||||
if ($author_id) {
|
}
|
||||||
$user = get_userdata($author_id);
|
if (!is_author()) {
|
||||||
$slug = $user ? $user->user_nicename : 'user-' . $author_id;
|
return;
|
||||||
wp_safe_redirect(home_url('/user/' . trailingslashit($slug)), 301);
|
}
|
||||||
|
$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('user_nicename') || 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;
|
exit;
|
||||||
}
|
}
|
||||||
});
|
}, 2);
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// AJAX: 保存用户个人资料(显示名称、简介、联系方式)
|
// AJAX: 保存用户个人资料(显示名称、简介、联系方式)
|
||||||
@@ -488,8 +488,16 @@ function aksrt_ensure_template_page(string $key): void {
|
|||||||
$cfg = $_aksrt_special_templates[$key];
|
$cfg = $_aksrt_special_templates[$key];
|
||||||
$desired_slug = sanitize_title($cfg['slug'] ?? $key);
|
$desired_slug = sanitize_title($cfg['slug'] ?? $key);
|
||||||
|
|
||||||
// 已有页面使用此模板?
|
// 已有页面使用此模板?仍校验模板 meta,避免空白默认页。
|
||||||
if (aksrt_find_template_page($cfg['file'])) return;
|
$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 !== '') {
|
if ($desired_slug !== '') {
|
||||||
$existing_page = get_page_by_path($desired_slug, OBJECT, 'page');
|
$existing_page = get_page_by_path($desired_slug, OBJECT, 'page');
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ $meta_items = is_array($args['meta_items'] ?? null) ? array_values(array_filter(
|
|||||||
|
|
||||||
$author_id = (int) get_the_author_meta('ID');
|
$author_id = (int) get_the_author_meta('ID');
|
||||||
$author_name = get_the_author();
|
$author_name = get_the_author();
|
||||||
$author_url = get_author_posts_url($author_id);
|
$author_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($author_id) : get_author_posts_url($author_id);
|
||||||
$modified_ts = (int) get_the_modified_time('U');
|
$modified_ts = (int) get_the_modified_time('U');
|
||||||
$published_ts = (int) get_the_time('U');
|
$published_ts = (int) get_the_time('U');
|
||||||
$now = (int) current_time('timestamp');
|
$now = (int) current_time('timestamp');
|
||||||
|
|||||||
Reference in new issue
Block a user