feat(widgets): deepen buttons, video player, recent comments
Add go_link/hollow/radius/icon slots for buttons; loop/poster/hide controls for video player; exclude post/keywords on recent comments.
This commit is contained in:
1 parent
e2decd8d71
commit
aabc1cd142
4 files changed
+455
-277
No files matched your search
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* Video player widget (zibll dplayer lite via native video / oEmbed).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
@@ -9,124 +11,123 @@ defined('ABSPATH') || exit;
|
||||
|
||||
class WidgetVideoPlayer extends \WP_Widget {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
'aksrt_video_player',
|
||||
__('视频播放器', 'aksrt'),
|
||||
['description' => __('在侧栏嵌入视频播放器。', 'aksrt')]
|
||||
);
|
||||
}
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
'aksrt_video_player',
|
||||
__('视频播放器', 'aksrt'),
|
||||
['description' => __('侧栏/流体区嵌入视频播放器。', 'aksrt')]
|
||||
);
|
||||
}
|
||||
|
||||
public function widget($args, $instance): void {
|
||||
$title = !empty($instance['title']) ? $instance['title'] : '';
|
||||
$video_url = !empty($instance['video_url']) ? $instance['video_url'] : '';
|
||||
$poster = !empty($instance['poster']) ? $instance['poster'] : '';
|
||||
$autoplay = !empty($instance['autoplay']);
|
||||
$aspect_ratio = !empty($instance['aspect_ratio']) ? $instance['aspect_ratio'] : '16:9';
|
||||
public function widget($args, $instance): void {
|
||||
$title = (string) ($instance['title'] ?? '');
|
||||
$video_url = trim((string) ($instance['video_url'] ?? $instance['url'] ?? ''));
|
||||
$poster = trim((string) ($instance['poster'] ?? $instance['pic'] ?? ''));
|
||||
$autoplay = !empty($instance['autoplay']);
|
||||
$loop = !empty($instance['loop']);
|
||||
$muted = $autoplay || !empty($instance['muted']);
|
||||
$hide_controller = !empty($instance['hide_controller']);
|
||||
$scale = max(20, min(100, (int) ($instance['scale_height'] ?? 56)));
|
||||
$aspect = (string) ($instance['aspect_ratio'] ?? '');
|
||||
|
||||
if (empty($video_url)) return;
|
||||
if ($video_url === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析视频类型
|
||||
$embed_url = $this->get_embed_url($video_url);
|
||||
$is_embed = !empty($embed_url);
|
||||
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
|
||||
}
|
||||
|
||||
echo $args['before_widget'];
|
||||
if ($aspect !== '' && str_contains($aspect, ':')) {
|
||||
$parts = explode(':', $aspect);
|
||||
if (count($parts) === 2 && (int) $parts[0] > 0) {
|
||||
$scale = (int) round(((int) $parts[1] / (int) $parts[0]) * 100);
|
||||
}
|
||||
}
|
||||
|
||||
if ($title) {
|
||||
echo $args['before_title'] . esc_html($title) . $args['after_title'];
|
||||
}
|
||||
$embed = $this->get_embed_url($video_url);
|
||||
$cls = 'aksrt-video-widget' . ($hide_controller ? ' controller-hide' : '');
|
||||
echo '<div class="' . esc_attr($cls) . '" style="padding-bottom:' . esc_attr((string) $scale) . '%">';
|
||||
if ($embed !== '') {
|
||||
$src = $embed;
|
||||
if ($autoplay) {
|
||||
$src = add_query_arg(['autoplay' => '1', 'mute' => '1'], $src);
|
||||
}
|
||||
echo '<iframe src="' . esc_url($src) . '" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe>';
|
||||
} else {
|
||||
$attrs = ' controls playsinline';
|
||||
if ($autoplay) {
|
||||
$attrs .= ' autoplay';
|
||||
}
|
||||
if ($loop) {
|
||||
$attrs .= ' loop';
|
||||
}
|
||||
if ($muted) {
|
||||
$attrs .= ' muted';
|
||||
}
|
||||
if ($poster !== '') {
|
||||
$attrs .= ' poster="' . esc_url($poster) . '"';
|
||||
}
|
||||
echo '<video' . $attrs . '><source src="' . esc_url($video_url) . '"></video>';
|
||||
}
|
||||
echo '</div>';
|
||||
|
||||
// 计算 padding-bottom
|
||||
$ratio_parts = explode(':', $aspect_ratio);
|
||||
if (count($ratio_parts) === 2 && (int) $ratio_parts[1] > 0) {
|
||||
$padding = ((int) $ratio_parts[1] / (int) $ratio_parts[0]) * 100;
|
||||
} else {
|
||||
$padding = 56.25; // 16:9
|
||||
}
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
echo '<div class="aksrt-video-widget" style="padding-bottom: ' . esc_attr(number_format($padding, 4)) . '%;">';
|
||||
private function get_embed_url(string $url): string {
|
||||
if (preg_match('#(?:youtube\.com/watch\?v=|youtu\.be/)([A-Za-z0-9_-]+)#', $url, $m)) {
|
||||
return 'https://www.youtube.com/embed/' . rawurlencode($m[1]);
|
||||
}
|
||||
if (preg_match('#bilibili\.com/video/(BV[\w]+)#', $url, $m)) {
|
||||
return 'https://player.bilibili.com/player.html?bvid=' . rawurlencode($m[1]) . '&high_quality=1';
|
||||
}
|
||||
if (preg_match('#v\.qq\.com/.+?/([A-Za-z0-9]+)\.html#', $url, $m)) {
|
||||
return 'https://v.qq.com/txp/iframe/player.html?vid=' . rawurlencode($m[1]);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($is_embed) {
|
||||
echo '<iframe src="' . esc_url($embed_url) . '" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen' . (function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('widget') : ' loading="lazy"') . '></iframe>';
|
||||
} else {
|
||||
echo '<video' . ($autoplay ? ' autoplay' : '') . ' controls playsinline';
|
||||
if ($poster) echo ' poster="' . esc_url($poster) . '"';
|
||||
echo '>';
|
||||
echo '<source src="' . esc_url($video_url) . '">';
|
||||
echo '</video>';
|
||||
}
|
||||
public function form($instance): void {
|
||||
?>
|
||||
<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('视频 URL', 'aksrt'); ?>
|
||||
<input class="widefat" type="url" name="<?php echo esc_attr($this->get_field_name('video_url')); ?>" value="<?php echo esc_attr((string) ($instance['video_url'] ?? '')); ?>">
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php esc_html_e('封面图 URL', 'aksrt'); ?>
|
||||
<input class="widefat" type="url" name="<?php echo esc_attr($this->get_field_name('poster')); ?>" value="<?php echo esc_attr((string) ($instance['poster'] ?? '')); ?>">
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php esc_html_e('高度占比 %', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="20" max="100" name="<?php echo esc_attr($this->get_field_name('scale_height')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['scale_height'] ?? 56))); ?>">
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('autoplay')); ?>" value="1" <?php checked(!empty($instance['autoplay'])); ?>> <?php esc_html_e('自动播放', 'aksrt'); ?></label><br>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('loop')); ?>" value="1" <?php checked(!empty($instance['loop'])); ?>> <?php esc_html_e('循环', 'aksrt'); ?></label><br>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_controller')); ?>" value="1" <?php checked(!empty($instance['hide_controller'])); ?>> <?php esc_html_e('隐藏控制条样式', 'aksrt'); ?></label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
echo $args['after_widget'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 YouTube / Bilibili 链接为嵌入 URL
|
||||
*/
|
||||
private function get_embed_url(string $url): string {
|
||||
// YouTube
|
||||
if (preg_match('/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]+)/', $url, $m)) {
|
||||
return 'https://www.youtube.com/embed/' . $m[1];
|
||||
}
|
||||
|
||||
// Bilibili
|
||||
if (preg_match('/bilibili\.com\/video\/(BV[a-zA-Z0-9]+)/', $url, $m)) {
|
||||
return 'https://player.bilibili.com/player.html?bvid=' . $m[1] . '&high_quality=1';
|
||||
}
|
||||
|
||||
// 腾讯视频
|
||||
if (preg_match('/v\.qq\.com\/x\/page\/([a-zA-Z0-9]+)/', $url, $m)) {
|
||||
return 'https://v.qq.com/txp/iframe/player.html?vid=' . $m[1];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function form($instance): void {
|
||||
$title = !empty($instance['title']) ? $instance['title'] : '';
|
||||
$video_url = !empty($instance['video_url']) ? $instance['video_url'] : '';
|
||||
$poster = !empty($instance['poster']) ? $instance['poster'] : '';
|
||||
$autoplay = !empty($instance['autoplay']);
|
||||
$aspect_ratio = !empty($instance['aspect_ratio']) ? $instance['aspect_ratio'] : '16:9';
|
||||
?>
|
||||
<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('video_url')); ?>"><?php esc_html_e('视频 URL:', 'aksrt'); ?></label>
|
||||
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('video_url')); ?>" name="<?php echo esc_attr($this->get_field_name('video_url')); ?>" type="url" value="<?php echo esc_attr($video_url); ?>" placeholder="https://...">
|
||||
<small><?php esc_html_e('支持 MP4、YouTube、Bilibili、腾讯视频链接', 'aksrt'); ?></small>
|
||||
</p>
|
||||
<p>
|
||||
<label for="<?php echo esc_attr($this->get_field_id('poster')); ?>"><?php esc_html_e('封面图 URL:', 'aksrt'); ?></label>
|
||||
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('poster')); ?>" name="<?php echo esc_attr($this->get_field_name('poster')); ?>" type="url" value="<?php echo esc_attr($poster); ?>">
|
||||
</p>
|
||||
<p>
|
||||
<label for="<?php echo esc_attr($this->get_field_id('aspect_ratio')); ?>"><?php esc_html_e('宽高比:', 'aksrt'); ?></label>
|
||||
<select class="widefat" id="<?php echo esc_attr($this->get_field_id('aspect_ratio')); ?>" name="<?php echo esc_attr($this->get_field_name('aspect_ratio')); ?>">
|
||||
<option value="16:9" <?php selected($aspect_ratio, '16:9'); ?>>16:9</option>
|
||||
<option value="4:3" <?php selected($aspect_ratio, '4:3'); ?>>4:3</option>
|
||||
<option value="1:1" <?php selected($aspect_ratio, '1:1'); ?>>1:1</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input type="checkbox" id="<?php echo esc_attr($this->get_field_id('autoplay')); ?>" name="<?php echo esc_attr($this->get_field_name('autoplay')); ?>" value="1" <?php checked($autoplay); ?>>
|
||||
<?php esc_html_e('自动播放(仅 MP4)', 'aksrt'); ?>
|
||||
</label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function update($new_instance, $old_instance): array {
|
||||
$instance = [];
|
||||
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
|
||||
$instance['video_url'] = esc_url_raw($new_instance['video_url'] ?? '');
|
||||
$instance['poster'] = esc_url_raw($new_instance['poster'] ?? '');
|
||||
$instance['autoplay'] = !empty($new_instance['autoplay']);
|
||||
$instance['aspect_ratio'] = in_array($new_instance['aspect_ratio'] ?? '', ['16:9', '4:3', '1:1'], true) ? $new_instance['aspect_ratio'] : '16:9';
|
||||
return $instance;
|
||||
}
|
||||
public function update($new_instance, $old_instance): array {
|
||||
return [
|
||||
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||
'video_url' => esc_url_raw(trim((string) ($new_instance['video_url'] ?? ''))),
|
||||
'poster' => esc_url_raw(trim((string) ($new_instance['poster'] ?? ''))),
|
||||
'scale_height' => max(20, min(100, (int) ($new_instance['scale_height'] ?? 56))),
|
||||
'autoplay' => !empty($new_instance['autoplay']) ? 1 : 0,
|
||||
'loop' => !empty($new_instance['loop']) ? 1 : 0,
|
||||
'hide_controller' => !empty($new_instance['hide_controller']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user