yoone-wc-product-bundles/templates/global/yoone-bundle-form.php

183 lines
9.3 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
/**
* Yoone Product Bundles - Mix and Match Product Selection Form
*
* This template part contains the full frontend interface for selecting bundle components,
* including the card-based layout, quantity inputs, and dynamically updated total count.
* It is hooked into `woocommerce_single_product_summary` to replace the standard add-to-cart form.
*
* @version 3.0.1
*/
defined('ABSPATH') || exit;
global $product;
// --- 数据准备逻辑 ---
$config = Yoone_Product_Bundles::get_bundle_config($product);
$allowed = $config['allowed_products'];
$select_mode = isset($config['select_mode']) ? $config['select_mode'] : 'include';
$min_qty = max(0, absint($config['min_qty']));
// 是否允许在购物车中编辑混装
$edit_in_cart_enabled = isset($config['edit_in_cart']) && $config['edit_in_cart'] === 'yes';
// 折扣设置
$discount_type = isset($config['discount_type']) ? $config['discount_type'] : 'none';
$discount_amount = isset($config['discount_amount']) ? floatval($config['discount_amount']) : 0.0;
// 价格显示格式(用于前端计算与显示)
$currency_symbol = get_woocommerce_currency_symbol();
$price_decimals = wc_get_price_decimals();
$decimal_separator = wc_get_price_decimal_separator();
$thousand_separator = wc_get_price_thousand_separator();
// 读取按 taxonomy 分组的配置(支持 product_cat / product_tag
$group_taxonomy = isset($config['group_taxonomy']) ? $config['group_taxonomy'] : 'product_cat';
$term_ids = isset($config['group_terms']) ? (array) $config['group_terms'] : array();
$allowed_products = array();
foreach ($allowed as $pid) {
$p = wc_get_product($pid);
if ($p && $p->is_type('simple')) {
$allowed_products[$pid] = $p;
}
}
// 兜底:如果为 exclude/all 模式,但由于缓存或其他原因导致 allowed_products 为空,则直接读取所有 simple 产品
if (empty($allowed_products) && in_array($select_mode, array('exclude','all'), true)) {
$all_ids = wc_get_products(array(
'type' => array('simple'),
'status' => array('publish'),
'catalog_visibility' => 'any',
'limit' => -1,
'return' => 'ids',
));
if (is_array($all_ids)) {
foreach ($all_ids as $pid) {
$p = wc_get_product($pid);
if ($p && $p->is_type('simple')) {
$allowed_products[$pid] = $p;
}
}
}
}
$groups = array();
if (!empty($term_ids)) {
$is_grouped = true;
$others = array();
foreach ($allowed_products as $pid => $p) {
$terms = get_the_terms($pid, $group_taxonomy);
$matched = false;
if (is_array($terms)) {
foreach ($terms as $t) {
if (in_array($t->term_id, $term_ids, true)) {
if (!isset($groups[$t->term_id])) {
$groups[$t->term_id] = array('term' => $t, 'items' => array());
}
$groups[$t->term_id]['items'][] = $p;
$matched = true;
}
}
}
if (!$matched) $others[] = $p;
}
if (!empty($others)) $groups[0] = array('term' => null, 'items' => $others);
} else {
$is_grouped = false;
$groups[0] = array('term' => null, 'items' => array_values($allowed_products));
}
// --- 数据准备逻辑结束 ---
?>
<div class="yoone-bundle-form-container">
<?php do_action('woocommerce_before_add_to_cart_form'); ?>
<form class="cart yoone-bundle-form" action="<?php echo esc_url(apply_filters('woocommerce_add_to_cart_form_action', $product->get_permalink())); ?>" method="post" enctype="multipart/form-data"
data-currency-symbol="<?php echo esc_attr($currency_symbol); ?>"
data-price-decimals="<?php echo esc_attr($price_decimals); ?>"
data-decimal-separator="<?php echo esc_attr($decimal_separator); ?>"
data-thousand-separator="<?php echo esc_attr($thousand_separator); ?>"
data-discount-type="<?php echo esc_attr($discount_type); ?>"
data-discount-amount="<?php echo esc_attr($discount_amount); ?>"
>
<div class="yoone-bundle-meta">
<p class="yoone-bundle-min"><?php printf(esc_html__('Select at least %d items to build your bundle.', 'yoone-product-bundles'), $min_qty); ?></p>
<p class="yoone-bundle-selected"><?php esc_html_e('Currently selected:', 'yoone-product-bundles'); ?> <span class="yoone-bundle-selected-count">0</span></p>
<?php if ($edit_in_cart_enabled) : ?>
<div class="yoone-bundle-edit-in-cart">
<label>
<input type="checkbox" name="yoone_bundle_edit_in_cart" value="1" checked />
<?php esc_html_e('Allow editing bundle items in Cart (quantities and removal).', 'yoone-product-bundles'); ?>
</label>
</div>
<?php endif; ?>
<div class="yoone-bundle-totals">
<p class="yoone-bundle-total-raw">
<?php esc_html_e('Selected items total:', 'yoone-product-bundles'); ?>
<span class="yoone-bundle-total-raw-value">0</span>
</p>
<?php if ($discount_type !== 'none' && $discount_amount > 0) : ?>
<p class="yoone-bundle-total-discounted">
<?php esc_html_e('After bundle discount:', 'yoone-product-bundles'); ?>
<span class="yoone-bundle-total-discounted-value">0</span>
</p>
<?php endif; ?>
</div>
<div class="yoone-bundle-actions">
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr($product->get_id()); ?>" />
<?php
// 在按钮之前触发钩子,方便订阅等插件在此渲染选项
do_action('woocommerce_before_add_to_cart_button');
?>
<button type="submit" class="single_add_to_cart_button button alt" disabled><?php echo esc_html( apply_filters( 'woocommerce_product_single_add_to_cart_text', __( 'Add to Cart', 'yoone-product-bundles' ) ) ); ?></button>
<?php
// 在按钮之后触发钩子,保持与 Woo 默认模板一致
do_action('woocommerce_after_add_to_cart_button');
?>
</div>
</div>
<?php if (empty($allowed_products)) : ?>
<p><?php esc_html_e('No products are available for this bundle. Please configure it in the backend.', 'yoone-product-bundles'); ?></p>
<?php else : ?>
<?php foreach ($groups as $gid => $group) : ?>
<div class="yoone-bundle-group">
<?php if (!empty($group['term'])) : ?>
<h3 class="yoone-bundle-group-title"><?php echo esc_html($group['term']->name); ?></h3>
<?php else : ?>
<h3 class="yoone-bundle-group-title">
<?php echo $is_grouped
? esc_html__('Others', 'yoone-product-bundles')
: esc_html__('All Products', 'yoone-product-bundles'); ?>
</h3>
<?php endif; ?>
<?php if (empty($group['items'])) : ?>
<p class="yoone-bundle-no-items"><?php esc_html_e('No products available in this group.', 'yoone-product-bundles'); ?></p>
<?php else : ?>
<div class="yoone-bundle-items-wrapper">
<?php foreach ($group['items'] as $item) : ?>
<?php
$pid = $item->get_id();
$thumbnail = $item->get_image('woocommerce_thumbnail');
?>
<div class="yoone-bundle-item-card">
<div class="item-image">
<a href="<?php echo esc_url(get_permalink($pid)); ?>" target="_blank">
<?php echo $thumbnail ? $thumbnail : wc_placeholder_img('woocommerce_thumbnail'); ?>
</a>
</div>
<h4 class="item-title">
<a href="<?php echo esc_url(get_permalink($pid)); ?>" target="_blank"><?php echo esc_html($item->get_name()); ?></a>
</h4>
<div class="item-price">
<?php echo wp_kses_post($item->get_price_html()); ?>
</div>
<div class="item-quantity">
<input type="number" min="0" step="1" class="yoone-bundle-qty" name="yoone_bundle_components[<?php echo esc_attr($pid); ?>]" value="0" placeholder="0" data-unit-price="<?php echo esc_attr($item->get_price()); ?>" />
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
</form>
<?php do_action('woocommerce_after_add_to_cart_form'); ?>
</div>