feat: 添加 Gutenberg、Elementor 和短代码支持
新增 Gutenberg 区块、Elementor 小组件和短代码功能,用于在产品页显示混装选择表单。扩展插件兼容性,支持更多内容构建方式。 - 注册 Gutenberg 区块,支持动态渲染混装产品选择表单 - 添加 Elementor 小组件,提供可视化配置界面 - 实现短代码功能,方便在文章/页面中插入表单 - 更新插件元数据,声明 WooCommerce 依赖
This commit is contained in:
parent
f950b59f20
commit
08a6245a6b
|
|
@ -1,11 +1,11 @@
|
|||
# 忽略 docs 目录中的所有图片与设计源文件(防止误提交到仓库)
|
||||
docs/**/*.png
|
||||
docs/**/*.jpg
|
||||
docs/**/*.jpeg
|
||||
docs/**/*.gif
|
||||
docs/**/*.svg
|
||||
docs/**/*.webp
|
||||
docs/**/*.psd
|
||||
docs/**/*.ai
|
||||
docs/**/*.fig
|
||||
docs/**/*.sketch
|
||||
**/*.png
|
||||
**/*.jpg
|
||||
**/*.jpeg
|
||||
**/*.gif
|
||||
**/*.svg
|
||||
**/*.webp
|
||||
**/*.psd
|
||||
**/*.ai
|
||||
**/*.fig
|
||||
**/*.sketch
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Gutenberg Block: Yoone Bundle Selector
|
||||
* 在产品页插入混装产品选择与加购表单。
|
||||
*/
|
||||
(function(wp){
|
||||
const { registerBlockType } = wp.blocks;
|
||||
const { __ } = wp.i18n;
|
||||
const { InspectorControls } = wp.blockEditor || wp.editor;
|
||||
const { PanelBody, ToggleControl, TextControl } = wp.components;
|
||||
|
||||
registerBlockType('yoone/bundle-selector', {
|
||||
title: __('Yoone Bundle Selector', 'yoone-product-bundles'),
|
||||
icon: 'cart',
|
||||
category: 'widgets',
|
||||
attributes: {
|
||||
useCurrentProduct: { type: 'boolean', default: true },
|
||||
productId: { type: 'number', default: 0 },
|
||||
},
|
||||
description: __('在产品页显示“混装产品列表与加购”表单;可选择当前产品或指定产品ID。', 'yoone-product-bundles'),
|
||||
edit: (props) => {
|
||||
const { attributes, setAttributes } = props;
|
||||
const { useCurrentProduct, productId } = attributes;
|
||||
return (
|
||||
wp.element.createElement('div', { className: 'yoone-pb-block-editor' },
|
||||
wp.element.createElement(InspectorControls, null,
|
||||
wp.element.createElement(PanelBody, { title: __('设置', 'yoone-product-bundles'), initialOpen: true },
|
||||
wp.element.createElement(ToggleControl, {
|
||||
label: __('使用当前产品页面', 'yoone-product-bundles'),
|
||||
checked: !!useCurrentProduct,
|
||||
onChange: (val) => setAttributes({ useCurrentProduct: !!val })
|
||||
}),
|
||||
!useCurrentProduct && wp.element.createElement(TextControl, {
|
||||
label: __('指定产品ID(Mix and Match 类型)', 'yoone-product-bundles'),
|
||||
type: 'number',
|
||||
value: productId || 0,
|
||||
onChange: (val) => setAttributes({ productId: parseInt(val || '0', 10) || 0 })
|
||||
})
|
||||
)
|
||||
),
|
||||
wp.element.createElement('div', { className: 'yoone-pb-block-preview' },
|
||||
wp.element.createElement('p', null, __('Yoone Bundle Selector(编辑器预览)', 'yoone-product-bundles')),
|
||||
wp.element.createElement('p', null, useCurrentProduct
|
||||
? __('将渲染当前产品的混装选择表单(需为 Mix and Match 类型)。', 'yoone-product-bundles')
|
||||
: __('将渲染指定产品ID的混装选择表单。', 'yoone-product-bundles')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
save: () => null, // 由后端动态渲染
|
||||
});
|
||||
})(window.wp);
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
/**
|
||||
* 注册 Gutenberg 区块:Yoone Bundle Selector(混装产品选择与加购)。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class Yoone_PB_Blocks {
|
||||
protected static $instance = null;
|
||||
|
||||
public static function instance() {
|
||||
if (null === self::$instance) self::$instance = new self();
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct() {
|
||||
add_action('init', array($this, 'register_blocks'));
|
||||
}
|
||||
|
||||
public function register_blocks() {
|
||||
// 注册编辑器脚本
|
||||
// 计算插件主文件路径,确保 plugins_url 基准正确
|
||||
$plugin_file = dirname(__DIR__) . '/yoone-product-bundles.php';
|
||||
|
||||
wp_register_script(
|
||||
'yoone-pb-blocks',
|
||||
plugins_url('assets/js/blocks/bundle-selector.js', $plugin_file),
|
||||
array('wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n'),
|
||||
defined('YOONE_PB_VERSION') ? YOONE_PB_VERSION : '0.1.0',
|
||||
true
|
||||
);
|
||||
|
||||
register_block_type('yoone/bundle-selector', array(
|
||||
'editor_script' => 'yoone-pb-blocks',
|
||||
'render_callback' => array($this, 'render_bundle_selector_block'),
|
||||
'attributes' => array(
|
||||
'useCurrentProduct' => array('type' => 'boolean', 'default' => true),
|
||||
'productId' => array('type' => 'integer', 'default' => 0),
|
||||
),
|
||||
'supports' => array('anchor' => true),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态渲染区块内容:在产品页或指定产品ID下渲染混装选择表单。
|
||||
*/
|
||||
public function render_bundle_selector_block($attributes, $content) {
|
||||
// 仅在前端渲染;编辑器中显示占位提示
|
||||
if (is_admin() && function_exists('wp_doing_ajax') && ! wp_doing_ajax()) {
|
||||
return '<div class="yoone-pb-block-preview">' . esc_html__('Yoone Bundle Selector (预览):此区块在产品页前端渲染完整选择表单。', 'yoone-product-bundles') . '</div>';
|
||||
}
|
||||
|
||||
$use_current = ! empty($attributes['useCurrentProduct']);
|
||||
$product_id = absint(isset($attributes['productId']) ? $attributes['productId'] : 0);
|
||||
|
||||
// 确定要渲染的产品对象
|
||||
$product = null;
|
||||
if ($use_current && is_singular('product')) {
|
||||
global $post;
|
||||
if ($post) $product = wc_get_product($post->ID);
|
||||
} elseif ($product_id > 0) {
|
||||
$product = wc_get_product($product_id);
|
||||
}
|
||||
|
||||
// 安全检查:仅对我们定义的混装产品类型渲染表单
|
||||
if (! $product || $product->get_type() !== Yoone_Product_Bundles::TYPE) {
|
||||
return '<div class="yoone-pb-block-notice">' . esc_html__('请选择或切换到一个“Mix and Match (Yoone Bundle)”产品以显示表单。', 'yoone-product-bundles') . '</div>';
|
||||
}
|
||||
|
||||
// 前端资源
|
||||
wp_enqueue_style('yoone-pb-frontend');
|
||||
wp_enqueue_script('yoone-pb-frontend');
|
||||
|
||||
// 复用插件模板输出完整表单
|
||||
ob_start();
|
||||
wc_get_template('global/yoone-bundle-form.php', array(), '', YOONE_PB_PATH . 'templates/');
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
/**
|
||||
* Elementor Widget: Yoone Bundle Selector
|
||||
* 在产品页或指定产品ID渲染混装产品选择与加购表单。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// 如果 Elementor 未加载,其父类不存在,避免在文件被提前引入时产生致命错误
|
||||
if (class_exists('\\Elementor\\Widget_Base')) {
|
||||
if (! class_exists('Yoone_PB_Elementor_Widget')) {
|
||||
class Yoone_PB_Elementor_Widget extends \Elementor\Widget_Base {
|
||||
public function get_name() { return 'yoone_pb_bundle_selector'; }
|
||||
public function get_title() { return __('Yoone Bundle Selector', 'yoone-product-bundles'); }
|
||||
public function get_icon() { return 'eicon-cart'; }
|
||||
public function get_categories() { return array('general'); }
|
||||
|
||||
protected function _register_controls() {
|
||||
$this->start_controls_section('section_settings', array('label' => __('设置', 'yoone-product-bundles')));
|
||||
|
||||
$this->add_control('use_current_product', array(
|
||||
'label' => __('使用当前产品页面', 'yoone-product-bundles'),
|
||||
'type' => \Elementor\Controls_Manager::SWITCHER,
|
||||
'label_on' => __('是', 'yoone-product-bundles'),
|
||||
'label_off' => __('否', 'yoone-product-bundles'),
|
||||
'return_value' => 'yes',
|
||||
'default' => 'yes',
|
||||
));
|
||||
|
||||
$this->add_control('product_id', array(
|
||||
'label' => __('指定产品ID(Mix and Match 类型)', 'yoone-product-bundles'),
|
||||
'type' => \Elementor\Controls_Manager::NUMBER,
|
||||
'default' => 0,
|
||||
'condition' => array('use_current_product!' => 'yes'),
|
||||
));
|
||||
|
||||
$this->end_controls_section();
|
||||
}
|
||||
|
||||
protected function render() {
|
||||
$settings = $this->get_settings_for_display();
|
||||
$use_current = isset($settings['use_current_product']) && $settings['use_current_product'] === 'yes';
|
||||
$product_id = absint(isset($settings['product_id']) ? $settings['product_id'] : 0);
|
||||
|
||||
// 确定产品对象
|
||||
$product = null;
|
||||
if ($use_current && is_singular('product')) {
|
||||
global $post; if ($post) $product = wc_get_product($post->ID);
|
||||
} elseif ($product_id > 0) {
|
||||
$product = wc_get_product($product_id);
|
||||
}
|
||||
|
||||
if (! $product || $product->get_type() !== Yoone_Product_Bundles::TYPE) {
|
||||
echo '<div class="yoone-pb-elementor-notice">' . esc_html__('请选择或切换到一个“Mix and Match (Yoone Bundle)”产品以显示表单。', 'yoone-product-bundles') . '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// 前端资源
|
||||
wp_enqueue_style('yoone-pb-frontend');
|
||||
wp_enqueue_script('yoone-pb-frontend');
|
||||
|
||||
// 渲染模板
|
||||
wc_get_template('global/yoone-bundle-form.php', array(), '', YOONE_PB_PATH . 'templates/');
|
||||
}
|
||||
|
||||
public static function register() {
|
||||
if (! class_exists('Elementor\\Plugin')) return;
|
||||
add_action('elementor/widgets/register', function($widgets_manager) {
|
||||
$widgets_manager->register(new self());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 定义一个降级的空壳类,至少保证调用 register() 不会报错
|
||||
if (! class_exists('Yoone_PB_Elementor_Widget')) {
|
||||
class Yoone_PB_Elementor_Widget {
|
||||
public static function register() { /* noop: Elementor 未加载*/ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* 注册短代码: [yoone_bundle_selector use_current_product="yes" product_id="123"]
|
||||
* 作用:在任何页面/文章中插入混装产品选择与加购表单。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (! class_exists('Yoone_PB_Shortcodes')) {
|
||||
class Yoone_PB_Shortcodes {
|
||||
public static function init() {
|
||||
add_action('init', array(__CLASS__, 'register_shortcodes'));
|
||||
}
|
||||
|
||||
public static function register_shortcodes() {
|
||||
add_shortcode('yoone_bundle_selector', array(__CLASS__, 'shortcode_bundle_selector'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染短代码内容
|
||||
* @param array $atts
|
||||
* @param string|null $content
|
||||
* @return string
|
||||
*/
|
||||
public static function shortcode_bundle_selector($atts, $content = null) {
|
||||
$atts = shortcode_atts(array(
|
||||
'use_current_product' => 'yes', // yes|no
|
||||
'product_id' => 0,
|
||||
), $atts, 'yoone_bundle_selector');
|
||||
|
||||
$use_current = strtolower($atts['use_current_product']) === 'yes' || $atts['use_current_product'] === '1' || $atts['use_current_product'] === 1;
|
||||
$product_id = absint($atts['product_id']);
|
||||
|
||||
// 解析产品对象
|
||||
$product = null;
|
||||
if ($use_current && function_exists('is_singular') && is_singular('product')) {
|
||||
global $post; if ($post) $product = wc_get_product($post->ID);
|
||||
} elseif ($product_id > 0) {
|
||||
$product = wc_get_product($product_id);
|
||||
}
|
||||
|
||||
// 安全检查:仅渲染我们定义的混装产品类型
|
||||
if (! $product || ! method_exists($product, 'get_type') || $product->get_type() !== Yoone_Product_Bundles::TYPE) {
|
||||
return '<div class="yoone-pb-shortcode-notice">' . esc_html__('请选择或传入一个 “Mix and Match (Yoone Bundle)” 产品以显示表单。', 'yoone-product-bundles') . '</div>';
|
||||
}
|
||||
|
||||
// 前端资源
|
||||
wp_enqueue_style('yoone-pb-frontend');
|
||||
wp_enqueue_script('yoone-pb-frontend');
|
||||
|
||||
// 输出模板
|
||||
ob_start();
|
||||
wc_get_template('global/yoone-bundle-form.php', array(), '', YOONE_PB_PATH . 'templates/');
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
// 启动短代码注册
|
||||
Yoone_PB_Shortcodes::init();
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
* Version: 0.1.0
|
||||
* Requires at least: 6.0
|
||||
* Requires PHP: 7.4
|
||||
* Requires Plugins: woocommerce
|
||||
* WC requires at least: 6.0
|
||||
* WC tested up to: 8.x
|
||||
*/
|
||||
|
|
@ -29,6 +30,9 @@ require_once YOONE_PB_PATH . 'includes/class-yoone-product-bundles.php';
|
|||
require_once YOONE_PB_PATH . 'includes/class-yoone-product-type-bundle.php';
|
||||
require_once YOONE_PB_PATH . 'includes/admin/class-yoone-product-bundles-admin.php';
|
||||
require_once YOONE_PB_PATH . 'includes/frontend/class-yoone-product-bundles-frontend.php';
|
||||
require_once YOONE_PB_PATH . 'includes/blocks/register.php';
|
||||
require_once YOONE_PB_PATH . 'includes/shortcodes/register.php';
|
||||
// 注意:Elementor 小组件文件依赖 Elementor 的类,需在 Elementor 加载后再引入,避免致命错误
|
||||
|
||||
// 引导插件
|
||||
add_action('plugins_loaded', function () {
|
||||
|
|
@ -36,6 +40,17 @@ add_action('plugins_loaded', function () {
|
|||
Yoone_Product_Bundles::instance();
|
||||
Yoone_Product_Bundles_Admin::instance();
|
||||
Yoone_Product_Bundles_Frontend::instance();
|
||||
// 注册 Gutenberg 区块
|
||||
if (function_exists('register_block_type')) {
|
||||
Yoone_PB_Blocks::instance();
|
||||
}
|
||||
// 注册 Elementor 小组件(在 Elementor 通知 widgets 可注册时再加载并注册)
|
||||
add_action('elementor/widgets/register', function($widgets_manager){
|
||||
require_once YOONE_PB_PATH . 'includes/elementor/class-yoone-pb-elementor-widget.php';
|
||||
if (class_exists('Yoone_PB_Elementor_Widget') && class_exists('\\Elementor\\Widget_Base')) {
|
||||
$widgets_manager->register(new Yoone_PB_Elementor_Widget());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 插件版本号
|
||||
|
|
|
|||
Loading…
Reference in New Issue