Files
wordpress-theme-aksrt/inc/helpers/search/jio-search-box.php
T
kate522andClaude Opus 5 35bb96e82f refactor: rename the theme brand and every identifier from AKSRT to Jio
Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-01 20:05:04 +08:00

410 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Search box markup (legacy parity).
*
* Used by layout-2 menu_search AJAX panel and layout 1/3 .navbar-search.
*
* @package Jio
*/
defined('ABSPATH') || exit;
if (!function_exists('jio_save_history_search')) :
/** Store the legacy history_search cookie (newest first, maximum thirty). */
function jio_save_history_search(string $search): void {
$search = trim(wp_strip_all_tags($search));
$search_text = jio_get_search_keywords_text($search);
if ($search_text === '' || mb_strlen($search_text) >= 30 || headers_sent()) {
return;
}
$history = jio_get_search_history_keywords();
$history = array_values(array_filter($history, static function (string $item) use ($search_text): bool {
return jio_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('jio_get_main_search')) :
/** legacy main-search defaults backed only by the reference option IDs. */
function jio_get_main_search(array $args = [], bool $echo = false) {
$settings = class_exists('\Jio\Settings\Settings') ? \Jio\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 jio_get_search_box(wp_parse_args($args, $defaults), $echo);
}
endif;
if (!function_exists('jio_get_search_history_keywords')) :
/**
* @return list<string>
*/
function jio_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('jio_get_search_keywords_text')) :
function jio_get_search_keywords_text(string $search): string {
$search = str_replace('&amp;type', '&type', $search);
$index = strpos($search, '&type=');
return trim($index === false ? $search : substr($search, 0, $index));
}
endif;
if (!function_exists('jio_update_search_keywords')) :
function jio_update_search_keywords(string $search): void {
$search = trim(wp_strip_all_tags($search));
$text = jio_get_search_keywords_text($search);
if (mb_strlen($text) < 2 || mb_strlen($text) > 8) {
return;
}
if (class_exists('\Jio\Settings\Settings') && !\Jio\Settings\Settings::hot_search_enabled()) {
return;
}
$keywords = get_option('search_keywords', []);
$keywords = is_array($keywords) ? $keywords : [];
$limit = class_exists('\Jio\Settings\Settings')
? max(10, min(50, (int) \Jio\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('jio_get_search_keywords_but')) :
/**
* Render keyword chip links.
*
* @param list<string> $keywords
* @param string $type popular|history
*/
function jio_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 = jio_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('jio_get_search_box')) :
/**
* legacy-compatible search box.
*
* @param array<string,mixed> $args
* @param bool $echo
* @return string|void
*/
function jio_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('\Jio\Settings\Settings')
&& method_exists('\Jio\Settings\Settings', 'search_popular_title')) {
$args['keywords_title'] = (string) \Jio\Settings\Settings::search_popular_title();
}
if ($args['keywords_title'] === '') {
$args['keywords_title'] = __('热门搜索', 'jio');
}
if ($args['placeholder'] === '' && function_exists('jio_get_search_placeholder')) {
$args['placeholder'] = jio_get_search_placeholder();
}
if ($args['placeholder'] === '') {
$args['placeholder'] = __('开启精彩搜索', 'jio');
}
$args['placeholder'] = esc_attr((string) $args['placeholder']);
$form_html = '';
if (!empty($args['show_form'])) {
$state = function_exists('jio_get_search_form_state')
? jio_get_search_form_state()
: [
'type' => 'post',
'types' => ['post' => __('文章', 'jio')],
'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('jio_get_search_categories')) {
$category_terms = jio_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__('全部', 'jio') . '</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)
: __('请选择', 'jio');
$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__('搜索', 'jio') . '"><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('\Jio\Settings\Settings') && method_exists('\Jio\Settings\Settings', 'hot_search_enabled')) {
$show = (bool) \Jio\Settings\Settings::hot_search_enabled();
}
if ($show) {
$keywords = function_exists('jio_get_search_hot_keywords') ? jio_get_search_hot_keywords() : [];
$limit = (int) $args['popular_limit'];
$keyword_link = jio_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('jio_search_history_enabled')) {
$show_h = jio_search_history_enabled();
} elseif (class_exists('\Jio\Settings\Settings') && method_exists('\Jio\Settings\Settings', 'search_history_enabled')) {
$show_h = (bool) \Jio\Settings\Settings::search_history_enabled();
}
if ($show_h) {
$hist = jio_get_search_history_keywords();
$keyword_link = jio_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__('历史搜索', 'jio') . '</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__('清空历史', 'jio') . '"><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('\Jio\Settings\Settings') && method_exists('\Jio\Settings\Settings', 'search_posts_enabled')) {
$show_p = (bool) \Jio\Settings\Settings::search_posts_enabled();
}
if ($show_p && function_exists('jio_get_search_posts')) {
$slides = jio_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__('热门文章', 'jio') . '</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('jio_get_remote_box')) :
/**
* Lazy remote HTML mount (legacy).
*
* @param array<string,mixed> $args
*/
function jio_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;