Files
wordpress-theme-aksrt/src/AKSRT/Widgets/SearchWidget.php
T
kate522 0d4d5166b4 feat(widgets): SearchWidget type tabs + category scope
Align sidebar search with header/search.js contracts: type buttons,
category select + hidden aksrt_category, history/hot keywords retained.
2026-07-21 08:19:06 +08:00

304 lines
14 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 with hot keywords + type/cat scope (zibll widget_ui_search / zib_get_search_box).
*
* @package AKSRT
*/
namespace AKSRT\Widgets;
defined('ABSPATH') || exit;
class SearchWidget extends \WP_Widget {
public function __construct() {
parent::__construct('aksrt_search', esc_html__('AKSRT 搜索', 'aksrt'), [
'description' => esc_html__('搜索框:类型切换、分类范围、热门关键词与搜索历史。', 'aksrt'),
'classname' => 'widget_aksrt_search',
]);
}
public function widget($args, $instance): void {
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$placeholder = sanitize_text_field((string) ($instance['placeholder'] ?? __('开启精彩搜索', 'aksrt')));
if ($placeholder === '' && function_exists('aksrt_get_search_placeholder')) {
$placeholder = aksrt_get_search_placeholder();
}
$show_kw = !empty($instance['show_keywords']);
$show_history = !empty($instance['show_history']);
$show_types = !empty($instance['show_type']) || !isset($instance['show_type']);
$show_cat = !empty($instance['show_input_cat']);
$kw_title = sanitize_text_field((string) ($instance['keywords_title'] ?? __('热门搜索', 'aksrt')));
$more_but = sanitize_text_field((string) ($instance['more_but'] ?? ''));
$more_url = esc_url_raw(trim((string) ($instance['more_but_url'] ?? '')));
$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_options = is_array($state['types'] ?? null) ? $state['types'] : ['post' => __('文章', 'aksrt')];
$in_type = sanitize_key((string) ($instance['in_type'] ?? $state['type'] ?? 'post'));
if (!isset($type_options[$in_type])) {
$in_type = array_key_first($type_options) ?: 'post';
}
// Category scope.
$in_cat = max(0, (int) ($instance['in_cat'] ?? 0));
if ($in_cat <= 0) {
$in_cat = (int) ($state['category_id'] ?? 0);
}
$cat_enabled = $show_cat && ($state['category_enabled'] || !empty($instance['show_input_cat']));
$categories = [];
if ($cat_enabled) {
$more_raw = trim((string) ($instance['more_cats'] ?? ''));
if ($more_raw !== '') {
$ids = array_values(array_filter(array_map('intval', preg_split('/[,,\s]+/', $more_raw) ?: [])));
if ($ids) {
$got = get_categories([
'taxonomy' => 'category',
'include' => $ids,
'hide_empty' => false,
'orderby' => 'include',
]);
$categories = is_array($got) ? $got : [];
}
}
if (!$categories) {
$categories = is_array($state['categories'] ?? null) ? $state['categories'] : [];
}
if (!$categories && function_exists('aksrt_get_search_categories')) {
$categories = aksrt_get_search_categories();
}
}
// Only show type UI when more than one type is configured, unless forced.
if ($show_types && count($type_options) < 2 && empty($instance['force_show_type'])) {
// Still keep hidden type field for default.
$show_types_ui = false;
} else {
$show_types_ui = $show_types && count($type_options) >= 1;
}
$keywords = [];
if ($show_kw) {
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'hot_search_keywords')) {
$keywords = \AKSRT\Settings\Settings::hot_search_keywords();
} elseif (function_exists('aksrt_get_search_hot_keywords')) {
$keywords = aksrt_get_search_hot_keywords();
} elseif (function_exists('aksrt_get_setting')) {
$raw = (string) aksrt_get_setting('hot_search_keywords', '');
$keywords = array_values(array_filter(array_map('trim', preg_split('/[\r\n,,]+/', $raw) ?: [])));
}
$custom = trim((string) ($instance['keywords'] ?? ''));
if ($custom !== '') {
$keywords = array_values(array_filter(array_map('trim', preg_split('/[\r\n,,]+/', $custom) ?: [])));
}
$keywords = array_slice(is_array($keywords) ? $keywords : [], 0, 12);
}
$uid = 'aksrt-sw-' . esc_attr($this->id);
?>
<div class="widget-search-box aksrt-search-widget search-input" id="<?php echo $uid; ?>">
<form
role="search"
method="get"
class="aksrt-search-widget__form search-form"
action="<?php echo esc_url(home_url('/')); ?>"
data-aksrt-search-form="widget"
data-default-search-type="<?php echo esc_attr($in_type); ?>"
data-default-category="<?php echo esc_attr((string) $in_cat); ?>"
>
<?php if ($show_types_ui) : ?>
<div class="aksrt-search-widget__types" role="tablist" aria-label="<?php esc_attr_e('搜索类型', 'aksrt'); ?>">
<?php foreach ($type_options as $type_key => $type_label) : ?>
<button
type="button"
class="aksrt-search-widget__type<?php echo $in_type === $type_key ? ' is-active' : ''; ?>"
data-search-type="<?php echo esc_attr((string) $type_key); ?>"
><?php echo esc_html((string) $type_label); ?></button>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="aksrt-search-widget__line line-form">
<?php if ($cat_enabled && !empty($categories)) : ?>
<div class="aksrt-search-widget__cat option-dropdown">
<label class="screen-reader-text" for="<?php echo $uid; ?>-cat"><?php esc_html_e('分类', 'aksrt'); ?></label>
<select
id="<?php echo $uid; ?>-cat"
class="aksrt-search-widget__cat-select"
data-search-category-select
<?php disabled($in_type !== 'post'); ?>
>
<option value="0"><?php esc_html_e('全部分类', 'aksrt'); ?></option>
<?php foreach ($categories as $term) :
if (!$term instanceof \WP_Term) {
continue;
}
?>
<option value="<?php echo esc_attr((string) $term->term_id); ?>" <?php selected($in_cat, (int) $term->term_id); ?>>
<?php echo esc_html($term->name); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<div class="aksrt-search-widget__field search-input-text">
<label class="screen-reader-text" for="<?php echo $uid; ?>-s"><?php esc_html_e('搜索关键词', 'aksrt'); ?></label>
<input
id="<?php echo $uid; ?>-s"
type="search"
name="s"
class="widget-search-box__input line-form-input"
placeholder="<?php echo esc_attr($placeholder); ?>"
value="<?php echo esc_attr(get_search_query()); ?>"
autocomplete="off"
>
<button type="submit" class="widget-search-box__btn" aria-label="<?php esc_attr_e('搜索', 'aksrt'); ?>">
<i class="fas fa-search" aria-hidden="true"></i>
</button>
</div>
</div>
<input type="hidden" name="aksrt_search_type" value="<?php echo esc_attr($in_type); ?>">
<?php if ($cat_enabled) : ?>
<input type="hidden" name="aksrt_category" value="<?php echo esc_attr($in_type === 'post' && $in_cat > 0 ? (string) $in_cat : ''); ?>">
<?php endif; ?>
</form>
<?php if ($show_history) : ?>
<div class="aksrt-search-widget__history" data-aksrt-search-history>
<div class="aksrt-search-widget__kw-head">
<div class="aksrt-search-widget__kw-title"><?php esc_html_e('搜索历史', 'aksrt'); ?></div>
<button type="button" class="aksrt-search-widget__history-clear" data-aksrt-search-history-clear hidden><?php esc_html_e('清空', 'aksrt'); ?></button>
</div>
<div class="aksrt-search-widget__history-list" data-aksrt-search-history-list></div>
</div>
<?php endif; ?>
<?php if ($keywords) : ?>
<div class="aksrt-search-widget__keywords">
<?php if ($kw_title !== '') : ?>
<div class="aksrt-search-widget__kw-title"><?php echo esc_html($kw_title); ?></div>
<?php endif; ?>
<div class="aksrt-search-widget__kw-list">
<?php foreach ($keywords as $kw) :
$kw = is_array($kw) ? (string) ($kw['keyword'] ?? $kw['text'] ?? '') : (string) $kw;
if ($kw === '') {
continue;
}
$url = function_exists('aksrt_build_search_url')
? aksrt_build_search_url($kw, ['aksrt_search_type' => $in_type])
: add_query_arg(['s' => $kw, 'aksrt_search_type' => $in_type], home_url('/'));
?>
<a class="aksrt-search-widget__kw" href="<?php echo esc_url($url); ?>"><?php echo esc_html($kw); ?></a>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php if ($more_but !== '' && $more_url !== '') : ?>
<div class="aksrt-search-widget__more">
<a href="<?php echo esc_url($more_url); ?>"><?php echo esc_html($more_but); ?></a>
</div>
<?php endif; ?>
</div>
<?php
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
public function form($instance): void {
$type_options = function_exists('aksrt_get_search_type_options')
? aksrt_get_search_type_options()
: ['post' => __('文章', 'aksrt')];
$in_type = sanitize_key((string) ($instance['in_type'] ?? 'post'));
?>
<p>
<label><?php esc_html_e('标题(可选)', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title')); ?>" value="<?php echo esc_attr((string) ($instance['title'] ?? '')); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('占位文本', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('placeholder')); ?>" value="<?php echo esc_attr((string) ($instance['placeholder'] ?? __('开启精彩搜索', 'aksrt'))); ?>">
</label>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_type')); ?>" value="1" <?php checked(!empty($instance['show_type']) || !isset($instance['show_type'])); ?>> <?php esc_html_e('显示类型切换(≥2 种时)', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_input_cat')); ?>" value="1" <?php checked(!empty($instance['show_input_cat'])); ?>> <?php esc_html_e('显示分类筛选', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_keywords')); ?>" value="1" <?php checked(!empty($instance['show_keywords'])); ?>> <?php esc_html_e('显示热门关键词', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_history')); ?>" value="1" <?php checked(!empty($instance['show_history'])); ?>> <?php esc_html_e('显示搜索历史', 'aksrt'); ?></label>
</p>
<p>
<label><?php esc_html_e('默认类型', 'aksrt'); ?>
<select class="widefat" name="<?php echo esc_attr($this->get_field_name('in_type')); ?>">
<?php foreach ($type_options as $k => $label) : ?>
<option value="<?php echo esc_attr($k); ?>" <?php selected($in_type, $k); ?>><?php echo esc_html($label); ?></option>
<?php endforeach; ?>
</select>
</label>
</p>
<p>
<label><?php esc_html_e('默认分类 ID(0=全部)', 'aksrt'); ?>
<input class="tiny-text" type="number" min="0" name="<?php echo esc_attr($this->get_field_name('in_cat')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['in_cat'] ?? 0))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('可选分类 ID(逗号;空=后台/全部分类)', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('more_cats')); ?>" value="<?php echo esc_attr((string) ($instance['more_cats'] ?? '')); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('关键词标题', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('keywords_title')); ?>" value="<?php echo esc_attr((string) ($instance['keywords_title'] ?? __('热门搜索', 'aksrt'))); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('自定义关键词(逗号/换行;空=后台配置)', 'aksrt'); ?>
<textarea class="widefat" rows="2" name="<?php echo esc_attr($this->get_field_name('keywords')); ?>"><?php echo esc_textarea((string) ($instance['keywords'] ?? '')); ?></textarea>
</label>
</p>
<p>
<label><?php esc_html_e('更多按钮文案', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('more_but')); ?>" value="<?php echo esc_attr((string) ($instance['more_but'] ?? '')); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('更多按钮链接', 'aksrt'); ?>
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('more_but_url')); ?>" value="<?php echo esc_attr((string) ($instance['more_but_url'] ?? '')); ?>">
</label>
</p>
<?php
}
public function update($new_instance, $old_instance): array {
return [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'placeholder' => sanitize_text_field((string) ($new_instance['placeholder'] ?? '')),
'show_keywords' => !empty($new_instance['show_keywords']) ? 1 : 0,
'show_history' => !empty($new_instance['show_history']) ? 1 : 0,
'show_type' => !empty($new_instance['show_type']) ? 1 : 0,
'show_input_cat' => !empty($new_instance['show_input_cat']) ? 1 : 0,
'in_type' => sanitize_key((string) ($new_instance['in_type'] ?? 'post')),
'in_cat' => max(0, (int) ($new_instance['in_cat'] ?? 0)),
'more_cats' => sanitize_text_field((string) ($new_instance['more_cats'] ?? '')),
'keywords_title' => sanitize_text_field((string) ($new_instance['keywords_title'] ?? '')),
'keywords' => sanitize_textarea_field((string) ($new_instance['keywords'] ?? '')),
'more_but' => sanitize_text_field((string) ($new_instance['more_but'] ?? '')),
'more_but_url' => esc_url_raw(trim((string) ($new_instance['more_but_url'] ?? ''))),
];
}
}