80 lines
3.0 KiB
PHP
80 lines
3.0 KiB
PHP
<?php
|
||
/**
|
||
* 核心:注册产品类型、常量、工具方法。
|
||
*/
|
||
defined('ABSPATH') || exit;
|
||
|
||
class Yoone_Product_Bundles {
|
||
const TYPE = 'yoone_bundle';
|
||
|
||
// 配置的 postmeta 键名
|
||
const META_ALLOWED_PRODUCTS = '_yoone_bundle_allowed_products'; // array<int>
|
||
const META_MIN_QTY = '_yoone_bundle_min_quantity'; // int
|
||
const META_CATEGORIES = '_yoone_bundle_categories'; // array<int> product_cat term_ids
|
||
|
||
protected static $instance = null;
|
||
|
||
public static function instance() {
|
||
if (null === self::$instance) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
private function __construct() {
|
||
// 将产品类型加入选择器
|
||
add_filter('product_type_selector', array($this, 'register_product_type_in_selector'));
|
||
// 将类型映射到我们的 WC_Product 派生类
|
||
add_filter('woocommerce_product_class', array($this, 'map_product_class'), 10, 2);
|
||
}
|
||
|
||
/**
|
||
* 在后台“产品类型”下拉中添加“混装产品”。
|
||
*/
|
||
public function register_product_type_in_selector($types) {
|
||
$types[self::TYPE] = __('混装产品 (Yoone Bundle)', 'yoone-product-bundles');
|
||
return $types;
|
||
}
|
||
|
||
/**
|
||
* 将类型映射到类名,WooCommerce 会实例化对应产品对象。
|
||
*/
|
||
public function map_product_class($classname, $product_type) {
|
||
if ($product_type === self::TYPE) {
|
||
$classname = 'WC_Product_Yoone_Bundle';
|
||
}
|
||
return $classname;
|
||
}
|
||
|
||
/**
|
||
* 读取并规范化 bundle 配置。
|
||
* @param int|WC_Product $product
|
||
* @return array{allowed_products:int[],min_qty:int,categories:int[]}
|
||
*/
|
||
public static function get_bundle_config($product) {
|
||
$product = is_numeric($product) ? wc_get_product($product) : $product;
|
||
if (! $product) return array('allowed_products' => array(), 'min_qty' => 0, 'categories' => array());
|
||
$pid = $product->get_id();
|
||
$allowed = get_post_meta($pid, self::META_ALLOWED_PRODUCTS, true);
|
||
$min = absint(get_post_meta($pid, self::META_MIN_QTY, true));
|
||
$cats = get_post_meta($pid, self::META_CATEGORIES, true);
|
||
// 仅保留 simple 产品(避免后台选择了变体或其他类型导致前端不显示)
|
||
$allowed = is_array($allowed) ? array_values(array_map('absint', $allowed)) : array();
|
||
if (! empty($allowed)) {
|
||
$simple_only = array();
|
||
foreach ($allowed as $aid) {
|
||
$p = wc_get_product($aid);
|
||
if ($p && $p->is_type('simple')) {
|
||
$simple_only[] = $aid;
|
||
}
|
||
}
|
||
$allowed = $simple_only;
|
||
}
|
||
$cats = is_array($cats) ? array_values(array_map('absint', $cats)) : array();
|
||
return array(
|
||
'allowed_products' => $allowed,
|
||
'min_qty' => max(0, $min),
|
||
'categories' => $cats,
|
||
);
|
||
}
|
||
} |