- Add AKSRT\Core\Color::sanitize($value, $allow_alpha) as the single PHP color sanitizer; replace sanitize_hex_color calls and per-class regexes (FloatButtons, FieldSchema, ThemeSearch, icon cards, TicketStatusService) - SchemaProvider / ControllerBase sanitize `color` fields as colors; alpha kept only when the schema sets showAlpha - Split SchemaProvider OAuth validation and option matching into sibling traits to stay under the 1000-line limit - Add AksColorPicker.vue + utils/color.js mirroring the PHP rules; AksField, FloatBtnCommonFields and TicketStatusPanel use it - Widget background color input now uses wpColorPicker - Remove dead AksCompositeField dimensions/spacing/background branches and the unused Gutenberg ColorPicker var - Add color-unification contract test; update harness requires and tests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
602 lines
24 KiB
PHP
602 lines
24 KiB
PHP
<?php
|
||
/**
|
||
* @package AKSRT
|
||
*/
|
||
|
||
namespace AKSRT\Settings;
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
class ThemeSearch {
|
||
|
||
public static function search_placeholder(): string {
|
||
$placeholder = trim((string) Settings::get_value('search_placeholder', ''));
|
||
return $placeholder !== '' ? $placeholder : __('开启精彩搜索', 'aksrt');
|
||
}
|
||
|
||
public static function search_history_enabled(): bool {
|
||
$settings = Settings::get_all();
|
||
return !array_key_exists('search_history', $settings) || !empty($settings['search_history']);
|
||
}
|
||
|
||
public static function hot_search_enabled(): bool {
|
||
$settings = Settings::get_all();
|
||
return !array_key_exists('search_popular_key', $settings) || !empty($settings['search_popular_key']);
|
||
}
|
||
|
||
public static function hot_search_keywords(): array {
|
||
$items = self::search_popular_sticky();
|
||
$counts = get_option('search_keywords', []);
|
||
if (is_array($counts)) {
|
||
$items = array_merge($items, array_keys($counts));
|
||
}
|
||
|
||
$items = array_map(
|
||
static function ($keyword): string {
|
||
return trim(sanitize_text_field((string) $keyword));
|
||
},
|
||
$items
|
||
);
|
||
|
||
$items = array_values(array_filter(array_unique($items), static function (string $keyword): bool {
|
||
return $keyword !== '';
|
||
}));
|
||
|
||
$limit = max(1, min(50, absint(Settings::get_value('search_popular_key_num', 20))));
|
||
|
||
return array_slice($items, 0, $limit);
|
||
}
|
||
|
||
public static function search_popular_title(): string {
|
||
$title = trim((string) Settings::get_value('search_popular_title', ''));
|
||
return $title !== '' ? $title : __('热门搜索', 'aksrt');
|
||
}
|
||
|
||
public static function search_popular_sticky(): array {
|
||
$raw = Settings::get_value('search_popular_sticky', '');
|
||
if (is_array($raw)) {
|
||
$items = $raw;
|
||
} else {
|
||
$items = preg_split('/[\r\n,,]+/', (string) $raw) ?: [];
|
||
}
|
||
$items = array_map(static fn($k) => trim(sanitize_text_field((string) $k)), $items);
|
||
return array_values(array_filter(array_unique($items), fn(string $k) => $k !== ''));
|
||
}
|
||
|
||
public static function search_posts_enabled(): bool {
|
||
return !empty(Settings::get_value('search_posts', false));
|
||
}
|
||
|
||
public static function search_no_page(): bool {
|
||
return !empty(Settings::get_value('search_no_page', false));
|
||
}
|
||
|
||
public static function search_exclude_cats(): array {
|
||
$raw = Settings::get_value('search_exclude_cats', '');
|
||
if (is_array($raw)) {
|
||
$items = $raw;
|
||
} else {
|
||
$items = preg_split('/[,,\s]+/', (string) $raw) ?: [];
|
||
}
|
||
$items = array_map(static fn($id) => absint($id), $items);
|
||
return array_values(array_filter(array_unique($items), fn(int $id) => $id > 0));
|
||
}
|
||
|
||
public static function search_cat_enabled(): bool {
|
||
return !empty(Settings::get_value('search_cat', false));
|
||
}
|
||
|
||
public static function search_cat_in(): string {
|
||
return trim((string) Settings::get_value('search_cat_in', ''));
|
||
}
|
||
|
||
public static function search_more_cat_obj(): array {
|
||
$raw = Settings::get_value('search_more_cat_obj', []);
|
||
$items = is_array($raw) ? $raw : (preg_split('/[,,\s]+/', (string) $raw) ?: []);
|
||
return array_values(array_filter(array_unique(array_map('absint', $items))));
|
||
}
|
||
|
||
public static function search_custom_key_enabled(): bool {
|
||
return !empty(Settings::get_value('search_custom_key_s', false));
|
||
}
|
||
|
||
public static function search_custom_key(): array {
|
||
$raw = Settings::get_value('search_custom_key', ['title', 'content', 'excerpt', 'category', 'post_tag']);
|
||
if (is_array($raw)) {
|
||
$items = $raw;
|
||
} else {
|
||
$items = preg_split('/[,,\s]+/', (string) $raw) ?: [];
|
||
}
|
||
$items = array_map(static fn($k) => trim(sanitize_key((string) $k)), $items);
|
||
$valid = ['title', 'content', 'excerpt', 'category', 'post_tag', 'coment', 'user'];
|
||
return array_values(array_intersect(array_filter(array_unique($items)), $valid));
|
||
}
|
||
|
||
public static function search_facets_enabled(): bool {
|
||
return !empty(Settings::get_value('search_facets', []));
|
||
}
|
||
|
||
public static function search_facets_order(): array {
|
||
$raw = Settings::get_value('search_facets', []);
|
||
$items = is_array($raw) ? array_keys($raw) : [];
|
||
$items = array_map(static fn($s) => trim(sanitize_key((string) $s)), $items);
|
||
return array_values(array_filter(array_unique($items), fn(string $s) => $s !== ''));
|
||
}
|
||
|
||
public static function get_meilisearch_config(): array {
|
||
$s = Settings::get_all();
|
||
$opt = is_array($s['search_ms_opt'] ?? null) ? $s['search_ms_opt'] : [];
|
||
|
||
$enabled = !empty($s['search_ms_s']);
|
||
$api_url = esc_url_raw(trim((string) ($opt['api_url'] ?? 'http://127.0.0.1:7700')));
|
||
$api_key = sanitize_text_field((string) ($opt['api_key'] ?? ''));
|
||
$index_prefix = sanitize_key((string) ($opt['index_prefix'] ?? 'aksrt'));
|
||
$synonyms_raw = $opt['synonyms'] ?? [];
|
||
$synonyms = [];
|
||
foreach ((array) $synonyms_raw as $row) {
|
||
if (!is_array($row)) {
|
||
continue;
|
||
}
|
||
$key = trim(sanitize_text_field((string) ($row['key'] ?? '')));
|
||
$values = array_values(array_filter(array_map('trim', explode(',', sanitize_text_field((string) ($row['val'] ?? ''))))));
|
||
if ($key !== '' && $values) {
|
||
$synonyms[$key] = $values;
|
||
}
|
||
}
|
||
|
||
return [
|
||
'enabled' => $enabled,
|
||
'api_url' => $api_url,
|
||
'api_key' => $api_key,
|
||
'index_prefix' => $index_prefix !== '' ? $index_prefix : 'aksrt',
|
||
'synonyms' => $synonyms,
|
||
'index_name' => ($index_prefix !== '' ? $index_prefix : 'aksrt') . '_posts',
|
||
];
|
||
}
|
||
|
||
public static function filter_posts_search(string $search, \WP_Query $query): string {
|
||
if (!$query->is_search() || !$query->get('s') || !self::search_custom_key_enabled()) {
|
||
return $search;
|
||
}
|
||
if (sanitize_key((string) $query->get('type')) === 'user') {
|
||
return ' AND 1=0';
|
||
}
|
||
$config = self::get_meilisearch_config();
|
||
if (!empty($config['enabled'])) {
|
||
return $search;
|
||
}
|
||
$keys = self::search_custom_key();
|
||
if (!$keys) {
|
||
return $search;
|
||
}
|
||
global $wpdb;
|
||
$terms = (array) ($query->query_vars['search_terms'] ?? []);
|
||
if (!$terms) {
|
||
$terms = [(string) $query->get('s')];
|
||
}
|
||
$groups = [];
|
||
$taxonomies = ['post_tag', 'category'];
|
||
foreach ($terms as $term) {
|
||
$like = (!empty($query->query_vars['exact']) ? '' : '%') . $wpdb->esc_like((string) $term) . (!empty($query->query_vars['exact']) ? '' : '%');
|
||
$parts = [];
|
||
foreach ($keys as $key) {
|
||
if ($key === 'title') $parts[] = $wpdb->prepare("{$wpdb->posts}.post_title LIKE %s", $like);
|
||
elseif ($key === 'content') $parts[] = $wpdb->prepare("{$wpdb->posts}.post_content LIKE %s", $like);
|
||
elseif ($key === 'excerpt') $parts[] = $wpdb->prepare("{$wpdb->posts}.post_excerpt LIKE %s", $like);
|
||
elseif (in_array($key, $taxonomies, true)) $parts[] = $wpdb->prepare('(aksrt_search_tt.taxonomy = %s AND aksrt_search_terms.name LIKE %s)', $key, $like);
|
||
elseif ($key === 'coment') $parts[] = $wpdb->prepare('aksrt_search_comments.comment_content LIKE %s', $like);
|
||
elseif ($key === 'user') $parts[] = $wpdb->prepare('(aksrt_search_users.user_nicename LIKE %s OR aksrt_search_users.display_name LIKE %s)', $like, $like);
|
||
}
|
||
if ($parts) {
|
||
$groups[] = '(' . implode(' OR ', $parts) . ')';
|
||
}
|
||
}
|
||
if (!$groups) {
|
||
return $search;
|
||
}
|
||
if (!is_user_logged_in()) {
|
||
$groups[] = "({$wpdb->posts}.post_password = '')";
|
||
}
|
||
return ' AND ' . implode(' AND ', $groups);
|
||
}
|
||
|
||
public static function filter_posts_search_join(string $join, \WP_Query $query): string {
|
||
if (!$query->is_search() || !$query->get('s') || !self::search_custom_key_enabled() || !empty(self::get_meilisearch_config()['enabled'])) {
|
||
return $join;
|
||
}
|
||
global $wpdb;
|
||
$keys = self::search_custom_key();
|
||
if (in_array('coment', $keys, true)) {
|
||
$join .= " LEFT JOIN {$wpdb->comments} AS aksrt_search_comments ON ({$wpdb->posts}.ID = aksrt_search_comments.comment_post_ID)";
|
||
}
|
||
if (in_array('user', $keys, true)) {
|
||
$join .= " LEFT JOIN {$wpdb->users} AS aksrt_search_users ON ({$wpdb->posts}.post_author = aksrt_search_users.ID)";
|
||
}
|
||
if (array_intersect(['post_tag', 'category'], $keys)) {
|
||
$join .= " LEFT JOIN {$wpdb->term_relationships} AS aksrt_search_tr ON ({$wpdb->posts}.ID = aksrt_search_tr.object_id)";
|
||
$join .= " LEFT JOIN {$wpdb->term_taxonomy} AS aksrt_search_tt ON (aksrt_search_tr.term_taxonomy_id = aksrt_search_tt.term_taxonomy_id)";
|
||
$join .= " LEFT JOIN {$wpdb->terms} AS aksrt_search_terms ON (aksrt_search_tt.term_id = aksrt_search_terms.term_id)";
|
||
}
|
||
return $join;
|
||
}
|
||
|
||
public static function filter_posts_search_distinct(string $distinct, \WP_Query $query): string {
|
||
return $query->is_search() && $query->get('s') && self::search_custom_key_enabled() ? 'DISTINCT' : $distinct;
|
||
}
|
||
|
||
public static function filter_search_query($query): void {
|
||
if (is_admin() || !$query->is_main_query() || !$query->is_search()) {
|
||
return;
|
||
}
|
||
|
||
$type = isset($_REQUEST['type']) ? sanitize_key((string) wp_unslash($_REQUEST['type'])) : '';
|
||
if (!in_array($type, ['post', 'user'], true)) {
|
||
$type = self::get_search_content_types()['default'];
|
||
}
|
||
$query->set('type', $type);
|
||
|
||
if ($type === 'user') {
|
||
$query->set('post__in', [0]);
|
||
return;
|
||
}
|
||
|
||
if (self::search_no_page()) {
|
||
$existing = $query->get('post_type');
|
||
if (empty($existing)) {
|
||
$query->set('post_type', 'post');
|
||
}
|
||
}
|
||
|
||
$exclude_cats = self::search_exclude_cats();
|
||
if (!empty($exclude_cats)) {
|
||
foreach ($exclude_cats as $category_id) {
|
||
$children = get_term_children($category_id, 'category');
|
||
if (!is_wp_error($children)) {
|
||
$exclude_cats = array_merge($exclude_cats, $children);
|
||
}
|
||
}
|
||
$query->set('category__not_in', array_values(array_unique(array_map('absint', $exclude_cats))));
|
||
}
|
||
|
||
$term_id = isset($_REQUEST['trem']) ? absint(wp_unslash($_REQUEST['trem'])) : 0;
|
||
if ($term_id > 0) {
|
||
$term = get_term($term_id);
|
||
if ($term instanceof \WP_Term) {
|
||
$tax_query = (array) $query->get('tax_query');
|
||
$tax_query[] = [
|
||
'taxonomy' => $term->taxonomy,
|
||
'field' => 'term_id',
|
||
'terms' => $term->term_id,
|
||
];
|
||
$query->set('tax_query', $tax_query);
|
||
}
|
||
}
|
||
|
||
$user_id = isset($_REQUEST['user']) ? absint(wp_unslash($_REQUEST['user'])) : 0;
|
||
if ($user_id > 0) {
|
||
$query->set('author', $user_id);
|
||
}
|
||
|
||
$orderby = isset($_REQUEST['orderby']) ? sanitize_key((string) wp_unslash($_REQUEST['orderby'])) : '';
|
||
$meta_keys = [
|
||
'views' => 'aksrt_post_views',
|
||
'like' => '_aksrt_like_count',
|
||
'favorite' => '_aksrt_favorite_count',
|
||
'sales_volume' => '_aksrt_sales_volume',
|
||
];
|
||
if (isset($meta_keys[$orderby])) {
|
||
$query->set('meta_key', $meta_keys[$orderby]);
|
||
$query->set('orderby', ['meta_value_num' => 'DESC', 'date' => 'DESC']);
|
||
$query->set('order', 'DESC');
|
||
} elseif ($orderby === 'comment_count') {
|
||
$query->set('orderby', 'comment_count');
|
||
$query->set('order', 'DESC');
|
||
} elseif ($orderby === 'date') {
|
||
$query->set('orderby', 'date');
|
||
$query->set('order', 'DESC');
|
||
}
|
||
}
|
||
|
||
public static function apply_list_orderby($query): void {
|
||
if (is_admin() || !$query->is_main_query()) {
|
||
return;
|
||
}
|
||
if (!$query->is_archive() && !$query->is_search() && !$query->is_home()) {
|
||
return;
|
||
}
|
||
if ($query->get('orderby')) {
|
||
return;
|
||
}
|
||
|
||
$s = Settings::get_all();
|
||
$key = sanitize_key((string) ($s['list_orderby'] ?? 'modified'));
|
||
if ($key === '' || $key === 'default') {
|
||
return;
|
||
}
|
||
|
||
switch ($key) {
|
||
case 'modified':
|
||
$query->set('orderby', 'modified');
|
||
$query->set('order', 'DESC');
|
||
break;
|
||
case 'date':
|
||
$query->set('orderby', 'date');
|
||
$query->set('order', 'DESC');
|
||
break;
|
||
case 'comments':
|
||
$query->set('orderby', 'comment_count');
|
||
$query->set('order', 'DESC');
|
||
break;
|
||
}
|
||
}
|
||
|
||
public static function get_search_content_types(): array {
|
||
$types = ['post', 'user'];
|
||
$default = sanitize_key((string) Settings::get_value('search_type_in', 'post'));
|
||
if (!in_array($default, $types, true)) {
|
||
$default = 'post';
|
||
}
|
||
|
||
return [
|
||
'types' => $types,
|
||
'default' => $default,
|
||
];
|
||
}
|
||
|
||
public static function theme_mode(): string {
|
||
$mode = sanitize_key((string) Settings::get_value('theme_mode', 'time-auto'));
|
||
$valid = ['white-theme', 'dark-theme', 'time-auto'];
|
||
return in_array($mode, $valid, true) ? $mode : 'time-auto';
|
||
}
|
||
|
||
public static function theme_mode_js_value(): string {
|
||
$mode = self::theme_mode();
|
||
$map = ['white-theme' => 'light', 'dark-theme' => 'dark', 'time-auto' => 'time-auto'];
|
||
return $map[$mode] ?? 'time-auto';
|
||
}
|
||
|
||
public static function time_auto_theme_mode(): string {
|
||
$hour = (int) current_time('G');
|
||
return ($hour >= 20 || $hour < 8) ? 'dark' : 'light';
|
||
}
|
||
|
||
public static function initial_theme_mode(): string {
|
||
$cookie = isset($_COOKIE['theme_mode'])
|
||
? sanitize_key((string) wp_unslash($_COOKIE['theme_mode']))
|
||
: '';
|
||
$map = [
|
||
'dark-theme' => 'dark',
|
||
'white-theme' => 'light',
|
||
'dark' => 'dark',
|
||
'light' => 'light',
|
||
];
|
||
if (isset($map[$cookie])) {
|
||
return $map[$cookie];
|
||
}
|
||
|
||
$mode = self::theme_mode();
|
||
if ($mode === 'dark-theme') {
|
||
return 'dark';
|
||
}
|
||
if ($mode === 'white-theme') {
|
||
return 'light';
|
||
}
|
||
if ($mode === 'time-auto') {
|
||
return self::time_auto_theme_mode();
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
/** 全局主题色:theme_skin_custom 优先,清空时使用 theme_skin 预置色(对齐参考主题 zib_head_css)。 */
|
||
public static function theme_color(): string {
|
||
$custom = \AKSRT\Core\Color::sanitize(Settings::get_value('theme_skin_custom', ''));
|
||
if ($custom !== '') {
|
||
return $custom;
|
||
}
|
||
$skin = ltrim(trim((string) Settings::get_value('theme_skin', 'f04494')), '#');
|
||
return preg_match('/^[0-9a-fA-F]{6}$/', $skin) ? '#' . $skin : '#f04494';
|
||
}
|
||
|
||
/** 夜间模式主题色;未设置返回空串,夜间沿用全局主题色。 */
|
||
public static function dark_theme_color(): string {
|
||
return \AKSRT\Core\Color::sanitize(Settings::get_value('dark_theme_skin_custom', ''));
|
||
}
|
||
|
||
public static function get_theme_mode_button_positions(): array {
|
||
$raw = Settings::get_value('theme_mode_button', ['pc_nav', 'm_menu']);
|
||
return array_values(array_intersect(array_map('sanitize_key', (array) $raw), ['pc_nav', 'm_menu']));
|
||
}
|
||
|
||
/** 卡片圆角 theme_main_radius(0–30,默认 12)→ --main-radius。 */
|
||
public static function main_radius(): int {
|
||
return max(0, min(30, (int) Settings::get_value('theme_main_radius', 12)));
|
||
}
|
||
|
||
public static function close_backdrop(): bool {
|
||
return !empty(Settings::get_value('close_backdrop', false));
|
||
}
|
||
|
||
/**
|
||
* 背景图 CSS 声明(不含选择器);无颜色且无图片时返回空串。
|
||
* 子键白名单与 GlobalSchema::background_field() / layout.js bgField 一致。
|
||
*/
|
||
public static function background_css(string $key): string {
|
||
$bg = Settings::get_value($key, []);
|
||
if (!is_array($bg)) {
|
||
return '';
|
||
}
|
||
$color = \AKSRT\Core\Color::sanitize($bg['color'] ?? '');
|
||
$image = esc_url_raw(trim((string) ($bg['image'] ?? '')));
|
||
if ($color === '' && $image === '') {
|
||
return '';
|
||
}
|
||
$allowed = [
|
||
'position' => ['left top', 'left center', 'left bottom', 'center top', 'center center', 'center bottom', 'right top', 'right center', 'right bottom'],
|
||
'repeat' => ['repeat', 'no-repeat', 'repeat-x', 'repeat-y'],
|
||
'attachment' => ['scroll', 'fixed'],
|
||
'size' => ['100%', 'cover', 'contain', 'auto'],
|
||
'origin' => ['padding-box', 'border-box', 'content-box'],
|
||
];
|
||
$css = $color !== '' ? 'background-color:' . $color . ';' : '';
|
||
if ($image !== '') {
|
||
$css .= 'background-image:url("' . str_replace(['"', '\\', "\n", "\r"], '', $image) . '");';
|
||
foreach ($allowed as $prop => $values) {
|
||
$value = (string) ($bg[$prop] ?? '');
|
||
if (in_array($value, $values, true)) {
|
||
$css .= 'background-' . $prop . ':' . $value . ';';
|
||
}
|
||
}
|
||
}
|
||
return $css;
|
||
}
|
||
|
||
public static function is_qj_loading_enabled(): bool {
|
||
return (bool) Settings::get_value('qj_loading', false);
|
||
}
|
||
|
||
public static function get_qj_loading_style(): string {
|
||
$style = (string) Settings::get_value('qj_dh_xs', 'no1');
|
||
if (!preg_match('/^no([1-9]|10)$/', $style)) {
|
||
return 'no1';
|
||
}
|
||
return $style;
|
||
}
|
||
|
||
public static function container_max_width(): int {
|
||
$width = (int) Settings::get_value('container_max_width', 1200);
|
||
return max(1200, min(2200, $width));
|
||
}
|
||
|
||
public static function font_family(): string {
|
||
$family = sanitize_key((string) Settings::get_value('font_family', 'system'));
|
||
return in_array($family, ['system', 'noto-sans-sc', 'noto-serif-sc', 'custom'], true) ? $family : 'system';
|
||
}
|
||
|
||
/** 自定义 font-family 字体栈,只保留字体名、引号、逗号等安全字符。 */
|
||
public static function font_family_custom(): string {
|
||
$stack = (string) Settings::get_value('font_family_custom', '');
|
||
$stack = preg_replace('/[^\p{L}\p{N}\s,"\'\-_.]/u', '', $stack);
|
||
return trim((string) preg_replace('/\s+/', ' ', (string) $stack), " ,");
|
||
}
|
||
|
||
public static function get_code_highlight_config(): array {
|
||
$s = Settings::get_all();
|
||
|
||
$light_themes = ['enlighter','bootstrap4','classic','beyond','mowtwo','eclipse','droide','minimal','rowhammer','godzilla','dracula','atomic','monokai'];
|
||
$dark_themes = ['dracula','atomic','monokai','enlighter','bootstrap4'];
|
||
|
||
$light = sanitize_key((string) ($s['highlight_zt'] ?? 'enlighter'));
|
||
$dark = sanitize_key((string) ($s['highlight_dark_zt'] ?? 'monokai'));
|
||
|
||
$max_height_raw = $s['highlight_maxheight'] ?? 400;
|
||
$max_height = absint(is_numeric($max_height_raw) ? $max_height_raw : preg_replace('/[^0-9]/', '', $max_height_raw));
|
||
if ($max_height === 0 && !in_array($max_height_raw, [0, '0', '0px'], true)) {
|
||
$max_height = 400;
|
||
}
|
||
|
||
return [
|
||
'enabled' => !isset($s['highlight_kg']) || !empty($s['highlight_kg']),
|
||
'lightTheme' => in_array($light, $light_themes, true) ? $light : 'enlighter',
|
||
'darkTheme' => in_array($dark, $dark_themes, true) ? $dark : 'monokai',
|
||
'lineNumbers' => !empty($s['highlight_hh']),
|
||
'showButtons' => !isset($s['highlight_btn']) || !empty($s['highlight_btn']),
|
||
'maxHeight' => $max_height,
|
||
];
|
||
}
|
||
|
||
public static function get_system_notice_config(): array {
|
||
$s = Settings::get_all();
|
||
|
||
$policy = sanitize_key((string) ($s['system_notice_policy'] ?? ''));
|
||
if (!in_array($policy, ['', 'signin', 'vip', 'free', 'auth'], true)) {
|
||
$legacy_map = ['always' => '', 'once' => '', 'daily' => ''];
|
||
$policy = $legacy_map[$policy] ?? '';
|
||
}
|
||
|
||
$size = sanitize_key((string) ($s['system_notice_size'] ?? ''));
|
||
if (!in_array($size, ['', 'modal-mini', 'modal-sm', 'modal-lg'], true)) {
|
||
$size = '';
|
||
}
|
||
|
||
$radius_raw = $s['system_notice_radius'] ?? '0';
|
||
$radius = absint(preg_replace('/[^0-9]/', '', $radius_raw));
|
||
|
||
$allowed_colors = ['primary', 'success', 'warning', 'danger', 'info', 'purple', 'dark'];
|
||
$buttons = [];
|
||
|
||
for ($i = 1; $i <= 4; $i++) {
|
||
$text = trim((string) ($s["system_notice_btn{$i}_text"] ?? ''));
|
||
$link = esc_url_raw((string) ($s["system_notice_btn{$i}_link"] ?? ''));
|
||
$color = sanitize_key((string) ($s["system_notice_btn{$i}_color"] ?? 'primary'));
|
||
|
||
if ($i === 1 && $text === '') {
|
||
$text = trim((string) ($s['system_notice_button'] ?? ''));
|
||
$link = $link ?: esc_url_raw((string) ($s['system_notice_link'] ?? ''));
|
||
}
|
||
|
||
if ($text === '') continue;
|
||
if (!in_array($color, $allowed_colors, true)) {
|
||
$color = 'primary';
|
||
}
|
||
|
||
$buttons[] = [
|
||
'text' => $text,
|
||
'link' => $link,
|
||
'color' => $color,
|
||
];
|
||
}
|
||
|
||
return [
|
||
'enabled' => !empty($s['system_notice_enabled']),
|
||
'policy' => $policy,
|
||
'title' => trim((string) ($s['system_notice_title'] ?? '')),
|
||
'content' => trim((string) ($s['system_notice_content'] ?? '')),
|
||
'buttons' => $buttons,
|
||
'size' => $size,
|
||
'radius' => $radius,
|
||
'class' => sanitize_html_class((string) ($s['system_notice_class'] ?? '')),
|
||
'title_icon' => trim((string) ($s['system_notice_title_icon'] ?? '')),
|
||
'title_class' => sanitize_html_class((string) ($s['system_notice_title_class'] ?? '')),
|
||
'title_style' => trim((string) ($s['system_notice_title_style'] ?? '')),
|
||
'expires' => absint($s['system_notice_expires'] ?? 24),
|
||
];
|
||
}
|
||
|
||
public static function get_sidebar_config(): array {
|
||
$s = Settings::get_all();
|
||
|
||
$position = sanitize_key((string) ($s['sidebar_position'] ?? 'right'));
|
||
$width = max(200, min(400, (int) ($s['sidebar_width'] ?? 311)));
|
||
|
||
return [
|
||
'enabled' => !isset($s['sidebar_enabled']) || !empty($s['sidebar_enabled']),
|
||
'position' => in_array($position, ['left', 'right'], true) ? $position : 'right',
|
||
'width' => $width,
|
||
'home' => !isset($s['sidebar_home_enabled']) || !empty($s['sidebar_home_enabled']),
|
||
'category' => !isset($s['sidebar_category_enabled']) || !empty($s['sidebar_category_enabled']),
|
||
'tag' => !isset($s['sidebar_tag_enabled']) || !empty($s['sidebar_tag_enabled']),
|
||
'single' => !isset($s['sidebar_single_enabled']) || !empty($s['sidebar_single_enabled']),
|
||
'page' => !isset($s['sidebar_page_enabled']) || !empty($s['sidebar_page_enabled']),
|
||
'search' => !isset($s['sidebar_search_enabled']) || !empty($s['sidebar_search_enabled']),
|
||
];
|
||
}
|
||
|
||
public static function get_i18n_config(): array {
|
||
$s = Settings::get_all();
|
||
|
||
$enabled = !empty($s['i18n_enabled']) || !empty($s['frontend_translate_enabled']);
|
||
$source = $s['i18n_default_lang'] ?? $s['frontend_translate_source'] ?? 'zh-CN';
|
||
|
||
return [
|
||
'enabled' => $enabled,
|
||
'autoDetect' => !isset($s['i18n_auto_detect']) || !empty($s['i18n_auto_detect']),
|
||
'defaultLang' => $source,
|
||
'availableLangs' => $s['i18n_available_langs'] ?? "zh-CN|简体中文\nen|English",
|
||
'nomenclature' => $s['i18n_nomenclature'] ?? '',
|
||
'switcherPosition' => $s['i18n_switcher_position'] ?? 'footer',
|
||
'urlStrategy' => $s['i18n_url_strategy'] ?? 'query',
|
||
];
|
||
}
|
||
}
|