$cat,
'initial_content' => $initial,
];
}
/**
* Render posts list HTML (zibll zib_get_documentnav_posts).
*/
public static function render_posts_html(\WP_Query $query): string {
if (!$query->have_posts()) {
$empty = function_exists('aksrt_get_null')
? aksrt_get_null(__('暂无相应内容', 'aksrt'), 40)
: '
' . esc_html__('暂无相应内容', 'aksrt') . '
';
return '' . $empty . '
';
}
$html = '';
while ($query->have_posts()) {
$query->the_post();
$time_ago = human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt');
$subtitle = (string) get_post_meta(get_the_ID(), 'subtitle', true);
if ($subtitle === '') {
$subtitle = (string) get_post_meta(get_the_ID(), 'aksrt_subtitle', true);
}
$html .= '
';
$html .= '' . esc_html($time_ago) . '';
$html .= esc_html(get_the_title());
if ($subtitle !== '') {
$html .= ' ' . esc_html($subtitle) . '';
}
$html .= '';
}
$html .= '
';
wp_reset_postdata();
return $html;
}
/**
* Simple paginate links for document nav container.
*/
public static function render_paginate(int $total, int $current, int $page_size, array $args = []): string {
$max = (int) ceil(max(0, $total) / max(1, $page_size));
if ($max <= 1) {
return '';
}
$current = max(1, min($current, $max));
$html = '';
for ($i = 1; $i <= $max; $i++) {
$url = add_query_arg(array_merge($args, ['paged' => $i]));
$cls = $i === $current ? 'current' : '';
$html .= '
' . (int) $i . ' ';
}
$html .= '
';
return $html;
}
/**
* Recursive category accordion HTML.
*/
public static function render_panels(int $cat_id, string $data_parent = 'accordion', string $class = 'panel', bool &$is_on_open = true): string {
if ($cat_id <= 0) {
return '';
}
$terms = _get_term_hierarchy('category');
if (empty($terms[$cat_id]) || !is_array($terms[$cat_id])) {
return '';
}
$html = '';
foreach ($terms[$cat_id] as $child) {
$child = (int) $child;
if ($child === $cat_id) {
continue;
}
$cat_obj = get_category($child);
if (!$cat_obj || is_wp_error($cat_obj)) {
continue;
}
$has_kids = !empty($terms[$child]);
if ($has_kids) {
$open = $is_on_open;
$is_on_open = false;
$html .= '
';
$html .= '
';
$html .= '
';
$html .= '
';
$html .= self::render_panels($child, 'dosc-cat-nav-panel-' . $child, 'panel panel-child', $is_on_open);
$html .= '
';
} else {
$html .= '
';
$html .= '' . esc_html($cat_obj->name);
$html .= '';
}
}
$html .= '
';
return $html;
}
public function ajax_posts(): void {
$search = isset($_REQUEST['search']) ? sanitize_text_field(wp_unslash((string) $_REQUEST['search'])) : '';
$cat_id = isset($_REQUEST['cat_id']) ? absint($_REQUEST['cat_id']) : 0;
$one_cat = isset($_REQUEST['one_cat']) ? absint($_REQUEST['one_cat']) : 0;
$paged = isset($_REQUEST['paged']) ? max(1, absint($_REQUEST['paged'])) : 1;
$page_size = 12;
if ($search === '' && $cat_id <= 0) {
wp_send_json(['error' => 1, 'ys' => 'danger', 'msg' => __('参数传入错误!', 'aksrt')]);
}
$args = [
'ignore_sticky_posts' => true,
'paged' => $paged,
'posts_per_page' => $page_size,
'post_status' => 'publish',
'post_type' => 'post',
];
if ($search !== '') {
$args['s'] = $search;
$args['cat'] = $one_cat > 0 ? $one_cat : 0;
// Persist simple history (user meta or cookie-less option list is optional).
$this->remember_search($search);
} else {
$args['cat'] = $cat_id;
}
$query = new \WP_Query($args);
$html = self::render_posts_html($query);
$html .= self::render_paginate(
(int) $query->found_posts,
$paged,
$page_size,
[
'action' => 'aksrt_documentnav_posts',
'cat_id' => $cat_id,
'search' => $search,
'one_cat' => $one_cat,
]
);
wp_send_json([
'error' => 0,
'html' => $html,
'total' => (int) $query->found_posts,
'history_search' => $this->history_buttons_html(),
]);
}
private function remember_search(string $term): void {
$term = trim($term);
if ($term === '' || mb_strlen($term) < 2) {
return;
}
$key = is_user_logged_in() ? 'aksrt_doc_search_history_' . get_current_user_id() : '';
$list = [];
if ($key !== '') {
$saved = get_user_meta(get_current_user_id(), 'aksrt_doc_search_history', true);
$list = is_array($saved) ? $saved : [];
} else {
$cookie = isset($_COOKIE['aksrt_doc_search_history']) ? wp_unslash((string) $_COOKIE['aksrt_doc_search_history']) : '';
$decoded = json_decode($cookie, true);
$list = is_array($decoded) ? $decoded : [];
}
$list = array_values(array_unique(array_filter(array_map('strval', $list))));
array_unshift($list, $term);
$list = array_slice(array_values(array_unique($list)), 0, 8);
if ($key !== '') {
update_user_meta(get_current_user_id(), 'aksrt_doc_search_history', $list);
} elseif (!headers_sent()) {
setcookie('aksrt_doc_search_history', wp_json_encode($list), time() + WEEK_IN_SECONDS, COOKIEPATH ?: '/', COOKIE_DOMAIN, is_ssl(), true);
}
}
/**
* @return list
*/
private function get_history(): array {
if (is_user_logged_in()) {
$saved = get_user_meta(get_current_user_id(), 'aksrt_doc_search_history', true);
return is_array($saved) ? array_values(array_filter(array_map('strval', $saved))) : [];
}
$cookie = isset($_COOKIE['aksrt_doc_search_history']) ? wp_unslash((string) $_COOKIE['aksrt_doc_search_history']) : '';
$decoded = json_decode($cookie, true);
return is_array($decoded) ? array_values(array_filter(array_map('strval', $decoded))) : [];
}
public function history_buttons_html(): string {
$items = $this->get_history();
if (!$items) {
return '';
}
$html = '';
foreach ($items as $term) {
$html .= '' . esc_html($term) . '';
}
return $html;
}
public function register_meta_box(): void {
add_meta_box(
'aksrt_documentnav_meta',
__('文档导航设置', 'aksrt'),
[$this, 'render_meta_box'],
'page',
'side',
'default'
);
}
public function render_meta_box(\WP_Post $post): void {
$tpl = (string) get_post_meta($post->ID, '_wp_page_template', true);
if ($tpl !== 'templates/pages/page-documentnav.php') {
echo '' . esc_html__('将模板设为「AKSRT - 文档导航」后配置。', 'aksrt') . '
';
return;
}
$opt = self::get_options((int) $post->ID);
wp_nonce_field('aksrt_documentnav_meta', 'aksrt_documentnav_meta_nonce');
$cats = get_categories(['hide_empty' => false, 'parent' => 0]);
?>
$cat,
'initial_content' => $initial,
]);
}
}