yoone-wc-product-bundles/includes/frontend/class-yoone-product-bundles...

198 lines
7.7 KiB
PHP
Raw Permalink 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
/**
* 前端:为混装产品渲染自定义的“添加到购物车”表单,并处理验证和加入购物车的逻辑。
*/
defined('ABSPATH') || exit;
class Yoone_Product_Bundles_Frontend {
private static $_instance = null;
public static function instance() {
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() {
$this->setup_hooks();
}
/**
* 设置所有与前端相关的钩子。
*/
public function setup_hooks() {
// 处理混装产品的自定义“添加到购物车”流程
add_filter('woocommerce_add_to_cart_validation', array($this, 'process_bundle_add_to_cart'), 10, 3);
// 当混装容器被移除时,移除其子项目
add_action('woocommerce_cart_item_removed', array($this, 'remove_bundle_children'), 10, 2);
// 隐藏购物车中子项目的“移除”链接
add_filter('woocommerce_cart_item_remove_link', array($this, 'hide_child_remove_link'), 10, 2);
// 在购物车中,显示子项目所属的混装产品
add_filter('woocommerce_get_item_data', array($this, 'display_child_bundle_link'), 10, 2);
// 为混装产品页面添加 body class以便于样式化
add_filter('body_class', array($this, 'filter_body_class'));
// 用我们的自定义表单替换默认的“添加到购物车”按钮
add_action('woocommerce_single_product_summary', array($this, 'remove_default_add_to_cart_for_bundle'), 29);
add_action('woocommerce_single_product_summary', array($this, 'render_bundle_add_to_cart_form'), 30);
}
/**
* 劫持混装产品的“添加到购物车”流程。
* 验证提交,然后将容器和所有子产品添加到购物车。
*
* @return bool False 以阻止默认的“添加到购物车”操作。
*/
public function process_bundle_add_to_cart($passed, $product_id, $quantity) {
$product = wc_get_product($product_id);
if (!$product || $product->get_type() !== Yoone_Product_Bundles::TYPE) {
return $passed; // 不是我们的产品,直接通过。
}
// 1. 验证
$config = Yoone_Product_Bundles::get_bundle_config($product);
$min_qty = max(1, absint($config['min_qty']));
$components = !empty($_POST['yoone_bundle_components']) ? (array) $_POST['yoone_bundle_components'] : array();
$total_qty = 0;
$clean_components = array();
foreach ($components as $comp_id => $qty) {
$qty = absint($qty);
if ($qty > 0) {
$total_qty += $qty;
$clean_components[absint($comp_id)] = $qty;
}
}
if ($total_qty < $min_qty) {
wc_add_notice(sprintf(__('You need to select at least %d items to add this bundle to your cart.', 'yoone-product-bundles'), $min_qty), 'error');
return false;
}
// 2. 添加商品到购物车
try {
$bundle_container_id = uniqid('bundle_');
// 添加主混装产品作为价格为0的容器
WC()->cart->add_to_cart($product_id, 1, 0, array(), array('yoone_bundle_container_id' => $bundle_container_id));
// 添加子组件
foreach ($clean_components as $comp_id => $qty) {
WC()->cart->add_to_cart($comp_id, $qty, 0, array(), array(
'yoone_bundle_parent_id' => $bundle_container_id,
'yoone_bundle_parent_product_id' => $product_id
));
}
// 设置成功消息并重定向
wc_add_to_cart_message(array($product_id => 1), true);
add_filter('woocommerce_add_to_cart_redirect', function() { return wc_get_cart_url(); });
} catch (Exception $e) {
wc_add_notice($e->getMessage(), 'error');
return false;
}
// 阻止主产品的默认“添加到购物车”行为
return false;
}
/**
* 当一个购物车项目被移除时,检查它是否是一个混装容器。
* 如果是,则找到并移除其所有的子项目。
*/
public function remove_bundle_children($removed_cart_item_key, $cart) {
// 此钩子在项目已从购物车会话中移除后触发,所以我们在 `removed_cart_contents` 中查找它。
if (!isset($cart->removed_cart_contents[$removed_cart_item_key])) {
return;
}
$removed_item = $cart->removed_cart_contents[$removed_cart_item_key];
// 检查被移除的商品是否是我们的混装容器。
if (isset($removed_item['yoone_bundle_container_id'])) {
$bundle_container_id = $removed_item['yoone_bundle_container_id'];
$child_item_keys_to_remove = [];
// 遍历购物车,找到所有属于此容器的子项目。
// 我们不能在遍历时直接修改购物车所以我们先收集要移除的项目的key。
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
if (isset($cart_item['yoone_bundle_parent_id']) && $cart_item['yoone_bundle_parent_id'] === $bundle_container_id) {
$child_item_keys_to_remove[] = $cart_item_key;
}
}
// 现在遍历收集到的key并从购物车中移除子项目。
foreach ($child_item_keys_to_remove as $key_to_remove) {
$cart->remove_cart_item($key_to_remove);
}
}
}
/**
* 隐藏混装产品子项目的移除链接。
*/
public function hide_child_remove_link($link, $cart_item_key) {
$cart_item = WC()->cart->get_cart_item($cart_item_key);
if (isset($cart_item['yoone_bundle_parent_id'])) {
return '';
}
return $link;
}
/**
* 对于子项目,在购物车中添加一个元信息行,以链接回父混装产品。
*/
public function display_child_bundle_link($item_data, $cart_item) {
if (isset($cart_item['yoone_bundle_parent_product_id'])) {
$parent_product = wc_get_product($cart_item['yoone_bundle_parent_product_id']);
if ($parent_product) {
$item_data[] = array(
'key' => __('Part of', 'yoone-product-bundles'),
'value' => $parent_product->get_name(),
);
}
}
return $item_data;
}
/**
* 仅为混装产品移除默认的“添加到购物车”按钮。
*/
public function remove_default_add_to_cart_for_bundle() {
global $product;
if ($product && $product->get_type() === Yoone_Product_Bundles::TYPE) {
remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30);
}
}
/**
* 为混装产品渲染自定义的“添加到购物车”表单。
*/
public function render_bundle_add_to_cart_form() {
global $product;
if ($product && $product->get_type() === Yoone_Product_Bundles::TYPE) {
wc_get_template('global/yoone-bundle-form.php', array(), '', YOONE_PB_PATH . 'templates/');
}
}
/**
* 为混装产品页面添加一个 body class。
*/
public function filter_body_class($classes) {
global $post;
if (is_singular('product') && $post) {
$product = wc_get_product($post->ID);
if ($product && $product->get_type() === Yoone_Product_Bundles::TYPE) {
$classes[] = 'yoone-bundle-product';
}
}
return $classes;
}
}