fix(widgets): restore article list rendering and reference styles

This commit is contained in:
kate522 committed 2026-10-30 12:47:07 +08:00
1 parent 4ea00f1322
commit fc04bf65e6
18 files changed
+345 -97

No files matched your search

+4 -4
View File
@@ -23,19 +23,18 @@ final class FrontendRenderer {
}
AssetManager::enqueue_for($definition);
if (in_array($definition->slug(), ['user_card', 'author_card', 'tab_posts'], true)) {
if (in_array($definition->slug(), ['user_card', 'author_card', 'tab_posts', 'posts'], true)) {
self::render_reference_widget($definition, $instance, $widget, $content);
return;
}
if (in_array($definition->slug(), [
'post_pay', 'posts', 'oneline_posts', 'hot_posts',
'post_pay', 'oneline_posts', 'hot_posts',
'slider', 'slider_media_combo', 'icon_cards', 'icon_cover_cards',
'buttons', 'notice', 'term_cards', 'term_aggregation', 'media_cards',
'combo_info', 'partners', 'recent_comments', 'posts_toc',
], true)) {
echo (string) ($args['before_widget'] ?? '');
if ($definition->slug() !== 'post_pay') echo self::reference_title($instance);
$animation = '';
$content_classes = ['widget-content'];
$device_class = WidgetVisibility::device_class($instance);
if ($device_class !== '') {
@@ -107,7 +106,8 @@ final class FrontendRenderer {
}
$style = self::style($instance);
echo '<div class="' . esc_attr(implode(' ', $classes)) . '" data-aksrt-widget="' . esc_attr($definition->slug()) . '" data-widget-id="' . esc_attr((string) $widget->id) . '"' . ($style !== '' ? ' style="' . esc_attr($style) . '"' : '') . '>';
$affix_attr = !empty($instance['sidebar_affix']) ? ' data-affix="true"' : '';
echo '<div class="' . esc_attr(implode(' ', $classes)) . '" data-aksrt-widget="' . esc_attr($definition->slug()) . '" data-widget-id="' . esc_attr((string) $widget->id) . '"' . $affix_attr . ($style !== '' ? ' style="' . esc_attr($style) . '"' : '') . '>';
echo '<div class="widget-container"><div>';
echo self::reference_title($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="' . esc_attr(implode(' ', $content_classes)) . '">' . $content . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+24 -14
View File
@@ -24,7 +24,7 @@ final class PostQuery {
'ignore_sticky_posts' => true,
'no_found_rows' => false,
];
if (array_key_exists('paginate', $config) && in_array((string) $config['paginate'], ['', 'none'], true)) {
if (isset($config['paginate']) && $config['paginate'] === '') {
$args['no_found_rows'] = true;
$args['paged'] = 1;
}
@@ -33,13 +33,22 @@ final class PostQuery {
// category_ids remains available only to the unrelated generic posts
// widgets; a tab segment must never fall back to it.
$is_reference_segment = array_key_exists('cat', $segment);
$cat_raw = array_key_exists('cat', $config) ? (string) $config['cat'] : ($is_reference_segment ? '' : (string) ($config['category_ids'] ?? ''));
$categories = self::signed_ids($cat_raw);
if (!empty($config['category_id'])) $categories = [(int) $config['category_id']];
$cat_in = array_values(array_filter($categories, static fn(int $id): bool => $id > 0));
$cat_not = array_values(array_map('abs', array_filter($categories, static fn(int $id): bool => $id < 0)));
if ($cat_in) $args['category__in'] = $cat_in;
if ($cat_not) $args['category__not_in'] = $cat_not;
if (array_key_exists('cat', $config)) {
// WP_Query's `cat` expands included parents to descendants and
// applies negative IDs with the same reference-theme semantics.
$categories = self::signed_ids((string) $config['cat']);
if ($categories) {
$args['cat'] = implode(',', $categories);
}
} else {
// Generic widgets retain their explicit category ID/list behavior.
$categories = self::signed_ids((string) ($config['category_ids'] ?? ''));
if (!empty($config['category_id'])) $categories = [(int) $config['category_id']];
$cat_in = array_values(array_filter($categories, static fn(int $id): bool => $id > 0));
$cat_not = array_values(array_map('abs', array_filter($categories, static fn(int $id): bool => $id < 0)));
if ($cat_in) $args['category__in'] = $cat_in;
if ($cat_not) $args['category__not_in'] = $cat_not;
}
$tags = $is_reference_segment ? [] : RendererHelpers::ids((string) ($config['tag_ids'] ?? ''));
if ($tags) {
$args['tag__in'] = $tags;
@@ -47,14 +56,15 @@ final class PostQuery {
$days = max(0, (int) ($config['limit_day'] ?? 0));
if ($days > 0) {
$now = function_exists('current_time') ? current_time('timestamp') : time();
$format = static function (int $timestamp): string {
return function_exists('wp_date') ? wp_date('Y-m-d H:i:s', $timestamp) : date('Y-m-d H:i:s', $timestamp);
};
$args['date_query'] = [['after' => $format($now - ($days * DAY_IN_SECONDS)), 'before' => $format($now), 'inclusive' => true]];
$now = current_datetime();
$args['date_query'] = [[
'after' => $now->modify('-' . $days . ' days')->format('Y-m-d H:i:s'),
'before' => $now->format('Y-m-d H:i:s'),
'inclusive' => true,
]];
}
self::apply_order($args, (string) ($config['orderby'] ?? 'date'), (string) ($config['order'] ?? 'DESC'));
$pay = $is_reference_segment ? ($config['zibpay_type'] ?? []) : ($config['pay_type'] ?? '');
$pay = array_key_exists('zibpay_type', $config) ? $config['zibpay_type'] : ($config['pay_type'] ?? '');
self::apply_pay_type($args, $pay);
return $args;
}
+18 -10
View File
@@ -16,6 +16,10 @@ final class PostRenderer {
}
public static function payload(array $instance, string $slug, int $page = 1, string $segment = ''): array {
$page = max(1, $page);
if (($instance['paginate'] ?? '') === '') {
$page = 1;
}
$segment_config = $slug === 'tab_posts' ? PostQuery::segment($instance, $segment) : [];
$query = PostQuery::build($instance, $page, $segment_config);
$html = self::items($query, $instance, $slug, $page);
@@ -47,9 +51,7 @@ final class PostRenderer {
'is_tag' => false,
'is_author' => false,
'is_search' => false,
'is_mult_thumb' => 'disable',
'is_no_thumb' => 'disable',
'show_number' => in_array('show_number', $mini_opt, true),
'show_number' => $page === 1 && in_array('show_number', $mini_opt, true),
'show_thumb' => in_array('show_thumb', $mini_opt, true),
'show_meta' => in_array('show_meta', $mini_opt, true),
'number_offset' => ($page - 1) * max(1, (int) ($instance['count'] ?? 8)),
@@ -60,6 +62,11 @@ final class PostRenderer {
if ($mode === 'mini') {
return aksrt_render_mini_list($query, array_merge($config, ['class' => 'ajax-item']), false);
}
if ($mode === 'list') {
// Zibll suppresses archive-only thumb variants in widget list mode.
$config['is_mult_thumb'] = 'disable';
$config['is_no_thumb'] = 'disable';
}
// The .widget-ajaxpager container rendered by the caller is the ajax
// target, so item markup goes in without the page-level list wrapper.
return aksrt_render_post_list(array_merge($config, ['skip_wrapper' => true]), $query, false);
@@ -78,11 +85,12 @@ final class PostRenderer {
'show_number' => false,
])) : '';
} else {
$items .= aksrt_render_post(array_merge($config, [
'type' => $style === 'card' ? 'card' : 'list',
'is_mult_thumb' => 'disable',
'is_no_thumb' => 'disable',
]));
$item_config = array_merge($config, ['type' => $style === 'card' ? 'card' : 'list']);
if ($style === 'list') {
$item_config['is_mult_thumb'] = 'disable';
$item_config['is_no_thumb'] = 'disable';
}
$items .= aksrt_render_post($item_config);
}
}
wp_reset_postdata();
@@ -98,13 +106,13 @@ final class PostRenderer {
*/
private static function pagination(array $instance, int $page, int $max_pages): string {
$mode = (string) ($instance['paginate'] ?? '');
if ($mode === '' || $mode === 'none') {
if ($mode === '') {
return '<div class="ajax-pag hide"><div class="next-page"><a href="#"></a></div></div>';
}
if ($max_pages <= 1) {
return '';
}
if ($mode === 'number' || $mode === 'numbered') {
if ($mode === 'number') {
$links = '';
$mobile = wp_is_mobile();
$mid_size = $mobile ? 0 : 2;
@@ -47,13 +47,11 @@ final class ContentRenderer {
if ($segment !== '') {
$attrs .= ' data-segment="' . esc_attr($segment) . '"';
}
$loader = '<div class="post_ajax_loader" role="status" aria-label="' . esc_attr__('正在加载', 'aksrt') . '">' . self::placeholder($instance) . '</div>';
if (($instance['load_mode'] ?? '') === 'ajax') {
// The runtime (lazysizes + lazyload-action) reveals this container
// and clicks the single .ias-btn trigger; frontend.js then loads
// the first page through the REST client.
$trigger = '<span class="hide aksrt-ias-trigger"><a class="ias-btn" no-scroll="true" href="javascript:void(0)" data-widget-ias="1" data-next-page="1" aria-hidden="true" tabindex="-1"></a></span>';
return '<div class="widget-ajaxpager lazyload" lazyload-action="ias"' . $attrs . ' aria-live="polite" aria-busy="true">' . $trigger . $loader . '</div>';
$lazy = ($instance['load_mode'] ?? '') === 'ajax';
$loader = '<div class="post_ajax_loader' . ($lazy ? ' is-loading' : '') . '" role="status" aria-label="' . esc_attr__('正在加载', 'aksrt') . '">' . self::placeholder($instance) . '</div>';
if ($lazy) {
// lazySizes reveals the pager; the widget client owns its request.
return '<div class="widget-ajaxpager lazyload" data-widget-lazy' . $attrs . ' aria-live="polite" aria-busy="true">' . $loader . '</div>';
}
$payload = PostRenderer::payload($instance, $slug, $page, $segment);
// The loader must live inside the pager: the REST client in frontend.js
+1 -1
View File
@@ -34,7 +34,7 @@ final class RestController extends \WP_REST_Controller {
* @return \WP_REST_Response|\WP_Error
*/
public function get_items($request) {
$unknown = array_diff(array_keys($request->get_params()), ['widget', 'instance', 'page', 'segment']);
$unknown = array_diff(array_keys($request->get_params()), ['widget', 'instance', 'page', 'segment', 'rest_route']);
if ($unknown) {
return new \WP_Error('aksrt_widget_unknown_parameter', __('请求包含不支持的参数。', 'aksrt'), ['status' => 400, 'parameters' => array_values($unknown)]);
}
+1 -1
View File
@@ -71,7 +71,7 @@ final class WidgetCatalog {
'size' => $size,
'common' => [
'title' => !in_array($slug, ['post_pay', 'layout_gap', 'slider', 'slider_media_combo', 'buttons', 'posts_toc'], true),
'affix' => ($size === 'sidebar' && $slug !== 'posts_toc') || in_array($slug, ['buttons', 'notice'], true),
'affix' => ($size === 'sidebar' && $slug !== 'posts_toc') || in_array($slug, ['buttons', 'notice', 'posts'], true),
'animation' => !in_array($slug, ['buttons', 'term_cards', 'term_aggregation', 'media_cards', 'combo_info', 'slider_media_combo'], true),
],
'fields' => WidgetSchemas::for($slug),