184 lines
8.1 KiB
PHP
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;
|
|
}
|
|
}
|