Files
wordpress-theme-aksrt/inc/helpers/aksrt-ajax-list.php
T
kate522 9375b1c30c refactor(assets): vendor 资产迁入标准目录并全仓去除 zibll 标识
- assets/vendor 全量迁移: fontawesome5→assets/fontawesome5, css→assets/css,
  js→assets/js/runtime(避开 14 个同名自有文件), img 合并去重→assets/img,
  fonts→assets/fonts; 删除 assets/vendor
- libs 五个与 widgets/third-party 字节相同的库不重复入库, loader paths 改指向
- 运行时切换: _win.uri=assets 根, loader baseUrl=/js/runtime, enlighter 注入
  路径同步; PHP 7 个引用文件切换并改名 $zibll_*→$runtime_*
- 去品牌: Qinver 头注释/品牌 console.log/演示链接清除, 默认文案中性化
- 功能标识符改名: zib__→aksrt__, zib_ajax→aksrt_ajax, window.zib→
  window.aksrtLegacy, zibllblock/*→aksrtblock/*, .zib-widget→.aksrt-panel,
  .zib-slider→.aksrt-slider, zib_menu_options meta 键等
- 自有 CSS 改名: legacy-utilities/compat-vars/footer shell
- admin SPA 重建; 契约测试同步(路径/断言/文件更名)
- 例外保留: tests/visual 对照环境与 fixtures 前缀(外部 Zibll 产品引用)

验证: php -l 133 个改动文件通过; runtime 86 个 JS node --check 通过;
契约测试 68/70(2 个失败经 stash 对照确认为存量问题)
2026-08-22 16:16:30 +08:00

196 lines
6.7 KiB
PHP

<?php
/**
* Ajax list helpers and declarative modal trigger markup.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_ajax_null')) {
/**
* Empty state for AJAX list replace.
*/
function aksrt_get_ajax_null(?string $text = null, $margin = 60, string $img = 'null.svg'): string {
if (null === $text) {
$text = __('内容空空如也', 'aksrt');
}
if (function_exists('aksrt_get_null')) {
return aksrt_get_null($text, $margin, $img, 'ajax-item aksrt-ajax-null');
}
return '<div class="text-center ajax-item aksrt-ajax-null" style="padding:' . esc_attr((string) $margin) . 'px 0;">'
. '<p class="muted-3-color">' . esc_html((string) $text) . '</p></div>';
}
}
if (!function_exists('aksrt_get_ajax_next_paginate')) {
/**
* Load-more style paginate block (legacy subset).
*
* @param int $count_all Total items.
* @param int $page Current page (1-based).
* @param int $per_page Per page.
* @param string $ajax_url Next page URL (full or REST).
* @param string $pag_class Wrapper class.
* @param string $next_class Link class.
* @param string $label Button label.
*/
function aksrt_get_ajax_next_paginate(
int $count_all,
int $page = 1,
int $per_page = 10,
string $ajax_url = '',
string $pag_class = 'text-center theme-pagination ajax-pag',
string $next_class = 'next-page ajax-next',
string $label = ''
): string {
$page = max(1, $page);
$per_page = max(1, $per_page);
$max = (int) ceil($count_all / $per_page);
if ($page >= $max || $count_all <= 0) {
return '<div class="' . esc_attr($pag_class) . ' hide"><div class="' . esc_attr($next_class) . '"><a href="#"></a></div></div>';
}
if ($label === '') {
$label = __('加载更多', 'aksrt');
}
$next = $page + 1;
$url = $ajax_url !== '' ? $ajax_url : '#';
// Prefer caller-provided URL already containing next page.
return '<div class="' . esc_attr($pag_class) . '">'
. '<div class="' . esc_attr($next_class) . '">'
. '<a href="' . esc_url($url) . '" class="ajax-next" data-page="' . esc_attr((string) $next) . '">'
. esc_html($label)
. '</a></div></div>';
}
}
if (!function_exists('aksrt_get_modal_link')) {
/**
* Build a declarative modal runtime trigger.
*
* @param array{
* tag?:string,class?:string,text?:string,url?:string,
* data_class?:string,height?:int,mobile_bottom?:bool,
* query_arg?:array<string,scalar>
* } $args
*/
function aksrt_get_modal_link(array $args = []): string {
$tag = sanitize_key((string) ($args['tag'] ?? 'a'));
if (!in_array($tag, ['a', 'button', 'span'], true)) {
$tag = 'a';
}
$class = trim((string) ($args['class'] ?? ''));
$text = (string) ($args['text'] ?? __('打开', 'aksrt'));
$url = (string) ($args['url'] ?? '');
if ($url === '' && !empty($args['query_arg']) && is_array($args['query_arg'])) {
// Prefer REST absolute URL if provided via action helper.
$url = add_query_arg($args['query_arg'], admin_url('admin-ajax.php'));
}
$data_class = (string) ($args['data_class'] ?? 'modal-mini full-sm');
$height = isset($args['height']) ? (int) $args['height'] : 0;
$mobile = !isset($args['mobile_bottom']) || !empty($args['mobile_bottom']);
$cache = !isset($args['cache']) || !empty($args['cache']);
$attrs = ' class="' . esc_attr(trim($class . ' aksrt-modal-link')) . '"';
$attrs .= ' data-aksrt-modal="remote"';
$attrs .= ' data-aksrt-modal-url="' . esc_url($url) . '"';
$attrs .= ' data-aksrt-modal-class="' . esc_attr($data_class) . '"';
if (!$cache) {
$attrs .= ' data-aksrt-modal-cache="false"';
}
if ($height > 0) {
$attrs .= ' data-aksrt-modal-height="' . esc_attr((string) $height) . '"';
}
if ($mobile) {
$attrs .= ' data-aksrt-modal-mobile-bottom="true"';
}
if ($tag === 'a') {
$attrs .= ' href="' . esc_url($url !== '' ? $url : '#') . '"';
} else {
$attrs .= ' type="button"';
}
return '<' . $tag . $attrs . '>' . esc_html($text) . '</' . $tag . '>';
}
}
if (!function_exists('aksrt_get_ajax_number_paginate')) {
/**
* Numbered AJAX pager (legacy 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 '<div class="' . esc_attr($pag_class) . ' hide"><div class="' . esc_attr($next_class) . '"><a href="#"></a></div></div>';
}
$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[] = '<a class="' . esc_attr($next_class) . ' prev page-numbers" ajax-replace="true" href="' . $url . '"><i class="fa fas fa-angle-left em12" aria-hidden="true"></i></a>';
}
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[] = '<span class="page-numbers dots">&hellip;</span>';
$dots = true;
continue;
}
$dots = false;
if ($n === $page) {
$links[] = '<span class="page-numbers current">' . (int) $n . '</span>';
} else {
$url = esc_url(str_replace('%#%', (string) $n, $base));
$links[] = '<a class="' . esc_attr($next_class) . ' page-numbers" ajax-replace="true" href="' . $url . '">' . (int) $n . '</a>';
}
}
// Next.
if ($page < $total_pages) {
$url = esc_url(str_replace('%#%', (string) ($page + 1), $base));
$links[] = '<a class="' . esc_attr($next_class) . ' next page-numbers" ajax-replace="true" href="' . $url . '"><i class="fa fas fa-angle-right em12" aria-hidden="true"></i></a>';
}
return '<div class="pagenav ' . esc_attr($pag_class) . '">' . implode('', $links) . '</div>';
}
}