524 lines
18 KiB
PHP
524 lines
18 KiB
PHP
<?php
|
||
/**
|
||
* 前端功能管理类
|
||
*
|
||
* 处理前端页面展示和用户交互
|
||
*/
|
||
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* 前端管理类
|
||
*/
|
||
class Yoone_Frontend {
|
||
|
||
/**
|
||
* 构造函数
|
||
*/
|
||
public function __construct() {
|
||
$this->init_hooks();
|
||
}
|
||
|
||
/**
|
||
* 初始化钩子
|
||
*/
|
||
private function init_hooks() {
|
||
// 产品页面钩子
|
||
add_action('woocommerce_single_product_summary', array($this, 'display_bundle_options'), 25);
|
||
add_action('woocommerce_single_product_summary', array($this, 'display_subscription_options'), 30);
|
||
|
||
// 购物车钩子
|
||
add_filter('woocommerce_cart_item_name', array($this, 'display_cart_bundle_info'), 10, 3);
|
||
add_filter('woocommerce_cart_item_price', array($this, 'display_cart_subscription_info'), 10, 3);
|
||
|
||
// 结账钩子
|
||
add_action('woocommerce_checkout_order_review', array($this, 'display_checkout_subscription_info'));
|
||
|
||
// 我的账户钩子
|
||
add_filter('woocommerce_account_menu_items', array($this, 'add_subscriptions_menu_item'));
|
||
add_action('init', array($this, 'add_subscriptions_endpoint'));
|
||
add_action('woocommerce_account_subscriptions_endpoint', array($this, 'subscriptions_content'));
|
||
|
||
// AJAX 钩子
|
||
add_action('wp_ajax_yoone_calculate_bundle_price', array($this, 'ajax_calculate_bundle_price'));
|
||
add_action('wp_ajax_nopriv_yoone_calculate_bundle_price', array($this, 'ajax_calculate_bundle_price'));
|
||
add_action('wp_ajax_yoone_add_bundle_to_cart', array($this, 'ajax_add_bundle_to_cart'));
|
||
add_action('wp_ajax_nopriv_yoone_add_bundle_to_cart', array($this, 'ajax_add_bundle_to_cart'));
|
||
|
||
// 脚本和样式
|
||
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
|
||
|
||
// 产品类型支持
|
||
add_filter('woocommerce_product_class', array($this, 'product_class_filter'), 10, 2);
|
||
}
|
||
|
||
/**
|
||
* 加载脚本和样式
|
||
*/
|
||
public function enqueue_scripts() {
|
||
if (is_product() || is_cart() || is_checkout() || is_account_page()) {
|
||
wp_enqueue_script(
|
||
'yoone-frontend',
|
||
YOONE_SUBSCRIPTIONS_PLUGIN_URL . 'assets/js/frontend.js',
|
||
array('jquery'),
|
||
YOONE_SUBSCRIPTIONS_VERSION,
|
||
true
|
||
);
|
||
|
||
wp_enqueue_style(
|
||
'yoone-frontend',
|
||
YOONE_SUBSCRIPTIONS_PLUGIN_URL . 'assets/css/frontend.css',
|
||
array(),
|
||
YOONE_SUBSCRIPTIONS_VERSION
|
||
);
|
||
|
||
wp_localize_script('yoone-frontend', 'yoone_frontend_params', array(
|
||
'ajax_url' => admin_url('admin-ajax.php'),
|
||
'nonce' => wp_create_nonce('yoone_frontend_nonce'),
|
||
'i18n' => array(
|
||
'loading' => __('加载中...', 'yoone-subscriptions'),
|
||
'error' => __('发生错误,请重试', 'yoone-subscriptions'),
|
||
'select_products' => __('请选择产品', 'yoone-subscriptions'),
|
||
'min_quantity' => __('最小数量: %d', 'yoone-subscriptions'),
|
||
'max_quantity' => __('最大数量: %d', 'yoone-subscriptions'),
|
||
'bundle_savings' => __('套装优惠: %s', 'yoone-subscriptions'),
|
||
'subscription_info' => __('订阅信息', 'yoone-subscriptions'),
|
||
)
|
||
));
|
||
}
|
||
}
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| 产品页面功能
|
||
|--------------------------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* 显示套装选项
|
||
*/
|
||
public function display_bundle_options() {
|
||
global $product;
|
||
|
||
if (!$product || $product->get_type() !== 'yoone_bundle') {
|
||
return;
|
||
}
|
||
|
||
$bundle = new Yoone_Bundle();
|
||
$bundle_data = $bundle->get_bundle_by_product_id($product->get_id());
|
||
|
||
if (!$bundle_data) {
|
||
return;
|
||
}
|
||
|
||
$bundle_items = $bundle->get_bundle_items($bundle_data['id']);
|
||
|
||
if (empty($bundle_items)) {
|
||
return;
|
||
}
|
||
|
||
wc_get_template(
|
||
'single-product/bundle-options.php',
|
||
array(
|
||
'bundle' => $bundle_data,
|
||
'bundle_items' => $bundle_items,
|
||
'product' => $product
|
||
),
|
||
'',
|
||
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 显示订阅选项
|
||
*/
|
||
public function display_subscription_options() {
|
||
global $product;
|
||
|
||
if (!$product) {
|
||
return;
|
||
}
|
||
|
||
$subscription_enabled = $product->get_meta('_yoone_subscription_enabled');
|
||
|
||
if ($subscription_enabled !== 'yes') {
|
||
return;
|
||
}
|
||
|
||
$subscription_data = array(
|
||
'period' => $product->get_meta('_yoone_subscription_period'),
|
||
'interval' => $product->get_meta('_yoone_subscription_interval'),
|
||
'length' => $product->get_meta('_yoone_subscription_length'),
|
||
'trial' => $product->get_meta('_yoone_subscription_trial_length'),
|
||
'signup' => $product->get_meta('_yoone_subscription_signup_fee')
|
||
);
|
||
|
||
wc_get_template(
|
||
'single-product/subscription-options.php',
|
||
array(
|
||
'subscription_data' => $subscription_data,
|
||
'product' => $product
|
||
),
|
||
'',
|
||
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
|
||
);
|
||
}
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| 购物车功能
|
||
|--------------------------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* 显示购物车套装信息
|
||
*/
|
||
public function display_cart_bundle_info($name, $cart_item, $cart_item_key) {
|
||
if (isset($cart_item['yoone_bundle_data'])) {
|
||
$bundle_data = $cart_item['yoone_bundle_data'];
|
||
|
||
$name .= '<div class="yoone-bundle-info">';
|
||
$name .= '<small>' . __('套装产品', 'yoone-subscriptions') . '</small>';
|
||
|
||
if (!empty($bundle_data['items'])) {
|
||
$name .= '<ul class="yoone-bundle-items">';
|
||
foreach ($bundle_data['items'] as $item) {
|
||
$item_product = wc_get_product($item['product_id']);
|
||
if ($item_product) {
|
||
$name .= '<li>' . $item_product->get_name() . ' × ' . $item['quantity'] . '</li>';
|
||
}
|
||
}
|
||
$name .= '</ul>';
|
||
}
|
||
|
||
if (isset($bundle_data['savings']) && $bundle_data['savings'] > 0) {
|
||
$name .= '<small class="yoone-savings">' . sprintf(__('节省: %s', 'yoone-subscriptions'), wc_price($bundle_data['savings'])) . '</small>';
|
||
}
|
||
|
||
$name .= '</div>';
|
||
}
|
||
|
||
return $name;
|
||
}
|
||
|
||
/**
|
||
* 显示购物车订阅信息
|
||
*/
|
||
public function display_cart_subscription_info($price, $cart_item, $cart_item_key) {
|
||
if (isset($cart_item['yoone_subscription_data'])) {
|
||
$subscription_data = $cart_item['yoone_subscription_data'];
|
||
|
||
$price .= '<div class="yoone-subscription-info">';
|
||
$price .= '<small>' . $this->format_subscription_string($subscription_data) . '</small>';
|
||
$price .= '</div>';
|
||
}
|
||
|
||
return $price;
|
||
}
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| 结账功能
|
||
|--------------------------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* 显示结账订阅信息
|
||
*/
|
||
public function display_checkout_subscription_info() {
|
||
$has_subscription = false;
|
||
|
||
foreach (WC()->cart->get_cart() as $cart_item) {
|
||
if (isset($cart_item['yoone_subscription_data'])) {
|
||
$has_subscription = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!$has_subscription) {
|
||
return;
|
||
}
|
||
|
||
echo '<div class="yoone-checkout-subscription-info">';
|
||
echo '<h3>' . __('订阅信息', 'yoone-subscriptions') . '</h3>';
|
||
echo '<p>' . __('您的订单包含订阅产品,将会自动续费。', 'yoone-subscriptions') . '</p>';
|
||
|
||
foreach (WC()->cart->get_cart() as $cart_item) {
|
||
if (isset($cart_item['yoone_subscription_data'])) {
|
||
$product = $cart_item['data'];
|
||
$subscription_data = $cart_item['yoone_subscription_data'];
|
||
|
||
echo '<div class="subscription-item">';
|
||
echo '<strong>' . $product->get_name() . '</strong><br>';
|
||
echo '<small>' . $this->format_subscription_string($subscription_data) . '</small>';
|
||
echo '</div>';
|
||
}
|
||
}
|
||
|
||
echo '</div>';
|
||
}
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| 我的账户功能
|
||
|--------------------------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* 添加订阅菜单项
|
||
*/
|
||
public function add_subscriptions_menu_item($items) {
|
||
$new_items = array();
|
||
|
||
foreach ($items as $key => $item) {
|
||
$new_items[$key] = $item;
|
||
|
||
if ($key === 'orders') {
|
||
$new_items['subscriptions'] = __('我的订阅', 'yoone-subscriptions');
|
||
}
|
||
}
|
||
|
||
return $new_items;
|
||
}
|
||
|
||
/**
|
||
* 添加订阅端点
|
||
*/
|
||
public function add_subscriptions_endpoint() {
|
||
add_rewrite_endpoint('subscriptions', EP_ROOT | EP_PAGES);
|
||
}
|
||
|
||
/**
|
||
* 订阅页面内容
|
||
*/
|
||
public function subscriptions_content() {
|
||
$customer_id = get_current_user_id();
|
||
|
||
if (!$customer_id) {
|
||
return;
|
||
}
|
||
|
||
// 获取用户订阅
|
||
global $wpdb;
|
||
|
||
$subscriptions = $wpdb->get_results($wpdb->prepare("
|
||
SELECT * FROM {$wpdb->prefix}yoone_subscriptions
|
||
WHERE customer_id = %d
|
||
ORDER BY created_at DESC
|
||
", $customer_id));
|
||
|
||
wc_get_template(
|
||
'myaccount/subscriptions.php',
|
||
array(
|
||
'subscriptions' => $subscriptions,
|
||
'customer_id' => $customer_id
|
||
),
|
||
'',
|
||
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
|
||
);
|
||
}
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| AJAX 处理
|
||
|--------------------------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* AJAX 计算套装价格
|
||
*/
|
||
public function ajax_calculate_bundle_price() {
|
||
check_ajax_referer('yoone_frontend_nonce', 'nonce');
|
||
|
||
$bundle_id = intval($_POST['bundle_id']);
|
||
$selected_items = isset($_POST['selected_items']) ? $_POST['selected_items'] : array();
|
||
|
||
if (!$bundle_id || empty($selected_items)) {
|
||
wp_send_json_error(__('无效的参数', 'yoone-subscriptions'));
|
||
}
|
||
|
||
$bundle = new Yoone_Bundle($bundle_id);
|
||
|
||
if (!$bundle->get_id()) {
|
||
wp_send_json_error(__('套装不存在', 'yoone-subscriptions'));
|
||
}
|
||
|
||
// 计算价格
|
||
$total_price = 0;
|
||
$original_price = 0;
|
||
$valid_items = array();
|
||
|
||
foreach ($selected_items as $item) {
|
||
$product_id = intval($item['product_id']);
|
||
$quantity = intval($item['quantity']);
|
||
|
||
if ($quantity <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$product = wc_get_product($product_id);
|
||
if (!$product) {
|
||
continue;
|
||
}
|
||
|
||
$item_price = $product->get_price() * $quantity;
|
||
$original_price += $item_price;
|
||
|
||
$valid_items[] = array(
|
||
'product_id' => $product_id,
|
||
'quantity' => $quantity,
|
||
'price' => $item_price
|
||
);
|
||
}
|
||
|
||
if (empty($valid_items)) {
|
||
wp_send_json_error(__('请选择有效的产品', 'yoone-subscriptions'));
|
||
}
|
||
|
||
// 应用套装折扣
|
||
$bundle_price = $bundle->calculate_bundle_price($valid_items);
|
||
$savings = $original_price - $bundle_price;
|
||
|
||
wp_send_json_success(array(
|
||
'original_price' => wc_price($original_price),
|
||
'bundle_price' => wc_price($bundle_price),
|
||
'savings' => wc_price($savings),
|
||
'savings_amount' => $savings
|
||
));
|
||
}
|
||
|
||
/**
|
||
* AJAX 添加套装到购物车
|
||
*/
|
||
public function ajax_add_bundle_to_cart() {
|
||
check_ajax_referer('yoone_frontend_nonce', 'nonce');
|
||
|
||
$bundle_id = intval($_POST['bundle_id']);
|
||
$selected_items = isset($_POST['selected_items']) ? $_POST['selected_items'] : array();
|
||
|
||
if (!$bundle_id || empty($selected_items)) {
|
||
wp_send_json_error(__('无效的参数', 'yoone-subscriptions'));
|
||
}
|
||
|
||
$bundle = new Yoone_Bundle($bundle_id);
|
||
|
||
if (!$bundle->get_id()) {
|
||
wp_send_json_error(__('套装不存在', 'yoone-subscriptions'));
|
||
}
|
||
|
||
// 验证数量限制
|
||
$total_quantity = array_sum(array_column($selected_items, 'quantity'));
|
||
|
||
if ($bundle->get_min_quantity() > 0 && $total_quantity < $bundle->get_min_quantity()) {
|
||
wp_send_json_error(sprintf(__('最小数量要求: %d', 'yoone-subscriptions'), $bundle->get_min_quantity()));
|
||
}
|
||
|
||
if ($bundle->get_max_quantity() > 0 && $total_quantity > $bundle->get_max_quantity()) {
|
||
wp_send_json_error(sprintf(__('最大数量限制: %d', 'yoone-subscriptions'), $bundle->get_max_quantity()));
|
||
}
|
||
|
||
// 创建套装产品并添加到购物车
|
||
$bundle_product_id = $bundle->get_product_id();
|
||
|
||
if (!$bundle_product_id) {
|
||
wp_send_json_error(__('套装产品不存在', 'yoone-subscriptions'));
|
||
}
|
||
|
||
// 计算套装价格
|
||
$bundle_price = $bundle->calculate_bundle_price($selected_items);
|
||
$original_price = 0;
|
||
|
||
foreach ($selected_items as $item) {
|
||
$product = wc_get_product($item['product_id']);
|
||
if ($product) {
|
||
$original_price += $product->get_price() * $item['quantity'];
|
||
}
|
||
}
|
||
|
||
$savings = $original_price - $bundle_price;
|
||
|
||
// 添加到购物车
|
||
$cart_item_data = array(
|
||
'yoone_bundle_data' => array(
|
||
'bundle_id' => $bundle_id,
|
||
'items' => $selected_items,
|
||
'original_price' => $original_price,
|
||
'bundle_price' => $bundle_price,
|
||
'savings' => $savings
|
||
)
|
||
);
|
||
|
||
$cart_item_key = WC()->cart->add_to_cart($bundle_product_id, 1, 0, array(), $cart_item_data);
|
||
|
||
if ($cart_item_key) {
|
||
wp_send_json_success(array(
|
||
'message' => __('套装已添加到购物车', 'yoone-subscriptions'),
|
||
'cart_url' => wc_get_cart_url()
|
||
));
|
||
} else {
|
||
wp_send_json_error(__('添加到购物车失败', 'yoone-subscriptions'));
|
||
}
|
||
}
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| 辅助方法
|
||
|--------------------------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* 格式化订阅字符串
|
||
*/
|
||
private function format_subscription_string($subscription_data) {
|
||
$period_strings = array(
|
||
'day' => __('天', 'yoone-subscriptions'),
|
||
'week' => __('周', 'yoone-subscriptions'),
|
||
'month' => __('月', 'yoone-subscriptions'),
|
||
'year' => __('年', 'yoone-subscriptions')
|
||
);
|
||
|
||
$period = isset($subscription_data['period']) ? $subscription_data['period'] : 'month';
|
||
$interval = isset($subscription_data['interval']) ? intval($subscription_data['interval']) : 1;
|
||
|
||
$period_string = isset($period_strings[$period]) ? $period_strings[$period] : $period;
|
||
|
||
if ($interval > 1) {
|
||
return sprintf(__('每 %d %s', 'yoone-subscriptions'), $interval, $period_string);
|
||
} else {
|
||
return sprintf(__('每%s', 'yoone-subscriptions'), $period_string);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 产品类型过滤器
|
||
*/
|
||
public function product_class_filter($classname, $product_type) {
|
||
if ($product_type === 'yoone_bundle') {
|
||
return 'Yoone_Bundle_Product';
|
||
}
|
||
|
||
return $classname;
|
||
}
|
||
|
||
/**
|
||
* 获取用户订阅统计
|
||
*/
|
||
public function get_customer_subscription_stats($customer_id) {
|
||
global $wpdb;
|
||
|
||
$stats = $wpdb->get_row($wpdb->prepare("
|
||
SELECT
|
||
COUNT(*) as total_subscriptions,
|
||
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active_subscriptions,
|
||
SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused_subscriptions,
|
||
SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) as cancelled_subscriptions,
|
||
SUM(CASE WHEN status = 'active' THEN total ELSE 0 END) as monthly_total
|
||
FROM {$wpdb->prefix}yoone_subscriptions
|
||
WHERE customer_id = %d
|
||
", $customer_id), ARRAY_A);
|
||
|
||
return $stats;
|
||
}
|
||
} |