subscription/includes/frontend/class-yoone-frontend.php

524 lines
18 KiB
PHP
Raw 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
/**
* 前端功能管理类
*
* 处理前端页面展示和用户交互
*/
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;
}
}