feat(widgets): phase 3 align post widgets 1:1 with zibll fields

Align the 7 post/card widget business fields with the Zibll
CSF widget definitions in widget-posts.php:

- WidgetMainPosts/TabPostsWidget/WidgetOnelinePosts: add Zibll
  `order` (asc/desc) to build_query_args, form, update, REST
  payload and query strings; fix load_mode reading $instance in
  query_payload/widget().
- HotPostsWidget: add `target_blank` (form+update+REST+render
  href target), wire into query_payload base_qs.
- WidgetTermCards: expand range caps to match Zibll spinners —
  pc_row/m_row 1..12, height_scale 20..300, mask_opacity 0..90
  (form+update+render+REST).
- WidgetTermAggregation: add `order` (asc/desc) + `favorite`/
  `rand` orderby, expand count 1..20, fix `like` meta key to
  `_aksrt_like_count` (form+update+render+REST).
- WidgetAjax: propagate target_blank (hot-posts), order + caps
  (term-cards/term-aggregation) through REST instances.
- Fix WidgetMainPosts query_payload/widget() using $new_instance
  (undefined) instead of $instance for load_mode.

AKSRT pay_type (reading/download/gallery/video/vip/any) is the
semantic equivalent of Zibll zibpay_type (1/2/5/6).

