subscription/includes/bundle/class-yoone-bundle.php

613 lines
16 KiB
PHP

<?php
/**
* 混装产品类
*
* 处理产品组合的创建、管理和计算
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* 混装产品类
*/
class Yoone_Bundle extends Abstract_Yoone_Data {
/**
* 对象类型
*/
protected $object_type = 'yoone_bundle';
/**
* 数据结构
*/
protected $data = array(
'name' => '',
'description' => '',
'status' => 'active',
'discount_type' => 'percentage',
'discount_value' => 0.00,
'min_quantity' => 1,
'max_quantity' => null,
'created_at' => null,
'updated_at' => null
);
/**
* 混装商品
*/
protected $items = array();
/**
* 构造函数
*/
public function __construct($id = 0) {
parent::__construct($id);
if ($this->get_id() > 0) {
$this->load_items();
}
}
/*
|--------------------------------------------------------------------------
| Getters
|--------------------------------------------------------------------------
*/
/**
* 获取名称
*/
public function get_name($context = 'view') {
return $this->get_prop('name', $context);
}
/**
* 获取描述
*/
public function get_description($context = 'view') {
return $this->get_prop('description', $context);
}
/**
* 获取状态
*/
public function get_status($context = 'view') {
return $this->get_prop('status', $context);
}
/**
* 获取折扣类型
*/
public function get_discount_type($context = 'view') {
return $this->get_prop('discount_type', $context);
}
/**
* 获取折扣值
*/
public function get_discount_value($context = 'view') {
return $this->get_prop('discount_value', $context);
}
/**
* 获取最小数量
*/
public function get_min_quantity($context = 'view') {
return $this->get_prop('min_quantity', $context);
}
/**
* 获取最大数量
*/
public function get_max_quantity($context = 'view') {
return $this->get_prop('max_quantity', $context);
}
/**
* 获取创建时间
*/
public function get_created_at($context = 'view') {
return $this->get_prop('created_at', $context);
}
/**
* 获取更新时间
*/
public function get_updated_at($context = 'view') {
return $this->get_prop('updated_at', $context);
}
/*
|--------------------------------------------------------------------------
| Setters
|--------------------------------------------------------------------------
*/
/**
* 设置名称
*/
public function set_name($name) {
$this->set_prop('name', sanitize_text_field($name));
}
/**
* 设置描述
*/
public function set_description($description) {
$this->set_prop('description', wp_kses_post($description));
}
/**
* 设置状态
*/
public function set_status($status) {
$valid_statuses = array('active', 'inactive', 'draft');
if (in_array($status, $valid_statuses)) {
$this->set_prop('status', $status);
}
}
/**
* 设置折扣类型
*/
public function set_discount_type($type) {
$valid_types = array('percentage', 'fixed', 'none');
if (in_array($type, $valid_types)) {
$this->set_prop('discount_type', $type);
}
}
/**
* 设置折扣值
*/
public function set_discount_value($value) {
$this->set_prop('discount_value', floatval($value));
}
/**
* 设置最小数量
*/
public function set_min_quantity($quantity) {
$this->set_prop('min_quantity', absint($quantity));
}
/**
* 设置最大数量
*/
public function set_max_quantity($quantity) {
$this->set_prop('max_quantity', $quantity ? absint($quantity) : null);
}
/*
|--------------------------------------------------------------------------
| 商品管理
|--------------------------------------------------------------------------
*/
/**
* 获取混装商品
*/
public function get_items() {
return $this->items;
}
/**
* 添加商品
*/
public function add_item($product_id, $quantity = 1, $args = array()) {
$defaults = array(
'discount_type' => 'none',
'discount_value' => 0.00,
'is_required' => false,
'sort_order' => 0
);
$args = wp_parse_args($args, $defaults);
$item = array(
'product_id' => absint($product_id),
'quantity' => absint($quantity),
'discount_type' => sanitize_text_field($args['discount_type']),
'discount_value' => floatval($args['discount_value']),
'is_required' => (bool) $args['is_required'],
'sort_order' => absint($args['sort_order'])
);
$this->items[] = $item;
return true;
}
/**
* 移除商品
*/
public function remove_item($index) {
if (isset($this->items[$index])) {
unset($this->items[$index]);
$this->items = array_values($this->items); // 重新索引
return true;
}
return false;
}
/**
* 清空商品
*/
public function clear_items() {
$this->items = array();
}
/**
* 加载商品
*/
protected function load_items() {
global $wpdb;
if (!$this->get_id()) {
return;
}
$items = $wpdb->get_results($wpdb->prepare("
SELECT product_id, quantity, discount_type, discount_value, is_required, sort_order
FROM {$wpdb->prefix}yoone_bundle_items
WHERE bundle_id = %d
ORDER BY sort_order ASC, id ASC
", $this->get_id()), ARRAY_A);
$this->items = $items ?: array();
}
/**
* 保存商品
*/
protected function save_items() {
global $wpdb;
if (!$this->get_id()) {
return false;
}
// 删除现有商品
$wpdb->delete(
$wpdb->prefix . 'yoone_bundle_items',
array('bundle_id' => $this->get_id()),
array('%d')
);
// 插入新商品
foreach ($this->items as $item) {
$wpdb->insert(
$wpdb->prefix . 'yoone_bundle_items',
array(
'bundle_id' => $this->get_id(),
'product_id' => $item['product_id'],
'quantity' => $item['quantity'],
'discount_type' => $item['discount_type'],
'discount_value' => $item['discount_value'],
'is_required' => $item['is_required'] ? 1 : 0,
'sort_order' => $item['sort_order']
),
array('%d', '%d', '%d', '%s', '%f', '%d', '%d')
);
}
return true;
}
/*
|--------------------------------------------------------------------------
| 价格计算
|--------------------------------------------------------------------------
*/
/**
* 计算混装价格
*/
public function calculate_price($selected_items = array()) {
$total = 0;
$items = $this->get_items();
if (empty($selected_items)) {
$selected_items = $items;
}
foreach ($selected_items as $item) {
$product = wc_get_product($item['product_id']);
if (!$product) {
continue;
}
$item_price = $product->get_price() * $item['quantity'];
// 应用商品级别折扣
if ($item['discount_type'] === 'percentage' && $item['discount_value'] > 0) {
$item_price = $item_price * (1 - $item['discount_value'] / 100);
} elseif ($item['discount_type'] === 'fixed' && $item['discount_value'] > 0) {
$item_price = max(0, $item_price - $item['discount_value']);
}
$total += $item_price;
}
// 应用混装级别折扣
if ($this->get_discount_type() === 'percentage' && $this->get_discount_value() > 0) {
$total = $total * (1 - $this->get_discount_value() / 100);
} elseif ($this->get_discount_type() === 'fixed' && $this->get_discount_value() > 0) {
$total = max(0, $total - $this->get_discount_value());
}
return apply_filters('yoone_bundle_calculate_price', $total, $this, $selected_items);
}
/**
* 获取节省金额
*/
public function get_savings($selected_items = array()) {
$original_total = 0;
$bundle_total = $this->calculate_price($selected_items);
$items = empty($selected_items) ? $this->get_items() : $selected_items;
foreach ($items as $item) {
$product = wc_get_product($item['product_id']);
if ($product) {
$original_total += $product->get_price() * $item['quantity'];
}
}
return max(0, $original_total - $bundle_total);
}
/*
|--------------------------------------------------------------------------
| 验证方法
|--------------------------------------------------------------------------
*/
/**
* 验证数量
*/
public function validate_quantity($quantity) {
$min = $this->get_min_quantity();
$max = $this->get_max_quantity();
if ($quantity < $min) {
return false;
}
if ($max && $quantity > $max) {
return false;
}
return true;
}
/**
* 检查是否可用
*/
public function is_available() {
return $this->get_status() === 'active' && !empty($this->get_items());
}
/*
|--------------------------------------------------------------------------
| 数据库操作
|--------------------------------------------------------------------------
*/
/**
* 从数据库读取
*/
protected function read() {
global $wpdb;
$data = $wpdb->get_row($wpdb->prepare("
SELECT * FROM {$wpdb->prefix}yoone_bundles WHERE id = %d
", $this->get_id()));
if ($data) {
$this->set_props(array(
'name' => $data->name,
'description' => $data->description,
'status' => $data->status,
'discount_type' => $data->discount_type,
'discount_value' => $data->discount_value,
'min_quantity' => $data->min_quantity,
'max_quantity' => $data->max_quantity,
'created_at' => $data->created_at,
'updated_at' => $data->updated_at
));
}
}
/**
* 创建记录
*/
protected function create() {
global $wpdb;
$data = array(
'name' => $this->get_name('edit'),
'description' => $this->get_description('edit'),
'status' => $this->get_status('edit'),
'discount_type' => $this->get_discount_type('edit'),
'discount_value' => $this->get_discount_value('edit'),
'min_quantity' => $this->get_min_quantity('edit'),
'max_quantity' => $this->get_max_quantity('edit'),
'created_at' => current_time('mysql'),
'updated_at' => current_time('mysql')
);
$result = $wpdb->insert(
$wpdb->prefix . 'yoone_bundles',
$data,
array('%s', '%s', '%s', '%s', '%f', '%d', '%d', '%s', '%s')
);
if ($result) {
$this->set_id($wpdb->insert_id);
$this->save_items();
do_action('yoone_bundle_created', $this->get_id(), $this);
}
return $result;
}
/**
* 更新记录
*/
protected function update() {
global $wpdb;
$changes = $this->get_changes();
if (empty($changes)) {
return true;
}
$changes['updated_at'] = current_time('mysql');
$result = $wpdb->update(
$wpdb->prefix . 'yoone_bundles',
$changes,
array('id' => $this->get_id()),
null,
array('%d')
);
if ($result !== false) {
$this->save_items();
do_action('yoone_bundle_updated', $this->get_id(), $this);
}
return $result !== false;
}
/**
* 从数据库删除
*/
protected function delete_from_database($force_delete = false) {
global $wpdb;
// 删除商品
$wpdb->delete(
$wpdb->prefix . 'yoone_bundle_items',
array('bundle_id' => $this->get_id()),
array('%d')
);
// 删除混装
$result = $wpdb->delete(
$wpdb->prefix . 'yoone_bundles',
array('id' => $this->get_id()),
array('%d')
);
return $result !== false;
}
/**
* 设置多个属性
*/
protected function set_props($props) {
foreach ($props as $prop => $value) {
if (array_key_exists($prop, $this->data)) {
$this->data[$prop] = $value;
}
}
}
/*
|--------------------------------------------------------------------------
| 前端辅助方法
|--------------------------------------------------------------------------
*/
/**
* 根据产品ID获取套装数据
*/
public function get_bundle_by_product_id($product_id) {
global $wpdb;
$bundle_data = $wpdb->get_row($wpdb->prepare("
SELECT * FROM {$wpdb->prefix}yoone_bundles
WHERE product_id = %d AND status = 'active'
LIMIT 1
", $product_id), ARRAY_A);
return $bundle_data;
}
/**
* 获取套装项目
*/
public function get_bundle_items($bundle_id = null) {
global $wpdb;
$id = $bundle_id ? $bundle_id : $this->get_id();
if (!$id) {
return array();
}
$items = $wpdb->get_results($wpdb->prepare("
SELECT bi.*, p.post_title as product_name
FROM {$wpdb->prefix}yoone_bundle_items bi
LEFT JOIN {$wpdb->posts} p ON bi.product_id = p.ID
WHERE bi.bundle_id = %d
ORDER BY bi.sort_order ASC
", $id), ARRAY_A);
return $items ? $items : array();
}
/**
* 计算套装价格
*/
public function calculate_bundle_price($selected_items) {
if (empty($selected_items)) {
return 0;
}
$total_price = 0;
// 计算原始总价
foreach ($selected_items as $item) {
$product = wc_get_product($item['product_id']);
if ($product) {
$total_price += $product->get_price() * $item['quantity'];
}
}
// 应用折扣
$discount_type = $this->get_discount_type();
$discount_value = $this->get_discount_value();
if ($discount_type === 'percentage' && $discount_value > 0) {
$discount_amount = $total_price * ($discount_value / 100);
$total_price -= $discount_amount;
} elseif ($discount_type === 'fixed' && $discount_value > 0) {
$total_price -= $discount_value;
}
// 确保价格不为负数
return max(0, $total_price);
}
/**
* 获取关联的产品ID
*/
public function get_product_id() {
return $this->get_prop('product_id');
}
/**
* 设置关联的产品ID
*/
public function set_product_id($product_id) {
$this->set_prop('product_id', absint($product_id));
}
}