'widget_aksrt_category_recommend', 'description' => esc_html__('分类推荐卡片区块,可挂载到首页内容挂载区。', 'aksrt'), 'customize_selective_refresh' => true, ] ); } public static function render_html(array $instance): string { $category_ids = aksrt_home_widget_normalize_category_ids($instance['category_ids'] ?? [], 4); $posts_per_cat = max(1, min(8, (int) ($instance['posts_per_category'] ?? 5))); $columns = max(1, min(4, (int) ($instance['columns'] ?? 2))); $show_views = ! empty($instance['show_views']); $show_description = ! empty($instance['show_description']); $show_dates = ! empty($instance['show_dates']); $show_more = ! empty($instance['show_more']); if (empty($category_ids)) { $category_ids = aksrt_home_widget_fallback_category_ids(4); } $cards = self::build_cards_static($category_ids, $posts_per_cat, $show_views, $show_description); if (empty($cards)) { return function_exists('aksrt_get_widget_null') ? aksrt_get_widget_null(__('暂无推荐分类', 'aksrt')) : '

' . esc_html__('暂无推荐分类', 'aksrt') . '

'; } $lazy = aksrt_home_widget_get_lazyload_args(); ob_start(); printf('
', (int) $columns); foreach ($cards as $card) { $cover = (string) ($card['cover'] ?? ''); $link = (string) ($card['link'] ?? ''); $name = (string) ($card['name'] ?? ''); $badge = sprintf(_n('%d 篇文章', '%d 篇文章', (int) $card['count'], 'aksrt'), (int) $card['count']); $more = ''; if ($show_views && (int) $card['views'] > 0) { $v = function_exists('aksrt_format_number') ? aksrt_format_number((int) $card['views']) : number_format_i18n((int) $card['views']); $more = ' ' . esc_html((string) $v) . ''; } echo '
'; if (function_exists('aksrt_graphic_card') && $cover !== '') { echo aksrt_graphic_card([ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 'type' => 'style-2', 'class' => 'aksrt-category-recommend__hero mb10', 'img' => $cover, 'alt' => $name, 'link' => ['url' => $link], 'text1' => $name, 'text2' => $show_description ? (string) $card['description'] : '', 'text3' => $badge, 'more' => $more, 'lazy' => true, ]); } else { echo '
'; echo ''; if ($lazy['enabled']) { echo ''; echo '' . esc_attr($name) . ''; } else { echo '' . esc_attr($name) . ''; } echo ''; echo '' . esc_html($badge) . ''; echo $more; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '
'; echo '
'; echo '

' . esc_html($name) . '

'; if ($show_description && $card['description'] !== '') { echo '

' . esc_html((string) $card['description']) . '

'; } echo '
'; } echo '
'; // Prefer shared mini list when post IDs available. if (!empty($card['post_ids']) && function_exists('aksrt_render_mini_list')) { $q = new \WP_Query([ 'post_type' => 'any', 'post__in' => array_map('intval', (array) $card['post_ids']), 'orderby' => 'post__in', 'posts_per_page' => count((array) $card['post_ids']), 'ignore_sticky_posts' => true, 'no_found_rows' => true, ]); echo '
'; aksrt_render_mini_list($q, ['context' => 'widget', 'show_thumb' => true, 'show_meta' => $show_dates]); echo '
'; wp_reset_postdata(); } else { echo '
    '; foreach ($card['posts'] as $post_item) { echo '
  • '; echo '' . esc_html($post_item['title']) . ''; if ($show_dates && $post_item['date'] !== '') { echo '' . esc_html($post_item['date']) . ''; } echo '
  • '; } echo '
'; } if ($show_more) { echo ''; } echo '
'; } echo '
'; return (string) ob_get_clean(); } public function widget($args, $instance): void { $title = apply_filters('widget_title', $instance['title'] ?? '', $instance, $this->id_base); $title = $title !== '' ? $title : __('分类推荐', 'aksrt'); $html = self::render_html($instance); echo $args['before_widget']; echo '
'; aksrt_home_widget_render_header($title); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '
'; echo $args['after_widget']; } public function form($instance): void { $title = (string) ($instance['title'] ?? __('分类推荐', 'aksrt')); $category_ids = aksrt_home_widget_normalize_category_ids($instance['category_ids'] ?? [], 4); $posts_per_cat = (int) ($instance['posts_per_category'] ?? 5); $columns = (int) ($instance['columns'] ?? 2); $show_views = ! empty($instance['show_views']); $show_description = ! array_key_exists('show_description', $instance) || ! empty($instance['show_description']); $show_dates = ! array_key_exists('show_dates', $instance) || ! empty($instance['show_dates']); $show_more = ! array_key_exists('show_more', $instance) || ! empty($instance['show_more']); $categories = aksrt_home_widget_available_categories(); ?>

id="get_field_id('show_views')); ?>" name="get_field_name('show_views')); ?>" value="1">

id="get_field_id('show_description')); ?>" name="get_field_name('show_description')); ?>" value="1">

id="get_field_id('show_dates')); ?>" name="get_field_name('show_dates')); ?>" value="1">

id="get_field_id('show_more')); ?>" name="get_field_name('show_more')); ?>" value="1">

sanitize_text_field($new_instance['title'] ?? ''), 'category_ids' => aksrt_home_widget_normalize_category_ids($new_instance['category_ids'] ?? [], 4), 'posts_per_category' => max(1, min(8, absint($new_instance['posts_per_category'] ?? 5))), 'columns' => max(1, min(4, absint($new_instance['columns'] ?? 2))), 'show_views' => ! empty($new_instance['show_views']) ? 1 : 0, 'show_description' => ! empty($new_instance['show_description']) ? 1 : 0, 'show_dates' => ! empty($new_instance['show_dates']) ? 1 : 0, 'show_more' => ! empty($new_instance['show_more']) ? 1 : 0, ]; } /** * Build category recommend cards. * * @param array $category_ids Category ids. * @param int $posts_per_cat Post count per category. * @param bool $show_views Whether to calculate views. * @param bool $show_description Whether to fetch description. * @return array> */ public static function build_cards_static(array $category_ids, int $posts_per_cat, bool $show_views, bool $show_description): array { $cards = []; foreach ($category_ids as $category_id) { $term = get_term($category_id, 'category'); if (! $term || is_wp_error($term)) { continue; } $posts = get_posts([ 'post_type' => aksrt_home_widget_post_types(), 'cat' => $category_id, 'posts_per_page' => $posts_per_cat, 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC', 'no_found_rows' => true, ]); $post_items = []; foreach ($posts as $post) { $post_items[] = [ 'title' => get_the_title($post->ID), 'link' => get_permalink($post->ID), 'date' => function_exists('aksrt_time_ago') ? aksrt_time_ago($post->post_date) : get_the_date('Y-m-d', $post->ID), ]; } $cards[] = [ 'name' => $term->name, 'link' => get_category_link($category_id), 'cover' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_category_cover_url($category_id) : (get_template_directory_uri() . '/assets/img/placeholder.svg'), 'description' => $show_description && class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_category_recommend_desc($category_id) : ($show_description ? (string) $term->description : ''), 'count' => (int) $term->count, 'views' => $show_views && function_exists('aksrt_get_category_total_views') ? aksrt_get_category_total_views($category_id) : 0, 'posts' => $post_items, ]; } return $cards; } }