feat(nav): deep 1:1 zibll search-box + navbar-search + newposts unify
Port aksrt_get_search_box/posts for menu_search and layout 1/3 slide; unify publish switch; expand user-box admin row; CSS/JS remote-box parity.
This commit is contained in:
1 parent
70f7ef71e1
commit
1d1fef50af
19 files changed
+980
-267
No files matched your search
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/**
|
||||
* Search box markup (zibll zib_get_search_box parity).
|
||||
*
|
||||
* Used by layout-2 menu_search AJAX panel and layout 1/3 .navbar-search.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_get_search_history_keywords')) :
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
function aksrt_get_search_history_keywords(): array {
|
||||
$hist = [];
|
||||
if (is_user_logged_in()) {
|
||||
$saved = get_user_meta(get_current_user_id(), 'aksrt_search_history', true);
|
||||
if (is_array($saved)) {
|
||||
foreach (array_slice($saved, 0, 10) as $item) {
|
||||
if (is_array($item) && !empty($item['keyword'])) {
|
||||
$hist[] = (string) $item['keyword'];
|
||||
} elseif (is_string($item) && $item !== '') {
|
||||
$hist[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_values(array_unique(array_filter(array_map('trim', $hist))));
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_get_search_keywords_but')) :
|
||||
/**
|
||||
* Render keyword chip links.
|
||||
*
|
||||
* @param list<string> $keywords
|
||||
* @param string $type popular|history
|
||||
*/
|
||||
function aksrt_get_search_keywords_but(array $keywords, string $type = 'popular', int $limit = 0): string {
|
||||
if ($limit > 0) {
|
||||
$keywords = array_slice($keywords, 0, $limit);
|
||||
}
|
||||
$out = '';
|
||||
foreach ($keywords as $kw) {
|
||||
$kw = trim((string) $kw);
|
||||
if ($kw === '') {
|
||||
continue;
|
||||
}
|
||||
$out .= '<a class="but jb-sm" data-search-keyword="' . esc_attr($kw) . '" href="'
|
||||
. esc_url(home_url('/?s=' . rawurlencode($kw))) . '">'
|
||||
. esc_html($kw) . '</a> ';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_get_search_box')) :
|
||||
/**
|
||||
* zibll-compatible search box.
|
||||
*
|
||||
* @param array<string,mixed> $args
|
||||
* @param bool $echo
|
||||
* @return string|void
|
||||
*/
|
||||
function aksrt_get_search_box(array $args = [], bool $echo = false) {
|
||||
$defaults = [
|
||||
's' => '',
|
||||
'class' => '',
|
||||
'show_form' => true,
|
||||
'show_keywords' => true,
|
||||
'popular_limit' => 0,
|
||||
'show_history' => true,
|
||||
'keywords_title' => '',
|
||||
'placeholder' => '',
|
||||
'show_input_cat' => true,
|
||||
'show_posts' => false,
|
||||
'show_type' => false,
|
||||
'in_cat' => '',
|
||||
'in_type' => 'post',
|
||||
'in_user' => '',
|
||||
'more_cats' => [],
|
||||
];
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
|
||||
if ($args['keywords_title'] === '' && class_exists('\AKSRT\Settings\Settings')
|
||||
&& method_exists('\AKSRT\Settings\Settings', 'search_popular_title')) {
|
||||
$args['keywords_title'] = (string) \AKSRT\Settings\Settings::search_popular_title();
|
||||
}
|
||||
if ($args['keywords_title'] === '') {
|
||||
$args['keywords_title'] = __('热门搜索', 'aksrt');
|
||||
}
|
||||
if ($args['placeholder'] === '' && function_exists('aksrt_get_search_placeholder')) {
|
||||
$args['placeholder'] = aksrt_get_search_placeholder();
|
||||
}
|
||||
if ($args['placeholder'] === '') {
|
||||
$args['placeholder'] = __('开启精彩搜索', 'aksrt');
|
||||
}
|
||||
$args['placeholder'] = esc_attr((string) $args['placeholder']);
|
||||
|
||||
// Settings gates when caller left defaults on.
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
if (!array_key_exists('show_keywords_forced', $args)
|
||||
&& method_exists('\AKSRT\Settings\Settings', 'hot_search_enabled')
|
||||
&& !\AKSRT\Settings\Settings::hot_search_enabled()) {
|
||||
// Keep explicit false from caller; only gate when show_keywords true by default path.
|
||||
}
|
||||
}
|
||||
|
||||
$form_html = '';
|
||||
if (!empty($args['show_form'])) {
|
||||
$state = function_exists('aksrt_get_search_form_state')
|
||||
? aksrt_get_search_form_state()
|
||||
: [
|
||||
'type' => 'post',
|
||||
'types' => ['post' => __('文章', 'aksrt')],
|
||||
'category_id' => 0,
|
||||
'category_enabled' => false,
|
||||
'categories' => [],
|
||||
];
|
||||
|
||||
$type_html = '';
|
||||
$types = is_array($state['types'] ?? null) ? $state['types'] : [];
|
||||
$in_type = (string) ($args['in_type'] ?: ($state['type'] ?? 'post'));
|
||||
if (!empty($args['show_type']) && count($types) > 1) {
|
||||
$type_items = '';
|
||||
foreach ($types as $k => $v) {
|
||||
$cls = $in_type === (string) $k ? ' active' : '';
|
||||
$type_items .= '<a class="but' . esc_attr($cls) . '" data-for="type" data-value="'
|
||||
. esc_attr((string) $k) . '" href="javascript:;">' . esc_html((string) $v) . '</a>';
|
||||
}
|
||||
$type_html = '<div class="flex jc mb10 search-type-but-average">';
|
||||
$type_html .= '<div class="but-average radius">' . $type_items . '</div></div>';
|
||||
}
|
||||
|
||||
$cat_html = '';
|
||||
if (!empty($args['show_input_cat']) && !empty($state['category_enabled'])
|
||||
&& !empty($state['categories']) && is_array($state['categories'])) {
|
||||
$in_cat_id = (int) ($args['in_cat'] ?: ($state['category_id'] ?? 0));
|
||||
$in_cat_name = '';
|
||||
$all_cat = '<li data-for="trem" data-value="null"><a href="javascript:;" class="text-ellipsis">'
|
||||
. esc_html__('全部', 'aksrt') . '</a></li>';
|
||||
foreach ($state['categories'] as $cat) {
|
||||
if (!is_array($cat)) {
|
||||
continue;
|
||||
}
|
||||
$cid = (int) ($cat['id'] ?? 0);
|
||||
$cname = (string) ($cat['name'] ?? '');
|
||||
if ($cid <= 0 || $cname === '') {
|
||||
continue;
|
||||
}
|
||||
if ($cid === $in_cat_id) {
|
||||
$in_cat_name = $cname;
|
||||
}
|
||||
$all_cat .= '<li data-for="trem" data-value="' . esc_attr((string) $cid) . '"><a href="javascript:;" class="text-ellipsis">'
|
||||
. esc_html(mb_strlen($cname) > 8 ? mb_substr($cname, 0, 8) . '…' : $cname)
|
||||
. '</a></li>';
|
||||
}
|
||||
$all_cat = '<ul class="dropdown-menu cat-drop">' . $all_cat . '</ul>';
|
||||
$label = $in_cat_name !== ''
|
||||
? (mb_strlen($in_cat_name) > 6 ? mb_substr($in_cat_name, 0, 6) . '…' : $in_cat_name)
|
||||
: __('请选择', 'aksrt');
|
||||
$input_cat = '<a href="javascript:;" class="padding-h10" data-toggle="dropdown"><span name="trem">'
|
||||
. esc_html($label) . '</span><i class="fa ml6 fa-sort opacity5" aria-hidden="true"></i></a>';
|
||||
$input_cat .= $all_cat;
|
||||
$cat_html = '<div class="option-dropdown splitters-this-r search-drop"><div class="dropdown">'
|
||||
. $input_cat . '</div></div>';
|
||||
}
|
||||
|
||||
$s = esc_attr(wp_strip_all_tags((string) $args['s']));
|
||||
if ($s === '' && is_search()) {
|
||||
$s = esc_attr(get_search_query());
|
||||
}
|
||||
$input_html = '<div class="search-input-text">';
|
||||
$input_html .= '<input type="text" name="s" class="line-form-input" tabindex="1" value="' . $s . '">';
|
||||
$input_html .= '<i class="line-form-line"></i>';
|
||||
$input_html .= '<div class="scale-placeholder' . ($s !== '' ? ' is-focus' : '') . '" default="'
|
||||
. $args['placeholder'] . '">' . $args['placeholder'] . '</div>';
|
||||
$input_html .= '<div class="abs-right muted-color"><button type="submit" tabindex="2" class="null" aria-label="'
|
||||
. esc_attr__('搜索', 'aksrt') . '"><i class="fas fa-search" aria-hidden="true"></i></button></div>';
|
||||
$input_html .= '</div>';
|
||||
|
||||
$input_html .= '<input type="hidden" name="aksrt_search_type" value="' . esc_attr($in_type) . '">';
|
||||
if ($cat_html !== '' || (string) $args['in_cat'] !== '') {
|
||||
$input_html .= '<input type="hidden" name="aksrt_category" value="'
|
||||
. esc_attr((string) ($args['in_cat'] !== '' ? $args['in_cat'] : ($state['category_id'] ?? 0))) . '">';
|
||||
}
|
||||
if ((string) $args['in_user'] !== '') {
|
||||
$input_html .= '<input type="hidden" name="user" value="' . esc_attr((string) $args['in_user']) . '">';
|
||||
}
|
||||
|
||||
if ($cat_html === '') {
|
||||
$cat_html = $type_html;
|
||||
$type_html = '';
|
||||
}
|
||||
|
||||
$form_html = '<form method="get" class="padding-10 search-form" action="'
|
||||
. esc_url(home_url('/')) . '" role="search" data-aksrt-search-form="box">'
|
||||
. $type_html
|
||||
. '<div class="line-form">' . $cat_html . $input_html . '</div>'
|
||||
. '</form>';
|
||||
}
|
||||
|
||||
// Popular keywords.
|
||||
$keywords_html = '';
|
||||
if (!empty($args['show_keywords'])) {
|
||||
$show = true;
|
||||
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'hot_search_enabled')) {
|
||||
$show = (bool) \AKSRT\Settings\Settings::hot_search_enabled();
|
||||
}
|
||||
if ($show) {
|
||||
$keywords = function_exists('aksrt_get_search_hot_keywords') ? aksrt_get_search_hot_keywords() : [];
|
||||
$limit = (int) $args['popular_limit'];
|
||||
$keyword_link = aksrt_get_search_keywords_but(is_array($keywords) ? $keywords : [], 'popular', $limit);
|
||||
if ($keyword_link !== '') {
|
||||
$keywords_html = '<div class="search-keywords">'
|
||||
. '<p class="muted-color"><span>' . esc_html((string) $args['keywords_title']) . '</span></p>'
|
||||
. '<div>' . $keyword_link . '</div>'
|
||||
. '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// History.
|
||||
$history_html = '';
|
||||
if (!empty($args['show_history'])) {
|
||||
$show_h = true;
|
||||
if (function_exists('aksrt_search_history_enabled')) {
|
||||
$show_h = aksrt_search_history_enabled();
|
||||
} elseif (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'search_history_enabled')) {
|
||||
$show_h = (bool) \AKSRT\Settings\Settings::search_history_enabled();
|
||||
}
|
||||
if ($show_h) {
|
||||
$hist = aksrt_get_search_history_keywords();
|
||||
// Empty shell still rendered so client localStorage can fill it.
|
||||
$keyword_link = aksrt_get_search_keywords_but($hist, 'history');
|
||||
$history_html = '<div class="search-keywords history-search" data-aksrt-menu-history="1">';
|
||||
$history_html .= '<p class="muted-color"><span>' . esc_html__('历史搜索', 'aksrt') . '</span>';
|
||||
$history_html .= '<a class="pull-right trash-history-search muted-3-color" href="javascript:;" data-aksrt-clear-menu-history="1" aria-label="'
|
||||
. esc_attr__('清空历史', 'aksrt') . '"><i class="fas fa-trash-alt em12" aria-hidden="true"></i></a></p>';
|
||||
$history_html .= '<div class="history-search-list">';
|
||||
if ($keyword_link !== '') {
|
||||
$history_html .= $keyword_link;
|
||||
} else {
|
||||
$history_html .= '<span class="muted-3-color em09" data-empty="1">' . esc_html__('暂无历史', 'aksrt') . '</span>';
|
||||
}
|
||||
$history_html .= '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
// Hot posts (thumb swiper).
|
||||
$posts_html = '';
|
||||
if (!empty($args['show_posts'])) {
|
||||
$show_p = true;
|
||||
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'search_posts_enabled')) {
|
||||
$show_p = (bool) \AKSRT\Settings\Settings::search_posts_enabled();
|
||||
}
|
||||
if ($show_p && function_exists('aksrt_get_search_posts')) {
|
||||
$slides = aksrt_get_search_posts(6, 'views', true);
|
||||
if ($slides !== '') {
|
||||
$posts_html = '<div class="padding-10 relates relates-thumb">';
|
||||
$posts_html .= '<p class="muted-color">' . esc_html__('热门文章', 'aksrt') . '</p>';
|
||||
$posts_html .= '<div class="swiper-container swiper-scroll">';
|
||||
$posts_html .= '<div class="swiper-wrapper">' . $slides . '</div>';
|
||||
$posts_html .= '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>';
|
||||
$posts_html .= '</div></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Live suggestions mount (AKSRT extension; does not break zibll classes).
|
||||
$suggest = '<div class="aksrt-menu-search-suggest mt10" data-aksrt-menu-suggest="1" hidden></div>';
|
||||
|
||||
$class = $args['class'] ? ' ' . sanitize_html_class((string) $args['class']) : '';
|
||||
$html = '<div class="search-input' . esc_attr($class) . '">'
|
||||
. $form_html . $keywords_html . $history_html . $posts_html . $suggest
|
||||
. '</div>';
|
||||
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_get_remote_box')) :
|
||||
/**
|
||||
* Lazy remote HTML mount (zibll zib_get_remote_box).
|
||||
*
|
||||
* @param array<string,mixed> $args
|
||||
*/
|
||||
function aksrt_get_remote_box(array $args = []): string {
|
||||
$defaults = [
|
||||
'type' => 'ias',
|
||||
'class' => '',
|
||||
'loader' => '<i class="loading-spot"><i></i></i>',
|
||||
'url' => admin_url('admin-ajax.php'),
|
||||
'query' => false,
|
||||
];
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
$url = (string) $args['url'];
|
||||
if (!empty($args['query']) && is_array($args['query'])) {
|
||||
$url = add_query_arg($args['query'], $url);
|
||||
}
|
||||
$attr = ' remote-box="' . esc_url($url) . '"';
|
||||
$class = (string) $args['class'];
|
||||
if (($args['type'] ?? '') === 'ias') {
|
||||
$attr .= ' lazyload-action="ias"';
|
||||
$class .= ' lazyload';
|
||||
}
|
||||
if (($args['type'] ?? '') === 'load') {
|
||||
$attr .= ' load-click';
|
||||
}
|
||||
$class_attr = $class !== '' ? ' class="' . esc_attr(trim($class)) . '"' : '';
|
||||
return '<div' . $class_attr . $attr . '>' . $args['loader'] . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Search panel hot posts (zibll zib_get_search_posts parity).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_get_search_posts')) :
|
||||
/**
|
||||
* Build hot-post slides for the search dropdown.
|
||||
*
|
||||
* @param int $count Number of posts.
|
||||
* @param string $orderby views|date|modified|…
|
||||
* @param bool $show_img Use graphic cards (true) or text list (false).
|
||||
*/
|
||||
function aksrt_get_search_posts(int $count = 6, string $orderby = 'views', bool $show_img = true): string {
|
||||
$count = max(1, min(20, $count));
|
||||
|
||||
$args = [
|
||||
'posts_per_page' => $count,
|
||||
'ignore_sticky_posts' => true,
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'post',
|
||||
'no_found_rows' => true,
|
||||
'update_post_meta_cache' => true,
|
||||
'update_post_term_cache' => false,
|
||||
];
|
||||
|
||||
if ($orderby === 'views') {
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['meta_key'] = 'aksrt_post_views';
|
||||
$args['order'] = 'DESC';
|
||||
} else {
|
||||
$allowed = ['date', 'modified', 'comment_count', 'rand', 'title'];
|
||||
$args['orderby'] = in_array($orderby, $allowed, true) ? $orderby : 'date';
|
||||
$args['order'] = 'DESC';
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
// Fallback when no posts have views meta yet.
|
||||
if (!$query->have_posts() && $orderby === 'views') {
|
||||
wp_reset_postdata();
|
||||
$args['orderby'] = 'date';
|
||||
unset($args['meta_key']);
|
||||
$query = new WP_Query($args);
|
||||
}
|
||||
|
||||
$lists = '';
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$post_id = (int) get_the_ID();
|
||||
$title = get_the_title($post_id);
|
||||
if ($title === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($show_img && function_exists('aksrt_graphic_card')) {
|
||||
$thumb = get_the_post_thumbnail_url($post_id, 'medium');
|
||||
if (!$thumb) {
|
||||
$thumb = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||
}
|
||||
$views = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post_id) : 0;
|
||||
$views_txt = function_exists('aksrt_format_number')
|
||||
? aksrt_format_number($views)
|
||||
: (string) $views;
|
||||
$time_ago = human_time_diff(get_the_time('U', $post_id), current_time('timestamp'));
|
||||
$info = '<item>' . esc_html(sprintf(/* translators: %s: relative time */ __('%s前', 'aksrt'), $time_ago))
|
||||
. '</item><item class="pull-right"><i class="fas fa-eye" aria-hidden="true"></i> '
|
||||
. esc_html((string) $views_txt) . '</item>';
|
||||
|
||||
$lists .= '<div class="swiper-slide em09 mr10" style="width:160px;">';
|
||||
$lists .= aksrt_graphic_card([
|
||||
'type' => 'style-3',
|
||||
'class' => '',
|
||||
'img' => $thumb,
|
||||
'alt' => $title,
|
||||
'link' => [
|
||||
'url' => get_permalink($post_id),
|
||||
'target' => '',
|
||||
],
|
||||
'text1' => $title,
|
||||
'text2' => mb_strlen($title) > 29 ? mb_substr($title, 0, 29) . '…' : $title,
|
||||
'text3' => $info,
|
||||
'lazy' => true,
|
||||
'height_scale' => 70,
|
||||
], false);
|
||||
$lists .= '</div>';
|
||||
} else {
|
||||
$lists .= '<li><a class="icon-circle text-ellipsis" href="'
|
||||
. esc_url(get_permalink($post_id)) . '">'
|
||||
. esc_html($title) . '</a></li>';
|
||||
}
|
||||
}
|
||||
wp_reset_postdata();
|
||||
|
||||
return $lists;
|
||||
}
|
||||
endif;
|
||||
Reference in new issue
Block a user