Files
wordpress-theme-aksrt/src/WidgetSystem/Renderers/UserRenderer.php
T
kate522 5984d4e42d fix(icons): 清理 FA4 残留图标类,统一为 Font Awesome 5 约定
- 通用 fa fa-X 前缀改为 fa fas fa-X(12 个生产文件)
- 重命名图标映射:fa-sign-in→fa-sign-in-alt、fa-envelope-o→far fa-envelope、
  fa-trash-o→far fa-trash-alt、fa-file-image-o→far fa-file-image、
  fa-dot-circle-o→far fa-dot-circle、fa-play-circle-o→far fa-play-circle、
  fa-pencil→fas fa-pencil-alt
- 修复 FA5 中不存在的 fa-pencil-square→fas fa-edit
2026-09-02 21:48:42 +08:00

311 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace AKSRT\WidgetSystem\Renderers;
use AKSRT\WidgetSystem\RendererHelpers;
defined('ABSPATH') || exit;
/** Render login, author, ranking and user-list widgets. */
final class UserRenderer {
public static function render(string $slug, array $instance, array $context = []): string {
unset($context);
switch ($slug) {
case 'user_card': return self::user_card($instance);
case 'author_card': return self::author_card($instance);
case 'user_ranking': return self::ranking($instance);
case 'user_list': return self::user_list($instance);
}
return '';
}
private static function user_card(array $i): string {
if (class_exists('AKSRT\\Settings\\Settings') && \AKSRT\Settings\Settings::close_sign()) {
return '';
}
$user_id = get_current_user_id();
if ($user_id <= 0) {
return self::guest_card($i);
}
$user = get_userdata($user_id);
if (!$user instanceof \WP_User) {
return '';
}
return '<div class="mb20">' . self::card_box($user_id, [
'show_posts' => false,
'show_checkin' => true,
'show_img_bg' => !isset($i['show_img_bg']) || !empty($i['show_img_bg']),
] + self::card_button_args($i)) . '</div>';
}
private static function author_card(array $i): string {
$post = get_post();
if (!$post instanceof \WP_Post) {
return '';
}
$user = get_userdata((int) $post->post_author);
if (!$user instanceof \WP_User) {
return '';
}
$post_style = sanitize_key((string) ($i['post_style'] ?? 'mini'));
return '<div class="mb20">' . self::card_box((int) $user->ID, [
'show_img_bg' => !isset($i['show_img_bg']) || !empty($i['show_img_bg']),
'show_posts' => !isset($i['show_posts']) || !empty($i['show_posts']),
'limit' => max(0, min(12, (int) ($i['limit'] ?? 6))),
'orderby' => sanitize_key((string) ($i['orderby'] ?? 'date')),
'post_type' => 'post',
'post_style' => $post_style === 'card' ? 'card' : 'mini',
] + self::card_button_args($i)) . '</div>';
}
private static function card_button_args(array $i): array {
return [
'show_button' => !isset($i['show_button']) || !empty($i['show_button']),
'button_1' => (string) ($i['button_1'] ?? 'post'),
'button_1_class' => (string) ($i['button_1_class'] ?? 'jb-pink'),
'button_1_text' => (string) ($i['button_1_text'] ?? ''),
'button_2' => (string) ($i['button_2'] ?? 'center'),
'button_2_class' => (string) ($i['button_2_class'] ?? 'jb-blue'),
'button_2_text' => (string) ($i['button_2_text'] ?? ''),
];
}
/**
* 未登录卡片(legacy zib_get_user_singin_page_box parity)。
*/
private static function guest_card(array $i): string {
$title = trim((string) ($i['loged_title'] ?? ''));
if ($title === '') {
$title = __('Hi!请登录', 'aksrt');
}
$cover = !isset($i['show_img_bg']) || !empty($i['show_img_bg'])
? self::cover(0, 'lazy_other')
: '';
$avatar = '<span class="avatar-img avatar-lg"><img alt="' . esc_attr__('默认头像', 'aksrt') . '" class="fit-cover avatar" src="' . esc_url(aksrt_get_default_avatar_url()) . '"></span>';
$buttons = '<a href="javascript:;" class="signin-loader but jb-blue padding-lg"><i class="fa fas fa-fw fa-sign-in-alt" aria-hidden="true"></i>' . esc_html__('登录', 'aksrt') . '</a>';
$registration_enabled = class_exists('AKSRT\\Settings\\Settings')
? \AKSRT\Settings\Settings::registration_enabled()
: (bool) get_option('users_can_register');
if ($registration_enabled) {
$buttons .= '<a href="javascript:;" class="signup-loader ml10 but jb-yellow padding-lg">' . aksrt_renderer_svg_icon('signup') . esc_html__('注册', 'aksrt') . '</a>';
}
return '<div class="mb20"><div class="user-card zib-widget widget">' . $cover
. '<div class="card-content mt10">'
. '<div class="user-content">'
. '<div class="user-avatar">' . $avatar . '</div>'
. '<div class="user-info mt10">'
. '<div class="text-center">'
. '<p class="muted-color box-body em12">' . esc_html($title) . '</p>'
. '<p>' . $buttons . '</p>'
. self::social_login()
. '</div></div></div></div></div></div>';
}
private static function social_login(): string {
if (!class_exists('AKSRT\\Auth\\OAuth')) {
return '';
}
$items = \AKSRT\Auth\OAuth::get_instance()->get_auth_providers_data();
if ($items === []) {
return '';
}
$html = '<div class="social-separator separator muted-3-color em09 mt20 mb20">' . esc_html__('社交账号登录', 'aksrt') . '</div><div class="social_loginbar">';
foreach ($items as $item) {
$name = sanitize_html_class((string) ($item['name'] ?? ''));
$style_name = str_starts_with($name, 'clogin_') ? substr($name, 7) : $name;
$label = trim((string) ($item['label'] ?? ''));
$url = (string) ($item['url'] ?? '');
if ($name === '' || $style_name === '' || $label === '' || $url === '') {
continue;
}
$html .= '<a rel="nofollow" href="' . esc_url($url) . '" class="social-login-item ' . esc_attr($style_name) . '" data-provider="' . esc_attr($name) . '" aria-label="' . esc_attr(sprintf(__('%s登录', 'aksrt'), $label)) . '" title="' . esc_attr($label) . '">' . (string) ($item['icon'] ?? '') . '</a>';
}
return $html . '</div>';
}
private static function cover(int $user_id, string $lazy_type): string {
$cover_url = aksrt_get_user_cover_url($user_id);
if ($cover_url === '') {
return '';
}
return '<div class="user-cover graphic" style="padding-bottom: 50%;"><img' . aksrt_get_lazy_attr($lazy_type, $cover_url, 'fit-cover', aksrt_get_lazy_thumb()) . ' alt="' . esc_attr__('用户封面', 'aksrt') . '"></div>';
}
/**
* 登录卡片(legacy zib_get_user_card_box parity)。
*
* @param int $user_id 卡片用户。
* @param array $args show_posts/show_checkin/show_img_bg/show_button/button_1,2 与文章模块参数。
*/
private static function card_box(int $user_id, array $args = []): string {
$args = wp_parse_args($args, [
'show_posts' => true,
'show_checkin' => false,
'show_img_bg' => false,
'show_button' => true,
'button_1' => 'post',
'button_1_class' => 'jb-pink',
'button_1_text' => __('发布文章', 'aksrt'),
'button_2' => 'center',
'button_2_class' => 'jb-blue',
'button_2_text' => __('用户中心', 'aksrt'),
'limit' => 6,
'orderby' => 'views',
'post_type' => 'post',
'post_style' => 'card',
]);
$avatar = aksrt_get_avatar_box($user_id, 'avatar-img avatar-lg');
$name = aksrt_get_user_name([
'id' => $user_id,
'class' => 'flex1 flex ac',
'vip' => false,
'medal' => true,
'auth' => true,
'level' => true,
'follow' => true,
]);
$tag_metas = aksrt_get_user_badges($user_id);
$desc = aksrt_get_user_description($user_id);
$btns = '';
$posts = '';
$checkin = '';
$cuid = get_current_user_id();
if (!$cuid || $cuid !== $user_id) {
$args['show_button'] = false;
}
if ($args['show_posts'] && (int) $args['limit'] > 0) {
$posts = aksrt_render_user_card_posts([
'user_id' => $user_id,
'limit' => (int) $args['limit'],
'orderby' => (string) $args['orderby'],
'post_type' => (string) $args['post_type'],
'post_style' => (string) $args['post_style'],
]);
}
if ($args['show_checkin'] && $cuid === $user_id) {
$checkin = aksrt_header_user_checkin_btn($user_id, true, 'img-badge jb-yellow');
}
if ($args['show_button']) {
$btns .= self::new_add_btn((string) $args['button_1'], 'but pw-1em mr6 ' . (string) $args['button_1_class'], (string) $args['button_1_text']);
if ('home' === $args['button_2']) {
$btns .= self::card_link(aksrt_get_user_home_url($user_id), (string) $args['button_2_class'], (string) $args['button_2_text']);
} else {
$btns .= self::card_link(aksrt_get_user_center_url(), (string) $args['button_2_class'], (string) $args['button_2_text'], true);
}
$btns = $btns !== '' ? '<div class="user-btns mt20">' . $btns . '</div>' : '';
}
$cover = !empty($args['show_img_bg']) ? self::cover($user_id, 'lazy_cover') : '';
return '<div class="user-card zib-widget widget">' . $cover
. '<div class="card-content mt10 relative">'
. '<div class="user-content">' . $checkin
. '<div class="user-avatar">' . $avatar . '</div>'
. '<div class="user-info mt20 mb10">'
. '<div class="user-name flex jc">' . $name . '</div>'
. '<div class="author-tag mt10 mini-scrollbar">' . $tag_metas . '</div>'
. '<div class="user-desc mt10 muted-2-color em09">' . esc_html($desc) . '</div>'
. $btns
. '</div></div>'
. $posts
. '</div></div>';
}
/**
* 卡片按钮1(legacy zib_get_new_add_btns 的 post 类型 parity)。
*/
private static function new_add_btn(string $type, string $class, string $text): string {
if ($type !== 'post') {
return '';
}
$url = aksrt_get_new_post_url();
if ($url === '') {
return '';
}
return '<a rel="nofollow" class="newadd-btns ' . esc_attr($class) . '" href="' . esc_url($url) . '"><icon class="jb-green"><i class="fa fas fa-edit" aria-hidden="true"></i></icon><text>' . esc_html($text) . '</text></a>';
}
private static function card_link(string $url, string $class, string $text, bool $nofollow = false): string {
if ($url === '') {
return '';
}
return '<a' . ($nofollow ? ' rel="nofollow"' : '') . ' href="' . esc_url($url) . '" class="but pw-1em ml6 ' . esc_attr($class) . '">' . esc_html($text) . '</a>';
}
private static function ranking(array $i): string {
$users = get_users(['number' => 200, 'orderby' => 'registered', 'order' => 'DESC']);
$metric = (string) $i['orderby'];
usort($users, static fn(\WP_User $a, \WP_User $b): int => self::metric($b, $metric) <=> self::metric($a, $metric));
$users = array_slice($users, 0, (int) $i['number']);
if (!$users) {
return RendererHelpers::empty_state(__('暂无用户数据', 'aksrt'));
}
$html = '<ol class="aksrt-user-ranking">';
foreach ($users as $index => $user) {
$html .= '<li><span class="aksrt-user-ranking__index' . (!empty($i['show_badge']) && $index < 3 ? ' is-top' : '') . '">' . ($index + 1) . '</span>' . self::user_tile($user, self::metric($user, $metric), self::metric_label($metric)) . '</li>';
}
return $html . '</ol>';
}
private static function user_list(array $i): string {
$args = ['number' => 200];
if (!empty($i['include'])) {
$args['include'] = RendererHelpers::ids((string) $i['include']);
}
if (!empty($i['exclude'])) {
$args['exclude'] = RendererHelpers::ids((string) $i['exclude']);
}
$users = get_users($args);
$orderby = (string) $i['orderby'];
usort($users, static function (\WP_User $a, \WP_User $b) use ($orderby): int {
if ($orderby === 'display_name') {
return strcasecmp($a->display_name, $b->display_name);
}
if ($orderby === 'registered') {
return strcmp($b->user_registered, $a->user_registered);
}
return self::metric($b, $orderby) <=> self::metric($a, $orderby);
});
$html = '<div class="aksrt-widget-grid aksrt-user-list">';
foreach (array_slice($users, 0, (int) $i['number']) as $user) {
$html .= '<article>' . self::user_tile($user, self::metric($user, $orderby), self::metric_label($orderby)) . '</article>';
}
return $html . '</div>';
}
private static function user_tile(\WP_User $user, int $value, string $label): string {
$url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user) : get_author_posts_url((int) $user->ID);
return '<a class="aksrt-user-tile" href="' . esc_url($url) . '">' . (function_exists('aksrt_get_avatar_html') ? aksrt_get_avatar_html($user->ID, 64) : get_avatar($user->ID, 64)) . '<span><strong>' . esc_html($user->display_name) . '</strong><small>' . esc_html($label) . ' ' . number_format_i18n($value) . '</small></span></a>';
}
private static function metric(\WP_User $user, string $metric): int {
$id = (int) $user->ID;
if ($metric === 'points') {
return aksrt_user_points($id);
}
if ($metric === 'followers') {
return class_exists('AKSRT\\User\\Follow') ? (int) \AKSRT\User\Follow::get_instance()->get_follower_count($id) : 0;
}
if ($metric === 'post_count') {
return (int) count_user_posts($id, 'post', true);
}
$key = $metric === 'checkin_continuous_day' ? 'aksrt_checkin_continuous_day' : 'aksrt_checkin_all_day';
return (int) get_user_meta($id, $key, true);
}
private static function metric_label(string $metric): string {
$labels = ['points' => __('积分', 'aksrt'), 'followers' => __('粉丝', 'aksrt'), 'post_count' => __('文章', 'aksrt'), 'registered' => __('新加入', 'aksrt'), 'display_name' => __('用户', 'aksrt'), 'checkin_all_day' => __('累计签到', 'aksrt'), 'checkin_continuous_day' => __('连续签到', 'aksrt')];
return $labels[$metric] ?? $labels['points'];
}
}