$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 = ''; 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 .= '' . esc_html($cat_obj->name); $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, ]); } }