Add AKSRT_User_Badges::auto_evaluate on login for get_type metrics, introduce aksrt_get_user_name (auth→wear medal→level→follow order), wire single author bar/card, and document transfer/withdraw default-closed semantics on capabilities page. audit errors=0.
238 lines
9.0 KiB
PHP
238 lines
9.0 KiB
PHP
<?php
|
|
/**
|
|
* Shared identity chrome: VIP / verify / level / badges for author bar & comments.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
if (!function_exists('aksrt_get_user_identity_signals')) {
|
|
/**
|
|
* @return list<array{type?:string,label:string,icon:string,tone:string,title?:string,icon_url?:string,slug?:string,wear?:bool}>
|
|
*/
|
|
function aksrt_get_user_identity_signals(int $user_id): array {
|
|
if ($user_id <= 0) {
|
|
return [];
|
|
}
|
|
if (class_exists('AKSRT_User_Home')) {
|
|
$signals = AKSRT_User_Home::get_instance()->get_profile_signals($user_id);
|
|
return is_array($signals) ? array_values($signals) : [];
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('aksrt_render_user_identity_chips')) {
|
|
/**
|
|
* Render compact identity chips (verify / level / badges).
|
|
*
|
|
* Badge signals with icon_url render as Zibll-like medal images.
|
|
*
|
|
* @param int $user_id
|
|
* @param string $context author|comment|card
|
|
*/
|
|
function aksrt_render_user_identity_chips(int $user_id, string $context = 'author'): string {
|
|
if ($user_id <= 0) {
|
|
return '';
|
|
}
|
|
$html = '';
|
|
if (function_exists('aksrt_render_vip_badge')) {
|
|
$vip = aksrt_render_vip_badge($user_id, 'sm');
|
|
if (is_string($vip) && $vip !== '') {
|
|
$html .= $vip;
|
|
}
|
|
}
|
|
$signals = aksrt_get_user_identity_signals($user_id);
|
|
// Comments stay compact; author/card can show more.
|
|
$limit = $context === 'comment' ? 3 : 6;
|
|
$n = 0;
|
|
foreach ($signals as $signal) {
|
|
if ($n >= $limit) {
|
|
break;
|
|
}
|
|
$label = trim((string) ($signal['label'] ?? ''));
|
|
if ($label === '') {
|
|
continue;
|
|
}
|
|
$tone = sanitize_html_class((string) ($signal['tone'] ?? 'info'));
|
|
$icon = sanitize_html_class((string) ($signal['icon'] ?? 'check'));
|
|
$icon_url = esc_url((string) ($signal['icon_url'] ?? ''));
|
|
$title = (string) ($signal['title'] ?? $label);
|
|
$is_wear = !empty($signal['wear']);
|
|
$type = sanitize_html_class((string) ($signal['type'] ?? ''));
|
|
|
|
// Image medal when dictionary provides icon_url.
|
|
if ($icon_url !== '') {
|
|
$classes = 'medal-icon img-icon ml3 aksrt-identity-medal aksrt-identity-medal--' . $context;
|
|
if ($is_wear) {
|
|
$classes .= ' is-wear';
|
|
}
|
|
if ($type !== '') {
|
|
$classes .= ' aksrt-identity-medal--' . $type;
|
|
}
|
|
$html .= '<img class="' . esc_attr($classes) . '" src="' . $icon_url . '" alt="' . esc_attr($label) . '" title="' . esc_attr($title) . '" loading="lazy" decoding="async" />';
|
|
$n++;
|
|
continue;
|
|
}
|
|
|
|
// Font Awesome: map short names to fa-* if needed.
|
|
if ($icon !== '' && !str_contains($icon, 'fa-')) {
|
|
$icon = 'fa-' . $icon;
|
|
}
|
|
$html .= '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--' . esc_attr($tone) . ' aksrt-identity-chip--' . esc_attr($context) . ($is_wear ? ' is-wear' : '') . '" title="' . esc_attr($title) . '">';
|
|
if ($icon !== '') {
|
|
$html .= '<i class="fa ' . esc_attr($icon) . '" aria-hidden="true"></i> ';
|
|
}
|
|
$html .= esc_html($label) . '</span>';
|
|
$n++;
|
|
}
|
|
return $html;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('aksrt_get_user_name')) {
|
|
/**
|
|
* Zibll zib_get_user_name parity: name link + auth + wear medal + level + optional follow.
|
|
*
|
|
* @param array|int $args User id or args array.
|
|
*/
|
|
function aksrt_get_user_name($args = []): string {
|
|
$defaults = [
|
|
'id' => 0,
|
|
'class' => 'flex ac flex1',
|
|
'name_class' => '',
|
|
'vip' => false,
|
|
'medal' => true,
|
|
'auth' => true,
|
|
'level' => true,
|
|
'follow' => false,
|
|
];
|
|
if (is_numeric($args)) {
|
|
$defaults['id'] = (int) $args;
|
|
$args = $defaults;
|
|
} else {
|
|
$args = wp_parse_args(is_array($args) ? $args : [], $defaults);
|
|
}
|
|
$user_id = (int) $args['id'];
|
|
if ($user_id <= 0) {
|
|
$user_id = get_current_user_id();
|
|
}
|
|
if ($user_id <= 0) {
|
|
return '';
|
|
}
|
|
|
|
$user = get_userdata($user_id);
|
|
if (!$user) {
|
|
return '';
|
|
}
|
|
|
|
$home = function_exists('get_author_posts_url') ? get_author_posts_url($user_id) : '';
|
|
$display = $user->display_name;
|
|
$vip_html = '';
|
|
if (!empty($args['vip']) && function_exists('aksrt_render_vip_badge')) {
|
|
$vip_html = (string) aksrt_render_vip_badge($user_id, 'sm');
|
|
}
|
|
$name_class = trim('display-name text-ellipsis ' . (string) $args['name_class']);
|
|
$name_link = '<a class="' . esc_attr($name_class) . '" href="' . esc_url($home) . '">' . $vip_html . esc_html($display) . '</a>';
|
|
|
|
$auth_html = '';
|
|
$medal_html = '';
|
|
$level_html = '';
|
|
$signals = aksrt_get_user_identity_signals($user_id);
|
|
foreach ($signals as $signal) {
|
|
$type = (string) ($signal['type'] ?? '');
|
|
$label = trim((string) ($signal['label'] ?? ''));
|
|
if ($label === '') {
|
|
continue;
|
|
}
|
|
$icon_url = esc_url((string) ($signal['icon_url'] ?? ''));
|
|
$title = (string) ($signal['title'] ?? $label);
|
|
if ($type === 'verify' && !empty($args['auth']) && $auth_html === '') {
|
|
$auth_html = '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--success" title="' . esc_attr($title) . '"><i class="fa fa-check-circle" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
|
} elseif ($type === 'level' && !empty($args['level']) && $level_html === '') {
|
|
$level_html = '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--info" title="' . esc_attr($title) . '"><i class="fa fa-layer-group" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
|
} elseif ($type === 'badge' && !empty($args['medal']) && $medal_html === '' && !empty($signal['wear'])) {
|
|
if ($icon_url !== '') {
|
|
$medal_html = '<img class="medal-icon img-icon ml3 aksrt-identity-medal is-wear" src="' . $icon_url . '" alt="' . esc_attr($label) . '" title="' . esc_attr($title) . '" loading="lazy" decoding="async" />';
|
|
} else {
|
|
$medal_html = '<span class="badg badg-sm ml3 aksrt-identity-chip is-wear" title="' . esc_attr($title) . '"><i class="fa fa-award" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
|
}
|
|
}
|
|
}
|
|
// If medal requested but no wear flag, use first badge with icon.
|
|
if (!empty($args['medal']) && $medal_html === '') {
|
|
foreach ($signals as $signal) {
|
|
if ((string) ($signal['type'] ?? '') !== 'badge') {
|
|
continue;
|
|
}
|
|
$label = trim((string) ($signal['label'] ?? ''));
|
|
$icon_url = esc_url((string) ($signal['icon_url'] ?? ''));
|
|
$title = (string) ($signal['title'] ?? $label);
|
|
if ($label === '') {
|
|
continue;
|
|
}
|
|
if ($icon_url !== '') {
|
|
$medal_html = '<img class="medal-icon img-icon ml3 aksrt-identity-medal" src="' . $icon_url . '" alt="' . esc_attr($label) . '" title="' . esc_attr($title) . '" loading="lazy" decoding="async" />';
|
|
} else {
|
|
$medal_html = '<span class="badg badg-sm ml3 aksrt-identity-chip" title="' . esc_attr($title) . '"><i class="fa fa-award" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
$follow_html = '';
|
|
if (!empty($args['follow']) && get_current_user_id() !== $user_id) {
|
|
if (is_user_logged_in()) {
|
|
$follow_html = '<button type="button" class="focus-color ml10 follow flex0 but" data-aksrt-follow="' . (int) $user_id . '"><i class="fa fa-heart em09" aria-hidden="true"></i> ' . esc_html__('关注', 'aksrt') . '</button>';
|
|
} else {
|
|
$login = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url();
|
|
$follow_html = '<a class="focus-color ml10 follow flex0 but" href="' . esc_url($login) . '"><i class="fa fa-heart em09" aria-hidden="true"></i> ' . esc_html__('关注', 'aksrt') . '</a>';
|
|
}
|
|
}
|
|
|
|
// Order: name → auth → wear medal → level → follow (Zibll).
|
|
$html = '<name class="' . esc_attr((string) $args['class']) . '">' . $name_link . $auth_html . $medal_html . $level_html . $follow_html . '</name>';
|
|
/**
|
|
* Filter rendered user name chrome.
|
|
*
|
|
* @param string $html
|
|
* @param int $user_id
|
|
* @param array $args
|
|
*/
|
|
return (string) apply_filters('aksrt_user_show_name', $html, $user_id, $args);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('aksrt_is_blog_comment_hot')) {
|
|
/**
|
|
* "神评" for ordinary post comments when likes cross threshold.
|
|
*/
|
|
function aksrt_is_blog_comment_hot($comment): bool {
|
|
$comment_id = $comment instanceof WP_Comment ? (int) $comment->comment_ID : (int) $comment;
|
|
if ($comment_id <= 0) {
|
|
return false;
|
|
}
|
|
if ('1' === (string) get_comment_meta($comment_id, '_aksrt_comment_hot', true)) {
|
|
return true;
|
|
}
|
|
$threshold = 10;
|
|
if (class_exists('AKSRT_Settings') && method_exists('AKSRT_Settings', 'get_comment_display_settings')) {
|
|
$display = AKSRT_Settings::get_comment_display_settings();
|
|
if (isset($display['hot_threshold'])) {
|
|
$threshold = max(1, (int) $display['hot_threshold']);
|
|
}
|
|
}
|
|
$all = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_all() : [];
|
|
if (isset($all['comment_hot_threshold'])) {
|
|
$threshold = max(1, (int) $all['comment_hot_threshold']);
|
|
}
|
|
$likes = function_exists('aksrt_get_comment_likes') ? aksrt_get_comment_likes($comment_id) : (int) get_comment_meta($comment_id, 'aksrt_comment_likes', true);
|
|
if ($likes < $threshold) {
|
|
return false;
|
|
}
|
|
update_comment_meta($comment_id, '_aksrt_comment_hot', '1');
|
|
return true;
|
|
}
|
|
}
|