From ea3c9876958f8632bf306532fc4a0ee9839ef095 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2026 12:16:57 +0800 Subject: [PATCH] feat(widgets): number paginate + main/tab query depth Add shared aksrt_get_ajax_number_paginate, MainPosts topics/pay_type/ favorites filters and number pager, TabPosts style/paginate/skeleton payload, REST wiring, product number AJAX parity. --- assets/js/widget-set.js | 7 +- inc/helpers/aksrt-ajax-list.php | 80 ++++++++++++++ src/AKSRT/Core/WidgetAjax.php | 39 ++++++- src/AKSRT/Widgets/TabPostsWidget.php | 140 ++++++++++++++++++------ src/AKSRT/Widgets/WidgetMainPosts.php | 134 ++++++++++++++++++++--- src/AKSRT/Widgets/WidgetProductList.php | 34 ++++-- 6 files changed, 373 insertions(+), 61 deletions(-) diff --git a/assets/js/widget-set.js b/assets/js/widget-set.js index 8726220f..5ee91678 100644 --- a/assets/js/widget-set.js +++ b/assets/js/widget-set.js @@ -25,11 +25,15 @@ var orderby = tab.getAttribute('data-orderby') || 'date'; var cat = tab.getAttribute('data-cat') || '0'; var tabCount = tab.getAttribute('data-tab-count') || '0'; + var style = widget.getAttribute('data-style') || 'mini'; + var paginate = widget.getAttribute('data-paginate') || 'none'; var qs = new URLSearchParams({ count: defaultCount, orderby: orderby, cat: cat, tab_count: tabCount, + style: style, + paginate: paginate, }); var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + qs.toString(); panel.classList.add('is-ajax-loading'); @@ -42,7 +46,8 @@ .then(function (j) { var d = (j && j.data) || j || {}; var html = d.html || ''; - panel.innerHTML = html || '

暂无文章

'; + var pag = d.paginate_html || d.paginateHtml || ''; + panel.innerHTML = (html || '

暂无文章

') + (pag || ''); panel.setAttribute('data-loaded', '1'); panel.classList.remove('is-ajax-loading'); }) diff --git a/inc/helpers/aksrt-ajax-list.php b/inc/helpers/aksrt-ajax-list.php index f870ef22..9013a057 100644 --- a/inc/helpers/aksrt-ajax-list.php +++ b/inc/helpers/aksrt-ajax-list.php @@ -109,3 +109,83 @@ if (!function_exists('aksrt_get_remote_modal_link')) { return '<' . $tag . $attrs . '>' . esc_html($text) . ''; } } + +if (!function_exists('aksrt_get_ajax_number_paginate')) { + /** + * Numbered AJAX pager (zibll zib_get_ajax_number_paginate subset). + * + * Links use class next-page ajax-next + ajax-replace so ajax-list.js + * replaces .ajax-item rows inside the nearest .ajaxpager. + * + * @param int $count_all Total items. + * @param int $page Current page (1-based). + * @param int $per_page Per page. + * @param string $ajax_url Base REST/URL (page query key replaced). + * @param string $pag_class Wrapper class. + * @param string $next_class Link base class. + * @param string $query_key Page query arg (default page). + */ + function aksrt_get_ajax_number_paginate( + int $count_all, + int $page = 1, + int $per_page = 10, + string $ajax_url = '', + string $pag_class = 'ajax-pag', + string $next_class = 'next-page ajax-next', + string $query_key = 'page' + ): string { + $page = max(1, $page); + $per_page = max(1, $per_page); + $total_pages = (int) ceil(max(0, $count_all) / $per_page); + if ($total_pages < 2 || $count_all <= 0) { + return '
'; + } + + $base = $ajax_url !== '' ? $ajax_url : '#'; + // Ensure %#% placeholder for page numbers. + if (strpos($base, '%#%') === false) { + $base = add_query_arg($query_key, '%#%', $base); + } + + $end_size = 1; + $mid_size = 2; + $links = []; + $dots = false; + + // Prev. + if ($page > 1) { + $url = esc_url(str_replace('%#%', (string) ($page - 1), $base)); + $links[] = ''; + } + + for ($n = 1; $n <= $total_pages; $n++) { + $in_window = $n <= $end_size + || $n > $total_pages - $end_size + || ($n >= $page - $mid_size && $n <= $page + $mid_size); + if (!$in_window) { + if ($dots) { + continue; + } + $links[] = '…'; + $dots = true; + continue; + } + $dots = false; + if ($n === $page) { + $links[] = '' . (int) $n . ''; + } else { + $url = esc_url(str_replace('%#%', (string) $n, $base)); + $links[] = '' . (int) $n . ''; + } + } + + // Next. + if ($page < $total_pages) { + $url = esc_url(str_replace('%#%', (string) ($page + 1), $base)); + $links[] = ''; + } + + return ''; + } +} + diff --git a/src/AKSRT/Core/WidgetAjax.php b/src/AKSRT/Core/WidgetAjax.php index d1daa471..d8b80ae4 100644 --- a/src/AKSRT/Core/WidgetAjax.php +++ b/src/AKSRT/Core/WidgetAjax.php @@ -61,11 +61,13 @@ class WidgetAjax { '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)), + 'topics' => sanitize_text_field((string) ($request->get_param('topics') ?? '')), + 'pay_type' => sanitize_key((string) ($request->get_param('pay_type') ?? '')), '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')), + 'paginate' => in_array(sanitize_key((string) ($request->get_param('paginate') ?? 'ajax')), ['none','ajax','number'], true) ? sanitize_key((string) ($request->get_param('paginate') ?? 'ajax')) : 'ajax', ]; $page = max(1, (int) ($request->get_param('page') ?? $request->get_param('paged') ?? 1)); return $this->payload(\AKSRT\Widgets\WidgetMainPosts::query_payload($instance, $page), $page); @@ -76,6 +78,15 @@ class WidgetAjax { return $this->fail(); } $default_count = max(1, min(20, (int) ($request->get_param('count') ?? 5))); + $style = sanitize_key((string) ($request->get_param('style') ?? 'mini')); + if (!in_array($style, ['list', 'card', 'mini'], true)) { + $style = 'mini'; + } + $paginate = sanitize_key((string) ($request->get_param('paginate') ?? 'none')); + if (!in_array($paginate, ['none', 'ajax', 'number'], true)) { + $paginate = 'none'; + } + $page = max(1, (int) ($request->get_param('page') ?? 1)); $tab = [ 'title' => '', 'category_id' => max(0, (int) ($request->get_param('cat') ?? $request->get_param('category_id') ?? 0)), @@ -83,15 +94,31 @@ class WidgetAjax { 'count' => max(0, min(20, (int) ($request->get_param('tab_count') ?? 0))), 'enabled' => true, ]; - $html = \AKSRT\Widgets\TabPostsWidget::render_tab_html($tab, $default_count); + $opts = [ + 'style' => $style, + 'paginate' => $paginate, + '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), + ]; + $payload = \AKSRT\Widgets\TabPostsWidget::render_tab_payload($tab, $default_count, $opts, $page); + $html = (string) ($payload['html'] ?? ''); if ($html === '') { $html = function_exists('aksrt_get_ajax_null') ? aksrt_get_ajax_null(__('暂无文章', 'aksrt')) : '

' . esc_html__('暂无文章', 'aksrt') . '

'; } else { - $html = '
' . $html . '
'; + $html = '
' . $html . '
'; } - return new \WP_REST_Response(['success' => true, 'html' => $html], 200); + return new \WP_REST_Response([ + 'success' => true, + 'html' => $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_paid_posts(\WP_REST_Request $request) { @@ -181,6 +208,8 @@ class WidgetAjax { '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)), + 'topics' => sanitize_text_field((string) ($request->get_param('topics') ?? '')), + 'pay_type' => sanitize_key((string) ($request->get_param('pay_type') ?? '')), ]; $html = \AKSRT\Widgets\WidgetOnelinePosts::render_html($instance); return new \WP_REST_Response(['success' => true, 'html' => $html], 200); @@ -193,7 +222,7 @@ class WidgetAjax { $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)), + 'outpost' => sanitize_text_field((string) ($request->get_param('outpost') ?? '')), 'outer' => sanitize_text_field((string) ($request->get_param('outer') ?? '')), ]; $html = \AKSRT\Widgets\RecentCommentsWidget::render_html($instance); diff --git a/src/AKSRT/Widgets/TabPostsWidget.php b/src/AKSRT/Widgets/TabPostsWidget.php index 24054024..1e9dcdb9 100644 --- a/src/AKSRT/Widgets/TabPostsWidget.php +++ b/src/AKSRT/Widgets/TabPostsWidget.php @@ -93,30 +93,72 @@ class TabPostsWidget extends \WP_Widget { * @param int $default_count * @return array */ - public static function tab_to_main_instance(array $tab, int $default_count): array { + public static function tab_to_main_instance(array $tab, int $default_count, array $opts = []): array { $count = !empty($tab['count']) ? (int) $tab['count'] : $default_count; + $style = sanitize_key((string) ($opts['style'] ?? $tab['style'] ?? 'mini')); + if (!in_array($style, ['list', 'card', 'mini'], true)) { + $style = 'mini'; + } + $paginate = sanitize_key((string) ($opts['paginate'] ?? $tab['paginate'] ?? 'none')); + if (!in_array($paginate, ['none', 'ajax', 'number'], true)) { + $paginate = 'none'; + } return [ - 'count' => max(1, min(30, $count)), - 'orderby' => sanitize_key((string) ($tab['orderby'] ?? 'date')), - 'cat' => absint($tab['category_id'] ?? 0), - 'style' => 'mini', - 'show_thumb' => 1, - 'show_meta' => 1, - 'show_number'=> 0, - 'paginate' => 'none', + 'count' => max(1, min(30, $count)), + 'orderby' => sanitize_key((string) ($tab['orderby'] ?? 'date')), + 'cat' => absint($tab['category_id'] ?? 0), + 'style' => $style, + 'show_thumb' => !isset($opts['show_thumb']) ? 1 : (int) $opts['show_thumb'], + 'show_meta' => !isset($opts['show_meta']) ? 1 : (int) $opts['show_meta'], + 'show_number' => !empty($opts['show_number']) ? 1 : 0, + 'paginate' => $paginate, ]; } /** * REST helper: render one tab list HTML. + * + * @param array $opts */ - public static function render_tab_html(array $tab, int $default_count): string { - $inst = self::tab_to_main_instance($tab, $default_count); + public static function render_tab_html(array $tab, int $default_count, array $opts = []): string { + $payload = self::render_tab_payload($tab, $default_count, $opts, 1); + return (string) ($payload['html'] ?? ''); + } + + /** + * Full tab payload (html + pager) for REST/ajax. + * + * @param array $opts + * @return array{html:string,paginate_html:string,has_more:bool,page:int,max_pages:int,total:int} + */ + public static function render_tab_payload(array $tab, int $default_count, array $opts = [], int $page = 1): array { + $inst = self::tab_to_main_instance($tab, $default_count, $opts); if (class_exists('\AKSRT\Widgets\WidgetMainPosts')) { - $payload = WidgetMainPosts::query_payload($inst, 1); - return (string) ($payload['html'] ?? ''); + return WidgetMainPosts::query_payload($inst, $page); } - return ''; + return [ + 'html' => '', + 'paginate_html' => '', + 'has_more' => false, + 'page' => 1, + 'max_pages' => 1, + 'total' => 0, + ]; + } + + /** Skeleton rows for lazy tab panels. */ + public static function skeleton_html(int $count = 5, string $style = 'mini'): string { + $count = max(1, min(12, $count)); + ob_start(); + echo '
'; + for ($i = 0; $i < $count; $i++) { + echo '
'; + echo '
'; + echo '
'; + echo '
'; + } + echo '
'; + return (string) ob_get_clean(); } public function widget($args, $instance): void { @@ -124,6 +166,14 @@ class TabPostsWidget extends \WP_Widget { $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); $count = absint($instance['count'] ?? 5); + $style = sanitize_key((string) ($instance['style'] ?? 'mini')); + if (!in_array($style, ['list', 'card', 'mini'], true)) { + $style = 'mini'; + } + $paginate = sanitize_key((string) ($instance['paginate'] ?? 'none')); + if (!in_array($paginate, ['none', 'ajax', 'number'], true)) { + $paginate = 'none'; + } $tabs = $this->normalize_tabs($instance['tabs'] ?? 'latest,comments,random'); $tabs = array_values(array_filter($tabs, static fn($t) => !empty($t['enabled']))); if (!$tabs) { @@ -147,7 +197,9 @@ class TabPostsWidget extends \WP_Widget {
+ data-count="" + data-style="" + data-paginate="">
    $tab) : $tab_key = 'tab-' . $i; @@ -175,24 +227,20 @@ class TabPostsWidget extends \WP_Widget { data-loaded="" role="tabpanel"> ' . $html . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - } else { - // Fallback to old mini list path. - $q = new \WP_Query(WidgetMainPosts::build_query_args(self::tab_to_main_instance($tab, $count), 1)); - if ($q->have_posts() && $use_shared) { - echo '
'; - aksrt_render_mini_list($q, ['context' => 'sidebar', 'show_thumb' => true, 'show_meta' => true], true); - echo '
'; + $opts = ['style' => $style, 'paginate' => $paginate]; + $payload = self::render_tab_payload($tab, $count, $opts, 1); + $html = (string) ($payload['html'] ?? ''); + if ($html !== '') { + echo '
' . $html . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + if (!empty($payload['paginate_html'])) { + echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } } else { echo function_exists('aksrt_get_widget_null') ? aksrt_get_widget_null(__('暂无文章', 'aksrt')) : '

' . esc_html__('暂无文章', 'aksrt') . '

'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } - wp_reset_postdata(); - } - else : ?> -
- + else : ?> +
+ @@ -223,6 +271,24 @@ class TabPostsWidget extends \WP_Widget {

+

+ +

+

+ +


sanitize_text_field((string) ($new_instance['title'] ?? '')), - 'count' => max(1, min(20, (int) ($new_instance['count'] ?? 5))), + 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')), + 'count' => max(1, min(20, (int) ($new_instance['count'] ?? 5))), + 'style' => $style, + 'paginate' => $paginate, ]; $tabs = []; if (isset($new_instance['tabs']) && is_array($new_instance['tabs'])) { diff --git a/src/AKSRT/Widgets/WidgetMainPosts.php b/src/AKSRT/Widgets/WidgetMainPosts.php index a42e3b1b..da78f0a8 100644 --- a/src/AKSRT/Widgets/WidgetMainPosts.php +++ b/src/AKSRT/Widgets/WidgetMainPosts.php @@ -61,6 +61,16 @@ class WidgetMainPosts extends \WP_Widget { $query['orderby'] = 'meta_value_num'; $query['order'] = 'DESC'; break; + case 'favorites': + $query['meta_key'] = '_aksrt_favorite_count'; + $query['orderby'] = 'meta_value_num'; + $query['order'] = 'DESC'; + break; + case 'downloads': + $query['meta_key'] = '_aksrt_res_download_count'; + $query['orderby'] = 'meta_value_num'; + $query['order'] = 'DESC'; + break; case 'rand': $query['orderby'] = 'rand'; break; @@ -72,6 +82,60 @@ class WidgetMainPosts extends \WP_Widget { $query['orderby'] = 'date'; $query['order'] = 'DESC'; } + + // Topics taxonomy (CSV term IDs). + $topics_raw = trim((string) ($instance['topics'] ?? '')); + if ($topics_raw !== '' && taxonomy_exists('topics')) { + $topic_ids = array_values(array_filter(array_map('intval', preg_split('/[,,\s]+/', $topics_raw) ?: []))); + if ($topic_ids) { + $query['tax_query'] = [ + [ + 'taxonomy' => 'topics', + 'field' => 'term_id', + 'terms' => $topic_ids, + ], + ]; + } + } + + // Pay type filter (reading/download/gallery/video/vip or any paid). + $pay_type = sanitize_key((string) ($instance['pay_type'] ?? '')); + if ($pay_type !== '' && $pay_type !== '0' && $pay_type !== 'no') { + $mq = isset($query['meta_query']) && is_array($query['meta_query']) ? $query['meta_query'] : []; + if ($pay_type === 'any' || $pay_type === 'paid') { + $mq[] = [ + 'relation' => 'OR', + [ + 'key' => '_aksrt_pay_price', + 'value' => 0, + 'compare' => '>', + 'type' => 'NUMERIC', + ], + [ + 'key' => '_aksrt_pay_type', + 'value' => ['reading', 'download', 'gallery', 'video', 'vip'], + 'compare' => 'IN', + ], + [ + 'key' => '_aksrt_visibility', + 'value' => ['pay', 'credits'], + 'compare' => 'IN', + ], + ]; + } else { + $mq[] = [ + 'key' => '_aksrt_pay_type', + 'value' => $pay_type, + ]; + } + if ($mq) { + if (count($mq) > 1) { + $mq['relation'] = 'AND'; + } + $query['meta_query'] = $mq; + } + } + return $query; } @@ -179,23 +243,32 @@ class WidgetMainPosts extends \WP_Widget { $max_pages = max(1, (int) $q->max_num_pages); $total = (int) $q->found_posts; $has_more = $page < $max_pages; + $base_qs = array_filter([ + 'count' => $count, + 'orderby' => sanitize_key((string) ($instance['orderby'] ?? 'date')), + 'cat' => (int) ($instance['cat'] ?? 0), + 'limit_day' => (int) ($instance['limit_day'] ?? 0), + 'topics' => (string) ($instance['topics'] ?? ''), + 'pay_type' => sanitize_key((string) ($instance['pay_type'] ?? '')), + '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' => $paginate, + ], static function ($v) { + return $v !== '' && $v !== null; + }); + $rest_base = add_query_arg($base_qs, rest_url('aksrt/v1/widgets/posts')); $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')); + $next = add_query_arg(['page' => $page + 1], $rest_base); $paginate_html = function_exists('aksrt_get_ajax_next_paginate') ? aksrt_get_ajax_next_paginate($total, $page, $count, $next) : ''; + } elseif ($paginate === 'number' && $max_pages > 1) { + $paginate_html = function_exists('aksrt_get_ajax_number_paginate') + ? aksrt_get_ajax_number_paginate($total, $page, $count, $rest_base) + : '
'; } else { $paginate_html = '
'; } @@ -230,7 +303,11 @@ class WidgetMainPosts extends \WP_Widget { } $rest = rest_url('aksrt/v1/widgets/posts'); - echo '
'; + $wrap_cls = 'aksrt-main-posts style-' . $style . ' ajaxpager'; + if ($style === 'mini') { + $wrap_cls .= ' zib-widget posts-mini-lists'; + } + echo '
'; echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo ''; @@ -268,6 +345,8 @@ class WidgetMainPosts extends \WP_Widget { + + @@ -287,6 +366,25 @@ class WidgetMainPosts extends \WP_Widget { + +

+

+ +

+

+

@@ -304,9 +402,13 @@ class WidgetMainPosts extends \WP_Widget { $style = 'list'; } $orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date')); - if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'likes', 'rand'], true)) { + if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'likes', 'favorites', 'downloads', 'rand'], true)) { $orderby = 'date'; } + $paginate = sanitize_key((string) ($new_instance['paginate'] ?? 'none')); + if (!in_array($paginate, ['none', 'ajax', 'number'], true)) { + $paginate = 'none'; + } return [ 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')), 'count' => max(1, min(30, (int) ($new_instance['count'] ?? 6))), @@ -314,7 +416,9 @@ 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', + 'topics' => sanitize_text_field((string) ($new_instance['topics'] ?? '')), + 'pay_type' => sanitize_key((string) ($new_instance['pay_type'] ?? '')), + 'paginate' => $paginate, '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, diff --git a/src/AKSRT/Widgets/WidgetProductList.php b/src/AKSRT/Widgets/WidgetProductList.php index 10cceac7..c9c67078 100644 --- a/src/AKSRT/Widgets/WidgetProductList.php +++ b/src/AKSRT/Widgets/WidgetProductList.php @@ -189,14 +189,32 @@ class WidgetProductList extends \WP_Widget { $paginate_html = ''; } } elseif ($paginate === 'number' && $max_pages > 1) { - $paginate_html = '
' . paginate_links([ - 'base' => add_query_arg('aksrt_product_page', '%#%'), - 'format' => '', - 'current' => $page, - 'total' => $max_pages, - 'prev_text' => '«', - 'next_text' => '»', - ]) . '
'; + $num_base = add_query_arg( + array_filter([ + 'per_page' => max(1, (int) ($instance['per_page'] ?? 8)), + 'orderby' => sanitize_key((string) ($instance['orderby'] ?? 'date')), + 'order' => sanitize_key((string) ($instance['order'] ?? 'DESC')), + 'cat_ids' => (string) ($instance['cat_ids'] ?? ''), + 'tag_ids' => (string) ($instance['tag_ids'] ?? ''), + 'discount_ids' => (string) ($instance['discount_ids'] ?? ''), + 'exclude_cat' => !empty($instance['exclude_cat']) ? 1 : 0, + 'style' => sanitize_key((string) ($instance['style'] ?? 'default')), + 'paginate' => 'number', + ], static function ($v) { + return $v !== '' && $v !== null; + }), + rest_url('aksrt/v1/shop/frontend/widgets/products') + ); + $paginate_html = function_exists('aksrt_get_ajax_number_paginate') + ? aksrt_get_ajax_number_paginate($total, $page, max(1, (int) ($instance['per_page'] ?? 8)), $num_base) + : '
' . paginate_links([ + 'base' => add_query_arg('aksrt_product_page', '%#%'), + 'format' => '', + 'current' => $page, + 'total' => $max_pages, + 'prev_text' => '«', + 'next_text' => '»', + ]) . '
'; } else { $paginate_html = '
'; }