454 lines
14 KiB
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';
|
|
}
|
|
} |