esc_html__('显示最新评论列表(posts-mini + 身份/点赞)。', 'aksrt'), ]); } /** * @param array $instance */ public static function render_html(array $instance): string { $count = max(1, min(20, (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', ]; // Include forum topics / products when active. if (post_type_exists('aksrt_forum_topic')) { $query['post_type'][] = 'aksrt_forum_topic'; } elseif (post_type_exists('forum_topic') || post_type_exists('forum_post')) { // Legacy CPT names. $query['post_type'][] = post_type_exists('forum_topic') ? 'forum_topic' : 'forum_post'; } if (post_type_exists('aksrt_product')) { $query['post_type'][] = 'aksrt_product'; } 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')) : '

' . esc_html__('暂无评论', 'aksrt') . '

'; } ob_start(); // zibll: .box-body.comment-mini-lists.zib-widget + .posts-mini rows. echo '
'; 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('/\/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 = '' . esc_html(get_comment_author($comment)) . ''; } 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 = '
'; } $like = function_exists('aksrt_get_comment_like_html') ? aksrt_get_comment_like_html($comment, true) : ''; echo '
'; echo $avatar; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '
'; echo '

'; echo ''; echo $user_name; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '' . esc_html($time) . ''; echo ''; if ($like !== '') { echo '' . $like . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } echo '

'; echo '' . esc_html($cont) . ''; echo '
'; } echo '
'; return (string) ob_get_clean(); } /** * @param array $args * @param array $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 } $in_affix = !empty($instance['in_affix']); if ($in_affix) { echo '
'; } echo self::render_html($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped if ($in_affix) { echo '
'; } echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * @param array $instance */ public function form($instance): void { ?>

$new_instance * @param array $old_instance * @return array */ public function update($new_instance, $old_instance): array { return [ 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')), 'count' => max(1, min(20, (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'] ?? '')), ]; } }