init_hooks(); } /** * 初始化钩子 */ private function init_hooks() { // 在产品页面显示混装选项 add_action('woocommerce_single_product_summary', array($this, 'display_bundle_options'), 25); // 处理混装产品添加到购物车 add_filter('woocommerce_add_to_cart_validation', array($this, 'validate_bundle_add_to_cart'), 10, 3); add_action('woocommerce_add_to_cart', array($this, 'add_bundle_to_cart'), 10, 6); // 在购物车中显示混装信息 add_filter('woocommerce_get_item_data', array($this, 'display_bundle_cart_item_data'), 10, 2); // 计算混装价格 add_action('woocommerce_before_calculate_totals', array($this, 'calculate_bundle_cart_item_price')); // 加载前端脚本和样式 add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); } /** * 显示混装选项 */ public function display_bundle_options() { global $product; if (!$product || !$this->is_bundle_product($product->get_id())) { return; } $bundle = $this->get_product_bundle($product->get_id()); if (!$bundle || !$bundle->is_available()) { return; } $items = $bundle->get_items(); if (empty($items)) { return; } // 加载模板 wc_get_template( 'single-product/bundle-options.php', array( 'bundle' => $bundle, 'items' => $items, 'product' => $product ), '', YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/frontend/' ); } /** * 验证混装产品添加到购物车 */ public function validate_bundle_add_to_cart($passed, $product_id, $quantity) { if (!$this->is_bundle_product($product_id)) { return $passed; } $bundle = $this->get_product_bundle($product_id); if (!$bundle) { wc_add_notice(__('混装产品不存在', 'yoone-subscriptions'), 'error'); return false; } // 验证数量 if (!$bundle->validate_quantity($quantity)) { $min = $bundle->get_min_quantity(); $max = $bundle->get_max_quantity(); if ($max) { $message = sprintf(__('数量必须在 %d 到 %d 之间', 'yoone-subscriptions'), $min, $max); } else { $message = sprintf(__('最小数量为 %d', 'yoone-subscriptions'), $min); } wc_add_notice($message, 'error'); return false; } // 验证选择的商品 $selected_items = isset($_POST['bundle_items']) ? $_POST['bundle_items'] : array(); if (empty($selected_items)) { wc_add_notice(__('请选择混装商品', 'yoone-subscriptions'), 'error'); return false; } // 验证必需商品 $bundle_items = $bundle->get_items(); foreach ($bundle_items as $item) { if ($item['is_required'] && !isset($selected_items[$item['product_id']])) { $product = wc_get_product($item['product_id']); $message = sprintf(__('必须选择商品: %s', 'yoone-subscriptions'), $product->get_name()); wc_add_notice($message, 'error'); return false; } } // 验证库存 foreach ($selected_items as $item_product_id => $item_quantity) { $item_product = wc_get_product($item_product_id); if (!$item_product) { continue; } if (!$item_product->has_enough_stock($item_quantity * $quantity)) { $message = sprintf(__('商品 %s 库存不足', 'yoone-subscriptions'), $item_product->get_name()); wc_add_notice($message, 'error'); return false; } } return $passed; } /** * 添加混装产品到购物车 */ public function add_bundle_to_cart($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) { if (!$this->is_bundle_product($product_id)) { return; } $selected_items = isset($_POST['bundle_items']) ? $_POST['bundle_items'] : array(); if (empty($selected_items)) { return; } // 保存混装信息到购物车项目 WC()->cart->cart_contents[$cart_item_key]['bundle_items'] = $selected_items; WC()->cart->cart_contents[$cart_item_key]['is_bundle'] = true; } /** * 在购物车中显示混装信息 */ public function display_bundle_cart_item_data($item_data, $cart_item) { if (!isset($cart_item['is_bundle']) || !$cart_item['is_bundle']) { return $item_data; } if (!isset($cart_item['bundle_items']) || empty($cart_item['bundle_items'])) { return $item_data; } $item_data[] = array( 'key' => __('混装商品', 'yoone-subscriptions'), 'value' => $this->format_bundle_items($cart_item['bundle_items']) ); return $item_data; } /** * 计算混装购物车项目价格 */ public function calculate_bundle_cart_item_price($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } foreach ($cart->get_cart() as $cart_item_key => $cart_item) { if (!isset($cart_item['is_bundle']) || !$cart_item['is_bundle']) { continue; } $product_id = $cart_item['product_id']; $bundle = $this->get_product_bundle($product_id); if (!$bundle) { continue; } $selected_items = isset($cart_item['bundle_items']) ? $cart_item['bundle_items'] : array(); $bundle_price = $bundle->calculate_price($this->format_selected_items($selected_items)); // 设置新价格 $cart_item['data']->set_price($bundle_price); } } /** * 加载前端脚本和样式 */ public function enqueue_scripts() { if (is_product()) { wp_enqueue_script( 'yoone-bundle-frontend', YOONE_SUBSCRIPTIONS_PLUGIN_URL . 'assets/js/bundle-frontend.js', array('jquery'), YOONE_SUBSCRIPTIONS_VERSION, true ); wp_enqueue_style( 'yoone-bundle-frontend', YOONE_SUBSCRIPTIONS_PLUGIN_URL . 'assets/css/bundle-frontend.css', array(), YOONE_SUBSCRIPTIONS_VERSION ); // 本地化脚本 wp_localize_script('yoone-bundle-frontend', 'yoone_bundle_params', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('yoone_bundle_nonce'), 'i18n' => array( 'select_items' => __('请选择商品', 'yoone-subscriptions'), 'calculating' => __('计算中...', 'yoone-subscriptions'), 'error' => __('发生错误', 'yoone-subscriptions') ) )); } } /* |-------------------------------------------------------------------------- | 辅助方法 |-------------------------------------------------------------------------- */ /** * 检查是否为混装产品 */ private function is_bundle_product($product_id) { $bundle = $this->get_product_bundle($product_id); return $bundle && $bundle->is_available(); } /** * 获取产品的混装配置 */ private function get_product_bundle($product_id) { static $bundles = array(); if (!isset($bundles[$product_id])) { global $wpdb; $bundle_id = $wpdb->get_var($wpdb->prepare(" SELECT id FROM {$wpdb->prefix}yoone_bundles WHERE product_id = %d AND status = 'active' LIMIT 1 ", $product_id)); if ($bundle_id) { $bundles[$product_id] = new Yoone_Bundle($bundle_id); } else { $bundles[$product_id] = false; } } return $bundles[$product_id]; } /** * 格式化混装商品显示 */ private function format_bundle_items($bundle_items) { $formatted = array(); foreach ($bundle_items as $product_id => $quantity) { $product = wc_get_product($product_id); if ($product) { $formatted[] = sprintf('%s × %d', $product->get_name(), $quantity); } } return implode(', ', $formatted); } /** * 格式化选择的商品为计算格式 */ private function format_selected_items($selected_items) { $formatted = array(); foreach ($selected_items as $product_id => $quantity) { $formatted[] = array( 'product_id' => $product_id, 'quantity' => $quantity, 'discount_type' => 'none', 'discount_value' => 0, 'is_required' => false, 'sort_order' => 0 ); } return $formatted; } } // 初始化 new Yoone_Bundle_Frontend();