410 lines
16 KiB
PHP
410 lines
16 KiB
PHP
<?php
|
||
/**
|
||
* Search box markup (legacy parity).
|
||
*
|
||
* Used by layout-2 menu_search AJAX panel and layout 1/3 .navbar-search.
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
if (!function_exists('aksrt_save_history_search')) :
|
||
/** Store the legacy history_search cookie (newest first, maximum thirty). */
|
||
function aksrt_save_history_search(string $search): void {
|
||
$search = trim(wp_strip_all_tags($search));
|
||
$search_text = aksrt_get_search_keywords_text($search);
|
||
if ($search_text === '' || mb_strlen($search_text) >= 30 || headers_sent()) {
|
||
return;
|
||
}
|
||
$history = aksrt_get_search_history_keywords();
|
||
$history = array_values(array_filter($history, static function (string $item) use ($search_text): bool {
|
||
return aksrt_get_search_keywords_text($item) !== $search_text;
|
||
}));
|
||
array_unshift($history, $search);
|
||
$history = array_slice($history, 0, 30);
|
||
setcookie('history_search', wp_json_encode($history), [
|
||
'expires' => time() + MONTH_IN_SECONDS,
|
||
'path' => COOKIEPATH ?: '/',
|
||
'domain' => COOKIE_DOMAIN,
|
||
'secure' => is_ssl(),
|
||
'httponly' => false,
|
||
'samesite' => 'Lax',
|
||
]);
|
||
$_COOKIE['history_search'] = wp_json_encode($history);
|
||
}
|
||
endif;
|
||
|
||
if (!function_exists('aksrt_get_main_search')) :
|
||
/** legacy main-search defaults backed only by the reference option IDs. */
|
||
function aksrt_get_main_search(array $args = [], bool $echo = false) {
|
||
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||
$search_cat = !array_key_exists('search_cat', $settings) || !empty($settings['search_cat']);
|
||
$search_type = !array_key_exists('search_type', $settings) || !empty($settings['search_type']);
|
||
$defaults = [
|
||
'class' => '',
|
||
'show_keywords' => !array_key_exists('search_popular_key', $settings) || !empty($settings['search_popular_key']),
|
||
'show_history' => !array_key_exists('search_history', $settings) || !empty($settings['search_history']),
|
||
'show_posts' => !array_key_exists('search_posts', $settings) || !empty($settings['search_posts']),
|
||
'show_input_cat' => $search_cat,
|
||
'more_cats' => $search_cat ? (array) ($settings['search_more_cat_obj'] ?? []) : [],
|
||
'in_cat' => $search_cat ? ($settings['search_cat_in'] ?? '') : '',
|
||
'show_type' => $search_type,
|
||
'in_type' => $search_type ? sanitize_key((string) ($settings['search_type_in'] ?? 'post')) : '',
|
||
'in_user' => '',
|
||
];
|
||
return aksrt_get_search_box(wp_parse_args($args, $defaults), $echo);
|
||
}
|
||
endif;
|
||
|
||
if (!function_exists('aksrt_get_search_history_keywords')) :
|
||
/**
|
||
* @return list<string>
|
||
*/
|
||
function aksrt_get_search_history_keywords(): array {
|
||
$raw = isset($_COOKIE['history_search'])
|
||
? wp_unslash((string) $_COOKIE['history_search'])
|
||
: '';
|
||
$decoded = $raw !== '' ? json_decode(stripslashes($raw), true) : [];
|
||
if (!is_array($decoded)) {
|
||
return [];
|
||
}
|
||
$hist = array_map(
|
||
static fn($item): string => sanitize_text_field((string) $item),
|
||
array_slice($decoded, 0, 30)
|
||
);
|
||
return array_values(array_unique(array_filter(array_map('trim', $hist))));
|
||
}
|
||
endif;
|
||
|
||
if (!function_exists('aksrt_get_search_keywords_text')) :
|
||
function aksrt_get_search_keywords_text(string $search): string {
|
||
$search = str_replace('&type', '&type', $search);
|
||
$index = strpos($search, '&type=');
|
||
return trim($index === false ? $search : substr($search, 0, $index));
|
||
}
|
||
endif;
|
||
|
||
if (!function_exists('aksrt_update_search_keywords')) :
|
||
function aksrt_update_search_keywords(string $search): void {
|
||
$search = trim(wp_strip_all_tags($search));
|
||
$text = aksrt_get_search_keywords_text($search);
|
||
if (mb_strlen($text) < 2 || mb_strlen($text) > 8) {
|
||
return;
|
||
}
|
||
if (class_exists('\AKSRT\Settings\Settings') && !\AKSRT\Settings\Settings::hot_search_enabled()) {
|
||
return;
|
||
}
|
||
$keywords = get_option('search_keywords', []);
|
||
$keywords = is_array($keywords) ? $keywords : [];
|
||
$limit = class_exists('\AKSRT\Settings\Settings')
|
||
? max(10, min(50, (int) \AKSRT\Settings\Settings::get_value('search_popular_key_num', 20)))
|
||
: 20;
|
||
$keywords = array_slice($keywords, 0, $limit + 10, true);
|
||
$keywords[$search] = isset($keywords[$search]) ? (int) $keywords[$search] + 1 : 1;
|
||
arsort($keywords, SORT_NUMERIC);
|
||
update_option('search_keywords', $keywords, false);
|
||
}
|
||
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;
|
||
}
|
||
$text = aksrt_get_search_keywords_text($kw);
|
||
$query = ['s' => $text];
|
||
if (preg_match('/&type=([a-z0-9_-]+)/i', $kw, $match)) {
|
||
$query['type'] = sanitize_key($match[1]);
|
||
}
|
||
$out .= '<a class="search_keywords muted-2-color but em09 mr6 mb6" data-search-keyword="' . esc_attr($kw) . '" href="'
|
||
. esc_url(add_query_arg($query, home_url('/'))) . '">'
|
||
. esc_html($text) . '</a> ';
|
||
}
|
||
return $out;
|
||
}
|
||
endif;
|
||
|
||
if (!function_exists('aksrt_get_search_box')) :
|
||
/**
|
||
* legacy-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']);
|
||
|
||
$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' => [],
|
||
];
|
||
|
||
$cat_html = '';
|
||
$category_terms = [];
|
||
if (!empty($args['show_input_cat'])) {
|
||
$category_ids = is_array($args['more_cats'])
|
||
? $args['more_cats']
|
||
: (preg_split('/[,,\s]+/', (string) $args['more_cats']) ?: []);
|
||
if ($category_ids && function_exists('aksrt_get_search_categories')) {
|
||
$category_terms = aksrt_get_search_categories($category_ids);
|
||
}
|
||
if ((int) $args['in_cat'] > 0) {
|
||
$selected_term = get_term((int) $args['in_cat']);
|
||
if ($selected_term && !is_wp_error($selected_term)) {
|
||
$selected_term_name = (string) $selected_term->name;
|
||
if (!$category_terms) {
|
||
$category_terms = [$selected_term];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ($category_terms) {
|
||
$in_cat_id = (int) $args['in_cat'];
|
||
$in_cat_name = $in_cat_id > 0 ? (string) ($selected_term_name ?? '') : '';
|
||
$all_cat = '<li data-for="trem" data-value="null"><a href="javascript:;" class="text-ellipsis">'
|
||
. esc_html__('全部', 'aksrt') . '</a></li>';
|
||
foreach ($category_terms as $cat) {
|
||
if (!$cat instanceof WP_Term) {
|
||
continue;
|
||
}
|
||
$cid = (int) $cat->term_id;
|
||
$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>';
|
||
}
|
||
|
||
$type_html = '';
|
||
$type_dropdown_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_name = (string) ($types[$in_type] ?? reset($types));
|
||
if ($cat_html !== '') {
|
||
$type_items = '';
|
||
foreach ($types as $key => $label) {
|
||
$cls = $in_type === (string) $key ? ' active' : '';
|
||
$type_items .= '<a class="but' . esc_attr($cls) . '" data-for="type" data-value="'
|
||
. esc_attr((string) $key) . '" href="javascript:;">' . esc_html((string) $label) . '</a>';
|
||
}
|
||
$type_html = '<div class="flex jc mb10 search-type-but-average"><div class="but-average radius">'
|
||
. $type_items . '</div></div>';
|
||
} else {
|
||
$type_items = '';
|
||
foreach ($types as $key => $label) {
|
||
$type_items .= '<li><a href="javascript:;" class="text-ellipsis" data-for="type" data-value="'
|
||
. esc_attr((string) $key) . '">' . esc_html((string) $label) . '</a></li>';
|
||
}
|
||
$type_dropdown_html = '<div class="option-dropdown splitters-this-r search-drop"><div class="dropdown">'
|
||
. '<a href="javascript:;" class="padding-h10" data-toggle="dropdown"><span name="type">'
|
||
. esc_html($type_name) . '</span><i class="fa ml6 fa-sort opacity5" aria-hidden="true"></i></a>'
|
||
. '<ul class="dropdown-menu">' . $type_items . '</ul></div></div>';
|
||
}
|
||
}
|
||
|
||
$s = esc_attr(wp_strip_all_tags((string) $args['s']));
|
||
$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') . '"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search"></use></svg></button></div>';
|
||
$input_html .= '</div>';
|
||
|
||
$input_html .= '<input type="hidden" name="type" value="' . esc_attr($in_type) . '">';
|
||
if ($cat_html !== '' || (string) $args['in_cat'] !== '') {
|
||
$input_html .= '<input type="hidden" name="trem" value="'
|
||
. esc_attr((string) $args['in_cat']) . '">';
|
||
}
|
||
if ((string) $args['in_user'] !== '') {
|
||
$input_html .= '<input type="hidden" name="user" value="' . esc_attr((string) $args['in_user']) . '">';
|
||
}
|
||
|
||
$form_html = '<form method="get" class="padding-10 search-form" action="'
|
||
. esc_url(home_url('/')) . '">'
|
||
. $type_html
|
||
. '<div class="line-form">' . ($cat_html !== '' ? $cat_html : $type_dropdown_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();
|
||
$keyword_link = aksrt_get_search_keywords_but($hist, 'history');
|
||
if ($keyword_link !== '') {
|
||
$history_html = '<div class="search-keywords history-search">';
|
||
$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-cookie-path="'
|
||
. esc_attr(COOKIEPATH ?: '/') . '" data-cookie-domain="' . esc_attr(COOKIE_DOMAIN) . '" aria-label="'
|
||
. esc_attr__('清空历史', 'aksrt') . '"><i class="fa fas fa-trash-alt em12" aria-hidden="true"></i></a></p>';
|
||
$history_html .= '<div>' . $keyword_link . '</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>';
|
||
}
|
||
}
|
||
}
|
||
|
||
$class_tokens = preg_split('/\s+/', trim((string) $args['class'])) ?: [];
|
||
$class_tokens = array_values(array_filter(array_map('sanitize_html_class', $class_tokens)));
|
||
$class = $class_tokens ? ' ' . implode(' ', $class_tokens) : '';
|
||
$html = '<div class="search-input' . esc_attr($class) . '">'
|
||
. $form_html . $keywords_html . $history_html . $posts_html
|
||
. '</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 (legacy).
|
||
*
|
||
* @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;
|