esc_html__('展示论坛 plate 版块列表,支持排序/卡片/AJAX。', 'aksrt'), 'classname' => 'widget_aksrt_forum_plate_lists', ] ); } /** * @return array */ public static function build_query_args(array $instance): array { $limit = max(1, min(30, (int) ($instance['showposts'] ?? 8))); $orderby = sanitize_key((string) ($instance['orderby'] ?? 'menu_order')); $filter = sanitize_key((string) ($instance['filter'] ?? '')); $cat_raw = (string) ($instance['cat'] ?? ''); $cat_ids = array_values(array_filter(array_map('intval', preg_split('/[\s,]+/', $cat_raw) ?: []))); $query_args = [ 'post_type' => 'aksrt_forum_plate', 'post_status' => 'publish', 'posts_per_page' => $limit, 'order' => 'ASC', 'no_found_rows' => true, ]; switch ($orderby) { case 'date': $query_args['orderby'] = 'date'; $query_args['order'] = 'DESC'; break; case 'posts': $query_args['meta_key'] = '_aksrt_posts_count'; $query_args['orderby'] = 'meta_value_num'; $query_args['order'] = 'DESC'; break; case 'views': $query_args['meta_key'] = '_aksrt_views'; $query_args['orderby'] = 'meta_value_num'; $query_args['order'] = 'DESC'; break; case 'follow': $query_args['meta_key'] = '_aksrt_follow_count'; $query_args['orderby'] = 'meta_value_num'; $query_args['order'] = 'DESC'; break; default: $query_args['orderby'] = 'menu_order title'; } if ($cat_ids) { $query_args['tax_query'] = [[ 'taxonomy' => 'aksrt_plate_cat', 'field' => 'term_id', 'terms' => $cat_ids, ]]; } if ($filter === 'is_hot') { $query_args['meta_query'] = [[ 'key' => '_aksrt_is_hot', 'value' => '1', 'compare' => '=', ]]; } return $query_args; } public static function render_items_html(array $plates, string $style = 'default'): string { if (!$plates) { return ''; } ob_start(); $self = new self(); if ($style === 'card') { echo '
'; foreach ($plates as $post) { if ($post instanceof \WP_Post) { $self->render_card($post); } } echo '
'; } else { echo '
'; foreach ($plates as $post) { if ($post instanceof \WP_Post) { $self->render_row($post); } } echo '
'; } return (string) ob_get_clean(); } /** * @return array{html:string} */ public static function query_payload(array $instance): array { if (!post_type_exists('aksrt_forum_plate')) { return ['html' => '']; } $style = sanitize_key((string) ($instance['style'] ?? 'default')); $plates = get_posts(self::build_query_args($instance)); $html = self::render_items_html($plates ?: [], $style === 'card' ? 'card' : 'default'); if ($html === '') { $html = function_exists('aksrt_get_ajax_null') ? aksrt_get_ajax_null(__('暂无版块', 'aksrt')) : '

' . esc_html__('暂无版块', 'aksrt') . '

'; } return ['html' => $html]; } public function widget($args, $instance): void { if (!post_type_exists('aksrt_forum_plate')) { return; } $style = sanitize_key((string) ($instance['style'] ?? 'default')); $payload = self::query_payload($instance); if ($payload['html'] === '') { return; } 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 } // IAS-like: first paint is SSR; optional remote refresh via rest for customize. $rest = rest_url('aksrt/v1/forum/frontend/widgets/plates'); echo '
'; echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '
'; echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } public function render_row(\WP_Post $post): void { $id = (int) $post->ID; $url = get_permalink($id); $thumb = get_the_post_thumbnail_url($id, 'thumbnail'); $icon = (string) get_post_meta($id, '_aksrt_icon', true); $count = (int) get_post_meta($id, '_aksrt_posts_count', true); $desc = $post->post_excerpt !== '' ? $post->post_excerpt : wp_trim_words(wp_strip_all_tags($post->post_content), 18); echo ''; echo '
'; if ($thumb) { echo ''; } elseif ($icon !== '') { echo ''; } else { echo ''; } echo '
'; echo '
'; echo '
' . esc_html(get_the_title($post)) . '
'; if ($desc !== '') { echo '
' . esc_html($desc) . '
'; } echo '
' . esc_html(sprintf(/* translators: %d topic count */ __('%d 帖', 'aksrt'), $count)) . '
'; echo '
'; } public function render_card(\WP_Post $post): void { $id = (int) $post->ID; $url = get_permalink($id); $thumb = get_the_post_thumbnail_url($id, 'medium'); $count = (int) get_post_meta($id, '_aksrt_posts_count', true); $follow = (int) get_post_meta($id, '_aksrt_follow_count', true); echo ''; echo '
'; echo '
' . esc_html(get_the_title($post)) . '
'; echo '
'; echo '' . esc_html(sprintf(__('%d 帖', 'aksrt'), $count)) . ''; echo '' . esc_html(sprintf(__('%d 关注', 'aksrt'), $follow)) . ''; echo '
'; } public function form($instance): void { ?>

sanitize_text_field((string) ($new_instance['title'] ?? '')), 'showposts' => max(1, min(30, (int) ($new_instance['showposts'] ?? 8))), 'orderby' => $orderby, 'style' => ($new_instance['style'] ?? '') === 'card' ? 'card' : 'default', 'filter' => ($new_instance['filter'] ?? '') === 'is_hot' ? 'is_hot' : '', 'cat' => sanitize_text_field((string) ($new_instance['cat'] ?? '')), ]; } }