diff --git a/src/AKSRT/Forum/Forum.php b/src/AKSRT/Forum/Forum.php index 5c504996..f04561e8 100644 --- a/src/AKSRT/Forum/Forum.php +++ b/src/AKSRT/Forum/Forum.php @@ -246,6 +246,40 @@ class Forum { $this->view_builder()->ajax_board_topics(); } + public function register_widget_routes(): void { + register_rest_route('aksrt/v1', '/forum/frontend/widgets/topics', [ + 'methods' => 'GET', + 'callback' => [$this, 'rest_widget_topics'], + 'permission_callback' => '__return_true', + ]); + } + + public function rest_widget_topics(\WP_REST_Request $request) { + if (!class_exists('\AKSRT\Widgets\WidgetForumTopicLists')) { + return new \WP_REST_Response(['success' => false, 'message' => 'widget unavailable'], 500); + } + $instance = [ + 'count' => max(1, min(30, (int) ($request->get_param('count') ?? 8))), + 'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'date')), + 'style' => sanitize_key((string) ($request->get_param('style') ?? 'mini')), + 'plate_id' => max(0, (int) ($request->get_param('plate_id') ?? 0)), + 'paginate' => sanitize_key((string) ($request->get_param('paginate') ?? 'ajax')), + ]; + $page = max(1, (int) ($request->get_param('page') ?? $request->get_param('paged') ?? 1)); + $payload = \AKSRT\Widgets\WidgetForumTopicLists::query_payload($instance, $page); + return new \WP_REST_Response([ + 'success' => true, + 'html' => (string) ($payload['html'] ?? ''), + 'paginate_html' => (string) ($payload['paginate_html'] ?? ''), + 'has_more' => !empty($payload['has_more']), + 'page' => (int) ($payload['page'] ?? $page), + 'max_pages' => (int) ($payload['max_pages'] ?? 1), + 'total' => (int) ($payload['total'] ?? 0), + ], 200); + } + + + public function render_board_cards(array $boards): void { $this->view_builder()->render_board_cards($boards); } @@ -396,6 +430,7 @@ class Forum { // Public plate/board topic list (sort tabs) add_action('wp_ajax_aksrt_forum_board_topics', [$this, 'ajax_board_topics']); add_action('wp_ajax_nopriv_aksrt_forum_board_topics', [$this, 'ajax_board_topics']); + add_action('rest_api_init', [$this, 'register_widget_routes']); add_action('admin_init', [$this, 'maybe_migrate_boards'], 25); add_filter('template_include', [$this, 'template_routing']); diff --git a/src/AKSRT/Widgets/WidgetForumTopicLists.php b/src/AKSRT/Widgets/WidgetForumTopicLists.php index 72d559e1..b12ae482 100644 --- a/src/AKSRT/Widgets/WidgetForumTopicLists.php +++ b/src/AKSRT/Widgets/WidgetForumTopicLists.php @@ -1,6 +1,6 @@ esc_html__('按排序/版块筛选展示论坛帖子。', 'aksrt'), + 'description' => esc_html__('按排序/版块筛选展示论坛帖子(支持 AJAX 加载更多)。', 'aksrt'), 'classname' => 'widget_aksrt_forum_topic_lists', ] ); } - public function widget($args, $instance): void { - if (!post_type_exists('aksrt_forum_topic')) { - return; - } - - $count = max(1, min(30, (int) ($instance['count'] ?? 8))); - $orderby = sanitize_key((string) ($instance['orderby'] ?? 'date')); - $style = sanitize_key((string) ($instance['style'] ?? 'mini')); + /** + * @param array $instance + * @param int $paged + * @return array + */ + public static function build_query_args(array $instance, int $paged = 1): array { + $count = max(1, min(30, (int) ($instance['count'] ?? 8))); + $orderby = sanitize_key((string) ($instance['orderby'] ?? 'date')); $plate_id = (int) ($instance['plate_id'] ?? 0); - $current_plate = !empty($instance['current_plate']); - - if ($current_plate) { - $resolved = $this->resolve_current_plate_id(); - if ($resolved <= 0) { - return; - } - $plate_id = $resolved; - } $query = [ 'post_type' => 'aksrt_forum_topic', 'post_status' => 'publish', 'posts_per_page' => $count, + 'paged' => max(1, $paged), 'order' => 'DESC', ]; @@ -59,35 +51,41 @@ class WidgetForumTopicLists extends \WP_Widget { case 'modified': $query['orderby'] = 'modified'; break; + case 'essence': + $query['meta_query'] = [[ + 'key' => '_aksrt_essence', + 'value' => '1', + ]]; + $query['orderby'] = 'date'; + break; default: $query['orderby'] = 'date'; } if ($plate_id > 0) { - $query['meta_query'] = [[ - 'key' => '_aksrt_plate_id', - 'value' => $plate_id, - ]]; + $query['meta_query'] = array_values(array_filter(array_merge( + isset($query['meta_query']) ? $query['meta_query'] : [], + [[ + 'key' => '_aksrt_plate_id', + 'value' => $plate_id, + ]] + ))); } - $q = new \WP_Query($query); + return $query; + } + + public static function render_items_html(\WP_Query $q, string $style = 'mini'): string { if (!$q->have_posts()) { - wp_reset_postdata(); - return; + 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 - } - $list_class = $style === 'detail' ? 'aksrt-ftopic-list is-detail' : 'aksrt-ftopic-list is-mini'; + ob_start(); echo '