subscription/includes/class-yoone-frontend.php

454 lines
14 KiB
PHP

<?php
/**
* 前端类
*
* @package YooneSubscriptions
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Yoone_Frontend类
* 处理前端功能和显示
*/
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_add_cart_item_data', array($this, 'add_cart_item_data'), 10, 3);
add_filter('woocommerce_get_cart_item_from_session', array($this, 'get_cart_item_from_session'), 10, 3);
add_filter('woocommerce_cart_item_price', array($this, 'cart_item_price'), 10, 3);
add_filter('woocommerce_cart_item_name', array($this, 'cart_item_name'), 10, 3);
// 结账钩子
add_action('woocommerce_checkout_create_order_line_item', array($this, 'add_order_item_meta'), 10, 4);
// 我的账户钩子
add_filter('woocommerce_account_menu_items', array($this, 'add_account_menu_items'));
add_action('woocommerce_account_subscriptions_endpoint', array($this, 'subscriptions_endpoint_content'));
// 短代码
add_shortcode('yoone_subscriptions', array($this, 'subscriptions_shortcode'));
add_shortcode('yoone_bundles', array($this, 'bundles_shortcode'));
// 模板钩子
add_filter('woocommerce_locate_template', array($this, 'locate_template'), 10, 3);
}
/**
* 显示混装产品选项
*/
public function display_bundle_options() {
global $product;
if (!$product || $product->get_type() !== 'yoone_bundle') {
return;
}
$bundle_id = get_post_meta($product->get_id(), '_yoone_bundle_id', true);
if (!$bundle_id) {
return;
}
global $wpdb;
// 获取混装项目
$items = $wpdb->get_results($wpdb->prepare(
"SELECT bi.*, p.post_title as product_name
FROM {$wpdb->prefix}yoone_bundle_items bi
LEFT JOIN {$wpdb->posts} p ON bi.product_id = p.ID
WHERE bi.bundle_id = %d
ORDER BY bi.sort_order",
$bundle_id
));
if (empty($items)) {
return;
}
// 加载模板
wc_get_template(
'single-product/bundle-options.php',
array(
'bundle_id' => $bundle_id,
'items' => $items,
'product' => $product
),
'',
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
);
}
/**
* 显示订阅选项
*/
public function display_subscription_options() {
global $product;
if (!$product) {
return;
}
$is_subscription = get_post_meta($product->get_id(), '_yoone_subscription_enabled', true);
if ($is_subscription !== 'yes') {
return;
}
$subscription_periods = get_post_meta($product->get_id(), '_yoone_subscription_periods', true);
if (empty($subscription_periods)) {
return;
}
// 加载模板
wc_get_template(
'single-product/subscription-options.php',
array(
'product' => $product,
'subscription_periods' => $subscription_periods
),
'',
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
);
}
/**
* 添加购物车项目数据
*/
public function add_cart_item_data($cart_item_data, $product_id, $variation_id) {
// 处理混装产品数据
if (isset($_POST['yoone_bundle_items'])) {
$cart_item_data['yoone_bundle_items'] = $_POST['yoone_bundle_items'];
}
// 处理订阅数据
if (isset($_POST['yoone_subscription_period'])) {
$cart_item_data['yoone_subscription_period'] = $_POST['yoone_subscription_period'];
}
if (isset($_POST['yoone_subscription_type'])) {
$cart_item_data['yoone_subscription_type'] = $_POST['yoone_subscription_type'];
}
return $cart_item_data;
}
/**
* 从会话获取购物车项目
*/
public function get_cart_item_from_session($item, $values, $key) {
if (array_key_exists('yoone_bundle_items', $values)) {
$item['yoone_bundle_items'] = $values['yoone_bundle_items'];
}
if (array_key_exists('yoone_subscription_period', $values)) {
$item['yoone_subscription_period'] = $values['yoone_subscription_period'];
}
if (array_key_exists('yoone_subscription_type', $values)) {
$item['yoone_subscription_type'] = $values['yoone_subscription_type'];
}
return $item;
}
/**
* 修改购物车项目价格
*/
public function cart_item_price($price, $cart_item, $cart_item_key) {
if (isset($cart_item['yoone_bundle_items'])) {
// 计算混装产品价格
$bundle_price = $this->calculate_bundle_price($cart_item);
if ($bundle_price !== false) {
return wc_price($bundle_price);
}
}
if (isset($cart_item['yoone_subscription_period'])) {
// 计算订阅产品价格
$subscription_price = $this->calculate_subscription_price($cart_item);
if ($subscription_price !== false) {
return wc_price($subscription_price);
}
}
return $price;
}
/**
* 修改购物车项目名称
*/
public function cart_item_name($name, $cart_item, $cart_item_key) {
if (isset($cart_item['yoone_bundle_items'])) {
$name .= '<br><small>' . __('混装产品', 'yoone-subscriptions') . '</small>';
}
if (isset($cart_item['yoone_subscription_period'])) {
$period = $cart_item['yoone_subscription_period'];
$name .= '<br><small>' . sprintf(__('订阅周期: %s', 'yoone-subscriptions'), $period) . '</small>';
}
return $name;
}
/**
* 添加订单项目元数据
*/
public function add_order_item_meta($item, $cart_item_key, $values, $order) {
if (isset($values['yoone_bundle_items'])) {
$item->add_meta_data('_yoone_bundle_items', $values['yoone_bundle_items']);
}
if (isset($values['yoone_subscription_period'])) {
$item->add_meta_data('_yoone_subscription_period', $values['yoone_subscription_period']);
}
if (isset($values['yoone_subscription_type'])) {
$item->add_meta_data('_yoone_subscription_type', $values['yoone_subscription_type']);
}
}
/**
* 添加我的账户菜单项
*/
public function add_account_menu_items($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 subscriptions_endpoint_content() {
$customer_id = get_current_user_id();
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),
'',
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
);
}
/**
* 订阅短代码
*/
public function subscriptions_shortcode($atts) {
$atts = shortcode_atts(array(
'customer_id' => get_current_user_id(),
'status' => '',
'limit' => 10
), $atts);
if (!$atts['customer_id']) {
return '<p>' . __('请先登录查看订阅。', 'yoone-subscriptions') . '</p>';
}
global $wpdb;
$where_conditions = array('customer_id = %d');
$params = array($atts['customer_id']);
if ($atts['status']) {
$where_conditions[] = 'status = %s';
$params[] = $atts['status'];
}
$where_clause = implode(' AND ', $where_conditions);
$params[] = intval($atts['limit']);
$subscriptions = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_subscriptions
WHERE {$where_clause}
ORDER BY created_at DESC
LIMIT %d",
$params
));
ob_start();
wc_get_template(
'shortcodes/subscriptions.php',
array('subscriptions' => $subscriptions),
'',
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
);
return ob_get_clean();
}
/**
* 混装产品短代码
*/
public function bundles_shortcode($atts) {
$atts = shortcode_atts(array(
'limit' => 12,
'columns' => 4,
'orderby' => 'date',
'order' => 'DESC'
), $atts);
global $wpdb;
$bundles = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_bundles
WHERE status = 'active'
ORDER BY created_at %s
LIMIT %d",
$atts['order'] === 'ASC' ? 'ASC' : 'DESC',
intval($atts['limit'])
));
ob_start();
wc_get_template(
'shortcodes/bundles.php',
array(
'bundles' => $bundles,
'columns' => intval($atts['columns'])
),
'',
YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/'
);
return ob_get_clean();
}
/**
* 定位模板
*/
public function locate_template($template, $template_name, $template_path) {
if (strpos($template_name, 'yoone-') === 0) {
$plugin_template = YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/' . $template_name;
if (file_exists($plugin_template)) {
return $plugin_template;
}
}
return $template;
}
/**
* 计算混装产品价格
*/
private function calculate_bundle_price($cart_item) {
if (!isset($cart_item['yoone_bundle_items'])) {
return false;
}
$total_price = 0;
$bundle_items = $cart_item['yoone_bundle_items'];
foreach ($bundle_items as $product_id => $quantity) {
$product = wc_get_product($product_id);
if ($product) {
$total_price += $product->get_price() * intval($quantity);
}
}
// 应用混装折扣
$product = wc_get_product($cart_item['product_id']);
if ($product) {
$discount_type = get_post_meta($product->get_id(), '_yoone_bundle_discount_type', true);
$discount_value = get_post_meta($product->get_id(), '_yoone_bundle_discount_value', true);
if ($discount_type === 'percentage' && $discount_value > 0) {
$total_price = $total_price * (1 - $discount_value / 100);
} elseif ($discount_type === 'fixed' && $discount_value > 0) {
$total_price = max(0, $total_price - $discount_value);
}
}
return $total_price;
}
/**
* 计算订阅产品价格
*/
private function calculate_subscription_price($cart_item) {
if (!isset($cart_item['yoone_subscription_period'])) {
return false;
}
$product = wc_get_product($cart_item['product_id']);
if (!$product) {
return false;
}
$subscription_periods = get_post_meta($product->get_id(), '_yoone_subscription_periods', true);
$period = $cart_item['yoone_subscription_period'];
if (isset($subscription_periods[$period])) {
$period_data = $subscription_periods[$period];
$base_price = $product->get_price();
if (isset($period_data['discount_type']) && isset($period_data['discount_value'])) {
if ($period_data['discount_type'] === 'percentage') {
return $base_price * (1 - $period_data['discount_value'] / 100);
} elseif ($period_data['discount_type'] === 'fixed') {
return max(0, $base_price - $period_data['discount_value']);
}
}
}
return $product->get_price();
}
/**
* 获取订阅状态标签
*/
public static function get_subscription_status_label($status) {
$statuses = array(
'pending' => __('待处理', 'yoone-subscriptions'),
'active' => __('活跃', 'yoone-subscriptions'),
'paused' => __('已暂停', 'yoone-subscriptions'),
'cancelled' => __('已取消', 'yoone-subscriptions'),
'expired' => __('已过期', 'yoone-subscriptions'),
'failed' => __('失败', 'yoone-subscriptions')
);
return isset($statuses[$status]) ? $statuses[$status] : $status;
}
/**
* 获取订阅状态颜色
*/
public static function get_subscription_status_color($status) {
$colors = array(
'pending' => '#ffba00',
'active' => '#7ad03a',
'paused' => '#999999',
'cancelled' => '#a00',
'expired' => '#a00',
'failed' => '#a00'
);
return isset($colors[$status]) ? $colors[$status] : '#999999';
}
}