107 lines
4.4 KiB
PHP
107 lines
4.4 KiB
PHP
<?php
|
||
/**
|
||
* 核心:订阅计划配置的读写与工具函数。
|
||
*
|
||
* @package Yoone_Subscriptions
|
||
*/
|
||
defined('ABSPATH') || exit;
|
||
|
||
class Yoone_Subscriptions {
|
||
// postmeta 键名
|
||
const META_ENABLED = '_yoone_sub_enabled'; // bool
|
||
const META_PERIOD = '_yoone_sub_period'; // 'month'|'year'
|
||
const META_QTY_DEFAULT = '_yoone_sub_qty_default'; // int >=1
|
||
const META_PRICE = '_yoone_sub_price'; // decimal string
|
||
const META_ALLOW_ONETIME = '_yoone_sub_allow_onetime'; // bool
|
||
const META_MIN_QTY = '_yoone_sub_min_qty'; // int >=1(最小起订量,仅订阅模式下生效)
|
||
const META_TIER_RULES = '_yoone_sub_tier_rules'; // string 逗号分隔“数量:折扣%”对,如 10:5,20:10
|
||
// 新增:多订阅计划(每个计划包含:id、label、period、price、discount_percent 可选)
|
||
const META_PLANS = '_yoone_sub_plans'; // serialized array
|
||
|
||
protected static $instance = null;
|
||
|
||
/**
|
||
* 单例
|
||
*/
|
||
public static function instance() {
|
||
if (null === self::$instance) self::$instance = new self();
|
||
return self::$instance;
|
||
}
|
||
|
||
private function __construct() {
|
||
// 无需在此注册产品类型;订阅计划作为 simple/product 的增强配置存在
|
||
}
|
||
|
||
/**
|
||
* 获取产品的订阅配置(规范化)。
|
||
*
|
||
* @param int|WC_Product $product 产品或产品ID
|
||
* @return array{enabled:bool,period:string,qty_default:int,price:float,allow_onetime:bool}
|
||
*/
|
||
public static function get_config($product) {
|
||
$product = is_numeric($product) ? wc_get_product($product) : $product;
|
||
if (! $product) return self::defaults();
|
||
$pid = $product->get_id();
|
||
$enabled = (bool) get_post_meta($pid, self::META_ENABLED, true);
|
||
$period = get_post_meta($pid, self::META_PERIOD, true);
|
||
$qty = absint(get_post_meta($pid, self::META_QTY_DEFAULT, true));
|
||
$price = get_post_meta($pid, self::META_PRICE, true);
|
||
$onetime = (bool) get_post_meta($pid, self::META_ALLOW_ONETIME, true);
|
||
$min_qty = absint(get_post_meta($pid, self::META_MIN_QTY, true));
|
||
$tiers = get_post_meta($pid, self::META_TIER_RULES, true);
|
||
$plans = get_post_meta($pid, self::META_PLANS, true);
|
||
$period = in_array($period, array('month','year'), true) ? $period : 'month';
|
||
$qty = max(1, $qty);
|
||
$price = is_numeric($price) ? floatval($price) : 0.0; // 0 表示按产品原价
|
||
// 规范化计划数组
|
||
if (! is_array($plans)) {
|
||
$plans = array();
|
||
} else {
|
||
$norm = array();
|
||
foreach ($plans as $p) {
|
||
$norm[] = array(
|
||
'id' => isset($p['id']) ? sanitize_key($p['id']) : uniqid('plan_'),
|
||
'label' => isset($p['label']) ? sanitize_text_field($p['label']) : __('订阅计划', 'yoone-subscriptions'),
|
||
'period' => (isset($p['period']) && in_array($p['period'], array('month','year'), true)) ? $p['period'] : 'month',
|
||
'price' => isset($p['price']) && is_numeric($p['price']) ? floatval($p['price']) : 0.0,
|
||
'discount_percent' => isset($p['discount_percent']) && is_numeric($p['discount_percent']) ? floatval($p['discount_percent']) : 0.0,
|
||
);
|
||
}
|
||
$plans = $norm;
|
||
}
|
||
return array(
|
||
'enabled' => $enabled,
|
||
'period' => $period,
|
||
'qty_default' => $qty,
|
||
'price' => $price,
|
||
'allow_onetime' => $onetime,
|
||
'min_qty' => max(1, $min_qty),
|
||
'tier_rules' => is_string($tiers) ? $tiers : '',
|
||
'plans' => $plans,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 默认配置
|
||
*/
|
||
public static function defaults() {
|
||
return array(
|
||
'enabled' => false,
|
||
'period' => 'month',
|
||
'qty_default' => 1,
|
||
'price' => 0.0,
|
||
'allow_onetime' => true,
|
||
'min_qty' => 1,
|
||
'tier_rules' => '',
|
||
'plans' => array(),
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 周期对应的系数(用于价格计算)。
|
||
* month=1, year=12。
|
||
*/
|
||
public static function period_factor($period) {
|
||
return $period === 'year' ? 12 : 1;
|
||
}
|
||
} |