'', '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)); } }