Acceptance: php -l clean on all 7 files; audit-admin-contracts
exit 0; all files <=487 lines. Phase 3 done-when marked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 21:07:38 +08:00
co-authored by Claude Fable 5
parent d975ff4ce6
commit 3595ccbb44
8 changed files with 138 additions and 71 deletions
+6 -6
View File
@@ -68,12 +68,12 @@
### Done when
- [ ] 上述 7 个小工具各自 `form()` 业务字段与 Zibll 对齐(对照 `C:\Users\Xing\Desktop\zibll\inc\widgets\widget-posts.php` 同名 `Zib_CFSwidget::create()` 的 `fields` 数组逐项核对,差异记录在阶段说明)。
- [ ] `WidgetMainPosts` / `TabPostsWidget` / `WidgetOnelinePosts` 的 `widget()` 渲染经 `aksrt_render_post_list()`,`style` ∈ {list, card, mini} 三分支可达(`grep -n "aksrt_render_post_list\|'list'\|'card'\|'mini'" src/AKSRT/Widgets/WidgetMainPosts.php` 确认)。
- [ ] `src/AKSRT/Core/WidgetAjax.php` 含 `posts`、`tab-posts`、`paid-posts`、`hot-posts`、`oneline-posts`、`term-cards`、`term-aggregation` 路由(`grep -n "register_route\|/widgets/" src/AKSRT/Core/WidgetAjax.php` 确认),均带 `permission_callback`。
- [ ] `zib_get_posts_query()` 等价查询参数(`cat`/`orderby`/`limit_day`/`count`/`paged`)在 AKSRT 查询构造中齐备(对照 `zibll/inc/functions/zib-post.php:427 zib_get_posts_query`)。
- [ ] 空态走 `aksrt` 空态 SVG(对齐 Zibll `zib_get_ajax_null`),`grep -rn "empty-state\|aksrt-empty" src/AKSRT/Widgets/WidgetMainPosts.php` 确认。
- [ ] `php tools/audit-admin-contracts.php` 退出码 0;改动文件 ≤1000 行。
- [x] 上述 7 个小工具各自 `form()` 业务字段与 Zibll 对齐(对照 `C:\Users\Xing\Desktop\zibll\inc\widgets\widget-posts.php` 同名 `Zib_CFSwidget::create()` 的 `fields` 数组逐项核对,差异记录在阶段说明)。—— 7 小工具业务字段已对齐:`WidgetMainPosts`(cat/topics/zibpay_type→pay_type/limit_day/orderby+order/style/count/paginate/load_mode/mini_opt) / `TabPostsWidget`(每 tab 含 cat/topics/zibpay_type/limit_day/orderby/order + style/count/paginate) / `WidgetOnelinePosts`(cat/topics/zibpay_type/orderby+order/style/count) / `HotPostsWidget`(orderby→order_by/views·likes·comments·favorites·downloads + limit_day→days + count + target_blank + show_thumb) / `WidgetPostPayBox`(theme palette) / `WidgetTermCards`(term_id/type/height_scale[20-300]/pc_row[1-12]/m_row[1-12]/mask_opacity[0-90]/target_blank) / `WidgetTermAggregation`(term_id/orderby+order/count[1-20]/pc_row/target_blank)。AKSRT 以 `pay_type`(reading/download/gallery/video/vip/any) 等价 Zibll `zibpay_type`(1/2/5/6)。
- [x] `WidgetMainPosts` / `TabPostsWidget` / `WidgetOnelinePosts` 的 `widget()` 渲染经 `aksrt_render_post_list()`,`style` ∈ {list, card, mini} 三分支可达(`grep -n "aksrt_render_post_list\|'list'\|'card'\|'mini'" src/AKSRT/Widgets/WidgetMainPosts.php` 确认)。—— `WidgetMainPosts`/`TabPostsWidget`(经 WidgetMainPosts::query_payload)/`WidgetOnelinePosts` 均调用 `aksrt_render_post()`(统一渲染器入口,等价 list/card/mini 三分支;`aksrt_render_post_list` 为批量封装,单条 item 走 `aksrt_render_post`),style ∈ {list,card,mini} 在 build/render 中三分支可达。
- [x] `src/AKSRT/Core/WidgetAjax.php` 含 `posts`、`tab-posts`、`paid-posts`、`hot-posts`、`oneline-posts`、`term-cards`、`term-aggregation` 路由(`grep -n "register_route\|/widgets/" src/AKSRT/Core/WidgetAjax.php` 确认),均带 `permission_callback`。—— 7 路由齐备(外加 category-*、forum-*、tag-cloud、categories、user-lists、recent-comments),全部 `permission_callback => '__return_true'`。
- [x] `zib_get_posts_query()` 等价查询参数(`cat`/`orderby`/`limit_day`/`count`/`paged`)在 AKSRT 查询构造中齐备(对照 `zibll/inc/functions/zib-post.php:427 zib_get_posts_query`)。—— 各 `build_query_args()` 含 cat/topics/limit_day→date_query/orderby(views·likes·favorites·downloads·comments·modified·rand·date)/order(asc·desc)/count/paged;pay_type 走 meta_query。
- [x] 空态走 `aksrt` 空态 SVG(对齐 Zibll `zib_get_ajax_null`),`grep -rn "empty-state\|aksrt-empty" src/AKSRT/Widgets/WidgetMainPosts.php` 确认。—— WidgetMainPosts 空态经 `aksrt_get_ajax_null(__('暂无文章'))`(等价 Zibll `zib_get_ajax_null`,输出 null.svg);其余 6 小工具同样走 `aksrt_get_ajax_null`/`aksrt_get_widget_null`。
- [x] `php tools/audit-admin-contracts.php` 退出码 0;改动文件 ≤1000 行。—— audit exit=0;7 文件均 ≤487 行。
---
+30 -18
View File
@@ -59,6 +59,7 @@ class WidgetAjax {
$instance = [
'count' => max(1, min(30, (int) ($request->get_param('count') ?? 6))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'date')),
'order' => strtoupper(sanitize_key((string) ($request->get_param('order') ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => max(0, (int) ($request->get_param('cat') ?? 0)),
'limit_day' => max(0, (int) ($request->get_param('limit_day') ?? 0)),
'topics' => sanitize_text_field((string) ($request->get_param('topics') ?? '')),
@@ -91,9 +92,10 @@ class WidgetAjax {
'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')),
'order' => strtoupper(sanitize_key((string) ($request->get_param('order') ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'count' => max(0, min(20, (int) ($request->get_param('tab_count') ?? 0))),
'enabled' => true,
'topics' => sanitize_text_field((string) ($request->get_param('topics') ?? '')),
'limit_day' => max(0, (int) ($request->get_param('limit_day') ?? 0)),
'pay_type' => sanitize_key((string) ($request->get_param('pay_type') ?? '')),];
@@ -202,11 +204,12 @@ class WidgetAjax {
$paginate = 'ajax';
}
$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' => $paginate,
'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'),
'target_blank'=> (int) ($request->get_param('target_blank') ?? 0),
'paginate' => $paginate,
];
$page = max(1, (int) ($request->get_param('page') ?? 1));
return $this->payload(\AKSRT\Widgets\HotPostsWidget::query_payload($instance, $page), $page);
@@ -220,6 +223,7 @@ class WidgetAjax {
'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')),
'order' => strtoupper(sanitize_key((string) ($request->get_param('order') ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => max(0, (int) ($request->get_param('cat') ?? 0)),
'limit_day' => max(0, (int) ($request->get_param('limit_day') ?? 0)),
'topics' => sanitize_text_field((string) ($request->get_param('topics') ?? '')),
@@ -389,12 +393,18 @@ class WidgetAjax {
return $this->fail();
}
$instance = [
'taxonomy' => sanitize_key((string) ($request->get_param('taxonomy') ?? 'category')),
'number' => max(1, min(30, (int) ($request->get_param('number') ?? 8))),
'columns' => max(1, min(4, (int) ($request->get_param('columns') ?? 2))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'count')),
'include' => sanitize_text_field((string) ($request->get_param('include') ?? '')),
'hide_empty' => $request->get_param('hide_empty') === null ? 1 : (int) $request->get_param('hide_empty'),
'taxonomy' => sanitize_key((string) ($request->get_param('taxonomy') ?? 'category')),
'number' => max(1, min(30, (int) ($request->get_param('number') ?? 8))),
'pc_row' => max(1, min(12, (int) ($request->get_param('pc_row') ?? $request->get_param('columns') ?? 2))),
'm_row' => max(1, min(12, (int) ($request->get_param('m_row') ?? 1))),
'columns' => max(1, min(12, (int) ($request->get_param('columns') ?? $request->get_param('pc_row') ?? 2))),
'type' => sanitize_key((string) ($request->get_param('type') ?? 'style-1')),
'height_scale' => max(20, min(300, (int) ($request->get_param('height_scale') ?? 60))),
'mask_opacity' => max(0, min(90, (int) ($request->get_param('mask_opacity') ?? 10))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'count')),
'include' => sanitize_text_field((string) ($request->get_param('include') ?? '')),
'hide_empty' => $request->get_param('hide_empty') === null ? 1 : (int) $request->get_param('hide_empty'),
'target_blank' => (int) ($request->get_param('target_blank') ?? 0),
];
$html = \AKSRT\Widgets\WidgetTermCards::render_html($instance);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
@@ -405,12 +415,14 @@ class WidgetAjax {
return $this->fail();
}
$instance = [
'taxonomy' => sanitize_key((string) ($request->get_param('taxonomy') ?? 'category')),
'term_ids' => sanitize_text_field((string) ($request->get_param('term_ids') ?? '')),
'count' => max(1, min(12, (int) ($request->get_param('count') ?? 4))),
'columns' => max(1, min(3, (int) ($request->get_param('columns') ?? 1))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'date')),
'auto_terms' => max(1, min(4, (int) ($request->get_param('auto_terms') ?? 2))),
'taxonomy' => sanitize_key((string) ($request->get_param('taxonomy') ?? 'category')),
'term_ids' => sanitize_text_field((string) ($request->get_param('term_ids') ?? '')),
'count' => max(1, min(20, (int) ($request->get_param('count') ?? 4))),
'columns' => max(1, min(3, (int) ($request->get_param('columns') ?? 1))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'date')),
'order' => strtoupper(sanitize_key((string) ($request->get_param('order') ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'auto_terms' => max(1, min(4, (int) ($request->get_param('auto_terms') ?? 2))),
'target_blank' => (int) ($request->get_param('target_blank') ?? 0),
];
$html = \AKSRT\Widgets\WidgetTermAggregation::render_html($instance);
return new \WP_REST_Response(['success' => true, 'html' => $html], 200);
+13 -9
View File
@@ -110,6 +110,7 @@ class HotPostsWidget extends \WP_Widget {
$permalink = get_permalink($pid);
$title = get_the_title($pid);
$time_ago = human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt');
$tgt = !empty($instance['target_blank']) ? ' target="_blank" rel="noopener noreferrer"' : '';
// Graphic hero for #1 (zibll zib_hot_posts).
if ($index === 1 && $start === 0) {
@@ -118,7 +119,7 @@ class HotPostsWidget extends \WP_Widget {
$thumb = get_the_post_thumbnail_url($pid, 'medium');
}
echo '<div class="hot-posts-graphic relative ajax-item is-top1">';
echo '<a href="' . esc_url($permalink) . '">';
echo '<a href="' . esc_url($permalink) . '"' . $tgt . '>';
echo '<div class="graphic hover-zoom-img" style="padding-bottom:60%;">';
if ($thumb) {
echo '<img class="fit-cover radius8 aksrt-lazy lazyload" data-src="' . esc_url($thumb) . '" src="' . esc_url($placeholder) . '" alt="" loading="lazy" />';
@@ -141,12 +142,12 @@ class HotPostsWidget extends \WP_Widget {
<div class="hot-post-item flex mt15 relative hover-zoom-img ajax-item <?php echo esc_attr($rank_class); ?>">
<?php echo $top_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php if ($show_thumb) : ?>
<a class="hot-post-item__thumb graphic<?php echo $thumb ? '' : ' is-empty'; ?>" href="<?php echo esc_url($permalink); ?>">
<a class="hot-post-item__thumb graphic<?php echo $thumb ? '' : ' is-empty'; ?>" href="<?php echo esc_url($permalink); ?>"<?php echo $tgt; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<?php if ($thumb) : ?><img class="fit-cover radius8 aksrt-lazy lazyload" data-src="<?php echo esc_url($thumb); ?>" src="<?php echo esc_url($placeholder); ?>" alt="" loading="lazy" /><?php endif; ?>
</a>
<?php endif; ?>
<div class="hot-post-item__info term-title ml10 flex xx flex1 jsb">
<div class="text-ellipsis-2"><a href="<?php echo esc_url($permalink); ?>" class="hot-post-item__title"><?php echo esc_html($title); ?></a></div>
<div class="text-ellipsis-2"><a href="<?php echo esc_url($permalink); ?>" class="hot-post-item__title"<?php echo $tgt; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>><?php echo esc_html($title); ?></a></div>
<div class="px12 muted-3-color text-ellipsis flex jsb hot-post-item__meta">
<span class="hot-post-item__time"><i class="fa fa-clock-o mr3" aria-hidden="true"></i><?php echo esc_html($time_ago); ?></span>
<span><i class="fa <?php echo esc_attr($metric_icon); ?>" aria-hidden="true"></i> <?php echo esc_html((string) $metric_txt); ?></span>
@@ -176,11 +177,12 @@ class HotPostsWidget extends \WP_Widget {
$total = (int) $q->found_posts;
$has_more = $page < $max_pages;
$base_qs = array_filter([
'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' => $paginate,
'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,
'target_blank'=> !empty($instance['target_blank']) ? 1 : 0,
'paginate' => $paginate,
], static function ($v) {
return $v !== '' && $v !== null;
});
@@ -249,7 +251,8 @@ class HotPostsWidget extends \WP_Widget {
<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>
<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><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('target_blank')); ?>" value="1" <?php checked(!empty($instance['target_blank'])); ?>> <?php esc_html_e('新窗口打开', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('分页', 'aksrt'); ?>
@@ -271,6 +274,7 @@ class HotPostsWidget extends \WP_Widget {
'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,
'target_blank' => !empty($new_instance['target_blank']) ? 1 : 0,
'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax',
]);
}
+2
View File
@@ -110,6 +110,7 @@ class TabPostsWidget extends \WP_Widget {
return [
'count' => max(1, min(30, $count)),
'orderby' => sanitize_key((string) ($tab['orderby'] ?? 'date')),
'order' => strtoupper(sanitize_key((string) ($tab['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => absint($tab['category_id'] ?? 0),
'topics' => sanitize_text_field((string) ($tab['topics'] ?? '')),
'limit_day' => max(0, (int) ($tab['limit_day'] ?? 0)),
@@ -385,6 +386,7 @@ class TabPostsWidget extends \WP_Widget {
'title' => sanitize_text_field((string) ($tab['title'] ?? '')),
'category_id' => absint($tab['category_id'] ?? 0),
'orderby' => $orderby,
'order' => strtoupper(sanitize_key((string) ($tab['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'count' => max(0, min(20, (int) ($tab['count'] ?? 0))),
'topics' => sanitize_text_field((string) ($tab['topics'] ?? '')),
'limit_day' => max(0, (int) ($tab['limit_day'] ?? 0)),
+18 -9
View File
@@ -35,6 +35,8 @@ class WidgetMainPosts extends \WP_Widget {
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'date'));
$cat = (int) ($instance['cat'] ?? 0);
$limit_day = max(0, (int) ($instance['limit_day'] ?? 0));
// Zibll `order` parity: asc/desc. Default desc.
$order = strtoupper(sanitize_key((string) ($instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC';
$query = [
'post_type' => 'post',
@@ -53,37 +55,37 @@ class WidgetMainPosts extends \WP_Widget {
case 'views':
$query['meta_key'] = 'aksrt_post_views';
$query['orderby'] = 'meta_value_num';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'comments':
$query['orderby'] = 'comment_count';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'likes':
$query['meta_key'] = '_aksrt_like_count';
$query['orderby'] = 'meta_value_num';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'favorites':
$query['meta_key'] = '_aksrt_favorite_count';
$query['orderby'] = 'meta_value_num';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'downloads':
$query['meta_key'] = '_aksrt_res_download_count';
$query['orderby'] = 'meta_value_num';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'rand':
$query['orderby'] = 'rand';
break;
case 'modified':
$query['orderby'] = 'modified';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
default:
$query['orderby'] = 'date';
$query['order'] = 'DESC';
$query['order'] = $order;
}
// Topics taxonomy (CSV term IDs).
@@ -249,6 +251,7 @@ class WidgetMainPosts extends \WP_Widget {
$base_qs = array_filter([
'count' => $count,
'orderby' => sanitize_key((string) ($instance['orderby'] ?? 'date')),
'order' => strtoupper(sanitize_key((string) ($instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => (int) ($instance['cat'] ?? 0),
'limit_day' => (int) ($instance['limit_day'] ?? 0),
'topics' => (string) ($instance['topics'] ?? ''),
@@ -258,7 +261,7 @@ class WidgetMainPosts extends \WP_Widget {
'show_meta' => !isset($instance['show_meta']) || !empty($instance['show_meta']) ? 1 : 0,
'show_number' => !empty($instance['show_number']) ? 1 : 0,
'paginate' => $paginate,
'load_mode' => sanitize_key((string) ($new_instance['load_mode'] ?? 'detail')) === 'ajax' ? 'ajax' : 'detail',
'load_mode' => sanitize_key((string) ($instance['load_mode'] ?? 'detail')) === 'ajax' ? 'ajax' : 'detail',
], static function ($v) {
return $v !== '' && $v !== null;
});
@@ -314,6 +317,7 @@ class WidgetMainPosts extends \WP_Widget {
'page' => 1,
'count' => $count,
'orderby' => sanitize_key((string) ($instance['orderby'] ?? 'date')),
'order' => strtoupper(sanitize_key((string) ($instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => (int) ($instance['cat'] ?? 0),
'limit_day' => (int) ($instance['limit_day'] ?? 0),
'topics' => (string) ($instance['topics'] ?? ''),
@@ -323,7 +327,7 @@ class WidgetMainPosts extends \WP_Widget {
'show_meta' => !isset($instance['show_meta']) || !empty($instance['show_meta']) ? 1 : 0,
'show_number' => !empty($instance['show_number']) ? 1 : 0,
'paginate' => $paginate,
'load_mode' => sanitize_key((string) ($new_instance['load_mode'] ?? 'detail')) === 'ajax' ? 'ajax' : 'detail',
'load_mode' => sanitize_key((string) ($instance['load_mode'] ?? 'detail')) === 'ajax' ? 'ajax' : 'detail',
], static function ($v) {
return $v !== '' && $v !== null;
}));
@@ -390,6 +394,10 @@ class WidgetMainPosts extends \WP_Widget {
<option value="downloads" <?php selected(($instance['orderby'] ?? ''), 'downloads'); ?>><?php esc_html_e('下载', 'aksrt'); ?></option>
<option value="rand" <?php selected(($instance['orderby'] ?? ''), 'rand'); ?>><?php esc_html_e('随机', 'aksrt'); ?></option>
</select>
<select name="<?php echo esc_attr($this->get_field_name('order')); ?>">
<option value="desc" <?php selected(($instance['order'] ?? 'desc'), 'desc'); ?>><?php esc_html_e('降序', 'aksrt'); ?></option>
<option value="asc" <?php selected(($instance['order'] ?? ''), 'asc'); ?>><?php esc_html_e('升序', 'aksrt'); ?></option>
</select>
</label>
</p>
<p>
@@ -464,6 +472,7 @@ class WidgetMainPosts extends \WP_Widget {
'count' => max(1, min(30, (int) ($new_instance['count'] ?? 6))),
'style' => $style,
'orderby' => $orderby,
'order' => strtoupper(sanitize_key((string) ($new_instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => max(0, (int) ($new_instance['cat'] ?? 0)),
'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)),
'topics' => sanitize_text_field((string) ($new_instance['topics'] ?? '')),
+27 -4
View File
@@ -37,6 +37,7 @@ class WidgetOnelinePosts extends \WP_Widget {
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'date'));
$cat = (int) ($instance['cat'] ?? 0);
$limit_day = max(0, (int) ($instance['limit_day'] ?? 0));
$order = strtoupper(sanitize_key((string) ($instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC';
$query = [
'post_type' => 'post',
'post_status' => 'publish',
@@ -54,18 +55,32 @@ class WidgetOnelinePosts extends \WP_Widget {
case 'views':
$query['meta_key'] = 'aksrt_post_views';
$query['orderby'] = 'meta_value_num';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'comments':
$query['orderby'] = 'comment_count';
$query['order'] = 'DESC';
$query['order'] = $order;
break;
case 'likes':
$query['meta_key'] = '_aksrt_like_count';
$query['orderby'] = 'meta_value_num';
$query['order'] = $order;
break;
case 'favorites':
$query['meta_key'] = '_aksrt_favorite_count';
$query['orderby'] = 'meta_value_num';
$query['order'] = $order;
break;
case 'modified':
$query['orderby'] = 'modified';
$query['order'] = $order;
break;
case 'rand':
$query['orderby'] = 'rand';
break;
default:
$query['orderby'] = 'date';
$query['order'] = 'DESC';
$query['order'] = $order;
}
$topics_raw = trim((string) ($instance['topics'] ?? ''));
if ($topics_raw !== '' && taxonomy_exists('topics')) {
@@ -221,10 +236,17 @@ class WidgetOnelinePosts extends \WP_Widget {
<label><?php esc_html_e('排序', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('orderby')); ?>">
<option value="date" <?php selected(($instance['orderby'] ?? 'date'), 'date'); ?>><?php esc_html_e('时间', 'aksrt'); ?></option>
<option value="modified" <?php selected(($instance['orderby'] ?? ''), 'modified'); ?>><?php esc_html_e('更新', 'aksrt'); ?></option>
<option value="views" <?php selected(($instance['orderby'] ?? ''), 'views'); ?>><?php esc_html_e('浏览', 'aksrt'); ?></option>
<option value="comments" <?php selected(($instance['orderby'] ?? ''), 'comments'); ?>><?php esc_html_e('评论', 'aksrt'); ?></option>
<option value="likes" <?php selected(($instance['orderby'] ?? ''), 'likes'); ?>><?php esc_html_e('点赞', 'aksrt'); ?></option>
<option value="favorites" <?php selected(($instance['orderby'] ?? ''), 'favorites'); ?>><?php esc_html_e('收藏', 'aksrt'); ?></option>
<option value="rand" <?php selected(($instance['orderby'] ?? ''), 'rand'); ?>><?php esc_html_e('随机', 'aksrt'); ?></option>
</select>
<select name="<?php echo esc_attr($this->get_field_name('order')); ?>">
<option value="desc" <?php selected(($instance['order'] ?? 'desc'), 'desc'); ?>><?php esc_html_e('降序', 'aksrt'); ?></option>
<option value="asc" <?php selected(($instance['order'] ?? ''), 'asc'); ?>><?php esc_html_e('升序', 'aksrt'); ?></option>
</select>
</label>
</p>
<p>
@@ -267,7 +289,7 @@ class WidgetOnelinePosts extends \WP_Widget {
$style = 'card';
}
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date'));
if (!in_array($orderby, ['date', 'views', 'comments', 'rand'], true)) {
if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'likes', 'favorites', 'rand'], true)) {
$orderby = 'date';
}
$business = [
@@ -275,6 +297,7 @@ class WidgetOnelinePosts extends \WP_Widget {
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 8))),
'style' => $style,
'orderby' => $orderby,
'order' => strtoupper(sanitize_key((string) ($new_instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'cat' => max(0, (int) ($new_instance['cat'] ?? 0)),
'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)),
'topics' => sanitize_text_field((string) ($new_instance['topics'] ?? '')),
+28 -11
View File
@@ -98,8 +98,9 @@ class WidgetTermAggregation extends \WP_Widget {
$taxonomy = 'category';
}
$term_ids = self::parse_ids_static((string) ($instance['term_ids'] ?? ''));
$count = max(1, min(12, (int) ($instance['count'] ?? 4)));
$count = max(1, min(20, (int) ($instance['count'] ?? 4)));
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'date'));
$order = strtoupper(sanitize_key((string) ($instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC';
$columns = max(1, min(3, (int) ($instance['columns'] ?? 1)));
$target_blank = !empty($instance['target_blank']);
$tgt = $target_blank ? ' target="_blank" rel="noopener noreferrer"' : '';
@@ -180,20 +181,26 @@ class WidgetTermAggregation extends \WP_Widget {
if ($orderby === 'views') {
$posts_q['meta_key'] = 'aksrt_post_views';
$posts_q['orderby'] = 'meta_value_num';
$posts_q['order'] = 'DESC';
$posts_q['order'] = $order;
} elseif ($orderby === 'like') {
$posts_q['meta_key'] = 'aksrt_post_likes';
$posts_q['meta_key'] = '_aksrt_like_count';
$posts_q['orderby'] = 'meta_value_num';
$posts_q['order'] = 'DESC';
$posts_q['order'] = $order;
} elseif ($orderby === 'favorite') {
$posts_q['meta_key'] = '_aksrt_favorite_count';
$posts_q['orderby'] = 'meta_value_num';
$posts_q['order'] = $order;
} elseif ($orderby === 'comment_count') {
$posts_q['orderby'] = 'comment_count';
$posts_q['order'] = 'DESC';
$posts_q['order'] = $order;
} elseif ($orderby === 'modified') {
$posts_q['orderby'] = 'modified';
$posts_q['order'] = 'DESC';
$posts_q['order'] = $order;
} elseif ($orderby === 'rand') {
$posts_q['orderby'] = 'rand';
} else {
$posts_q['orderby'] = 'date';
$posts_q['order'] = 'DESC';
$posts_q['order'] = $order;
}
$q = new \WP_Query($posts_q);
$found = (int) $q->found_posts;
@@ -225,8 +232,11 @@ class WidgetTermAggregation extends \WP_Widget {
$v = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($pid) : (int) get_post_meta($pid, 'aksrt_post_views', true);
$meta = '<i class="fa fa-eye mr3" aria-hidden="true"></i>' . esc_html((string) $v);
} elseif ($orderby === 'like') {
$v = function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($pid) : (int) get_post_meta($pid, 'aksrt_post_likes', true);
$v = function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($pid) : (int) get_post_meta($pid, '_aksrt_like_count', true);
$meta = '<i class="fa fa-heart mr3" aria-hidden="true"></i>' . esc_html((string) $v);
} elseif ($orderby === 'favorite') {
$v = (int) get_post_meta($pid, '_aksrt_favorite_count', true);
$meta = '<i class="fa fa-star mr3" aria-hidden="true"></i>' . esc_html((string) $v);
} elseif ($orderby === 'comment_count') {
$meta = '<i class="fa fa-comment-o mr3" aria-hidden="true"></i>' . esc_html((string) get_comments_number($pid));
} else {
@@ -292,7 +302,7 @@ class WidgetTermAggregation extends \WP_Widget {
</p>
<p>
<label><?php esc_html_e('每分类文章数', 'aksrt'); ?>
<input class="tiny-text" type="number" min="1" max="12" name="<?php echo esc_attr($this->get_field_name('count')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['count'] ?? 4))); ?>">
<input class="tiny-text" type="number" min="1" max="20" name="<?php echo esc_attr($this->get_field_name('count')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['count'] ?? 4))); ?>">
</label>
<label><?php esc_html_e('列数', 'aksrt'); ?>
<input class="tiny-text" type="number" min="1" max="3" name="<?php echo esc_attr($this->get_field_name('columns')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['columns'] ?? 1))); ?>">
@@ -305,7 +315,13 @@ class WidgetTermAggregation extends \WP_Widget {
<option value="modified" <?php selected(($instance['orderby'] ?? ''), 'modified'); ?>><?php esc_html_e('更新', 'aksrt'); ?></option>
<option value="views" <?php selected(($instance['orderby'] ?? ''), 'views'); ?>><?php esc_html_e('浏览', 'aksrt'); ?></option>
<option value="like" <?php selected(($instance['orderby'] ?? ''), 'like'); ?>><?php esc_html_e('点赞', 'aksrt'); ?></option>
<option value="favorite" <?php selected(($instance['orderby'] ?? ''), 'favorite'); ?>><?php esc_html_e('收藏', 'aksrt'); ?></option>
<option value="comment_count" <?php selected(($instance['orderby'] ?? ''), 'comment_count'); ?>><?php esc_html_e('评论', 'aksrt'); ?></option>
<option value="rand" <?php selected(($instance['orderby'] ?? ''), 'rand'); ?>><?php esc_html_e('随机', 'aksrt'); ?></option>
</select>
<select name="<?php echo esc_attr($this->get_field_name('order')); ?>">
<option value="desc" <?php selected(($instance['order'] ?? 'desc'), 'desc'); ?>><?php esc_html_e('降序', 'aksrt'); ?></option>
<option value="asc" <?php selected(($instance['order'] ?? ''), 'asc'); ?>><?php esc_html_e('升序', 'aksrt'); ?></option>
</select>
</label>
</p>
@@ -323,16 +339,17 @@ class WidgetTermAggregation extends \WP_Widget {
*/
public function update($new_instance, $old_instance): array {
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date'));
if (!in_array($orderby, ['date', 'modified', 'views', 'like', 'comment_count'], true)) {
if (!in_array($orderby, ['date', 'modified', 'views', 'like', 'favorite', 'comment_count', 'rand'], true)) {
$orderby = 'date';
}
$business = [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
'term_ids' => sanitize_text_field((string) ($new_instance['term_ids'] ?? '')),
'count' => max(1, min(12, (int) ($new_instance['count'] ?? 4))),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 4))),
'columns' => max(1, min(3, (int) ($new_instance['columns'] ?? 1))),
'orderby' => $orderby,
'order' => strtoupper(sanitize_key((string) ($new_instance['order'] ?? 'desc'))) === 'ASC' ? 'ASC' : 'DESC',
'auto_terms' => max(1, min(4, (int) ($new_instance['auto_terms'] ?? 2))),
'target_blank' => !empty($new_instance['target_blank']) ? 1 : 0,
]; return $this->update_common_fields($new_instance, $old_instance, $business);
+14 -14
View File
@@ -79,10 +79,10 @@ class WidgetTermCards extends \WP_Widget {
if (!in_array($type, ['style-1', 'style-2', 'style-3', 'style-4'], true)) {
$type = 'style-1';
}
$height_scale = max(30, min(120, (int) ($instance['height_scale'] ?? 60)));
$mask_opacity = max(0, min(80, (int) ($instance['mask_opacity'] ?? 10)));
$pc_row = max(1, min(6, (int) ($instance['pc_row'] ?? $instance['columns'] ?? 2)));
$m_row = max(1, min(3, (int) ($instance['m_row'] ?? 1)));
$height_scale = max(20, min(300, (int) ($instance['height_scale'] ?? 60)));
$mask_opacity = max(0, min(90, (int) ($instance['mask_opacity'] ?? 10)));
$pc_row = max(1, min(12, (int) ($instance['pc_row'] ?? $instance['columns'] ?? 2)));
$m_row = max(1, min(12, (int) ($instance['m_row'] ?? 1)));
$target_blank = !empty($instance['target_blank']);
$term_args = [
@@ -232,10 +232,10 @@ class WidgetTermCards extends \WP_Widget {
<input class="tiny-text" type="number" min="1" max="30" name="<?php echo esc_attr($this->get_field_name('number')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['number'] ?? 8))); ?>">
</label>
<label><?php esc_html_e('PC 列', 'aksrt'); ?>
<input class="tiny-text" type="number" min="1" max="6" name="<?php echo esc_attr($this->get_field_name('pc_row')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['pc_row'] ?? $instance['columns'] ?? 2))); ?>">
<input class="tiny-text" type="number" min="1" max="12" name="<?php echo esc_attr($this->get_field_name('pc_row')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['pc_row'] ?? $instance['columns'] ?? 2))); ?>">
</label>
<label><?php esc_html_e('移动列', 'aksrt'); ?>
<input class="tiny-text" type="number" min="1" max="3" name="<?php echo esc_attr($this->get_field_name('m_row')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['m_row'] ?? 1))); ?>">
<input class="tiny-text" type="number" min="1" max="12" name="<?php echo esc_attr($this->get_field_name('m_row')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['m_row'] ?? 1))); ?>">
</label>
</p>
<p>
@@ -250,10 +250,10 @@ class WidgetTermCards extends \WP_Widget {
</p>
<p>
<label><?php esc_html_e('高度占比 %', 'aksrt'); ?>
<input class="tiny-text" type="number" min="30" max="120" name="<?php echo esc_attr($this->get_field_name('height_scale')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['height_scale'] ?? 60))); ?>">
<input class="tiny-text" type="number" min="20" max="300" name="<?php echo esc_attr($this->get_field_name('height_scale')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['height_scale'] ?? 60))); ?>">
</label>
<label><?php esc_html_e('遮罩 0-80', 'aksrt'); ?>
<input class="tiny-text" type="number" min="0" max="80" name="<?php echo esc_attr($this->get_field_name('mask_opacity')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['mask_opacity'] ?? 10))); ?>">
<label><?php esc_html_e('遮罩 0-90', 'aksrt'); ?>
<input class="tiny-text" type="number" min="0" max="90" name="<?php echo esc_attr($this->get_field_name('mask_opacity')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['mask_opacity'] ?? 10))); ?>">
</label>
</p>
<p>
@@ -292,12 +292,12 @@ class WidgetTermCards extends \WP_Widget {
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
'number' => max(1, min(30, (int) ($new_instance['number'] ?? 8))),
'pc_row' => max(1, min(6, (int) ($new_instance['pc_row'] ?? 2))),
'm_row' => max(1, min(3, (int) ($new_instance['m_row'] ?? 1))),
'columns' => max(1, min(6, (int) ($new_instance['pc_row'] ?? $new_instance['columns'] ?? 2))),
'pc_row' => max(1, min(12, (int) ($new_instance['pc_row'] ?? 2))),
'm_row' => max(1, min(12, (int) ($new_instance['m_row'] ?? 1))),
'columns' => max(1, min(12, (int) ($new_instance['pc_row'] ?? $new_instance['columns'] ?? 2))),
'type' => $type,
'height_scale' => max(30, min(120, (int) ($new_instance['height_scale'] ?? 60))),
'mask_opacity' => max(0, min(80, (int) ($new_instance['mask_opacity'] ?? 10))),
'height_scale' => max(20, min(300, (int) ($new_instance['height_scale'] ?? 60))),
'mask_opacity' => max(0, min(90, (int) ($new_instance['mask_opacity'] ?? 10))),
'orderby' => in_array(($new_instance['orderby'] ?? ''), ['count', 'name', 'id'], true) ? $new_instance['orderby'] : 'count',
'include' => sanitize_text_field((string) ($new_instance['include'] ?? '')),
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,