diff --git a/functions.php b/functions.php index 684ca546..a8463623 100644 --- a/functions.php +++ b/functions.php @@ -234,6 +234,10 @@ if (class_exists('\AKSRT\Core\DocsPresenter')) { if (class_exists('\AKSRT\Core\HomeModules')) { \AKSRT\Core\HomeModules::get_instance()->init(); } +// Public widget list REST (posts / tab-posts ajax) +if (class_exists('\AKSRT\Core\WidgetAjax')) { + \AKSRT\Core\WidgetAjax::get_instance()->init(); +} if (class_exists('\AKSRT\Content\Visibility')) { \AKSRT\Content\Visibility::get_instance()->init(); } diff --git a/src/AKSRT/Core/WidgetAjax.php b/src/AKSRT/Core/WidgetAjax.php new file mode 100644 index 00000000..7fd0c9b9 --- /dev/null +++ b/src/AKSRT/Core/WidgetAjax.php @@ -0,0 +1,92 @@ + 'GET', + 'callback' => [$this, 'rest_main_posts'], + 'permission_callback' => '__return_true', + ]); + register_rest_route('aksrt/v1', '/widgets/tab-posts', [ + 'methods' => 'GET', + 'callback' => [$this, 'rest_tab_posts'], + 'permission_callback' => '__return_true', + ]); + } + + public function rest_main_posts(\WP_REST_Request $request) { + if (!class_exists('\AKSRT\Widgets\WidgetMainPosts')) { + return new \WP_REST_Response(['success' => false, 'message' => 'unavailable'], 500); + } + $instance = [ + 'count' => max(1, min(30, (int) ($request->get_param('count') ?? 6))), + 'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'date')), + 'cat' => max(0, (int) ($request->get_param('cat') ?? 0)), + 'limit_day' => max(0, (int) ($request->get_param('limit_day') ?? 0)), + 'style' => sanitize_key((string) ($request->get_param('style') ?? 'list')), + 'show_thumb' => $request->get_param('show_thumb') === null ? 1 : (int) $request->get_param('show_thumb'), + 'show_meta' => $request->get_param('show_meta') === null ? 1 : (int) $request->get_param('show_meta'), + 'show_number' => (int) ($request->get_param('show_number') ?? 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\WidgetMainPosts::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 rest_tab_posts(\WP_REST_Request $request) { + if (!class_exists('\AKSRT\Widgets\TabPostsWidget')) { + return new \WP_REST_Response(['success' => false, 'message' => 'unavailable'], 500); + } + $default_count = max(1, min(20, (int) ($request->get_param('count') ?? 5))); + $tab = [ + 'title' => '', + 'category_id' => max(0, (int) ($request->get_param('cat') ?? $request->get_param('category_id') ?? 0)), + 'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'date')), + 'count' => max(0, min(20, (int) ($request->get_param('tab_count') ?? 0))), + 'enabled' => true, + ]; + $html = \AKSRT\Widgets\TabPostsWidget::render_tab_html($tab, $default_count); + if ($html === '') { + $html = function_exists('aksrt_get_ajax_null') + ? aksrt_get_ajax_null(__('暂无文章', 'aksrt')) + : '
'; + } else { + $html = ''; + } + return new \WP_REST_Response([ + 'success' => true, + 'html' => $html, + ], 200); + } +} diff --git a/src/AKSRT/Widgets/WidgetMainPosts.php b/src/AKSRT/Widgets/WidgetMainPosts.php index f2ce4ff8..8469ed6b 100644 --- a/src/AKSRT/Widgets/WidgetMainPosts.php +++ b/src/AKSRT/Widgets/WidgetMainPosts.php @@ -1,6 +1,6 @@ esc_html__('卡片/迷你/列表样式的文章模块。', 'aksrt'), + 'description' => esc_html__('卡片/迷你/列表样式的文章模块(支持 AJAX)。', 'aksrt'), 'classname' => 'widget_aksrt_main_posts', ] ); } - public function widget($args, $instance): void { + /** + * @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'] ?? 6))); - $style = sanitize_key((string) ($instance['style'] ?? 'list')); - if (!in_array($style, ['list', 'card', 'mini'], true)) { - $style = 'list'; - } $orderby = sanitize_key((string) ($instance['orderby'] ?? 'date')); $cat = (int) ($instance['cat'] ?? 0); $limit_day = max(0, (int) ($instance['limit_day'] ?? 0)); - $show_thumb = !isset($instance['show_thumb']) || !empty($instance['show_thumb']); - $show_meta = !isset($instance['show_meta']) || !empty($instance['show_meta']); - $show_number = !empty($instance['show_number']); $query = [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => $count, + 'paged' => max(1, $paged), 'ignore_sticky_posts' => true, - 'no_found_rows' => true, ]; if ($cat > 0) { $query['cat'] = $cat; @@ -51,39 +49,48 @@ class WidgetMainPosts extends \WP_Widget { switch ($orderby) { case 'views': $query['meta_key'] = 'aksrt_post_views'; - $query['orderby'] = 'meta_value_num'; - $query['order'] = 'DESC'; + $query['orderby'] = 'meta_value_num'; + $query['order'] = 'DESC'; break; case 'comments': $query['orderby'] = 'comment_count'; - $query['order'] = 'DESC'; + $query['order'] = 'DESC'; + break; + case 'likes': + $query['meta_key'] = '_aksrt_like_count'; + $query['orderby'] = 'meta_value_num'; + $query['order'] = 'DESC'; break; case 'rand': $query['orderby'] = 'rand'; break; case 'modified': $query['orderby'] = 'modified'; - $query['order'] = 'DESC'; + $query['order'] = 'DESC'; break; default: $query['orderby'] = 'date'; - $query['order'] = 'DESC'; + $query['order'] = 'DESC'; } + return $query; + } - $q = new \WP_Query($query); + public static function render_items_html(\WP_Query $q, array $instance): 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 + $style = sanitize_key((string) ($instance['style'] ?? 'list')); + if (!in_array($style, ['list', 'card', 'mini'], true)) { + $style = 'list'; } + $show_thumb = !isset($instance['show_thumb']) || !empty($instance['show_thumb']); + $show_meta = !isset($instance['show_meta']) || !empty($instance['show_meta']); + $show_number = !empty($instance['show_number']); + $start = max(0, (int) ($instance['_start_index'] ?? 0)); - echo '' . esc_html__('暂无文章', 'aksrt') . '
'; + } + $max_pages = max(1, (int) $q->max_num_pages); + $total = (int) $q->found_posts; + $has_more = $page < $max_pages; + $paginate_html = ''; + if ($paginate === 'ajax' && $has_more) { + $next = add_query_arg(array_filter([ + 'page' => $page + 1, + 'count' => $count, + 'orderby' => sanitize_key((string) ($instance['orderby'] ?? 'date')), + 'cat' => (int) ($instance['cat'] ?? 0), + 'limit_day' => (int) ($instance['limit_day'] ?? 0), + 'style' => sanitize_key((string) ($instance['style'] ?? 'list')), + 'show_thumb' => !isset($instance['show_thumb']) || !empty($instance['show_thumb']) ? 1 : 0, + 'show_meta' => !isset($instance['show_meta']) || !empty($instance['show_meta']) ? 1 : 0, + 'show_number' => !empty($instance['show_number']) ? 1 : 0, + 'paginate' => 'ajax', + ]), rest_url('aksrt/v1/widgets/posts')); + $paginate_html = function_exists('aksrt_get_ajax_next_paginate') + ? aksrt_get_ajax_next_paginate($total, $page, $count, $next) + : '+ +
@@ -189,7 +281,7 @@ class WidgetMainPosts extends \WP_Widget {
$style = 'list';
}
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date'));
- if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'rand'], true)) {
+ if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'likes', 'rand'], true)) {
$orderby = 'date';
}
return [
@@ -199,6 +291,7 @@ class WidgetMainPosts extends \WP_Widget {
'orderby' => $orderby,
'cat' => max(0, (int) ($new_instance['cat'] ?? 0)),
'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)),
+ 'paginate' => sanitize_key((string) ($new_instance['paginate'] ?? 'none')) === 'ajax' ? 'ajax' : 'none',
'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0,
'show_meta' => !empty($new_instance['show_meta']) ? 1 : 0,
'show_number' => !empty($new_instance['show_number']) ? 1 : 0,