diff --git a/assets/admin/src/schema/sections/extensions/ip.js b/assets/admin/src/schema/sections/extensions/ip.js index ab6ede35..a058cf48 100644 --- a/assets/admin/src/schema/sections/extensions/ip.js +++ b/assets/admin/src/schema/sections/extensions/ip.js @@ -7,7 +7,7 @@ export const ipSchema = { ip_geo_enabled: false, ip_addr_sdk: 'null', ip_geo_cache_ttl: 86400, - ip_geo_display: ['comment'], + ip_geo_display: ['comment', 'user_home', 'user_center', 'post'], ip_geo_format: 'province_city', ip_geo_fallback_text: '', ip_addr_sdk_qq_appkey: '', @@ -59,13 +59,15 @@ export const ipSchema = { key: 'ip_geo_display', label: '展示位置', type: 'checkbox', - default: ['comment'], + default: ['comment', 'user_home', 'user_center', 'post'], options: [ { label: '评论区', value: 'comment' }, { label: '用户主页', value: 'user_home' }, - { label: '文章页', value: 'post' }, + { label: '用户中心', value: 'user_center' }, + { label: '文章详细页', value: 'post' }, ], dependsOn: { key: 'ip_geo_enabled', value: true }, + help: '用户主页/用户中心还需在「用户 → 用户功能」开启「显示城市」;评论区还需在评论设置开启「评论城市」。', }, { key: 'ip_geo_format', diff --git a/assets/admin/src/schema/sections/users/features.js b/assets/admin/src/schema/sections/users/features.js index 719b9593..ac02b98b 100644 --- a/assets/admin/src/schema/sections/users/features.js +++ b/assets/admin/src/schema/sections/users/features.js @@ -9,7 +9,8 @@ export const featuresSchema = { user_cover_upload: true, user_social_links: true, user_desc_std: '这家伙很懒…', - user_city_s: false, + user_city_s: true, + user_city_type: 'province', user_join_day_my_name: '本站', user_avatar_default: '', user_cover_img: '', @@ -30,7 +31,19 @@ export const featuresSchema = { { key: 'user_cover_upload', label: '封面上传', type: 'switch', default: true }, { key: 'user_social_links', label: '社交链接', type: 'switch', default: true }, { key: 'user_desc_std', label: '默认签名', type: 'input', default: '这家伙很懒…', help: '用户未设置个人简介时显示的默认文案' }, - { key: 'user_city_s', label: '显示城市', type: 'switch', default: false }, + { key: 'user_city_s', label: '显示城市(IP 归属地)', type: 'switch', default: true, help: '根据用户登录 IP 在用户主页与用户中心显示归属地;需同时在「扩展 → IP归属地」启用并勾选对应展示位置' }, + { + key: 'user_city_type', + label: '位置精度', + type: 'radio', + default: 'province', + options: [ + { label: '省份', value: 'province' }, + { label: '省份+城市', value: 'province_city' }, + { label: '国家+省份', value: 'country_province' }, + ], + dependsOn: { key: 'user_city_s', value: true }, + }, { key: 'user_join_day_my_name', label: '站名', type: 'input', default: '本站', help: '用于「已加入 X 天」显示中的站点名称' }, { key: 'user_avatar_default', label: '默认头像', type: 'media', default: '' }, { key: 'user_cover_img', label: '默认封面', type: 'media', default: '' }, diff --git a/assets/css/frontend/comments/mobile-item.css b/assets/css/frontend/comments/mobile-item.css index 705ed394..9f883d60 100644 --- a/assets/css/frontend/comments/mobile-item.css +++ b/assets/css/frontend/comments/mobile-item.css @@ -87,3 +87,24 @@ #comments .comt-avatar .avatar-img { width: 60px; height: 60px; border-radius: 50%; } #comments .comt-box #comment { min-height: 88px; resize: vertical; } @media (min-width: 768px) { .hide-pc { display: none !important; } } + +/* IP geo badges */ +.comt-meta .comment-city-badge, +.comt-meta .aksrt-ip-geo-badge { + margin-left: 0.35em; + vertical-align: middle; +} +.aksrt-author-hero__identity .aksrt-ip-geo-badge, +.uc-header__meta .aksrt-ip-geo-badge, +.article-avatar .aksrt-ip-geo-badge { + margin-left: 0.35em; + margin-right: 0.15em; + vertical-align: middle; +} +.aksrt-author-hero__identity { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.35rem; + margin-top: 0.35rem; +} diff --git a/assets/css/routes/user-home.css b/assets/css/routes/user-home.css index 20770a4c..3caec0ed 100644 --- a/assets/css/routes/user-home.css +++ b/assets/css/routes/user-home.css @@ -583,3 +583,6 @@ .aksrt-user-home .dashboard-tabs__count.opacity8 { opacity: 0.8; } + +.aksrt-author-hero__identity { display:flex; flex-wrap:wrap; align-items:center; gap:.35rem; margin-top:.35rem; } +.aksrt-author-hero__identity .aksrt-ip-geo-badge { margin:0; } diff --git a/inc/bootstrap.php b/inc/bootstrap.php index 80a28f96..424482b9 100644 --- a/inc/bootstrap.php +++ b/inc/bootstrap.php @@ -17,6 +17,7 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-domain-model.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-template-tags.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-frontend-tags.php'; // Comment kernel (shared by post / forum / shop surfaces). +require_once AKSRT_DIR . '/inc/helpers/aksrt-ip-geo.php'; require_once AKSRT_DIR . '/inc/helpers/comments/content.php'; require_once AKSRT_DIR . '/inc/helpers/comments/actions.php'; require_once AKSRT_DIR . '/inc/helpers/comments/geo.php'; diff --git a/inc/helpers/aksrt-ip-geo.php b/inc/helpers/aksrt-ip-geo.php new file mode 100644 index 00000000..5e667c04 --- /dev/null +++ b/inc/helpers/aksrt-ip-geo.php @@ -0,0 +1,312 @@ + + */ + function aksrt_get_ip_geo_config(): array { + if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_ip_geo_settings')) { + return \AKSRT\Settings\Settings::get_ip_geo_settings(); + } + return [ + 'ip_geo_enabled' => false, + 'ip_geo_display' => ['comment'], + 'ip_geo_format' => 'province_city', + 'ip_geo_fallback_text' => '', + ]; + } +endif; + +if (!function_exists('aksrt_ip_geo_master_enabled')) : + function aksrt_ip_geo_master_enabled(): bool { + $c = aksrt_get_ip_geo_config(); + return !empty($c['ip_geo_enabled']); + } +endif; + +if (!function_exists('aksrt_ip_geo_display_enabled')) : + /** + * Whether a surface may show IP 归属地 badges. + * + * @param string $location comment|user_home|user_center|post + */ + function aksrt_ip_geo_display_enabled(string $location): bool { + if (!aksrt_ip_geo_master_enabled()) { + return false; + } + $c = aksrt_get_ip_geo_config(); + $display = $c['ip_geo_display'] ?? []; + if (!is_array($display)) { + $display = [$display]; + } + $display = array_map('sanitize_key', $display); + return in_array(sanitize_key($location), $display, true); + } +endif; + +if (!function_exists('aksrt_ip_geo_format_key')) : + function aksrt_ip_geo_format_key(): string { + $c = aksrt_get_ip_geo_config(); + $format = sanitize_key((string) ($c['ip_geo_format'] ?? 'province_city')); + return in_array($format, ['province_city', 'province', 'country_province'], true) + ? $format + : 'province_city'; + } +endif; + +if (!function_exists('aksrt_user_city_enabled')) : + /** + * Users feature switch (user home / user center), independent of comment city_s. + */ + function aksrt_user_city_enabled(): bool { + if (!class_exists('\AKSRT\Settings\Settings')) { + return false; + } + $all = \AKSRT\Settings\Settings::get_all(); + return !empty($all['user_city_s']); + } +endif; + +if (!function_exists('aksrt_user_city_type')) : + /** + * User-facing precision (maps to shared format keys). + */ + function aksrt_user_city_type(): string { + if (!class_exists('\AKSRT\Settings\Settings')) { + return aksrt_ip_geo_format_key(); + } + $all = \AKSRT\Settings\Settings::get_all(); + $type = sanitize_key((string) ($all['user_city_type'] ?? '')); + // zibll: pro / city + if ($type === 'pro' || $type === 'province') { + return 'province'; + } + if ($type === 'city' || $type === 'province_city') { + return 'province_city'; + } + if ($type === 'country_province') { + return 'country_province'; + } + return aksrt_ip_geo_format_key(); + } +endif; + +if (!function_exists('aksrt_normalize_geo_addr')) : + /** + * @param mixed $raw Meta value. + * @return array{country:string,province:string,city:string} + */ + function aksrt_normalize_geo_addr($raw): array { + if (!is_array($raw)) { + return ['country' => '', 'province' => '', 'city' => '']; + } + // Accept zibll-shaped nation → country. + $country = trim((string) ($raw['country'] ?? $raw['nation'] ?? '')); + return [ + 'country' => $country, + 'province' => trim((string) ($raw['province'] ?? '')), + 'city' => trim((string) ($raw['city'] ?? '')), + ]; + } +endif; + +if (!function_exists('aksrt_format_geo_label')) : + /** + * @param array $addr Addr. + * @param string $type Format key. + */ + function aksrt_format_geo_label(array $addr, string $type = 'province_city'): string { + $addr = aksrt_normalize_geo_addr($addr); + if (class_exists('\AKSRT\Extensions\IPGeo')) { + $label = \AKSRT\Extensions\IPGeo::get_instance()->format($addr, $type); + if (is_string($label) && $label !== '') { + return $label; + } + } + // Local fallback (mirrors IPGeo::format). + switch ($type) { + case 'province': + return $addr['province'] !== '' ? $addr['province'] : $addr['city']; + case 'country_province': + return trim($addr['country'] . ' ' . $addr['province']); + case 'province_city': + default: + $parts = array_filter([$addr['province'], $addr['city']]); + if (empty($parts) && $addr['country'] !== '') { + return $addr['country']; + } + return implode(' ', $parts); + } + } +endif; + +if (!function_exists('aksrt_get_geo_badge_html')) : + /** + * @param array|mixed $addr Addr meta. + * @param string $type Format. + * @param string $class CSS classes. + * @param string $title Title attr. + */ + function aksrt_get_geo_badge_html($addr, string $type = 'province_city', string $class = 'badg badg-sm', string $title = ''): string { + $label = aksrt_format_geo_label(is_array($addr) ? $addr : [], $type); + if ($label === '') { + $fallback = (string) (aksrt_get_ip_geo_config()['ip_geo_fallback_text'] ?? ''); + if ($fallback === '') { + return ''; + } + $label = $fallback; + } + if ($title === '') { + $title = __('IP 属地', 'aksrt'); + } + $class = trim($class . ' aksrt-ip-geo-badge'); + return '' . esc_html($label) . ''; + } +endif; + +if (!function_exists('aksrt_lookup_geo_for_ip')) : + /** + * @return array{country:string,province:string,city:string} + */ + function aksrt_lookup_geo_for_ip(string $ip): array { + $ip = trim($ip); + if ($ip === '' || !class_exists('\AKSRT\Extensions\IPGeo')) { + return ['country' => '', 'province' => '', 'city' => '']; + } + $geo = \AKSRT\Extensions\IPGeo::get_instance()->lookup($ip); + return aksrt_normalize_geo_addr(is_array($geo) ? $geo : []); + } +endif; + +if (!function_exists('aksrt_store_user_addr')) : + /** + * Resolve current client IP and persist user meta. + * Zibll: refresh on every login when user_city_s is on. + * Also refresh when article (post) display needs author addr. + */ + function aksrt_store_user_addr(int $user_id, ?string $ip = null): void { + if ($user_id <= 0 || !aksrt_ip_geo_master_enabled()) { + return; + } + $need = aksrt_user_city_enabled() + || aksrt_ip_geo_display_enabled('post') + || aksrt_ip_geo_display_enabled('user_home') + || aksrt_ip_geo_display_enabled('user_center'); + if (!$need) { + return; + } + + if ($ip === null || $ip === '') { + $ip = function_exists('aksrt_get_client_ip') ? (string) aksrt_get_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? ''); + } + $ip = trim($ip); + if ($ip === '') { + return; + } + + $addr = aksrt_lookup_geo_for_ip($ip); + if ($addr['country'] === '' && $addr['province'] === '' && $addr['city'] === '') { + return; + } + update_user_meta($user_id, 'aksrt_user_addr', $addr); + } +endif; + +if (!function_exists('aksrt_get_user_addr')) : + /** + * @param int $user_id User ID. + * @return array{country:string,province:string,city:string} + */ + function aksrt_get_user_addr(int $user_id): array { + if ($user_id <= 0) { + return ['country' => '', 'province' => '', 'city' => '']; + } + $raw = get_user_meta($user_id, 'aksrt_user_addr', true); + // Legacy / accidental zibll key. + if ((!is_array($raw) || empty($raw)) && metadata_exists('user', $user_id, 'user_addr')) { + $raw = get_user_meta($user_id, 'user_addr', true); + } + return aksrt_normalize_geo_addr($raw); + } +endif; + +if (!function_exists('aksrt_get_user_city_badge_html')) : + /** + * Badge for user home / user center (requires user_city_s + display location). + * + * @param int $user_id User. + * @param string $location user_home|user_center + * @param string $class CSS. + */ + 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()) { + return ''; + } + if (!aksrt_ip_geo_display_enabled($location)) { + return ''; + } + return aksrt_get_geo_badge_html(aksrt_get_user_addr($user_id), aksrt_user_city_type(), $class); + } +endif; + +if (!function_exists('aksrt_get_post_author_city_badge_html')) : + /** + * Article detail author IP 属地 (uses author last-login addr). + */ + function aksrt_get_post_author_city_badge_html(int $author_id = 0, string $class = 'badg badg-sm'): string { + if (!aksrt_ip_geo_display_enabled('post')) { + return ''; + } + if ($author_id <= 0) { + $author_id = (int) get_the_author_meta('ID'); + } + if ($author_id <= 0) { + return ''; + } + // Prefer user_city type when feature on; else global format. + $type = aksrt_user_city_enabled() ? aksrt_user_city_type() : aksrt_ip_geo_format_key(); + return aksrt_get_geo_badge_html(aksrt_get_user_addr($author_id), $type, $class); + } +endif; + +// ── Hooks: persist on login / register ────────────────────────────────────── + +add_action('wp_login', static function ($user_login, $user = null): void { + $user_id = 0; + if ($user instanceof WP_User) { + $user_id = (int) $user->ID; + } elseif (is_string($user_login) && $user_login !== '') { + $u = get_user_by('login', $user_login); + $user_id = $u instanceof WP_User ? (int) $u->ID : 0; + } + if ($user_id > 0 && function_exists('aksrt_store_user_addr')) { + aksrt_store_user_addr($user_id); + } +}, 20, 2); + +add_action('user_register', static function ($user_id): void { + $user_id = (int) $user_id; + if ($user_id <= 0) { + return; + } + $ip = function_exists('aksrt_get_client_ip') ? (string) aksrt_get_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? ''); + $ip = trim($ip); + if ($ip !== '') { + update_user_meta($user_id, 'aksrt_register_ip', $ip); + } + if (function_exists('aksrt_store_user_addr')) { + aksrt_store_user_addr($user_id, $ip !== '' ? $ip : null); + } +}, 20, 1); diff --git a/inc/helpers/comments/geo.php b/inc/helpers/comments/geo.php index fbc5c12e..f50de985 100644 --- a/inc/helpers/comments/geo.php +++ b/inc/helpers/comments/geo.php @@ -2,7 +2,8 @@ /** * Comment city / IP geo helpers. * - * Meta key: aksrt_comment_addr (array|string from IPGeo). + * Meta key: aksrt_comment_addr (array from IPGeo). + * Gates: extensions.ip_geo_enabled + ip_geo_display includes comment + comment_city_s. * * @package AKSRT */ @@ -14,6 +15,21 @@ if (!function_exists('aksrt_comment_city_enabled')) : * Whether comment city badges are enabled. */ function aksrt_comment_city_enabled(): bool { + // Prefer shared display gate when available. + if (function_exists('aksrt_ip_geo_display_enabled')) { + if (!aksrt_ip_geo_display_enabled('comment')) { + // Allow legacy path: comment_city_s alone still works if master is on + // but display list empty — require master + city_s at minimum. + if (!function_exists('aksrt_ip_geo_master_enabled') || !aksrt_ip_geo_master_enabled()) { + return false; + } + // Master on but location not selected → off. + return false; + } + } elseif (function_exists('aksrt_ip_geo_master_enabled') && !aksrt_ip_geo_master_enabled()) { + return false; + } + if (!class_exists('\AKSRT\Settings\Settings')) { return false; } @@ -28,7 +44,7 @@ if (!function_exists('aksrt_comment_city_type')) : */ function aksrt_comment_city_type(): string { if (!class_exists('\AKSRT\Settings\Settings')) { - return 'province_city'; + return function_exists('aksrt_ip_geo_format_key') ? aksrt_ip_geo_format_key() : 'province_city'; } $s = \AKSRT\Settings\Settings::get_comment_display_settings(); $type = sanitize_key((string) ($s['city_type'] ?? 'province_city')); @@ -54,19 +70,21 @@ if (!function_exists('aksrt_store_comment_addr')) : $ip = $comment instanceof WP_Comment ? (string) $comment->comment_author_IP : ''; } $ip = trim((string) $ip); - if ($ip === '' || !class_exists('\AKSRT\Extensions\IPGeo')) { + if ($ip === '') { return; } - $geo = \AKSRT\Extensions\IPGeo::get_instance()->lookup($ip); - if (!is_array($geo)) { + if (function_exists('aksrt_lookup_geo_for_ip')) { + $addr = aksrt_lookup_geo_for_ip($ip); + } elseif (class_exists('\AKSRT\Extensions\IPGeo')) { + $geo = \AKSRT\Extensions\IPGeo::get_instance()->lookup($ip); + $addr = [ + 'country' => (string) ($geo['country'] ?? ''), + 'province' => (string) ($geo['province'] ?? ''), + 'city' => (string) ($geo['city'] ?? ''), + ]; + } else { return; } - // Store compact array. - $addr = [ - 'country' => (string) ($geo['country'] ?? ''), - 'province' => (string) ($geo['province'] ?? ''), - 'city' => (string) ($geo['city'] ?? ''), - ]; if ($addr['country'] === '' && $addr['province'] === '' && $addr['city'] === '') { return; } @@ -85,6 +103,9 @@ if (!function_exists('aksrt_get_comment_addr')) : return []; } $raw = get_comment_meta($comment_id, 'aksrt_comment_addr', true); + if (function_exists('aksrt_normalize_geo_addr')) { + return aksrt_normalize_geo_addr($raw); + } return is_array($raw) ? $raw : []; } endif; @@ -97,6 +118,9 @@ if (!function_exists('aksrt_format_comment_city_label')) : * @param string $type Format. */ function aksrt_format_comment_city_label(array $addr, string $type = 'province_city'): string { + if (function_exists('aksrt_format_geo_label')) { + return aksrt_format_geo_label($addr, $type); + } $country = trim((string) ($addr['country'] ?? '')); $province = trim((string) ($addr['province'] ?? '')); $city = trim((string) ($addr['city'] ?? '')); @@ -125,7 +149,14 @@ if (!function_exists('aksrt_get_comment_city_badge_html')) : if (!aksrt_comment_city_enabled()) { return ''; } - $addr = aksrt_get_comment_addr($comment); + if (function_exists('aksrt_get_geo_badge_html')) { + return aksrt_get_geo_badge_html( + aksrt_get_comment_addr($comment), + aksrt_comment_city_type(), + 'badg badg-sm comment-city-badge' + ); + } + $addr = aksrt_get_comment_addr($comment); $label = aksrt_format_comment_city_label($addr, aksrt_comment_city_type()); if ($label === '') { return ''; diff --git a/inc/helpers/user-center-renderers/profile-header.php b/inc/helpers/user-center-renderers/profile-header.php index 43e1a6dc..de889ae9 100644 --- a/inc/helpers/user-center-renderers/profile-header.php +++ b/inc/helpers/user-center-renderers/profile-header.php @@ -49,7 +49,7 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_ -
+
user_login); ?> @@ -58,6 +58,15 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_ user_email); ?> +
diff --git a/src/AKSRT/Admin/Schema/SchemaExtensionsIP.php b/src/AKSRT/Admin/Schema/SchemaExtensionsIP.php index 0ff6873d..2df61483 100644 --- a/src/AKSRT/Admin/Schema/SchemaExtensionsIP.php +++ b/src/AKSRT/Admin/Schema/SchemaExtensionsIP.php @@ -33,10 +33,11 @@ class SchemaExtensionsIP { ['key' => 'ip_addr_sdk_amap_secretkey', 'label' => '高德 SecretKey', 'type' => 'input', 'default' => ''], ]], ['key' => 'display', 'title' => '展示设置', 'fields' => [ - ['key' => 'ip_geo_display', 'label' => '展示位置', 'type' => 'checkbox', 'default' => ['comment'], 'sanitize_type' => 'array', 'options' => [ + ['key' => 'ip_geo_display', 'label' => '展示位置', 'type' => 'checkbox', 'default' => ['comment', 'user_home', 'user_center', 'post'], 'sanitize_type' => 'array', 'options' => [ ['label' => '评论区', 'value' => 'comment'], ['label' => '用户主页', 'value' => 'user_home'], - ['label' => '文章页', 'value' => 'post'], + ['label' => '用户中心', 'value' => 'user_center'], + ['label' => '文章详细页', 'value' => 'post'], ]], ['key' => 'ip_geo_format', 'label' => '显示格式', 'type' => 'radio', 'default' => 'province_city', 'options' => [ ['label' => '省份+城市', 'value' => 'province_city'], diff --git a/src/AKSRT/Admin/Schema/SchemaUsers.php b/src/AKSRT/Admin/Schema/SchemaUsers.php index 7ad4cdde..3948a5eb 100644 --- a/src/AKSRT/Admin/Schema/SchemaUsers.php +++ b/src/AKSRT/Admin/Schema/SchemaUsers.php @@ -520,7 +520,12 @@ class SchemaUsers { ['key' => 'user_cover_upload', 'label' => '封面上传', 'type' => 'switch', 'default' => true], ['key' => 'user_social_links', 'label' => '社交链接', 'type' => 'switch', 'default' => true], ['key' => 'user_desc_std', 'label' => '默认签名', 'type' => 'input', 'default' => '这家伙很懒…', 'desc' => '用户未设置个人简介时显示的默认文案'], - ['key' => 'user_city_s', 'label' => '显示城市', 'type' => 'switch', 'default' => false], + ['key' => 'user_city_s', 'label' => '显示城市(IP 归属地)', 'type' => 'switch', 'default' => true], + ['key' => 'user_city_type', 'label' => '位置精度', 'type' => 'radio', 'default' => 'province', 'options' => [ + ['label' => '省份', 'value' => 'province'], + ['label' => '省份+城市', 'value' => 'province_city'], + ['label' => '国家+省份', 'value' => 'country_province'], + ]], ['key' => 'user_join_day_my_name', 'label' => '站名', 'type' => 'input', 'default' => '本站', 'desc' => '用于「已加入 X 天」显示中的站点名称'], ['key' => 'user_avatar_default', 'label' => '默认头像', 'type' => 'media', 'default' => ''], ['key' => 'user_cover_img', 'label' => '默认封面', 'type' => 'media', 'default' => ''], diff --git a/src/AKSRT/Settings/ExtensionRuntime.php b/src/AKSRT/Settings/ExtensionRuntime.php index 60041219..be43f120 100644 --- a/src/AKSRT/Settings/ExtensionRuntime.php +++ b/src/AKSRT/Settings/ExtensionRuntime.php @@ -53,8 +53,14 @@ class ExtensionRuntime { $provider = 'null'; } - $display_raw = $settings['ip_geo_display'] ?? ['comment']; + $display_raw = $settings['ip_geo_display'] ?? ['comment', 'user_home', 'user_center', 'post']; $display = is_array($display_raw) ? $display_raw : [$display_raw]; + $display = array_values(array_unique(array_filter(array_map('sanitize_key', $display)))); + $allowed_display = ['comment', 'user_home', 'user_center', 'post']; + $display = array_values(array_filter($display, static fn($v) => in_array($v, $allowed_display, true))); + if ($display === []) { + $display = ['comment', 'user_home', 'user_center', 'post']; + } $format = sanitize_key((string) ($settings['ip_geo_format'] ?? 'province_city')); if (!in_array($format, ['province_city', 'province', 'country_province'], true)) { diff --git a/templates/parts/single-author-bar.php b/templates/parts/single-author-bar.php index f3a7d674..bc20a6f5 100644 --- a/templates/parts/single-author-bar.php +++ b/templates/parts/single-author-bar.php @@ -94,6 +94,15 @@ $is_self = is_user_logged_in() && get_current_user_id() === $author_id; + diff --git a/templates/parts/user/author-hero.php b/templates/parts/user/author-hero.php index 62248511..32535af0 100644 --- a/templates/parts/user/author-hero.php +++ b/templates/parts/user/author-hero.php @@ -112,19 +112,30 @@ $pm_url = ($pm_enabled && $messages_url !== '') } ?> - description) : ?> -

description); ?>

+ + +
+ + + + + + + + + + + +
- -
- - - - - - -
+ description) : ?> +

description); ?>