Files
wordpress-theme-aksrt/src/Widgets/WidgetYiyan.php
T
kate522 bd7d3046a5 feat(widgets): simplify locations and paid sidebar
Remove deprecated widget locations and widgets, standardize sidebar labels, and render a compact paid-post purchase card in the article sidebar.
2026-08-14 01:49:50 +08:00

194 lines
8.1 KiB
PHP

<?php
/**
* Yiyan / Hitokoto widget (zibll widget_ui_yiyan shell + aksrt_render_yiyan_block).
*
* @package AKSRT
*/
namespace AKSRT\Widgets;
use AKSRT\Widgets\Traits\CommonWidgetFields;
defined('ABSPATH') || exit;
class WidgetYiyan extends \WP_Widget {
use CommonWidgetFields;
/**
* @return array<string,string>
*/
private static function type_labels(): array {
return [
'' => __('随机', 'aksrt'),
'a' => __('动画', 'aksrt'),
'b' => __('漫画', 'aksrt'),
'c' => __('游戏', 'aksrt'),
'd' => __('文学', 'aksrt'),
'e' => __('原创', 'aksrt'),
'f' => __('来自网络', 'aksrt'),
'g' => __('其他', 'aksrt'),
'h' => __('影视', 'aksrt'),
'i' => __('诗词', 'aksrt'),
'j' => __('网易云', 'aksrt'),
'k' => __('哲学', 'aksrt'),
'l' => __('抖机灵', 'aksrt'),
];
}
private static function sanitize_type(string $type): string {
$type = strtolower(trim($type));
return preg_match('/^[a-l]$/', $type) ? $type : '';
}
public function __construct() {
parent::__construct(
'aksrt_yiyan',
__('AKSRT 一言轮播', 'aksrt'),
[
'description' => __('显示随机一言/每日语录,支持自动轮播。', 'aksrt'),
'classname' => 'widget_aksrt_yiyan yiyan-box',
]
);
}
/**
* @param array<string,mixed> $args
* @param array<string,mixed> $instance
*/
public function widget($args, $instance): void {
$title = !empty($instance['title']) ? (string) $instance['title'] : '';
$count = !empty($instance['count']) ? max(1, min(10, (int) $instance['count'])) : 5;
$interval = !empty($instance['interval']) ? max(3, min(30, (int) $instance['interval'])) : 5;
$type = self::sanitize_type((string) ($instance['type'] ?? ''));
$icon = !empty($instance['icon']) ? (string) $instance['icon'] : 'fas fa-quote-left';
$affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => ''];
$anim = sanitize_key((string) ($instance['obs_animation'] ?? ''));
$anim_repeat = !empty($instance['animation_repeat']);
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ($title !== '') {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
// zibll shell: theme-box + yiyan-box main-bg text-center box-body radius8 main-shadow.
// NOTE: obs_animation is this widget's own per-widget animation business
// field (kept as-is); the shared common `animation_in` field added via
// render_common_form_section() is a separate additional control.
$pack = function_exists('aksrt_obs_animate_attrs')
? aksrt_obs_animate_attrs($anim, $anim_repeat, 0)
: ['class' => '', 'attr' => ''];
$box_class = 'theme-box yiyan-box-wrap' . $pack['class'];
echo '<div' . $affix['attr'] . ' class="' . esc_attr(trim($box_class)) . '"' . $pack['attr'] . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="yiyan-box main-bg text-center box-body radius8 main-shadow">';
if (function_exists('aksrt_render_yiyan_block')) {
aksrt_render_yiyan_block([
'class' => 'aksrt-yiyan yiyan',
'type' => $type,
'count' => $count,
'interval' => $interval,
'icon' => $icon,
]);
} else {
?>
<div class="aksrt-yiyan yiyan"
data-aksrt-yiyan
data-count="<?php echo esc_attr((string) $count); ?>"
data-interval="<?php echo esc_attr((string) $interval); ?>"
<?php echo $type !== '' ? ' data-type="' . esc_attr($type) . '"' : ''; ?>>
<div class="aksrt-yiyan__content">
<i class="<?php echo esc_attr($icon); ?> aksrt-yiyan__icon" aria-hidden="true"></i>
<p class="aksrt-yiyan__text"><?php esc_html_e('加载中…', 'aksrt'); ?></p>
<p class="aksrt-yiyan__from"></p>
</div>
<div class="aksrt-yiyan__dots" aria-hidden="true"></div>
</div>
<?php
}
echo '</div></div>';
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* @param array<string,mixed> $instance
*/
public function form($instance): void {
$title = !empty($instance['title']) ? (string) $instance['title'] : '一言';
$count = !empty($instance['count']) ? (int) $instance['count'] : 5;
$interval = !empty($instance['interval']) ? (int) $instance['interval'] : 5;
$type = self::sanitize_type((string) ($instance['type'] ?? ''));
$icon = !empty($instance['icon']) ? (string) $instance['icon'] : 'fas fa-quote-left';
$labels = self::type_labels();
$form_types = ['', 'a', 'd', 'i', 'k', 'h', 'j'];
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>"
name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text"
value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('count')); ?>"><?php esc_html_e('轮播条数', 'aksrt'); ?></label>
<input id="<?php echo esc_attr($this->get_field_id('count')); ?>"
name="<?php echo esc_attr($this->get_field_name('count')); ?>" type="number"
min="1" max="10" value="<?php echo esc_attr((string) $count); ?>" style="width:80px;">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('interval')); ?>"><?php esc_html_e('切换间隔(秒)', 'aksrt'); ?></label>
<input id="<?php echo esc_attr($this->get_field_id('interval')); ?>"
name="<?php echo esc_attr($this->get_field_name('interval')); ?>" type="number"
min="3" max="30" value="<?php echo esc_attr((string) $interval); ?>" style="width:80px;">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('type')); ?>"><?php esc_html_e('分类', 'aksrt'); ?></label>
<select id="<?php echo esc_attr($this->get_field_id('type')); ?>"
name="<?php echo esc_attr($this->get_field_name('type')); ?>">
<?php foreach ($form_types as $code) : ?>
<option value="<?php echo esc_attr($code); ?>" <?php selected($type, $code); ?>>
<?php echo esc_html($labels[$code] ?? $code); ?>
</option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('icon')); ?>"><?php esc_html_e('图标', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('icon')); ?>"
name="<?php echo esc_attr($this->get_field_name('icon')); ?>" type="text"
value="<?php echo esc_attr($icon); ?>">
</p>
<p>
<label><?php esc_html_e('入场动画', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('obs_animation')); ?>">
<option value="" <?php selected(($instance['obs_animation'] ?? ''), ''); ?>><?php esc_html_e('无', 'aksrt'); ?></option>
<option value="fade" <?php selected(($instance['obs_animation'] ?? ''), 'fade'); ?>><?php esc_html_e('淡入', 'aksrt'); ?></option>
<option value="slideup" <?php selected(($instance['obs_animation'] ?? ''), 'slideup'); ?>><?php esc_html_e('上滑', 'aksrt'); ?></option>
<option value="zoomin" <?php selected(($instance['obs_animation'] ?? ''), 'zoomin'); ?>><?php esc_html_e('放大', 'aksrt'); ?></option>
</select>
</label>
</p>
<?php $this->render_common_form_section($instance); ?>
<?php
}
/**
* @param array<string,mixed> $new_instance
* @param array<string,mixed> $old_instance
* @return array<string,mixed>
*/
public function update($new_instance, $old_instance): array {
return $this->update_common_fields($new_instance, $old_instance, [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(10, absint($new_instance['count'] ?? 5))),
'interval' => max(3, min(30, absint($new_instance['interval'] ?? 5))),
'type' => self::sanitize_type((string) ($new_instance['type'] ?? '')),
'icon' => sanitize_text_field((string) ($new_instance['icon'] ?? 'fas fa-quote-left')),
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
'animation_repeat' => !empty($new_instance['animation_repeat']) ? 1 : 0,
]);
}
}