Files
wordpress-theme-aksrt/src/Widgets/RecentCommentsWidget.php
T

215 lines
8.7 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
/**
* Recent comments mini list (zibll widget_ui_new_comment → zib_widget_comments).
*
* @package AKSRT
*/
namespace AKSRT\Widgets;
defined('ABSPATH') || exit;
class RecentCommentsWidget extends \WP_Widget {
public function __construct() {
parent::__construct('aksrt_recent_comments', esc_html__('AKSRT 最新评论', 'aksrt'), [
'description' => esc_html__('显示最新评论列表(posts-mini + 身份/点赞)。', 'aksrt'),
]);
}
/**
* @param array<string,mixed> $instance
*/
public static function render_html(array $instance): string {
$count = max(1, min(50, (int) ($instance['count'] ?? $instance['limit'] ?? 5)));
$show_avatar = !isset($instance['show_avatar']) || !empty($instance['show_avatar']);
// zibll: outpost = post__not_in (multi-ID), outer = author__not_in (multi-ID).
// Also keep optional keyword filter via outer_keywords for legacy installs.
$outpost_raw = (string) ($instance['outpost'] ?? '');
$outer_raw = (string) ($instance['outer'] ?? '');
$keywords = sanitize_text_field((string) ($instance['outer_keywords'] ?? ''));
$post_not_in = array_values(array_filter(array_map('intval', preg_split('/[,,\s]+/', $outpost_raw) ?: [])));
// Heuristic: if outer looks numeric/id-list → author__not_in; else treat as keyword filter (legacy).
$author_not_in = [];
$legacy_keys = [];
if ($outer_raw !== '') {
$parts = array_filter(array_map('trim', preg_split('/[,,\s]+/', $outer_raw) ?: []));
$all_numeric = $parts && array_reduce($parts, static function ($ok, $p) {
return $ok && ctype_digit((string) $p);
}, true);
if ($all_numeric) {
$author_not_in = array_values(array_filter(array_map('intval', $parts)));
} else {
$legacy_keys = $parts;
}
}
if ($keywords !== '') {
$legacy_keys = array_merge($legacy_keys, array_filter(array_map('trim', preg_split('/[,,]+/', $keywords) ?: [])));
}
$query = [
'number' => $count * 2, // over-fetch when filtering keywords.
'status' => 'approve',
'post_status' => 'publish',
'post_type' => ['post'],
'orderby' => 'comment_date_gmt',
'order' => 'DESC',
];
if ($post_not_in) {
$query['post__not_in'] = $post_not_in;
}
if ($author_not_in) {
$query['author__not_in'] = $author_not_in;
}
$comments = get_comments($query);
if ($legacy_keys && $comments) {
$comments = array_values(array_filter($comments, static function ($c) use ($legacy_keys) {
$body = (string) $c->comment_content;
foreach ($legacy_keys as $k) {
if ($k !== '' && str_contains($body, $k)) {
return false;
}
}
return true;
}));
}
$comments = array_slice($comments ?: [], 0, $count);
if (!$comments) {
return function_exists('aksrt_get_ajax_null')
? aksrt_get_ajax_null(__('暂无评论', 'aksrt'))
: '<p class="widget-empty ajax-item">' . esc_html__('暂无评论', 'aksrt') . '</p>';
}
ob_start();
// zibll: .box-body.comment-mini-lists.zib-widget + .posts-mini rows.
echo '<div class="box-body comment-mini-lists zib-widget ajax-item widget-recent-comments">';
foreach ($comments as $comment) {
$cid = (int) $comment->comment_ID;
$user_id = (int) $comment->user_id;
$link = get_comment_link($comment);
$time = human_time_diff(strtotime((string) $comment->comment_date), current_time('timestamp'));
// Content: strip imgs/code like zibll noimg filter.
$cont = get_comment_text($cid);
$cont = convert_smilies($cont);
$cont = preg_replace('/\<img(.*?)\>/i', '[' . __('图片', 'aksrt') . ']', $cont);
$cont = preg_replace('/\[code]([\s\S]*?)\[\/code]/i', '[' . __('代码', 'aksrt') . ']', (string) $cont);
$cont = wp_strip_all_tags((string) $cont);
$cont = wp_trim_words($cont, 40, '…');
// Name with identity.
if ($user_id > 0 && function_exists('aksrt_get_user_name')) {
$user_name = aksrt_get_user_name([
'id' => $user_id,
'class' => 'inflex ac relative-h',
'follow' => false,
'medal' => true,
'level' => true,
'auth' => true,
]);
} elseif ($user_id > 0) {
$home = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id);
$user_name = '<a href="' . esc_url($home) . '">' . esc_html(get_comment_author($comment)) . '</a>';
} else {
$user_name = esc_html(get_comment_author($comment));
}
$avatar = '';
if ($show_avatar) {
$avatar_url = $user_id > 0 && function_exists('aksrt_get_avatar_url')
? aksrt_get_avatar_url($user_id, ['size' => 42])
: get_avatar_url($comment, ['size' => 42]);
$ph = get_template_directory_uri() . '/assets/img/placeholder.svg';
$avatar = '<div class="avatar-img"><img class="avatar aksrt-lazy lazyload" data-src="' . esc_url($avatar_url) . '" src="' . esc_url($ph) . '" alt="" width="36" height="36" loading="lazy" /></div>';
}
$like = function_exists('aksrt_get_comment_like_html')
? aksrt_get_comment_like_html($comment, true)
: '';
echo '<div class="posts-mini">';
echo $avatar; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="posts-mini-con em09 ml10 flex xx jsb">';
echo '<p class="flex jsb">';
echo '<span class="flex1 flex">';
echo $user_name; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<span class="flex0 icon-spot muted-3-color" title="' . esc_attr((string) $comment->comment_date) . '">' . esc_html($time) . '</span>';
echo '</span>';
if ($like !== '') {
echo '<span class="ml10 flex0">' . $like . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '</p>';
echo '<a class="muted-color text-ellipsis-5" href="' . esc_url($link) . '">' . esc_html($cont) . '</a>';
echo '</div></div>';
}
echo '</div>';
return (string) ob_get_clean();
}
/**
* @param array<string,mixed> $args
* @param array<string,mixed> $instance
*/
public function widget($args, $instance): void {
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', (string) ($instance['title'] ?? __('最新评论', 'aksrt')), $instance, $this->id_base);
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo self::render_html($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* @param array<string,mixed> $instance
*/
public function form($instance): void {
?>
<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'] ?? __('最新评论', 'aksrt'))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('数量', 'aksrt'); ?>
<input class="tiny-text" type="number" min="1" max="50" name="<?php echo esc_attr($this->get_field_name('count')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['count'] ?? 5))); ?>">
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_avatar')); ?>" value="1" <?php checked(!isset($instance['show_avatar']) || !empty($instance['show_avatar'])); ?>> <?php esc_html_e('显示头像', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('排除文章 ID(逗号)', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('outpost')); ?>" value="<?php echo esc_attr((string) ($instance['outpost'] ?? '')); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('排除作者 ID(逗号)', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('outer')); ?>" value="<?php echo esc_attr((string) ($instance['outer'] ?? '')); ?>">
</label>
<small><?php esc_html_e('填数字 ID 时按作者排除;填文字时按内容关键词排除(兼容旧配置)。', 'aksrt'); ?></small>
</p>
<?php
}
/**
* @param array<string,mixed> $new_instance
* @param array<string,mixed> $old_instance
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(50, (int) ($new_instance['count'] ?? 5))),
'show_avatar' => !empty($new_instance['show_avatar']) ? 1 : 0,
'outpost' => sanitize_text_field((string) ($new_instance['outpost'] ?? '')),
'outer' => sanitize_text_field((string) ($new_instance['outer'] ?? '')),
'outer_keywords' => sanitize_text_field((string) ($new_instance['outer_keywords'] ?? '')),
];
}
}