feat(users): medal auto-grant + aksrt_get_user_name chrome

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.
This commit is contained in:
2026-07-17 01:12:09 +08:00
parent 1b0eed6ef7
commit b4d04ae346
5 changed files with 299 additions and 16 deletions
+132
View File
@@ -404,4 +404,136 @@ class AKSRT_User_Badges {
'message' => __('已收回徽章', 'aksrt'),
]);
}
/**
* Auto-grant medals whose get_type metrics meet get_val (skip manually_add).
*/
public static function auto_evaluate(int $user_id): void {
if ($user_id <= 0 || !self::enabled() || !class_exists('AKSRT_Settings')) {
return;
}
$settings = AKSRT_Settings::get_user_identity_settings();
$medal = is_array($settings['medal'] ?? null) ? $settings['medal'] : [];
$items = is_array($medal['items_by_slug'] ?? null) ? $medal['items_by_slug'] : [];
if (!$items) {
// Fall back to dictionary only — no get_type → nothing to auto-grant.
return;
}
$owned = self::get_owned($user_id);
$owned_map = array_fill_keys($owned, true);
foreach ($items as $slug => $item) {
if (!is_array($item)) {
continue;
}
$slug = sanitize_key((string) $slug);
if ($slug === '' || !empty($owned_map[$slug])) {
continue;
}
$type = sanitize_key((string) ($item['get_type'] ?? 'manually_add'));
if ($type === '' || $type === 'manually_add') {
continue;
}
$need = max(0, (float) ($item['get_val'] ?? 0));
$have = (float) self::metric_value($user_id, $type);
if ($have >= $need) {
self::grant($user_id, $slug, 0);
$owned_map[$slug] = true;
}
}
}
/**
* Numeric metric for a medal get_type.
*/
public static function metric_value(int $user_id, string $type): float {
switch ($type) {
case 'registration_time':
$user = get_userdata($user_id);
if (!$user) {
return 0.0;
}
$reg = get_date_from_gmt($user->user_registered, 'Y-m-d H:i:s');
$now = current_time('Y-m-d H:i:s');
return max(0.0, (strtotime($now) - strtotime($reg)) / 86400);
case 'checkin_all_day':
// Prefer dedicated check-in total meta if present.
$v = get_user_meta($user_id, 'aksrt_checkin_all_day', true);
if ($v === '' || $v === false) {
$v = get_user_meta($user_id, 'checkin_all_day', true);
}
return max(0.0, (float) $v);
case 'new_post':
return (float) count_user_posts($user_id, 'post', true);
case 'bbs_post':
$types = post_type_exists('forum_topic') ? 'forum_topic' : (post_type_exists('topic') ? 'topic' : '');
return $types !== '' ? (float) count_user_posts($user_id, $types, true) : 0.0;
case 'comment':
$counts = get_comments(['user_id' => $user_id, 'count' => true, 'status' => 'approve']);
return (float) $counts;
case 'followed':
$meta = get_user_meta($user_id, 'followed-user', true);
if (!is_array($meta)) {
$meta = get_user_meta($user_id, 'aksrt_followed_users', true);
}
return is_array($meta) ? (float) count($meta) : 0.0;
case 'like':
return (float) get_user_meta($user_id, 'aksrt_posts_like_sum', true);
case 'comment_like':
return (float) get_user_meta($user_id, 'aksrt_comment_like_sum', true);
case 'bbs_adopt':
return (float) get_user_meta($user_id, 'aksrt_bbs_adopt_count', true);
case 'bbs_comment_hot':
return (float) get_user_meta($user_id, 'aksrt_bbs_comment_hot_count', true);
case 'bbs_post_hot':
return (float) get_user_meta($user_id, 'aksrt_bbs_post_hot_count', true);
case 'bbs_essence':
return (float) get_user_meta($user_id, 'aksrt_bbs_essence_count', true);
case 'bbs_score':
return (float) get_user_meta($user_id, 'aksrt_bbs_score_sum', true);
case 'views':
return (float) get_user_meta($user_id, 'aksrt_posts_views_sum', true);
case 'pay_income':
return (float) get_user_meta($user_id, 'aksrt_pay_income_sum', true);
case 'pay_rebate':
return (float) get_user_meta($user_id, 'aksrt_pay_rebate_sum', true);
default:
return 0.0;
}
}
/**
* @param string $user_login
* @param WP_User $user
*/
public function on_login($user_login, $user): void {
$user_id = $user instanceof WP_User ? (int) $user->ID : 0;
if ($user_id > 0) {
self::auto_evaluate($user_id);
}
}
public function on_current_user_probe(): void {
$uid = get_current_user_id();
if ($uid > 0) {
self::auto_evaluate($uid);
}
}
}