yoone-wc-subscriptions/includes/class-yoone-subscriptions.php

107 lines
4.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}