Files
wordpress-theme-aksrt/inc/classes/widgets/class-aksrt-user-ranking-widget.php
T

184 lines
8.1 KiB
PHP

<?php
/**
* AKSRT User Ranking Widget — 用户排行榜
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
class AKSRT_Widget_User_Ranking extends WP_Widget {
public function __construct() {
parent::__construct(
'aksrt_user_ranking',
__('用户排行榜', 'aksrt'),
['description' => __('按积分、文章数或粉丝数排行的用户列表。', 'aksrt')]
);
}
public function widget($args, $instance): void {
$title = !empty($instance['title']) ? $instance['title'] : __('排行榜', 'aksrt');
$rank_by = !empty($instance['rank_by']) ? $instance['rank_by'] : 'credits';
$count = max(1, min(20, (int) ($instance['count'] ?? 5)));
$show_avatar = !empty($instance['show_avatar']);
$users = $this->get_ranking($rank_by, $count);
if (empty($users)) return;
echo $args['before_widget'];
echo $args['before_title'] . esc_html($title) . $args['after_title'];
echo '<ul class="aksrt-user-ranking">';
$rank = 0;
foreach ($users as $user) {
$rank++;
$rank_class = $rank <= 3 ? ' aksrt-user-ranking__item--top' : '';
$user_url = function_exists('aksrt_get_user_home_url')
? aksrt_get_user_home_url($user['id'])
: get_author_posts_url($user['id']);
echo '<li class="aksrt-user-ranking__item' . esc_attr($rank_class) . '">';
// 排名
echo '<span class="aksrt-user-ranking__rank">' . esc_html((string) $rank) . '</span>';
// 头像
if ($show_avatar) {
$avatar_url = function_exists('aksrt_get_avatar_url')
? aksrt_get_avatar_url($user['id'], ['size' => 36])
: get_avatar_url($user['id'], ['size' => 36]);
echo '<a href="' . esc_url($user_url) . '" class="aksrt-user-ranking__avatar">';
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>';
}
// 昵称
echo '<a href="' . esc_url($user_url) . '" class="aksrt-user-ranking__name">' . esc_html($user['name']) . '</a>';
// 数值
echo '<span class="aksrt-user-ranking__value">' . esc_html($user['value']) . '</span>';
echo '</li>';
}
echo '</ul>';
echo $args['after_widget'];
}
private function get_ranking(string $rank_by, int $count): array {
$users = [];
switch ($rank_by) {
case 'credits':
global $wpdb;
$rows = $wpdb->get_results($wpdb->prepare(
"SELECT user_id, meta_value as credits FROM {$wpdb->usermeta}
WHERE meta_key = 'aksrt_credits'
ORDER BY CAST(meta_value AS UNSIGNED) DESC
LIMIT %d",
$count
), ARRAY_A);
foreach ((array) $rows as $row) {
$user = get_userdata((int) $row['user_id']);
if ($user) {
$users[] = [
'id' => (int) $row['user_id'],
'name' => $user->display_name,
'value' => number_format_i18n((int) $row['credits']) . ' 积分',
];
}
}
break;
case 'posts':
$blog_users = get_users([
'number' => $count,
'orderby' => 'post_count',
'order' => 'DESC',
'who' => 'authors',
]);
foreach ($blog_users as $user) {
$post_count = count_user_posts($user->ID, 'post', true);
if ($post_count > 0) {
$users[] = [
'id' => $user->ID,
'name' => $user->display_name,
'value' => number_format_i18n($post_count) . ' 篇',
];
}
}
break;
case 'followers':
if (class_exists('AKSRT_Follow')) {
global $wpdb;
$follow_table = AKSRT_DB_Migrator::table('follow');
if ($follow_table) {
$rows = $wpdb->get_results($wpdb->prepare(
"SELECT following_id, COUNT(*) as cnt
FROM {$follow_table}
GROUP BY following_id
ORDER BY cnt DESC
LIMIT %d",
$count
), ARRAY_A);
foreach ((array) $rows as $row) {
$user = get_userdata((int) $row['following_id']);
if ($user) {
$users[] = [
'id' => (int) $row['following_id'],
'name' => $user->display_name,
'value' => number_format_i18n((int) $row['cnt']) . ' 粉丝',
];
}
}
}
}
break;
}
return $users;
}
public function form($instance): void {
$title = !empty($instance['title']) ? $instance['title'] : __('排行榜', 'aksrt');
$rank_by = !empty($instance['rank_by']) ? $instance['rank_by'] : 'credits';
$count = !empty($instance['count']) ? (int) $instance['count'] : 5;
$show_avatar = !empty($instance['show_avatar']);
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('rank_by')); ?>"><?php esc_html_e('排行依据:', 'aksrt'); ?></label>
<select class="widefat" id="<?php echo esc_attr($this->get_field_id('rank_by')); ?>" name="<?php echo esc_attr($this->get_field_name('rank_by')); ?>">
<option value="credits" <?php selected($rank_by, 'credits'); ?>><?php esc_html_e('积分', 'aksrt'); ?></option>
<option value="posts" <?php selected($rank_by, 'posts'); ?>><?php esc_html_e('文章数', 'aksrt'); ?></option>
<option value="followers" <?php selected($rank_by, 'followers'); ?>><?php esc_html_e('粉丝数', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('count')); ?>"><?php esc_html_e('显示数量:', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id('count')); ?>" name="<?php echo esc_attr($this->get_field_name('count')); ?>" type="number" value="<?php echo esc_attr((string) $count); ?>" min="1" max="20">
</p>
<p>
<label>
<input type="checkbox" id="<?php echo esc_attr($this->get_field_id('show_avatar')); ?>" name="<?php echo esc_attr($this->get_field_name('show_avatar')); ?>" value="1" <?php checked($show_avatar); ?>>
<?php esc_html_e('显示头像', 'aksrt'); ?>
</label>
</p>
<?php
}
public function update($new_instance, $old_instance): array {
$instance = [];
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
$instance['rank_by'] = in_array($new_instance['rank_by'] ?? '', ['credits', 'posts', 'followers'], true) ? $new_instance['rank_by'] : 'credits';
$instance['count'] = max(1, min(20, (int) ($new_instance['count'] ?? 5)));
$instance['show_avatar'] = !empty($new_instance['show_avatar']);
return $instance;
}
}