feat(widgets): hot posts AJAX load-more + REST expansion

HotPostsWidget query_payload; WidgetAjax routes for hot/oneline/
comments/users/forum topics/terms.
This commit is contained in:
2026-07-20 21:58:32 +08:00
parent 6a6154900b
commit 75e046ee7f
2 changed files with 324 additions and 190 deletions
+131 -49
View File
@@ -1,6 +1,6 @@
<?php
/**
* Public widget list REST endpoints (posts / tab-posts).
* Public widget list REST endpoints.
*
* @package AKSRT
*/
@@ -24,31 +24,30 @@ class WidgetAjax {
}
public function register_routes(): void {
register_rest_route('aksrt/v1', '/widgets/posts', [
'methods' => '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',
]);
register_rest_route('aksrt/v1', '/widgets/paid-posts', [
'methods' => 'GET',
'callback' => [$this, 'rest_paid_posts'],
'permission_callback' => '__return_true',
]);
register_rest_route('aksrt/v1', '/widgets/category-tabs', [
'methods' => 'GET',
'callback' => [$this, 'rest_category_tabs'],
'permission_callback' => '__return_true',
]);
$routes = [
'/widgets/posts' => 'rest_main_posts',
'/widgets/tab-posts' => 'rest_tab_posts',
'/widgets/paid-posts' => 'rest_paid_posts',
'/widgets/category-tabs' => 'rest_category_tabs',
'/widgets/hot-posts' => 'rest_hot_posts',
'/widgets/oneline-posts' => 'rest_oneline_posts',
'/widgets/recent-comments'=> 'rest_recent_comments',
'/widgets/user-lists' => 'rest_user_lists',
'/widgets/forum-topics' => 'rest_forum_topics',
'/widgets/forum-terms' => 'rest_forum_terms',
];
foreach ($routes as $path => $cb) {
register_rest_route('aksrt/v1', $path, [
'methods' => 'GET',
'callback' => [$this, $cb],
'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);
return $this->fail();
}
$instance = [
'count' => max(1, min(30, (int) ($request->get_param('count') ?? 6))),
@@ -62,21 +61,12 @@ class WidgetAjax {
'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);
return $this->payload(\AKSRT\Widgets\WidgetMainPosts::query_payload($instance, $page), $page);
}
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);
return $this->fail();
}
$default_count = max(1, min(20, (int) ($request->get_param('count') ?? 5)));
$tab = [
@@ -94,15 +84,12 @@ class WidgetAjax {
} else {
$html = '<div class="widget-tab-posts__list widget-tab-posts__list--mini aksrt-main-posts style-mini">' . $html . '</div>';
}
return new \WP_REST_Response([
'success' => true,
'html' => $html,
], 200);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
}
public function rest_paid_posts(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\WidgetPaidPosts')) {
return new \WP_REST_Response(['success' => false, 'message' => 'unavailable'], 500);
return $this->fail();
}
$instance = [
'count' => max(1, min(20, (int) ($request->get_param('count') ?? 6))),
@@ -110,16 +97,7 @@ class WidgetAjax {
'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\WidgetPaidPosts::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);
return $this->payload(\AKSRT\Widgets\WidgetPaidPosts::query_payload($instance, $page), $page);
}
public function rest_category_tabs(\WP_REST_Request $request) {
@@ -152,7 +130,111 @@ class WidgetAjax {
echo '</ul>';
}
wp_reset_postdata();
$html = (string) ob_get_clean();
return new \WP_REST_Response(['success' => true, 'html' => (string) ob_get_clean()], 200);
}
public function rest_hot_posts(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\HotPostsWidget')) {
return $this->fail();
}
$instance = [
'count' => max(1, min(20, (int) ($request->get_param('count') ?? 5))),
'order_by' => sanitize_key((string) ($request->get_param('order_by') ?? 'views')),
'days' => max(0, (int) ($request->get_param('days') ?? 30)),
'show_thumb' => $request->get_param('show_thumb') === null ? 1 : (int) $request->get_param('show_thumb'),
'paginate' => sanitize_key((string) ($request->get_param('paginate') ?? 'ajax')),
];
$page = max(1, (int) ($request->get_param('page') ?? 1));
return $this->payload(\AKSRT\Widgets\HotPostsWidget::query_payload($instance, $page), $page);
}
public function rest_oneline_posts(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\WidgetOnelinePosts')) {
return $this->fail();
}
$instance = [
'count' => max(1, min(20, (int) ($request->get_param('count') ?? 8))),
'style' => sanitize_key((string) ($request->get_param('style') ?? 'card')),
'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)),
];
$html = \AKSRT\Widgets\WidgetOnelinePosts::render_html($instance);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
}
public function rest_recent_comments(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\RecentCommentsWidget')) {
return $this->fail();
}
$instance = [
'count' => max(1, min(20, (int) ($request->get_param('count') ?? 5))),
'show_avatar' => $request->get_param('show_avatar') === null ? 1 : (int) $request->get_param('show_avatar'),
'outpost' => max(0, (int) ($request->get_param('outpost') ?? 0)),
'outer' => sanitize_text_field((string) ($request->get_param('outer') ?? '')),
];
$html = \AKSRT\Widgets\RecentCommentsWidget::render_html($instance);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
}
public function rest_user_lists(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\WidgetUserLists')) {
return $this->fail();
}
$instance = [
'number' => max(1, min(50, (int) ($request->get_param('number') ?? 8))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'user_registered')),
'order' => sanitize_key((string) ($request->get_param('order') ?? 'DESC')),
'include' => sanitize_text_field((string) ($request->get_param('include') ?? '')),
'exclude' => sanitize_text_field((string) ($request->get_param('exclude') ?? '')),
'hide_box' => (int) ($request->get_param('hide_box') ?? 0),
];
$html = \AKSRT\Widgets\WidgetUserLists::render_html($instance);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
}
public function rest_forum_topics(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\WidgetForumHotTopics')) {
return $this->fail();
}
$instance = [
'count' => max(1, min(20, (int) ($request->get_param('count') ?? 5))),
'period' => sanitize_key((string) ($request->get_param('period') ?? 'week')),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'views')),
'paginate' => sanitize_key((string) ($request->get_param('paginate') ?? 'ajax')),
];
$page = max(1, (int) ($request->get_param('page') ?? 1));
return $this->payload(\AKSRT\Widgets\WidgetForumHotTopics::query_payload($instance, $page), $page);
}
public function rest_forum_terms(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\WidgetForumTopicTerms')) {
return $this->fail();
}
$instance = [
'number' => max(1, min(40, (int) ($request->get_param('number') ?? 12))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'count')),
'hide_empty' => $request->get_param('hide_empty') === null ? 1 : (int) $request->get_param('hide_empty'),
'include' => sanitize_text_field((string) ($request->get_param('include') ?? '')),
'style' => sanitize_key((string) ($request->get_param('style') ?? 'mini')),
];
$html = \AKSRT\Widgets\WidgetForumTopicTerms::render_html($instance);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
}
private function fail(): \WP_REST_Response {
return new \WP_REST_Response(['success' => false, 'message' => 'unavailable'], 500);
}
private function payload(array $payload, int $page): \WP_REST_Response {
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);
}
}
+193 -141
View File
@@ -1,5 +1,7 @@
<?php
/**
* Hot posts ranking (zibll hot posts + ajax).
*
* @package AKSRT
*/
@@ -9,151 +11,201 @@ defined('ABSPATH') || exit;
class HotPostsWidget extends \WP_Widget {
public function __construct() {
parent::__construct(
'aksrt_hot_posts',
esc_html__('AKSRT 热榜文章', 'aksrt'),
[
'description' => esc_html__('按浏览量/评论数/点赞数排序的热门文章列表', 'aksrt'),
'customize_selective_refresh' => true,
]
);
}
public function __construct() {
parent::__construct(
'aksrt_hot_posts',
esc_html__('AKSRT 热榜文章', 'aksrt'),
[
'description' => esc_html__('按浏览量/评论数/点赞数排序的热门文章列表', 'aksrt'),
'customize_selective_refresh' => true,
]
);
}
public function widget($args, $instance): void {
echo $args['before_widget'];
public static function build_query_args(array $instance, int $paged = 1): array {
$count = max(1, min(20, (int) ($instance['count'] ?? 5)));
$order_by = sanitize_key((string) ($instance['order_by'] ?? 'views'));
$days = max(0, (int) ($instance['days'] ?? 30));
$query_args = [
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $count,
'paged' => max(1, $paged),
'ignore_sticky_posts' => true,
];
if ($days > 0 && $days < 365) {
$query_args['date_query'] = [['after' => $days . ' days ago']];
}
switch ($order_by) {
case 'comments':
$query_args['orderby'] = 'comment_count';
$query_args['order'] = 'DESC';
break;
case 'likes':
$query_args['meta_key'] = '_aksrt_like_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
case 'favorites':
$query_args['meta_key'] = '_aksrt_favorite_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
case 'downloads':
$query_args['meta_key'] = '_aksrt_res_download_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
case 'views':
default:
$query_args['meta_key'] = 'aksrt_post_views';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
}
return $query_args;
}
$title = apply_filters('widget_title', $instance['title'] ?? __('热门文章', 'aksrt'), $instance, $this->id_base);
$count = absint($instance['count'] ?? 5);
$order_by = $instance['order_by'] ?? 'views';
$days = absint($instance['days'] ?? 30);
$show_thumb = !empty($instance['show_thumb']);
public static function render_items_html(\WP_Query $query, array $instance, int $start = 0): string {
if (!$query->have_posts()) {
return '';
}
$show_thumb = !empty($instance['show_thumb']);
ob_start();
$index = $start;
while ($query->have_posts()) {
$query->the_post();
$index++;
$rank_class = $index <= 3 ? ' rank-top' : '';
$views = (int) get_post_meta(get_the_ID(), 'aksrt_post_views', true);
?>
<div class="hot-post-item ajax-item <?php echo esc_attr($rank_class); ?>">
<span class="hot-post-item__rank"><?php echo esc_html((string) $index); ?></span>
<?php if ($show_thumb) :
$thumb = get_the_post_thumbnail_url(get_the_ID(), 'thumbnail');
?>
<a class="hot-post-item__thumb<?php echo $thumb ? '' : ' is-empty'; ?>" href="<?php the_permalink(); ?>">
<?php if ($thumb) : ?><img src="<?php echo esc_url($thumb); ?>" alt="" loading="lazy" /><?php endif; ?>
</a>
<?php endif; ?>
<div class="hot-post-item__info">
<a href="<?php the_permalink(); ?>" class="hot-post-item__title"><?php the_title(); ?></a>
<div class="hot-post-item__meta">
<span><i class="fas fa-eye" aria-hidden="true"></i> <?php echo esc_html(function_exists('aksrt_format_number') ? aksrt_format_number($views) : (string) $views); ?></span>
<span class="hot-post-item__time"><?php echo esc_html(human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt')); ?></span>
</div>
</div>
</div>
<?php
}
wp_reset_postdata();
return (string) ob_get_clean();
}
if ($title) {
echo $args['before_title'] . esc_html($title) . $args['after_title'];
}
/**
* @return array{html:string,paginate_html:string,has_more:bool,page:int,max_pages:int,total:int}
*/
public static function query_payload(array $instance, int $page = 1): array {
$page = max(1, $page);
$count = max(1, min(20, (int) ($instance['count'] ?? 5)));
$paginate = sanitize_key((string) ($instance['paginate'] ?? 'ajax'));
$q = new \WP_Query(self::build_query_args($instance, $page));
$items = self::render_items_html($q, $instance, ($page - 1) * $count);
$html = $items !== '' ? '<div class="widget-hot-posts widget-hot-posts--mini">' . $items . '</div>' : '';
if ($html === '' && $page === 1) {
$html = function_exists('aksrt_get_widget_null')
? aksrt_get_widget_null(__('暂无热门文章', 'aksrt'))
: '<p class="widget-empty ajax-item">' . esc_html__('暂无热门文章', 'aksrt') . '</p>';
}
$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([
'page' => $page + 1,
'count' => $count,
'order_by' => sanitize_key((string) ($instance['order_by'] ?? 'views')),
'days' => max(0, (int) ($instance['days'] ?? 30)),
'show_thumb' => !empty($instance['show_thumb']) ? 1 : 0,
'paginate' => 'ajax',
], rest_url('aksrt/v1/widgets/hot-posts'));
$paginate_html = function_exists('aksrt_get_ajax_next_paginate')
? aksrt_get_ajax_next_paginate($total, $page, $count, $next)
: '<div class="text-center theme-pagination ajax-pag"><div class="next-page ajax-next"><a href="' . esc_url($next) . '">' . esc_html__('加载更多', 'aksrt') . '</a></div></div>';
} else {
$paginate_html = '<div class="ajax-pag hide"><div class="next-page ajax-next"><a href="#"></a></div></div>';
}
return compact('html', 'paginate_html', 'has_more', 'page', 'max_pages', 'total');
}
$query_args = [
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $count,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
];
public function widget($args, $instance): void {
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', $instance['title'] ?? __('热门文章', 'aksrt'), $instance, $this->id_base);
if ($title) {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$instance['paginate'] = sanitize_key((string) ($instance['paginate'] ?? 'ajax'));
$payload = self::query_payload($instance, 1);
$rest = rest_url('aksrt/v1/widgets/hot-posts');
echo '<div class="ajaxpager" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '">';
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
echo '</div>';
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
if ($days > 0 && $days < 365) {
$query_args['date_query'] = [['after' => $days . ' days ago']];
}
public function form($instance): void {
$title = $instance['title'] ?? __('热门文章', 'aksrt');
$count = (int) ($instance['count'] ?? 5);
$order_by = $instance['order_by'] ?? 'views';
$days = (int) ($instance['days'] ?? 30);
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr((string) $title); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('count')); ?>"><?php esc_html_e('显示数量:', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id('count')); ?>" name="<?php echo esc_attr($this->get_field_name('count')); ?>" type="number" min="1" max="20" value="<?php echo (int) $count; ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('order_by')); ?>"><?php esc_html_e('排序方式:', 'aksrt'); ?></label>
<select class="widefat" id="<?php echo esc_attr($this->get_field_id('order_by')); ?>" name="<?php echo esc_attr($this->get_field_name('order_by')); ?>">
<option value="views" <?php selected($order_by, 'views'); ?>><?php esc_html_e('浏览量', 'aksrt'); ?></option>
<option value="comments" <?php selected($order_by, 'comments'); ?>><?php esc_html_e('评论数', 'aksrt'); ?></option>
<option value="likes" <?php selected($order_by, 'likes'); ?>><?php esc_html_e('点赞数', 'aksrt'); ?></option>
<option value="favorites" <?php selected($order_by, 'favorites'); ?>><?php esc_html_e('收藏数', 'aksrt'); ?></option>
<option value="downloads" <?php selected($order_by, 'downloads'); ?>><?php esc_html_e('下载数', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('days')); ?>"><?php esc_html_e('时间范围(天,0=不限):', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id('days')); ?>" name="<?php echo esc_attr($this->get_field_name('days')); ?>" type="number" min="0" max="365" value="<?php echo (int) $days; ?>">
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_thumb')); ?>" value="1" <?php checked(!empty($instance['show_thumb'])); ?>> <?php esc_html_e('显示缩略图', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('分页', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('paginate')); ?>">
<option value="ajax" <?php selected(($instance['paginate'] ?? 'ajax'), 'ajax'); ?>><?php esc_html_e('AJAX', 'aksrt'); ?></option>
<option value="none" <?php selected(($instance['paginate'] ?? ''), 'none'); ?>><?php esc_html_e('无', 'aksrt'); ?></option>
</select>
</label>
</p>
<?php
}
switch ($order_by) {
case 'comments':
$query_args['orderby'] = 'comment_count';
$query_args['order'] = 'DESC';
break;
case 'likes':
$query_args['meta_key'] = '_aksrt_like_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
case 'favorites':
$query_args['meta_key'] = '_aksrt_favorite_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
case 'downloads':
$query_args['meta_key'] = '_aksrt_res_download_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
case 'views':
default:
$query_args['meta_key'] = 'aksrt_post_views';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = 'DESC';
break;
}
$query = new \WP_Query($query_args);
if ($query->have_posts()) {
echo '<div class="widget-hot-posts widget-hot-posts--mini">';
$index = 0;
while ($query->have_posts()) {
$query->the_post();
$index++;
$rank_class = $index <= 3 ? ' rank-top' : '';
$views = (int) get_post_meta(get_the_ID(), 'aksrt_post_views', true);
?>
<div class="hot-post-item <?php echo esc_attr($rank_class); ?>">
<span class="hot-post-item__rank"><?php echo esc_html($index); ?></span>
<?php if ($show_thumb) :
$thumb = get_the_post_thumbnail_url(get_the_ID(), 'thumbnail');
?>
<a class="hot-post-item__thumb<?php echo $thumb ? '' : ' is-empty'; ?>" href="<?php the_permalink(); ?>">
<?php if ($thumb) : ?><img src="<?php echo esc_url($thumb); ?>" alt="" loading="lazy" /><?php endif; ?>
</a>
<?php endif; ?>
<div class="hot-post-item__info">
<a href="<?php the_permalink(); ?>" class="hot-post-item__title"><?php the_title(); ?></a>
<div class="hot-post-item__meta">
<span><i class="fas fa-eye" aria-hidden="true"></i> <?php echo esc_html(function_exists('aksrt_format_number') ? aksrt_format_number($views) : (string) $views); ?></span>
<span class="hot-post-item__time"><?php echo esc_html(human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt')); ?></span>
</div>
</div>
</div>
<?php
}
echo '</div>';
wp_reset_postdata();
} else {
echo function_exists('aksrt_get_widget_null') ? aksrt_get_widget_null(__('暂无热门文章', 'aksrt')) : '<p class="widget-empty">' . esc_html__('暂无热门文章', 'aksrt') . '</p>';
}
echo $args['after_widget'];
}
public function form($instance): void {
$title = $instance['title'] ?? __('热门文章', 'aksrt');
$count = (int) ($instance['count'] ?? 5);
$order_by = $instance['order_by'] ?? 'views';
$days = (int) ($instance['days'] ?? 30);
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id('count'); ?>"><?php esc_html_e('显示数量:', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo $this->get_field_id('count'); ?>" name="<?php echo $this->get_field_name('count'); ?>" type="number" min="1" max="20" value="<?php echo $count; ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id('order_by'); ?>"><?php esc_html_e('排序方式:', 'aksrt'); ?></label>
<select class="widefat" id="<?php echo $this->get_field_id('order_by'); ?>" name="<?php echo $this->get_field_name('order_by'); ?>">
<option value="views" <?php selected($order_by, 'views'); ?>><?php esc_html_e('浏览量', 'aksrt'); ?></option>
<option value="comments" <?php selected($order_by, 'comments'); ?>><?php esc_html_e('评论数', 'aksrt'); ?></option>
<option value="likes" <?php selected($order_by, 'likes'); ?>><?php esc_html_e('点赞数', 'aksrt'); ?></option>
<option value="favorites" <?php selected($order_by, 'favorites'); ?>><?php esc_html_e('收藏数', 'aksrt'); ?></option>
<option value="downloads" <?php selected($order_by, 'downloads'); ?>><?php esc_html_e('下载数', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="<?php echo $this->get_field_id('days'); ?>"><?php esc_html_e('时间范围(天,0=不限):', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo $this->get_field_id('days'); ?>" name="<?php echo $this->get_field_name('days'); ?>" type="number" min="0" max="365" value="<?php echo $days; ?>">
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_thumb')); ?>" value="1" <?php checked(!empty($instance['show_thumb'])); ?>> <?php esc_html_e('显示缩略图', 'aksrt'); ?></label>
</p>
<?php
}
public function update($new_instance, $old_instance): array {
return [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'count' => absint($new_instance['count'] ?? 5),
'order_by' => in_array($new_instance['order_by'] ?? '', ['views', 'comments', 'likes', 'favorites', 'downloads'], true) ? $new_instance['order_by'] : 'views',
'days' => absint($new_instance['days'] ?? 30),
'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0,
];
}
public function update($new_instance, $old_instance): array {
return [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'count' => absint($new_instance['count'] ?? 5),
'order_by' => in_array($new_instance['order_by'] ?? '', ['views', 'comments', 'likes', 'favorites', 'downloads'], true) ? $new_instance['order_by'] : 'views',
'days' => absint($new_instance['days'] ?? 30),
'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0,
'paginate' => sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) === 'none' ? 'none' : 'ajax',
];
}
}