Files
wordpress-theme-aksrt/src/Settings/FloatButtons.php
T

243 lines
7.6 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
/**
* 右侧悬浮按钮:唯一的默认值 + 规范化来源(读取与保存共用)。
*
* 结构对齐参考主题 float_btn(sortable,固定类型,数组顺序即显示顺序)。
*
* @package AKSRT
*/
namespace AKSRT\Settings;
defined('ABSPATH') || exit;
class FloatButtons {
public const OPTION = 'aksrt_floating_buttons';
/** 固定按钮类型(默认显示顺序)。 */
public const TYPES = ['more', 'pay_vip', 'add', 'service_qq', 'service_wechat', 'theme_mode', 'qrcode', 'back_top'];
/**
* 默认配置。
*/
public static function defaults(): array {
$empty_color = ['color' => '', 'bg' => ''];
return [
'style' => 'round',
'position' => 'bottom',
'filter_blur' => ['m_s'],
'scroll_hide' => false,
'scroll_down_hide' => true,
'items' => [
[
'type' => 'more',
'buttons' => [self::gift_more_button()],
],
['type' => 'pay_vip', 'pc_s' => true, 'm_s' => true, 'color' => ['color' => '#f2c97d', 'bg' => 'rgba(62,62,67,0.9)']],
['type' => 'add', 'pc_s' => true, 'm_s' => false, 'color' => $empty_color, 'icon' => 'fa fas fa-pencil-alt'],
['type' => 'service_qq', 'pc_s' => false, 'm_s' => false, 'color' => $empty_color, 'qq' => ''],
['type' => 'service_wechat', 'pc_s' => true, 'm_s' => true, 'color' => $empty_color, 'wechat_img' => ''],
['type' => 'theme_mode', 'pc_s' => false, 'm_s' => false, 'color' => $empty_color],
['type' => 'qrcode', 'pc_s' => true, 'm_s' => false, 'color' => $empty_color, 'desc' => __('在手机上浏览此页面', 'aksrt')],
['type' => 'back_top', 'pc_s' => true, 'm_s' => true, 'color' => $empty_color],
],
];
}
/**
* 「更多按钮」出厂默认项(对齐参考主题 float_btn.more 默认值)。
*/
public static function gift_more_button(): array {
$img = get_template_directory_uri() . '/assets/img/logo.png';
return [
'desc' => '本站同款主题模板',
'icon' => 'zibsvg-gift-color',
'link' => ['url' => '', 'target' => ''],
'hover' => '<a href="https://www.zibll.com/" target="_blank">
<div class="flex c-red">
<img class="flex0" alt="zibll子比主题" src="' . esc_url($img) . '" height="30">
<div class="flex1 ml10">
<dt>本站同款主题模板</dt>
<div class="px12 mt10 muted-color">zibll子比主题是一款漂亮优雅的网站主题模板,功能强大,配置简单。</div>
<div class="but mt10 p2-10 c-blue btn-block px12">查看详情</div>
</div>
</div>
</a>',
'hover_width' => 240,
'pc_s' => true,
'm_s' => true,
'color' => ['color' => '', 'bg' => 'rgba(255, 111, 6, 0.2)'],
];
}
/**
* 「添加按钮」新增项默认值(参考主题 group 字段默认值)。
*/
public static function new_more_button(): array {
return [
'desc' => '',
'icon' => 'fa fas fa-heart',
'link' => ['url' => '', 'target' => ''],
'hover' => '',
'hover_width' => 200,
'pc_s' => true,
'm_s' => true,
'color' => ['color' => '', 'bg' => ''],
];
}
/**
* 读取已规范化的配置。
*/
public static function get(): array {
$saved = get_option(self::OPTION, []);
if (!is_array($saved) || $saved === []) {
return self::defaults();
}
return self::sanitize($saved);
}
/**
* 规范化完整配置(REST 保存与读取共用)。
*/
public static function sanitize(array $raw): array {
$defaults = self::defaults();
$filter_blur = [];
foreach ((array) ($raw['filter_blur'] ?? []) as $device) {
$device = (string) $device;
if (in_array($device, ['pc_s', 'm_s'], true) && !in_array($device, $filter_blur, true)) {
$filter_blur[] = $device;
}
}
return [
'style' => in_array($raw['style'] ?? '', ['round', 'square'], true) ? $raw['style'] : 'round',
'position' => in_array($raw['position'] ?? '', ['bottom', 'center'], true) ? $raw['position'] : 'bottom',
'filter_blur' => $filter_blur,
'scroll_hide' => !empty($raw['scroll_hide']),
'scroll_down_hide' => !empty($raw['scroll_down_hide']),
'items' => self::sanitize_items((array) ($raw['items'] ?? []), $defaults['items']),
];
}
/**
* 按提交顺序保留已知类型,重复丢弃,缺失类型用默认值补到末尾。
*/
private static function sanitize_items(array $raw_items, array $default_items): array {
$default_map = [];
foreach ($default_items as $item) {
$default_map[$item['type']] = $item;
}
$out = [];
$seen = [];
foreach ($raw_items as $item) {
if (!is_array($item)) {
continue;
}
$type = (string) ($item['type'] ?? '');
if (!isset($default_map[$type]) || isset($seen[$type])) {
continue;
}
$seen[$type] = true;
$out[] = self::sanitize_item($type, $item, $default_map[$type]);
}
foreach ($default_items as $item) {
if (!isset($seen[$item['type']])) {
$out[] = $item;
}
}
return $out;
}
private static function sanitize_item(string $type, array $item, array $default): array {
if ($type === 'more') {
$buttons = [];
foreach ((array) ($item['buttons'] ?? []) as $button) {
if (is_array($button)) {
$buttons[] = self::sanitize_more_button($button);
}
}
// 参考主题:至少保留一个。
if ($buttons === []) {
$buttons[] = self::new_more_button();
}
return ['type' => 'more', 'buttons' => $buttons];
}
$out = [
'type' => $type,
'pc_s' => !empty($item['pc_s']),
'm_s' => !empty($item['m_s']),
'color' => self::sanitize_color_group($item['color'] ?? []),
];
switch ($type) {
case 'add':
$out['icon'] = aksrt_sanitize_icon_value((string) ($item['icon'] ?? ''));
break;
case 'service_qq':
$out['qq'] = (string) preg_replace('/\D+/', '', (string) ($item['qq'] ?? ''));
break;
case 'service_wechat':
$out['wechat_img'] = esc_url_raw((string) ($item['wechat_img'] ?? ''));
break;
case 'qrcode':
$out['desc'] = sanitize_text_field((string) ($item['desc'] ?? ''));
break;
}
return $out;
}
private static function sanitize_more_button(array $button): array {
$link = is_array($button['link'] ?? null) ? $button['link'] : [];
$target = (string) ($link['target'] ?? '');
return [
'desc' => sanitize_text_field((string) ($button['desc'] ?? '')),
'icon' => aksrt_sanitize_icon_value((string) ($button['icon'] ?? '')),
'link' => [
'url' => esc_url_raw((string) ($link['url'] ?? '')),
'target' => $target === '_blank' ? '_blank' : '',
],
'hover' => wp_kses_post((string) ($button['hover'] ?? '')),
'hover_width' => max(50, min(500, (int) ($button['hover_width'] ?? 200))),
'pc_s' => !empty($button['pc_s']),
'm_s' => !empty($button['m_s']),
'color' => self::sanitize_color_group($button['color'] ?? []),
];
}
/**
* @param mixed $group
* @return array{color:string,bg:string}
*/
private static function sanitize_color_group($group): array {
$group = is_array($group) ? $group : [];
return [
'color' => self::sanitize_color((string) ($group['color'] ?? '')),
'bg' => self::sanitize_color((string) ($group['bg'] ?? '')),
];
}
/**
* 允许 #hex(3/4/6/8 位)与 rgb()/rgba()。
*/
public static function sanitize_color(string $value): string {
$value = trim($value);
if ($value === '') {
return '';
}
if (preg_match('/^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/', $value)) {
return $value;
}
if (preg_match('/^rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(?:,\s*(?:0|1|0?\.\d+)\s*)?\)$/', $value)) {
return $value;
}
return '';
}
}