Files
wordpress-theme-aksrt/src/AKSRT/Widgets/WidgetUserCard.php
T
kate522 d248727870 feat(widgets): reviews/pricing/announce empty + identity lazy avatars
Admin null states for reviews/pricing/announcement; lazyload avatars and
covers on about/author/user cards and review slides.
2026-07-21 11:17:01 +08:00

306 lines
16 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
/**
* Current-user / guest identity card (zibll widget_ui_user parity).
*
* @package AKSRT
*/
namespace AKSRT\Widgets;
defined('ABSPATH') || exit;
class WidgetUserCard extends \WP_Widget {
public function __construct() {
parent::__construct(
'aksrt_user_card',
__('用户卡片', 'aksrt'),
['description' => __('未登录显示登录入口;登录后显示当前用户卡片、签到、快捷按钮与更多文章。', 'aksrt')]
);
}
public function widget($args, $instance): void {
$show_cover = !isset($instance['show_img_bg']) || !empty($instance['show_img_bg']);
$show_stats = !empty($instance['show_stats']) || !isset($instance['show_stats']);
$show_actions = !empty($instance['show_button']) || !isset($instance['show_button']);
$show_checkin = !empty($instance['show_checkin']) || !isset($instance['show_checkin']);
// zibll user widget forces show_posts=false; author widget enables it.
// AKSRT keeps optional show_posts for current-user card (default off).
$show_posts = !empty($instance['show_posts']);
$loged_title = (string) ($instance['loged_title'] ?? __('Hi!请登录', 'aksrt'));
$btn1_text = (string) ($instance['button_1_text'] ?? __('发布文章', 'aksrt'));
$btn2_text = (string) ($instance['button_2_text'] ?? __('用户中心', 'aksrt'));
$post_style = sanitize_key((string) ($instance['post_style'] ?? 'mini'));
if (!in_array($post_style, ['card', 'mini'], true)) {
$post_style = 'mini';
}
$limit = max(0, min(12, (int) ($instance['limit'] ?? 6)));
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'date'));
// Fixed user id wins; else current user.
$user_id = !empty($instance['user_id']) ? (int) $instance['user_id'] : 0;
if ($user_id <= 0 && is_user_logged_in()) {
$user_id = get_current_user_id();
}
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
if ($user_id <= 0) {
$this->render_guest($show_cover, $loged_title);
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}
$user = get_userdata($user_id);
if (!$user) {
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}
$is_self = is_user_logged_in() && (int) get_current_user_id() === $user_id;
$avatar_url = function_exists('aksrt_get_avatar_url')
? aksrt_get_avatar_url($user_id, ['size' => 144])
: get_avatar_url($user_id, ['size' => 144]);
$profile_url = function_exists('aksrt_get_user_home_url')
? aksrt_get_user_home_url($user_id)
: get_author_posts_url($user_id);
$center_url = function_exists('aksrt_get_user_center_url')
? aksrt_get_user_center_url()
: $profile_url;
$compose_url = home_url('/');
if (function_exists('get_pages')) {
$pages = get_pages(['meta_key' => '_wp_page_template', 'meta_value' => 'templates/pages/page-submit.php', 'number' => 1]);
if (!empty($pages[0])) {
$compose_url = get_permalink($pages[0]);
}
}
if ($compose_url === home_url('/') && function_exists('aksrt_get_user_center_url')) {
$compose_url = aksrt_get_user_center_url('posts');
}
$bio = get_user_meta($user_id, 'description', true);
if (!is_string($bio) || $bio === '') {
$bio = (string) $user->description;
}
$cover = (string) get_user_meta($user_id, 'aksrt_cover', true);
if ($cover === '') {
$cover = (string) get_user_meta($user_id, 'custom_avatar_cover', true);
}
$post_count = count_user_posts($user_id, 'post', true);
$follower_count = 0;
$following_count = 0;
if (class_exists('\AKSRT\User\Follow')) {
$follower_count = \AKSRT\User\Follow::get_instance()->get_follower_count($user_id);
$following_count = \AKSRT\User\Follow::get_instance()->get_following_count($user_id);
}
$name_html = function_exists('aksrt_get_user_name')
? aksrt_get_user_name(['id' => $user_id, 'follow' => !$is_self, 'class' => 'flex ac jc'])
: '<a href="' . esc_url($profile_url) . '">' . esc_html($user->display_name) . '</a>';
echo '<div class="aksrt-user-card user-card zib-widget widget">';
if ($show_cover) {
if ($cover !== '') {
echo '<div class="aksrt-user-card__cover user-cover graphic" style="background-image:url(' . esc_url($cover) . ')"></div>';
} else {
// Prefer site default cover image when available.
$default_cover = '';
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_user_cover_default')) {
$default_cover = (string) \AKSRT\Settings\Settings::get_user_cover_default();
}
if ($default_cover === '' && function_exists('get_theme_mod')) {
$default_cover = (string) get_theme_mod('aksrt_user_cover', '');
}
if ($default_cover !== '') {
echo '<div class="aksrt-user-card__cover user-cover graphic" style="background-image:url(' . esc_url($default_cover) . ')"></div>';
} else {
echo '<div class="aksrt-user-card__cover user-cover graphic is-empty"></div>';
}
}
}
echo '<div class="aksrt-user-card__body card-content">';
if ($show_checkin && $is_self && function_exists('aksrt_header_user_checkin_btn')) {
$btn = aksrt_header_user_checkin_btn($user_id);
if ($btn !== '') {
echo '<div class="aksrt-user-card__checkin">' . $btn . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
echo '<div class="aksrt-user-card__avatar user-avatar">';
$ph = get_template_directory_uri() . '/assets/img/placeholder.svg';
echo '<a href="' . esc_url($profile_url) . '"><img class="aksrt-lazy lazyload" data-src="' . esc_url($avatar_url) . '" src="' . esc_url($ph) . '" alt="' . esc_attr($user->display_name) . '" loading="lazy" width="72" height="72" /></a>';
echo '</div>';
echo '<h4 class="aksrt-user-card__name user-name">' . $name_html . '</h4>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ($bio !== '') {
echo '<p class="aksrt-user-card__bio user-desc">' . esc_html(wp_trim_words($bio, 24)) . '</p>';
}
if ($show_stats) {
echo '<div class="aksrt-user-card__stats">';
echo '<div class="aksrt-user-card__stat"><span class="aksrt-user-card__stat-value">' . esc_html(number_format_i18n($post_count)) . '</span><span class="aksrt-user-card__stat-label">' . esc_html__('文章', 'aksrt') . '</span></div>';
echo '<div class="aksrt-user-card__stat"><span class="aksrt-user-card__stat-value">' . esc_html(number_format_i18n($follower_count)) . '</span><span class="aksrt-user-card__stat-label">' . esc_html__('粉丝', 'aksrt') . '</span></div>';
echo '<div class="aksrt-user-card__stat"><span class="aksrt-user-card__stat-value">' . esc_html(number_format_i18n($following_count)) . '</span><span class="aksrt-user-card__stat-label">' . esc_html__('关注', 'aksrt') . '</span></div>';
echo '</div>';
}
if ($show_actions && $is_self) {
echo '<div class="aksrt-user-card__actions user-btns">';
echo '<a class="aksrt-user-card__btn aksrt-user-card__btn--primary but jb-pink" href="' . esc_url($compose_url) . '">' . esc_html($btn1_text) . '</a>';
echo '<a class="aksrt-user-card__btn aksrt-user-card__btn--ghost but jb-blue" href="' . esc_url($center_url) . '">' . esc_html($btn2_text) . '</a>';
echo '</div>';
} elseif ($show_actions) {
echo '<div class="aksrt-user-card__actions"><a class="aksrt-user-card__btn aksrt-user-card__btn--primary" href="' . esc_url($profile_url) . '">' . esc_html__('查看主页', 'aksrt') . '</a></div>';
}
if ($show_posts && $limit > 0 && function_exists('aksrt_render_user_card_posts')) {
echo aksrt_render_user_card_posts([ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'user_id' => $user_id,
'limit' => $limit,
'orderby' => $orderby,
'post_style' => $post_style,
'post_type' => 'post',
'show_empty' => false,
]);
}
echo '</div></div>';
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
private function render_guest(bool $show_cover, string $loged_title): void {
$login = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url();
$register = function_exists('aksrt_get_register_url') ? aksrt_get_register_url() : wp_registration_url();
$default_avatar = function_exists('get_avatar_url')
? get_avatar_url(0, ['size' => 144, 'force_default' => true])
: includes_url('images/blank.gif');
$oauth_html = '';
if (class_exists('\AKSRT\Auth\OAuth')) {
$oauth = \AKSRT\Auth\OAuth::get_instance();
if (method_exists($oauth, 'render_social_buttons')) {
$oauth_html = (string) $oauth->render_social_buttons(__('社交账号登录', 'aksrt'));
} elseif (method_exists($oauth, 'get_login_buttons')) {
$oauth_html = (string) $oauth->get_login_buttons();
}
}
echo '<div class="aksrt-user-card user-card zib-widget widget is-guest">';
if ($show_cover) {
$default_cover = '';
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_user_cover_default')) {
$default_cover = (string) \AKSRT\Settings\Settings::get_user_cover_default();
}
if ($default_cover !== '') {
echo '<div class="aksrt-user-card__cover user-cover graphic" style="background-image:url(' . esc_url($default_cover) . ')"></div>';
} else {
echo '<div class="aksrt-user-card__cover user-cover graphic is-empty"></div>';
}
}
echo '<div class="aksrt-user-card__body card-content">';
echo '<div class="aksrt-user-card__avatar user-avatar"><img src="' . esc_url($default_avatar) . '" alt="" width="72" height="72" loading="lazy" /></div>';
echo '<div class="aksrt-user-card__guest-title">' . esc_html($loged_title) . '</div>';
echo '<div class="aksrt-user-card__actions">';
echo '<a class="aksrt-user-card__btn aksrt-user-card__btn--primary signin-loader" href="' . esc_url($login) . '">' . esc_html__('登录', 'aksrt') . '</a>';
if ($register) {
echo '<a class="aksrt-user-card__btn aksrt-user-card__btn--ghost signup-loader" href="' . esc_url($register) . '">' . esc_html__('注册', 'aksrt') . '</a>';
}
echo '</div>';
if ($oauth_html !== '') {
echo '<div class="aksrt-user-card__oauth social_loginbar">' . $oauth_html . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '</div></div>';
}
public function form($instance): void {
$post_style = sanitize_key((string) ($instance['post_style'] ?? 'mini'));
if (!in_array($post_style, ['card', 'mini'], true)) {
$post_style = 'mini';
}
?>
<p>
<label><?php esc_html_e('标题(可选)', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title')); ?>" value="<?php echo esc_attr((string) ($instance['title'] ?? '')); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('固定用户 ID(0=当前用户)', 'aksrt'); ?>
<input class="tiny-text" type="number" min="0" name="<?php echo esc_attr($this->get_field_name('user_id')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['user_id'] ?? 0))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('未登录文案', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('loged_title')); ?>" value="<?php echo esc_attr((string) ($instance['loged_title'] ?? __('Hi!请登录', 'aksrt'))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('按钮1文案', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('button_1_text')); ?>" value="<?php echo esc_attr((string) ($instance['button_1_text'] ?? __('发布文章', 'aksrt'))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('按钮2文案', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('button_2_text')); ?>" value="<?php echo esc_attr((string) ($instance['button_2_text'] ?? __('用户中心', 'aksrt'))); ?>">
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_img_bg')); ?>" value="1" <?php checked(!isset($instance['show_img_bg']) || !empty($instance['show_img_bg'])); ?>> <?php esc_html_e('显示封面', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_stats')); ?>" value="1" <?php checked(!isset($instance['show_stats']) || !empty($instance['show_stats'])); ?>> <?php esc_html_e('显示统计', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_button')); ?>" value="1" <?php checked(!isset($instance['show_button']) || !empty($instance['show_button'])); ?>> <?php esc_html_e('显示操作按钮', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_checkin')); ?>" value="1" <?php checked(!isset($instance['show_checkin']) || !empty($instance['show_checkin'])); ?>> <?php esc_html_e('显示签到(本人)', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_posts')); ?>" value="1" <?php checked(!empty($instance['show_posts'])); ?>> <?php esc_html_e('显示更多文章', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('文章数量', 'aksrt'); ?>
<input class="tiny-text" type="number" min="0" max="12" name="<?php echo esc_attr($this->get_field_name('limit')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['limit'] ?? 6))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('文章样式', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('post_style')); ?>">
<option value="mini" <?php selected($post_style, 'mini'); ?>><?php esc_html_e('迷你列表', 'aksrt'); ?></option>
<option value="card" <?php selected($post_style, 'card'); ?>><?php esc_html_e('卡片横滑', 'aksrt'); ?></option>
</select>
</label>
</p>
<p>
<label><?php esc_html_e('排序', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('orderby')); ?>">
<option value="date" <?php selected(($instance['orderby'] ?? 'date'), 'date'); ?>><?php esc_html_e('最新', 'aksrt'); ?></option>
<option value="views" <?php selected(($instance['orderby'] ?? ''), 'views'); ?>><?php esc_html_e('阅读量', 'aksrt'); ?></option>
<option value="comment_count" <?php selected(($instance['orderby'] ?? ''), 'comment_count'); ?>><?php esc_html_e('评论数', 'aksrt'); ?></option>
<option value="rand" <?php selected(($instance['orderby'] ?? ''), 'rand'); ?>><?php esc_html_e('随机', 'aksrt'); ?></option>
</select>
</label>
</p>
<?php
}
public function update($new_instance, $old_instance): array {
$post_style = sanitize_key((string) ($new_instance['post_style'] ?? 'mini'));
if (!in_array($post_style, ['card', 'mini'], true)) {
$post_style = 'mini';
}
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date'));
if (!in_array($orderby, ['date', 'views', 'comment_count', 'modified', 'rand'], true)) {
$orderby = 'date';
}
return [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'user_id' => max(0, (int) ($new_instance['user_id'] ?? 0)),
'loged_title' => sanitize_text_field((string) ($new_instance['loged_title'] ?? '')),
'button_1_text' => sanitize_text_field((string) ($new_instance['button_1_text'] ?? '')),
'button_2_text' => sanitize_text_field((string) ($new_instance['button_2_text'] ?? '')),
'show_img_bg' => !empty($new_instance['show_img_bg']) ? 1 : 0,
'show_stats' => !empty($new_instance['show_stats']) ? 1 : 0,
'show_button' => !empty($new_instance['show_button']) ? 1 : 0,
'show_checkin' => !empty($new_instance['show_checkin']) ? 1 : 0,
'show_posts' => !empty($new_instance['show_posts']) ? 1 : 0,
'limit' => max(0, min(12, (int) ($new_instance['limit'] ?? 6))),
'post_style' => $post_style,
'orderby' => $orderby,
];
}
}