278 lines
13 KiB
PHP
278 lines
13 KiB
PHP
<?php
|
|
/*
|
|
Plugin Name: Yoone Snow
|
|
Description: 首页 canvas 雪花效果
|
|
Version: 1.1.0
|
|
Author: Yoone
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) { exit; }
|
|
|
|
function yoone_snow_is_enabled() {
|
|
return function_exists('is_front_page') ? is_front_page() : false;
|
|
}
|
|
|
|
function yoone_snow_enqueue_assets() {
|
|
if (!yoone_snow_is_enabled()) { return; }
|
|
$style_handle = 'yoone-snow-style';
|
|
$style_src = plugins_url('css/snow.css', __FILE__);
|
|
wp_register_style($style_handle, $style_src, array(), '1.1.0', 'all');
|
|
wp_enqueue_style($style_handle);
|
|
|
|
// 注册形状渲染脚本 保证主脚本之前加载
|
|
$shape_index_handle = 'yoone-snow-shapes-index';
|
|
wp_register_script($shape_index_handle, plugins_url('js/shapes/index.js', __FILE__), array(), '1.1.0', true);
|
|
$shape_utils_handle = 'yoone-snow-shapes-utils';
|
|
wp_register_script($shape_utils_handle, plugins_url('js/shapes/utils.js', __FILE__), array($shape_index_handle), '1.1.0', true);
|
|
$shape_dot_handle = 'yoone-snow-shapes-dot';
|
|
wp_register_script($shape_dot_handle, plugins_url('js/shapes/dot.js', __FILE__), array($shape_index_handle), '1.1.0', true);
|
|
$shape_flake_handle = 'yoone-snow-shapes-flake';
|
|
wp_register_script($shape_flake_handle, plugins_url('js/shapes/flake.js', __FILE__), array($shape_index_handle), '1.1.0', true);
|
|
$shape_yuanbao_handle = 'yoone-snow-shapes-yuanbao';
|
|
wp_register_script($shape_yuanbao_handle, plugins_url('js/shapes/yuanbao.js', __FILE__), array($shape_index_handle), '1.1.0', true);
|
|
$shape_coin_handle = 'yoone-snow-shapes-coin';
|
|
wp_register_script($shape_coin_handle, plugins_url('js/shapes/coin.js', __FILE__), array($shape_index_handle), '1.1.0', true);
|
|
$shape_santa_handle = 'yoone-snow-shapes-santa-hat';
|
|
wp_register_script($shape_santa_handle, plugins_url('js/shapes/santa_hat.js', __FILE__), array($shape_utils_handle), '1.1.0', true);
|
|
$shape_cane_handle = 'yoone-snow-shapes-candy-cane';
|
|
wp_register_script($shape_cane_handle, plugins_url('js/shapes/candy_cane.js', __FILE__), array($shape_utils_handle), '1.1.0', true);
|
|
$shape_sock_handle = 'yoone-snow-shapes-christmas-sock';
|
|
wp_register_script($shape_sock_handle, plugins_url('js/shapes/christmas_sock.js', __FILE__), array($shape_utils_handle), '1.1.0', true);
|
|
$shape_tree_handle = 'yoone-snow-shapes-christmas-tree';
|
|
wp_register_script($shape_tree_handle, plugins_url('js/shapes/christmas_tree.js', __FILE__), array($shape_utils_handle), '1.1.0', true);
|
|
$shape_reindeer_handle = 'yoone-snow-shapes-reindeer';
|
|
wp_register_script($shape_reindeer_handle, plugins_url('js/shapes/reindeer.js', __FILE__), array($shape_utils_handle), '1.1.0', true);
|
|
$shape_berry_handle = 'yoone-snow-shapes-christmas-berry';
|
|
wp_register_script($shape_berry_handle, plugins_url('js/shapes/christmas_berry.js', __FILE__), array($shape_utils_handle), '1.1.0', true);
|
|
|
|
// 注册并加载主脚本 设置依赖确保顺序正确
|
|
$script_handle = 'yoone-snow-script';
|
|
$script_src = plugins_url('js/snow-canvas.js', __FILE__);
|
|
wp_register_script(
|
|
$script_handle,
|
|
$script_src,
|
|
array(
|
|
$shape_index_handle,
|
|
$shape_dot_handle,
|
|
$shape_flake_handle,
|
|
$shape_yuanbao_handle,
|
|
$shape_coin_handle,
|
|
$shape_santa_handle,
|
|
$shape_cane_handle,
|
|
$shape_sock_handle,
|
|
$shape_tree_handle,
|
|
$shape_reindeer_handle,
|
|
$shape_berry_handle
|
|
),
|
|
'1.1.0',
|
|
true
|
|
);
|
|
wp_enqueue_script($script_handle);
|
|
|
|
// 将后端设置传递到前端脚本 变量名称为 YooneSnowSettings
|
|
// 简化设置 仅保留复选框选择的形状集合
|
|
$mixed_items_option = get_option('yoone_snow_mixed_items', array('dot','flake'));
|
|
if (is_string($mixed_items_option)) {
|
|
$mixed_items_option = array_filter(array_map('trim', explode(',', $mixed_items_option)));
|
|
}
|
|
$allowed_shapes = array('dot','flake','yuanbao','coin','santa_hat','candy_cane','christmas_sock','christmas_tree','reindeer','christmas_berry');
|
|
$mixed_items_sanitized = array_values(array_unique(array_intersect($mixed_items_option, $allowed_shapes)));
|
|
if (empty($mixed_items_sanitized)) { $mixed_items_sanitized = array('dot','flake'); }
|
|
// 读取媒体形状集合 并映射为可用的 URL 列表
|
|
$media_ids = get_option('yoone_snow_media_items', array());
|
|
if (!is_array($media_ids)) { $media_ids = array(); }
|
|
$media_urls = array();
|
|
foreach ($media_ids as $mid) {
|
|
$url = wp_get_attachment_url(intval($mid));
|
|
if ($url) { $media_urls[] = $url; }
|
|
}
|
|
wp_localize_script($script_handle, 'YooneSnowSettings', array(
|
|
'selectedShapes' => $mixed_items_sanitized,
|
|
'mediaItems' => $media_urls,
|
|
// 传递资源基础映射 用于前端按需加载 SVG 图像
|
|
'assetsMap' => array(
|
|
'santa_hat' => plugins_url('assets/圣诞雪帽.svg', __FILE__),
|
|
'candy_cane' => plugins_url('assets/圣诞拐杖.svg', __FILE__),
|
|
'christmas_sock' => plugins_url('assets/圣诞袜子.svg', __FILE__),
|
|
'christmas_tree' => plugins_url('assets/圣诞树.svg', __FILE__),
|
|
'reindeer' => plugins_url('assets/圣诞麋鹿.svg', __FILE__),
|
|
'christmas_berry' => plugins_url('assets/圣诞果.svg', __FILE__),
|
|
),
|
|
));
|
|
}
|
|
|
|
// 在后台设置页面加载媒体库脚本和交互脚本 用于选择 SVG 或图片
|
|
function yoone_snow_admin_enqueue($hook) {
|
|
// 条件判断 仅在插件设置页面加载脚本 保持性能
|
|
if ($hook !== 'settings_page_yoone_snow') { return; }
|
|
// 加载媒体库脚本 以便使用 wp.media 选择器
|
|
wp_enqueue_media();
|
|
// 注册并加载后台交互脚本
|
|
$admin_script_handle = 'yoone-snow-admin-media';
|
|
wp_register_script($admin_script_handle, plugins_url('js/admin-media.js', __FILE__), array(), '1.1.0', true);
|
|
wp_enqueue_script($admin_script_handle);
|
|
}
|
|
|
|
function yoone_snow_render_overlay() {
|
|
if (!yoone_snow_is_enabled()) { return; }
|
|
static $yoone_snow_rendered = false;
|
|
if ($yoone_snow_rendered) { return; }
|
|
$yoone_snow_rendered = true;
|
|
echo '<canvas id="effectiveAppsSnow" aria-hidden="true"></canvas>';
|
|
}
|
|
|
|
add_action('wp_enqueue_scripts', 'yoone_snow_enqueue_assets');
|
|
add_action('wp_body_open', 'yoone_snow_render_overlay');
|
|
add_action('wp_footer', 'yoone_snow_render_overlay', 100);
|
|
|
|
// 注册设置页面和设置项 用于选择雪花形状
|
|
function yoone_snow_register_settings() {
|
|
// 移除形状下拉选项 仅保留复选集合设置
|
|
|
|
// 注册 mixed 形状集合设置项 默认包含 dot 和 flake
|
|
register_setting('yoone_snow_options', 'yoone_snow_mixed_items', array(
|
|
'type' => 'array',
|
|
'sanitize_callback' => function($value) {
|
|
// 将输入统一为数组 并过滤到允许的集合
|
|
$allowed = array('dot','flake','yuanbao','coin','santa_hat','candy_cane','christmas_sock','christmas_tree','reindeer','christmas_berry');
|
|
if (is_string($value)) {
|
|
$value = array_filter(array_map('trim', explode(',', $value)));
|
|
}
|
|
if (!is_array($value)) { $value = array('dot','flake'); }
|
|
$filtered = array_values(array_unique(array_intersect($value, $allowed)));
|
|
return !empty($filtered) ? $filtered : array('dot','flake');
|
|
},
|
|
'default' => array('dot','flake'),
|
|
));
|
|
|
|
// 添加设置分区 标题为 Snow Settings
|
|
add_settings_section(
|
|
'yoone_snow_section',
|
|
'Snow Settings',
|
|
function() {
|
|
// 输出分区描述 使用英文标点保证兼容
|
|
echo '<p>Configure snow appearance</p>';
|
|
},
|
|
'yoone_snow'
|
|
);
|
|
|
|
// 移除下拉字段 保留复选框作为唯一选择入口
|
|
|
|
// 添加形状复选集合 用于选择参与渲染的形状
|
|
add_settings_field(
|
|
'yoone_snow_mixed_items',
|
|
'Shapes',
|
|
function() {
|
|
$current_list = get_option('yoone_snow_mixed_items', array('dot','flake'));
|
|
if (is_string($current_list)) {
|
|
$current_list = array_filter(array_map('trim', explode(',', $current_list)));
|
|
}
|
|
$options = array(
|
|
'dot' => 'Dot',
|
|
'flake' => 'Snowflake',
|
|
'yuanbao' => 'Yuanbao',
|
|
'coin' => 'Coin',
|
|
'santa_hat' => 'Santa Hat',
|
|
'candy_cane' => 'Candy Cane',
|
|
'christmas_sock' => 'Christmas Sock',
|
|
'christmas_tree' => 'Christmas Tree',
|
|
'reindeer' => 'Reindeer',
|
|
'christmas_berry' => 'Christmas Berry',
|
|
);
|
|
foreach ($options as $key => $label) {
|
|
$checked = in_array($key, $current_list, true) ? 'checked' : '';
|
|
echo '<label style="margin-right:12px;"><input type="checkbox" name="yoone_snow_mixed_items[]" value="' . esc_attr($key) . '" ' . $checked . ' /> ' . esc_html($label) . '</label>';
|
|
}
|
|
echo '<p class="description">Choose shapes to render</p>';
|
|
},
|
|
'yoone_snow',
|
|
'yoone_snow_section'
|
|
);
|
|
|
|
// 注册媒体形状集合 设置项保存为附件 ID 数组
|
|
register_setting('yoone_snow_options', 'yoone_snow_media_items', array(
|
|
'type' => 'array',
|
|
'sanitize_callback' => function($value) {
|
|
// 将输入统一为整数 ID 数组 并过滤无效值
|
|
if (is_string($value)) {
|
|
$value = array_filter(array_map('trim', explode(',', $value)));
|
|
}
|
|
if (!is_array($value)) { $value = array(); }
|
|
$ids = array();
|
|
foreach ($value as $item) {
|
|
$id = intval($item);
|
|
if ($id > 0) { $ids[] = $id; }
|
|
}
|
|
return array_values(array_unique($ids));
|
|
},
|
|
'default' => array(),
|
|
));
|
|
|
|
// 添加媒体形状选择字段 支持从媒体库选择图片或 SVG
|
|
add_settings_field(
|
|
'yoone_snow_media_items',
|
|
'Media Shapes',
|
|
function() {
|
|
// 读取当前已选择的附件 ID 列表 并渲染缩略图列表与添加按钮
|
|
$current_media = get_option('yoone_snow_media_items', array());
|
|
if (!is_array($current_media)) { $current_media = array(); }
|
|
echo '<div id="yooneSnowMediaList" style="display:flex;flex-wrap:wrap;gap:12px;">';
|
|
foreach ($current_media as $attachment_id) {
|
|
$url = wp_get_attachment_thumb_url($attachment_id);
|
|
if (!$url) { $url = wp_get_attachment_url($attachment_id); }
|
|
$safe_id = intval($attachment_id);
|
|
$safe_url = esc_url($url);
|
|
echo '<div class="yoone-snow-media-item" data-attachment-id="' . $safe_id . '" style="border:1px solid #ddd;padding:8px;display:flex;flex-direction:column;align-items:center;">';
|
|
echo '<img src="' . $safe_url . '" alt="media" style="width:72px;height:72px;object-fit:contain;" />';
|
|
echo '<input type="hidden" name="yoone_snow_media_items[]" value="' . $safe_id . '" />';
|
|
echo '<button type="button" class="button yoone-snow-remove-media" style="margin-top:6px;">Remove</button>';
|
|
echo '</div>';
|
|
}
|
|
echo '</div>';
|
|
echo '<p><button type="button" class="button button-primary" id="yooneSnowAddMedia">Add Images</button></p>';
|
|
echo '<p class="description">Choose images or SVG from media library to render</p>';
|
|
},
|
|
'yoone_snow',
|
|
'yoone_snow_section'
|
|
);
|
|
}
|
|
|
|
// 添加设置页面到后台菜单 条目在设置菜单下
|
|
function yoone_snow_add_settings_page() {
|
|
add_options_page(
|
|
'Yoone Snow',
|
|
'Yoone Snow',
|
|
'manage_options',
|
|
'yoone_snow',
|
|
function() {
|
|
// 渲染设置页面 表单提交到 options.php
|
|
echo '<div class="wrap">';
|
|
echo '<h1>Yoone Snow</h1>';
|
|
echo '<form method="post" action="options.php">';
|
|
settings_fields('yoone_snow_options');
|
|
do_settings_sections('yoone_snow');
|
|
submit_button();
|
|
echo '</form>';
|
|
echo '</div>';
|
|
}
|
|
);
|
|
}
|
|
|
|
// 在 admin 初始化时注册设置 在 admin 菜单挂载页面
|
|
add_action('admin_init', 'yoone_snow_register_settings');
|
|
add_action('admin_menu', 'yoone_snow_add_settings_page');
|
|
add_action('admin_enqueue_scripts', 'yoone_snow_admin_enqueue');
|
|
|
|
// 在插件列表行添加 Settings 链接 指向设置页面
|
|
function yoone_snow_plugin_action_links($links) {
|
|
// 构造设置页面链接 使用 admin_url 保证后台路径正确
|
|
$settingsUrl = admin_url('options-general.php?page=yoone_snow');
|
|
$settingsLink = '<a href="' . esc_url($settingsUrl) . '">Settings</a>';
|
|
// 将设置链接插入到最前面 便于用户点击
|
|
array_unshift($links, $settingsLink);
|
|
return $links;
|
|
}
|
|
|
|
// 绑定到当前插件的 action links 钩子 使用 plugin_basename 计算插件标识
|
|
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'yoone_snow_plugin_action_links');
|