feat(widgets): ranking identity, moderators follow, plate chrome
Align UserRanking to zibll user-ranking-item + aksrt_get_user_name + badg, render moderators via shared rows with follow, deepen plate info cover/stats, and clean forum tab/terms empty shells.
This commit is contained in:
1 parent
9c5ac01119
commit
8b5ca8f287
5 files changed
+133
-97
No files matched your search
@@ -54,11 +54,12 @@ class WidgetForumPlateInfo extends \WP_Widget {
|
|||||||
: home_url('/');
|
: home_url('/');
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
echo '<div class="aksrt-plate-info ajax-item">';
|
echo '<div class="forum-header plate-info-sidebar aksrt-plate-info ajax-item">';
|
||||||
if ($thumb) {
|
if ($thumb) {
|
||||||
echo '<div class="aksrt-plate-info__cover" style="background-image:url(' . esc_url($thumb) . ')"></div>';
|
$ph = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||||
|
echo '<div class="aksrt-plate-info__cover plate-thumb"><img class="aksrt-lazy lazyload fit-cover" data-src="' . esc_url($thumb) . '" src="' . esc_url($ph) . '" alt="" loading="lazy" /></div>';
|
||||||
} elseif ($icon !== '') {
|
} elseif ($icon !== '') {
|
||||||
echo '<div class="aksrt-plate-info__cover is-icon"><i class="' . esc_attr($icon) . '" aria-hidden="true"></i></div>';
|
echo '<div class="aksrt-plate-info__cover plate-thumb is-icon"><i class="' . esc_attr($icon) . '" aria-hidden="true"></i></div>';
|
||||||
}
|
}
|
||||||
echo '<div class="aksrt-plate-info__body">';
|
echo '<div class="aksrt-plate-info__body">';
|
||||||
echo '<a class="aksrt-plate-info__title" href="' . esc_url($url) . '">' . esc_html(get_the_title($plate)) . '</a>';
|
echo '<a class="aksrt-plate-info__title" href="' . esc_url($url) . '">' . esc_html(get_the_title($plate)) . '</a>';
|
||||||
@@ -66,7 +67,7 @@ class WidgetForumPlateInfo extends \WP_Widget {
|
|||||||
echo '<div class="aksrt-plate-info__desc">' . esc_html($desc) . '</div>';
|
echo '<div class="aksrt-plate-info__desc">' . esc_html($desc) . '</div>';
|
||||||
}
|
}
|
||||||
if ($show_stats) {
|
if ($show_stats) {
|
||||||
echo '<div class="aksrt-plate-info__stats">';
|
echo '<div class="aksrt-plate-info__stats count-mates flex jsb">';
|
||||||
echo '<span title="' . esc_attr__('帖子', 'aksrt') . '"><i class="fas fa-file-alt" aria-hidden="true"></i> ' . esc_html((string) $posts) . '</span>';
|
echo '<span title="' . esc_attr__('帖子', 'aksrt') . '"><i class="fas fa-file-alt" aria-hidden="true"></i> ' . esc_html((string) $posts) . '</span>';
|
||||||
echo '<span title="' . esc_attr__('回复', 'aksrt') . '"><i class="fas fa-comment" aria-hidden="true"></i> ' . esc_html((string) $reply) . '</span>';
|
echo '<span title="' . esc_attr__('回复', 'aksrt') . '"><i class="fas fa-comment" aria-hidden="true"></i> ' . esc_html((string) $reply) . '</span>';
|
||||||
if ($views > 0) {
|
if ($views > 0) {
|
||||||
|
|||||||
@@ -74,13 +74,17 @@ class WidgetForumPlateModerator extends \WP_Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
echo '<div class="aksrt-plate-mods style-' . esc_attr($style) . ' ajax-item">';
|
echo '<div class="zib-widget moderator-box aksrt-plate-mods style-' . esc_attr($style) . ' ajax-item">';
|
||||||
if ($title_text !== '') {
|
if ($title_text !== '') {
|
||||||
echo '<div class="aksrt-plate-mods__head"><div class="title-theme">' . esc_html($title_text) . '</div></div>';
|
echo '<div class="mb10 flex jsb ac aksrt-plate-mods__head"><div class="title-theme">' . esc_html($title_text) . '</div></div>';
|
||||||
}
|
}
|
||||||
echo '<div class="aksrt-plate-mods__list">';
|
echo '<div class="aksrt-plate-mods__list">';
|
||||||
foreach ($people as $row) {
|
foreach ($people as $row) {
|
||||||
$uid = (int) $row['id'];
|
$uid = (int) $row['id'];
|
||||||
|
if (function_exists('aksrt_render_moderator_row')) {
|
||||||
|
echo aksrt_render_moderator_row($uid, (string) $row['role'], $show_avatar, $style); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$user = get_userdata($uid);
|
$user = get_userdata($uid);
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class WidgetForumTabTopics extends \WP_Widget {
|
|||||||
.then(function(r){return r.json()}).then(function(j){
|
.then(function(r){return r.json()}).then(function(j){
|
||||||
var d=(j&&j.data)||j||{};
|
var d=(j&&j.data)||j||{};
|
||||||
var html=d.html||'';
|
var html=d.html||'';
|
||||||
panel.innerHTML=html||'<p class="aksrt-ftab__empty">暂无内容</p>';
|
panel.innerHTML=html||'<div class="ajax-item aksrt-ftab__empty muted-2-color">暂无内容</div>';
|
||||||
panel.setAttribute('data-loaded','1');
|
panel.setAttribute('data-loaded','1');
|
||||||
panel.classList.remove('is-ajax-loading');
|
panel.classList.remove('is-ajax-loading');
|
||||||
}).catch(function(){panel.classList.remove('is-ajax-loading');});
|
}).catch(function(){panel.classList.remove('is-ajax-loading');});
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class WidgetForumTopicTerms extends \WP_Widget {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$icon = (string) get_term_meta($term->term_id, '_aksrt_icon', true);
|
$icon = (string) get_term_meta($term->term_id, '_aksrt_icon', true);
|
||||||
echo '<a class="aksrt-ftag-item" href="' . esc_url($link) . '">';
|
echo '<a class="aksrt-ftag-item but p2-10' . ($style === 'card' ? ' is-card' : '') . '" href="' . esc_url($link) . '">';
|
||||||
if ($icon !== '') {
|
if ($icon !== '') {
|
||||||
echo '<i class="' . esc_attr($icon) . '" aria-hidden="true"></i> ';
|
echo '<i class="' . esc_attr($icon) . '" aria-hidden="true"></i> ';
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ class WidgetForumTopicTerms extends \WP_Widget {
|
|||||||
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
// IAS-style wrap for remote refresh.
|
// IAS-style wrap for remote refresh.
|
||||||
echo '<div class="zib-widget padding-6 ajaxpager" data-aksrt-ajaxpager>';
|
echo '<div class="zib-widget padding-6 aksrt-ftag-wrap">';
|
||||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
|
* User ranking lists (zibll zib_user_ranking_lists parity).
|
||||||
|
*
|
||||||
* @package AKSRT
|
* @package AKSRT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -13,22 +15,26 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
parent::__construct(
|
parent::__construct(
|
||||||
'aksrt_user_ranking',
|
'aksrt_user_ranking',
|
||||||
__('用户排行榜', 'aksrt'),
|
__('用户排行榜', 'aksrt'),
|
||||||
['description' => __('按积分、文章数或粉丝数排行的用户列表。', 'aksrt')]
|
[
|
||||||
|
'description' => __('按积分、文章数或粉丝数排行的用户列表。', 'aksrt'),
|
||||||
|
'classname' => 'widget_aksrt_user_ranking',
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function widget($args, $instance): void {
|
public function widget($args, $instance): void {
|
||||||
$title = !empty($instance['title']) ? $instance['title'] : __('排行榜', 'aksrt');
|
$title = !empty($instance['title']) ? (string) $instance['title'] : __('排行榜', 'aksrt');
|
||||||
$rank_by = !empty($instance['rank_by']) ? $instance['rank_by'] : 'credits';
|
$rank_by = !empty($instance['rank_by']) ? (string) $instance['rank_by'] : 'credits';
|
||||||
$count = max(1, min(20, (int) ($instance['count'] ?? 5)));
|
$count = max(1, min(20, (int) ($instance['count'] ?? 5)));
|
||||||
$show_avatar = !empty($instance['show_avatar']);
|
$show_avatar = !isset($instance['show_avatar']) || !empty($instance['show_avatar']);
|
||||||
|
|
||||||
$desc_mode = sanitize_key((string) ($instance['desc'] ?? 'desc'));
|
$desc_mode = sanitize_key((string) ($instance['desc'] ?? 'desc'));
|
||||||
|
$top_badge = !empty($instance['top_badge']);
|
||||||
$users = $this->get_ranking($rank_by, $count, $desc_mode);
|
$users = $this->get_ranking($rank_by, $count, $desc_mode);
|
||||||
|
|
||||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
|
||||||
|
echo '<div class="zib-widget user-ranking-box aksrt-user-ranking-box">';
|
||||||
if (!empty($instance['checkin_btn']) && is_user_logged_in() && function_exists('aksrt_header_user_checkin_btn')) {
|
if (!empty($instance['checkin_btn']) && is_user_logged_in() && function_exists('aksrt_header_user_checkin_btn')) {
|
||||||
$cbtn = aksrt_header_user_checkin_btn(get_current_user_id());
|
$cbtn = aksrt_header_user_checkin_btn(get_current_user_id());
|
||||||
if ($cbtn !== '') {
|
if ($cbtn !== '') {
|
||||||
@@ -37,60 +43,75 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (empty($users)) {
|
if (empty($users)) {
|
||||||
echo '<p class="aksrt-user-ranking__empty muted-2-color">' . esc_html__('暂无排行数据', 'aksrt') . '</p>';
|
echo function_exists('aksrt_get_widget_null')
|
||||||
|
? aksrt_get_widget_null(__('暂无排行数据', 'aksrt')) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
: '<p class="aksrt-user-ranking__empty muted-2-color">' . esc_html__('暂无排行数据', 'aksrt') . '</p>';
|
||||||
|
echo '</div>';
|
||||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$top_badge = !empty($instance['top_badge']);
|
$ph = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||||
|
|
||||||
echo '<ul class="aksrt-user-ranking">';
|
|
||||||
$rank = 0;
|
$rank = 0;
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$rank++;
|
$rank++;
|
||||||
$rank_class = $rank <= 3 ? ' aksrt-user-ranking__item--top' : '';
|
$uid = (int) $user['id'];
|
||||||
$user_url = function_exists('aksrt_get_user_home_url')
|
$user_url = function_exists('aksrt_get_user_home_url')
|
||||||
? aksrt_get_user_home_url($user['id'])
|
? aksrt_get_user_home_url($uid)
|
||||||
: get_author_posts_url($user['id']);
|
: get_author_posts_url($uid);
|
||||||
|
|
||||||
echo '<li class="aksrt-user-ranking__item relative' . esc_attr($rank_class) . '">';
|
|
||||||
|
|
||||||
|
$top_bagd = '';
|
||||||
if ($top_badge && $rank <= 3) {
|
if ($top_badge && $rank <= 3) {
|
||||||
$tone = $rank === 1 ? 'jb-red' : ($rank === 2 ? 'jb-yellow' : 'b-gray');
|
$tone = $rank === 1 ? 'jb-red' : ($rank === 2 ? 'jb-yellow' : 'b-gray');
|
||||||
echo '<badge class="img-badge left hot ' . esc_attr($tone) . '"><i>TOP' . (int) $rank . '</i></badge>';
|
$top_bagd = '<badge class="img-badge left hot ' . esc_attr($tone) . '"><i>TOP' . (int) $rank . '</i></badge>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 排名
|
$name_html = function_exists('aksrt_get_user_name')
|
||||||
echo '<span class="aksrt-user-ranking__rank">' . esc_html((string) $rank) . '</span>';
|
? aksrt_get_user_name([
|
||||||
|
'id' => $uid,
|
||||||
|
'class' => 'flex ac flex1',
|
||||||
|
'follow' => false,
|
||||||
|
'medal' => true,
|
||||||
|
'level' => true,
|
||||||
|
])
|
||||||
|
: '<a class="font-bold" href="' . esc_url($user_url) . '">' . esc_html((string) $user['name']) . '</a>';
|
||||||
|
|
||||||
// 头像
|
$avatar_html = '';
|
||||||
if ($show_avatar) {
|
if ($show_avatar) {
|
||||||
$avatar_url = function_exists('aksrt_get_avatar_url')
|
$avatar_url = function_exists('aksrt_get_avatar_url')
|
||||||
? aksrt_get_avatar_url($user['id'], ['size' => 36])
|
? aksrt_get_avatar_url($uid, ['size' => 42])
|
||||||
: get_avatar_url($user['id'], ['size' => 36]);
|
: get_avatar_url($uid, ['size' => 42]);
|
||||||
echo '<a href="' . esc_url($user_url) . '" class="aksrt-user-ranking__avatar">';
|
$avatar_html = '<a class="avatar-img" href="' . esc_url($user_url) . '"><img class="avatar aksrt-lazy lazyload" data-src="' . esc_url($avatar_url) . '" src="' . esc_url($ph) . '" alt="" loading="lazy" width="36" height="36" /></a>';
|
||||||
echo '<img src="' . esc_url($avatar_url) . '" alt=""' . (function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('avatar') : ' loading="lazy"') . ' width="36" height="36">';
|
|
||||||
echo '</a>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 昵称 + 可选签名/附加信息
|
$desc = (string) ($user['desc'] ?? '');
|
||||||
echo '<div class="aksrt-user-ranking__meta">';
|
$value_label = (string) ($user['value_label'] ?? $user['value'] ?? '');
|
||||||
echo '<a href="' . esc_url($user_url) . '" class="aksrt-user-ranking__name">' . esc_html($user['name']) . '</a>';
|
$value_icon = (string) ($user['value_icon'] ?? 'fa-trophy');
|
||||||
if (!empty($user['desc'])) {
|
$right_badge = '<span class="badg" title="' . esc_attr($value_label) . '"><i class="fa ' . esc_attr($value_icon) . '" aria-hidden="true"></i><span class="ml6">' . esc_html((string) ($user['value_num'] ?? $user['value'] ?? '')) . '</span></span>';
|
||||||
echo '<div class="aksrt-user-ranking__desc em09 muted-2-color">' . esc_html((string) $user['desc']) . '</div>';
|
|
||||||
|
$mt = $rank > 1 ? ' mt20' : '';
|
||||||
|
echo '<div class="user-ranking-item aksrt-user-ranking__item relative' . esc_attr($mt) . ($rank <= 3 ? ' is-top' : '') . '">';
|
||||||
|
echo $top_bagd; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
echo '<div class="user-info flex ac">';
|
||||||
|
echo $avatar_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
echo '<div class="user-right flex flex1 ac jsb ml10">';
|
||||||
|
echo '<div class="flex1 min-w0">';
|
||||||
|
echo '<div class="font-bold aksrt-user-ranking__name">' . $name_html . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
if ($desc !== '') {
|
||||||
|
echo '<div class="mt3 em09 muted-color text-ellipsis aksrt-user-ranking__desc">' . esc_html($desc) . '</div>';
|
||||||
}
|
}
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
|
echo '<div class="ml20 flex0 aksrt-user-ranking__value">' . $right_badge . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
// 数值
|
echo '</div></div></div>';
|
||||||
echo '<span class="aksrt-user-ranking__value">' . esc_html($user['value']) . '</span>';
|
|
||||||
|
|
||||||
echo '</li>';
|
|
||||||
}
|
}
|
||||||
echo '</ul>';
|
echo '</div>';
|
||||||
|
|
||||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<array{id:int,name:string,value:string,value_num:string,value_label:string,value_icon:string,desc:string}>
|
||||||
|
*/
|
||||||
private function get_ranking(string $rank_by, int $count, string $desc_mode = 'desc'): array {
|
private function get_ranking(string $rank_by, int $count, string $desc_mode = 'desc'): array {
|
||||||
$users = [];
|
$users = [];
|
||||||
|
|
||||||
@@ -107,10 +128,14 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
foreach ((array) $rows as $row) {
|
foreach ((array) $rows as $row) {
|
||||||
$user = get_userdata((int) $row['user_id']);
|
$user = get_userdata((int) $row['user_id']);
|
||||||
if ($user) {
|
if ($user) {
|
||||||
|
$num = (int) $row['credits'];
|
||||||
$users[] = [
|
$users[] = [
|
||||||
'id' => (int) $row['user_id'],
|
'id' => (int) $row['user_id'],
|
||||||
'name' => $user->display_name,
|
'name' => $user->display_name,
|
||||||
'value' => number_format_i18n((int) $row['credits']) . ' 积分',
|
'value' => number_format_i18n($num) . ' 积分',
|
||||||
|
'value_num' => (string) number_format_i18n($num),
|
||||||
|
'value_label' => sprintf(__('积分:%s', 'aksrt'), number_format_i18n($num)),
|
||||||
|
'value_icon' => 'fa-diamond',
|
||||||
'desc' => $this->user_extra_desc((int) $row['user_id'], $user, $desc_mode),
|
'desc' => $this->user_extra_desc((int) $row['user_id'], $user, $desc_mode),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -131,6 +156,9 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
'id' => $user->ID,
|
'id' => $user->ID,
|
||||||
'name' => $user->display_name,
|
'name' => $user->display_name,
|
||||||
'value' => number_format_i18n($post_count) . ' 篇',
|
'value' => number_format_i18n($post_count) . ' 篇',
|
||||||
|
'value_num' => (string) number_format_i18n($post_count),
|
||||||
|
'value_label' => sprintf(__('共%d篇文章', 'aksrt'), $post_count),
|
||||||
|
'value_icon' => 'fa-file-text-o',
|
||||||
'desc' => $this->user_extra_desc($user->ID, $user, $desc_mode),
|
'desc' => $this->user_extra_desc($user->ID, $user, $desc_mode),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -138,57 +166,11 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'checkin_all_day':
|
case 'checkin_all_day':
|
||||||
global $wpdb;
|
$users = $this->meta_rank('aksrt_checkin_all_day', ['checkin_all_day'], $count, $desc_mode, 'fa-calendar-check-o', __('累计签到%d天', 'aksrt'), ' 天');
|
||||||
$rows = $wpdb->get_results($wpdb->prepare(
|
|
||||||
"SELECT user_id, meta_value as val FROM {$wpdb->usermeta}
|
|
||||||
WHERE meta_key IN ('aksrt_checkin_all_day','checkin_all_day')
|
|
||||||
ORDER BY CAST(meta_value AS UNSIGNED) DESC
|
|
||||||
LIMIT %d",
|
|
||||||
$count * 2
|
|
||||||
), ARRAY_A);
|
|
||||||
$seen = [];
|
|
||||||
foreach ((array) $rows as $row) {
|
|
||||||
$uid = (int) $row['user_id'];
|
|
||||||
if (isset($seen[$uid])) continue;
|
|
||||||
$seen[$uid] = true;
|
|
||||||
$user = get_userdata($uid);
|
|
||||||
if ($user) {
|
|
||||||
$users[] = [
|
|
||||||
'id' => $uid,
|
|
||||||
'name' => $user->display_name,
|
|
||||||
'value' => number_format_i18n((int) $row['val']) . ' 天',
|
|
||||||
'desc' => $this->user_extra_desc($uid, $user, $desc_mode),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (count($users) >= $count) break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'checkin_continuous_day':
|
case 'checkin_continuous_day':
|
||||||
global $wpdb;
|
$users = $this->meta_rank('aksrt_checkin_continuous_day', ['checkin_continuous_day'], $count, $desc_mode, 'fa-calendar-check-o', __('连续签到%d天', 'aksrt'), ' 天');
|
||||||
$rows = $wpdb->get_results($wpdb->prepare(
|
|
||||||
"SELECT user_id, meta_value as val FROM {$wpdb->usermeta}
|
|
||||||
WHERE meta_key IN ('aksrt_checkin_continuous_day','checkin_continuous_day')
|
|
||||||
ORDER BY CAST(meta_value AS UNSIGNED) DESC
|
|
||||||
LIMIT %d",
|
|
||||||
$count * 2
|
|
||||||
), ARRAY_A);
|
|
||||||
$seen = [];
|
|
||||||
foreach ((array) $rows as $row) {
|
|
||||||
$uid = (int) $row['user_id'];
|
|
||||||
if (isset($seen[$uid])) continue;
|
|
||||||
$seen[$uid] = true;
|
|
||||||
$user = get_userdata($uid);
|
|
||||||
if ($user) {
|
|
||||||
$users[] = [
|
|
||||||
'id' => $uid,
|
|
||||||
'name' => $user->display_name,
|
|
||||||
'value' => number_format_i18n((int) $row['val']) . ' 天',
|
|
||||||
'desc' => $this->user_extra_desc($uid, $user, $desc_mode),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (count($users) >= $count) break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'followers':
|
case 'followers':
|
||||||
@@ -207,10 +189,14 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
foreach ((array) $rows as $row) {
|
foreach ((array) $rows as $row) {
|
||||||
$user = get_userdata((int) $row['following_id']);
|
$user = get_userdata((int) $row['following_id']);
|
||||||
if ($user) {
|
if ($user) {
|
||||||
|
$num = (int) $row['cnt'];
|
||||||
$users[] = [
|
$users[] = [
|
||||||
'id' => (int) $row['following_id'],
|
'id' => (int) $row['following_id'],
|
||||||
'name' => $user->display_name,
|
'name' => $user->display_name,
|
||||||
'value' => number_format_i18n((int) $row['cnt']) . ' 粉丝',
|
'value' => number_format_i18n($num) . ' 粉丝',
|
||||||
|
'value_num' => (string) number_format_i18n($num),
|
||||||
|
'value_label' => sprintf(__('共%d个粉丝', 'aksrt'), $num),
|
||||||
|
'value_icon' => 'fa-heart',
|
||||||
'desc' => $this->user_extra_desc((int) $row['following_id'], $user, $desc_mode),
|
'desc' => $this->user_extra_desc((int) $row['following_id'], $user, $desc_mode),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -223,6 +209,51 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
return $users;
|
return $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<string> $alt_keys
|
||||||
|
* @return list<array{id:int,name:string,value:string,value_num:string,value_label:string,value_icon:string,desc:string}>
|
||||||
|
*/
|
||||||
|
private function meta_rank(string $primary_key, array $alt_keys, int $count, string $desc_mode, string $icon, string $label_tpl, string $suffix): array {
|
||||||
|
global $wpdb;
|
||||||
|
$keys = array_merge([$primary_key], $alt_keys);
|
||||||
|
$in = implode(',', array_fill(0, count($keys), '%s'));
|
||||||
|
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
$sql = $wpdb->prepare(
|
||||||
|
"SELECT user_id, meta_value as val FROM {$wpdb->usermeta}
|
||||||
|
WHERE meta_key IN ($in)
|
||||||
|
ORDER BY CAST(meta_value AS UNSIGNED) DESC
|
||||||
|
LIMIT %d",
|
||||||
|
...array_merge($keys, [$count * 2])
|
||||||
|
);
|
||||||
|
$rows = $wpdb->get_results($sql, ARRAY_A);
|
||||||
|
$seen = [];
|
||||||
|
$users = [];
|
||||||
|
foreach ((array) $rows as $row) {
|
||||||
|
$uid = (int) $row['user_id'];
|
||||||
|
if (isset($seen[$uid])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$seen[$uid] = true;
|
||||||
|
$user = get_userdata($uid);
|
||||||
|
if (!$user) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$num = (int) $row['val'];
|
||||||
|
$users[] = [
|
||||||
|
'id' => $uid,
|
||||||
|
'name' => $user->display_name,
|
||||||
|
'value' => number_format_i18n($num) . $suffix,
|
||||||
|
'value_num' => (string) number_format_i18n($num),
|
||||||
|
'value_label' => sprintf($label_tpl, $num),
|
||||||
|
'value_icon' => $icon,
|
||||||
|
'desc' => $this->user_extra_desc($uid, $user, $desc_mode),
|
||||||
|
];
|
||||||
|
if (count($users) >= $count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
|
|
||||||
private function user_extra_desc(int $user_id, $user, string $mode): string {
|
private function user_extra_desc(int $user_id, $user, string $mode): string {
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
@@ -258,7 +289,7 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
$title = !empty($instance['title']) ? $instance['title'] : __('排行榜', 'aksrt');
|
$title = !empty($instance['title']) ? $instance['title'] : __('排行榜', 'aksrt');
|
||||||
$rank_by = !empty($instance['rank_by']) ? $instance['rank_by'] : 'credits';
|
$rank_by = !empty($instance['rank_by']) ? $instance['rank_by'] : 'credits';
|
||||||
$count = !empty($instance['count']) ? (int) $instance['count'] : 5;
|
$count = !empty($instance['count']) ? (int) $instance['count'] : 5;
|
||||||
$show_avatar = !empty($instance['show_avatar']);
|
$show_avatar = !isset($instance['show_avatar']) || !empty($instance['show_avatar']);
|
||||||
?>
|
?>
|
||||||
<p>
|
<p>
|
||||||
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
|
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
|
||||||
@@ -313,9 +344,9 @@ class WidgetUserRanking extends \WP_Widget {
|
|||||||
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
|
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
|
||||||
$instance['rank_by'] = in_array($new_instance['rank_by'] ?? '', ['credits', 'posts', 'followers', 'checkin_all_day', 'checkin_continuous_day'], true) ? $new_instance['rank_by'] : 'credits';
|
$instance['rank_by'] = in_array($new_instance['rank_by'] ?? '', ['credits', 'posts', 'followers', 'checkin_all_day', 'checkin_continuous_day'], true) ? $new_instance['rank_by'] : 'credits';
|
||||||
$instance['count'] = max(1, min(20, (int) ($new_instance['count'] ?? 5)));
|
$instance['count'] = max(1, min(20, (int) ($new_instance['count'] ?? 5)));
|
||||||
$instance['show_avatar'] = !empty($new_instance['show_avatar']);
|
$instance['show_avatar'] = !empty($new_instance['show_avatar']) ? 1 : 0;
|
||||||
$instance['checkin_btn'] = !empty($new_instance['checkin_btn']);
|
$instance['checkin_btn'] = !empty($new_instance['checkin_btn']) ? 1 : 0;
|
||||||
$instance['top_badge'] = !empty($new_instance['top_badge']);
|
$instance['top_badge'] = !empty($new_instance['top_badge']) ? 1 : 0;
|
||||||
$instance['desc'] = in_array($new_instance['desc'] ?? '', ['desc', 'user_registered', 'last_login', 'last_checkin'], true) ? $new_instance['desc'] : 'desc';
|
$instance['desc'] = in_array($new_instance['desc'] ?? '', ['desc', 'user_registered', 'last_login', 'last_checkin'], true) ? $new_instance['desc'] : 'desc';
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user