esc_html__('分类封面 + 最新文章列表聚合卡。', 'aksrt'), 'classname' => 'widget_aksrt_term_aggregation', ] ); } public function widget($args, $instance): void { $taxonomy = sanitize_key((string) ($instance['taxonomy'] ?? 'category')); if (!taxonomy_exists($taxonomy)) { $taxonomy = 'category'; } $term_ids = $this->parse_ids((string) ($instance['term_ids'] ?? '')); $count = max(1, min(12, (int) ($instance['count'] ?? 4))); $orderby = sanitize_key((string) ($instance['orderby'] ?? 'date')); $columns = max(1, min(3, (int) ($instance['columns'] ?? 1))); if (!$term_ids) { // Fallback: top terms by count. $terms = get_terms([ 'taxonomy' => $taxonomy, 'number' => max(1, min(4, (int) ($instance['auto_terms'] ?? 2))), 'orderby' => 'count', 'order' => 'DESC', 'hide_empty' => true, ]); if (is_wp_error($terms) || !$terms) { return; } $term_ids = array_map(static fn($t) => (int) $t->term_id, $terms); } 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 } echo '
'; foreach ($term_ids as $term_id) { $term = get_term($term_id, $taxonomy); if (!$term || is_wp_error($term)) { continue; } $link = get_term_link($term); if (is_wp_error($link)) { continue; } $cover = ''; $img_id = (int) get_term_meta($term_id, 'thumbnail_id', true); if (!$img_id) { $img_id = (int) get_term_meta($term_id, '_aksrt_cover', true); } if ($img_id) { $cover = wp_get_attachment_image_url($img_id, 'medium') ?: ''; } if ($cover === '') { $cover = (string) get_term_meta($term_id, '_aksrt_cover_url', true); } $posts_q = [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => $count, 'ignore_sticky_posts' => true, 'no_found_rows' => true, 'tax_query' => [[ 'taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $term_id, ]], ]; if ($orderby === 'views') { $posts_q['meta_key'] = 'aksrt_post_views'; $posts_q['orderby'] = 'meta_value_num'; $posts_q['order'] = 'DESC'; } elseif ($orderby === 'modified') { $posts_q['orderby'] = 'modified'; $posts_q['order'] = 'DESC'; } else { $posts_q['orderby'] = 'date'; $posts_q['order'] = 'DESC'; } $q = new \WP_Query($posts_q); echo '
'; echo ''; echo '
'; echo '
' . esc_html($term->name) . '
'; echo '
' . esc_html(sprintf(_n('%d 篇', '%d 篇', (int) $term->count, 'aksrt'), (int) $term->count)) . '
'; echo '
'; if ($q->have_posts()) { echo ''; wp_reset_postdata(); } echo '
'; } echo '
'; echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** @return array */ private function parse_ids(string $raw): array { if ($raw === '') { return []; } $ids = []; foreach (preg_split('/[\s,]+/', $raw) ?: [] as $p) { $id = (int) $p; if ($id > 0) { $ids[] = $id; } } return array_values(array_unique($ids)); } public function form($instance): void { $taxs = get_taxonomies(['public' => true], 'objects'); ?>

sanitize_text_field((string) ($new_instance['title'] ?? '')), 'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')), 'term_ids' => sanitize_text_field((string) ($new_instance['term_ids'] ?? '')), 'count' => max(1, min(12, (int) ($new_instance['count'] ?? 4))), 'columns' => max(1, min(3, (int) ($new_instance['columns'] ?? 1))), 'orderby' => $orderby, 'auto_terms' => max(1, min(4, (int) ($new_instance['auto_terms'] ?? 2))), ]; } }