feat(订阅): 新增订阅管理功能与分级折扣配置
- 添加后台订阅列表管理页面,支持筛选、分页和状态管理 - 引入最小起订量和分级折扣规则配置 - 优化一次性购买逻辑,不再显示订阅信息 - 添加兜底机制确保订阅表存在 - 更新需求文档
This commit is contained in:
parent
69c5d866d6
commit
b172bd61bf
|
|
@ -0,0 +1,4 @@
|
||||||
|
- 扣款失败需要发邮件给客户
|
||||||
|
- 后台有用户订阅列表管理页面
|
||||||
|
- 数据存储在数据库
|
||||||
|
- 前端用户登陆后可以在 my account 页面中查看已设置的订阅
|
||||||
|
|
@ -16,6 +16,9 @@ class Yoone_Subscriptions_Admin {
|
||||||
add_filter('woocommerce_product_data_tabs', array($this, 'add_tab'));
|
add_filter('woocommerce_product_data_tabs', array($this, 'add_tab'));
|
||||||
add_action('woocommerce_product_data_panels', array($this, 'render_panel'));
|
add_action('woocommerce_product_data_panels', array($this, 'render_panel'));
|
||||||
add_action('woocommerce_admin_process_product_meta', array($this, 'save_meta'));
|
add_action('woocommerce_admin_process_product_meta', array($this, 'save_meta'));
|
||||||
|
|
||||||
|
// 在 WooCommerce 菜单下添加“Subscriptions”子菜单
|
||||||
|
add_action('admin_menu', array($this, 'register_submenu'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,6 +76,17 @@ class Yoone_Subscriptions_Admin {
|
||||||
'description' => __('用于前端默认数量,可在产品页调整。', 'yoone-subscriptions'),
|
'description' => __('用于前端默认数量,可在产品页调整。', 'yoone-subscriptions'),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// 最小起订量(仅订阅模式下生效)
|
||||||
|
woocommerce_wp_text_input(array(
|
||||||
|
'id' => 'yoone_sub_min_qty',
|
||||||
|
'label' => __('最小起订量', 'yoone-subscriptions'),
|
||||||
|
'type' => 'number',
|
||||||
|
'value' => isset($cfg['min_qty']) ? intval($cfg['min_qty']) : 1,
|
||||||
|
'custom_attributes' => array('min' => '1', 'step' => '1'),
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __('仅在订阅购买模式下生效,购物车与订单将进行数量校验与提示。', 'yoone-subscriptions'),
|
||||||
|
));
|
||||||
|
|
||||||
// 订阅价格(可选,留空则使用产品常规价)
|
// 订阅价格(可选,留空则使用产品常规价)
|
||||||
woocommerce_wp_text_input(array(
|
woocommerce_wp_text_input(array(
|
||||||
'id' => 'yoone_sub_price',
|
'id' => 'yoone_sub_price',
|
||||||
|
|
@ -83,6 +97,17 @@ class Yoone_Subscriptions_Admin {
|
||||||
'description' => __('留空表示使用产品常规价。', 'yoone-subscriptions'),
|
'description' => __('留空表示使用产品常规价。', 'yoone-subscriptions'),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// 分级折扣配置(逗号分隔的“数量:折扣%”对)
|
||||||
|
woocommerce_wp_text_input(array(
|
||||||
|
'id' => 'yoone_sub_tier_rules',
|
||||||
|
'label' => __('分级折扣规则', 'yoone-subscriptions'),
|
||||||
|
'type' => 'text',
|
||||||
|
'placeholder' => '10:5,20:10',
|
||||||
|
'value' => isset($cfg['tier_rules']) ? esc_attr($cfg['tier_rules']) : '',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __('格式:数量:折扣%,用逗号分隔多级。如“10:5,20:10”表示≥10件打95折,≥20件打9折。留空则不启用。', 'yoone-subscriptions'),
|
||||||
|
));
|
||||||
|
|
||||||
// 是否允许一次性购买
|
// 是否允许一次性购买
|
||||||
woocommerce_wp_checkbox(array(
|
woocommerce_wp_checkbox(array(
|
||||||
'id' => 'yoone_sub_allow_onetime',
|
'id' => 'yoone_sub_allow_onetime',
|
||||||
|
|
@ -107,7 +132,9 @@ class Yoone_Subscriptions_Admin {
|
||||||
$enabled = isset($_POST['yoone_sub_enabled']) && 'yes' === $_POST['yoone_sub_enabled'];
|
$enabled = isset($_POST['yoone_sub_enabled']) && 'yes' === $_POST['yoone_sub_enabled'];
|
||||||
$period = isset($_POST['yoone_sub_period']) ? sanitize_text_field($_POST['yoone_sub_period']) : 'month';
|
$period = isset($_POST['yoone_sub_period']) ? sanitize_text_field($_POST['yoone_sub_period']) : 'month';
|
||||||
$qty = isset($_POST['yoone_sub_qty_default']) ? absint($_POST['yoone_sub_qty_default']) : 1;
|
$qty = isset($_POST['yoone_sub_qty_default']) ? absint($_POST['yoone_sub_qty_default']) : 1;
|
||||||
|
$min_qty = isset($_POST['yoone_sub_min_qty']) ? absint($_POST['yoone_sub_min_qty']) : 1;
|
||||||
$price = isset($_POST['yoone_sub_price']) ? wc_clean($_POST['yoone_sub_price']) : '';
|
$price = isset($_POST['yoone_sub_price']) ? wc_clean($_POST['yoone_sub_price']) : '';
|
||||||
|
$tiers = isset($_POST['yoone_sub_tier_rules']) ? sanitize_text_field($_POST['yoone_sub_tier_rules']) : '';
|
||||||
$onetime = isset($_POST['yoone_sub_allow_onetime']) && 'yes' === $_POST['yoone_sub_allow_onetime'];
|
$onetime = isset($_POST['yoone_sub_allow_onetime']) && 'yes' === $_POST['yoone_sub_allow_onetime'];
|
||||||
|
|
||||||
$period = in_array($period, array('month','year'), true) ? $period : 'month';
|
$period = in_array($period, array('month','year'), true) ? $period : 'month';
|
||||||
|
|
@ -117,11 +144,193 @@ class Yoone_Subscriptions_Admin {
|
||||||
update_post_meta($post_id, Yoone_Subscriptions::META_ENABLED, $enabled ? '1' : '');
|
update_post_meta($post_id, Yoone_Subscriptions::META_ENABLED, $enabled ? '1' : '');
|
||||||
update_post_meta($post_id, Yoone_Subscriptions::META_PERIOD, $period);
|
update_post_meta($post_id, Yoone_Subscriptions::META_PERIOD, $period);
|
||||||
update_post_meta($post_id, Yoone_Subscriptions::META_QTY_DEFAULT, $qty);
|
update_post_meta($post_id, Yoone_Subscriptions::META_QTY_DEFAULT, $qty);
|
||||||
|
update_post_meta($post_id, Yoone_Subscriptions::META_MIN_QTY, max(1, $min_qty));
|
||||||
if ($price_v === '') {
|
if ($price_v === '') {
|
||||||
delete_post_meta($post_id, Yoone_Subscriptions::META_PRICE);
|
delete_post_meta($post_id, Yoone_Subscriptions::META_PRICE);
|
||||||
} else {
|
} else {
|
||||||
update_post_meta($post_id, Yoone_Subscriptions::META_PRICE, $price_v);
|
update_post_meta($post_id, Yoone_Subscriptions::META_PRICE, $price_v);
|
||||||
}
|
}
|
||||||
|
if ($tiers === '') {
|
||||||
|
delete_post_meta($post_id, Yoone_Subscriptions::META_TIER_RULES);
|
||||||
|
} else {
|
||||||
|
update_post_meta($post_id, Yoone_Subscriptions::META_TIER_RULES, $tiers);
|
||||||
|
}
|
||||||
update_post_meta($post_id, Yoone_Subscriptions::META_ALLOW_ONETIME, $onetime ? '1' : '');
|
update_post_meta($post_id, Yoone_Subscriptions::META_ALLOW_ONETIME, $onetime ? '1' : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册 WooCommerce → Subscriptions 子菜单。
|
||||||
|
*/
|
||||||
|
public function register_submenu() {
|
||||||
|
// 仅限具有管理 WooCommerce 权限的用户可访问
|
||||||
|
add_submenu_page(
|
||||||
|
'woocommerce',
|
||||||
|
__('Subscriptions', 'yoone-subscriptions'),
|
||||||
|
__('Subscriptions', 'yoone-subscriptions'),
|
||||||
|
'manage_woocommerce',
|
||||||
|
'yoone-subscriptions',
|
||||||
|
array($this, 'render_subscriptions_page'),
|
||||||
|
56 // 显示位置(可选)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染订阅列表管理页面。
|
||||||
|
* 支持按用户、产品、状态筛选与分页。
|
||||||
|
*/
|
||||||
|
public function render_subscriptions_page() {
|
||||||
|
if (! current_user_can('manage_woocommerce')) {
|
||||||
|
wp_die(__('您没有权限查看该页面。', 'yoone-subscriptions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理状态更新操作(pause/resume/cancel),带 nonce
|
||||||
|
if (isset($_POST['yoone_sub_action']) && isset($_POST['_wpnonce']) && wp_verify_nonce($_POST['_wpnonce'], 'yoone_subscriptions_action')) {
|
||||||
|
$action = sanitize_key($_POST['yoone_sub_action']);
|
||||||
|
$sub_id = isset($_POST['yoone_sub_id']) ? absint($_POST['yoone_sub_id']) : 0;
|
||||||
|
$allowed = array('pause' => 'paused', 'resume' => 'active', 'cancel' => 'canceled');
|
||||||
|
if ($sub_id > 0 && isset($allowed[$action])) {
|
||||||
|
if (class_exists('Yoone_Subscriptions_DB')) {
|
||||||
|
Yoone_Subscriptions_DB::update($sub_id, array('status' => $allowed[$action]));
|
||||||
|
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__('状态已更新。', 'yoone-subscriptions') . '</p></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取筛选参数
|
||||||
|
$status = isset($_GET['status']) ? sanitize_key($_GET['status']) : '';
|
||||||
|
$product_id = isset($_GET['product_id']) ? absint($_GET['product_id']) : 0;
|
||||||
|
$user_query = isset($_GET['user']) ? sanitize_text_field($_GET['user']) : '';
|
||||||
|
$paged = isset($_GET['paged']) ? max(1, absint($_GET['paged'])) : 1;
|
||||||
|
$per_page = 20;
|
||||||
|
$offset = ($paged - 1) * $per_page;
|
||||||
|
|
||||||
|
global $wpdb;
|
||||||
|
$table = method_exists('Yoone_Subscriptions_DB', 'table_name') ? Yoone_Subscriptions_DB::table_name() : $wpdb->prefix . 'yoone_subscriptions';
|
||||||
|
|
||||||
|
// 构造 WHERE 条件
|
||||||
|
$where = array('1=1');
|
||||||
|
$params = array();
|
||||||
|
if (! empty($status)) { $where[] = 'status = %s'; $params[] = $status; }
|
||||||
|
if ($product_id > 0) { $where[] = 'product_id = %d'; $params[] = $product_id; }
|
||||||
|
$user_clause = '';
|
||||||
|
if (! empty($user_query)) {
|
||||||
|
// 支持用用户ID或邮箱搜索
|
||||||
|
if (is_numeric($user_query)) {
|
||||||
|
$where[] = 'user_id = %d'; $params[] = absint($user_query);
|
||||||
|
} else {
|
||||||
|
// 通过邮箱查询用户ID
|
||||||
|
$user = get_user_by('email', $user_query);
|
||||||
|
if ($user) { $where[] = 'user_id = %d'; $params[] = $user->ID; }
|
||||||
|
else { $where[] = '0=1'; } // 无匹配,返回空
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询总数用于分页
|
||||||
|
$sql_count = "SELECT COUNT(*) FROM {$table} WHERE " . implode(' AND ', $where);
|
||||||
|
$total = $wpdb->get_var($wpdb->prepare($sql_count, $params));
|
||||||
|
|
||||||
|
// 查询当前页数据
|
||||||
|
$sql = "SELECT * FROM {$table} WHERE " . implode(' AND ', $where) . " ORDER BY id DESC LIMIT %d OFFSET %d";
|
||||||
|
$params_page = array_merge($params, array($per_page, $offset));
|
||||||
|
$rows = $wpdb->get_results($wpdb->prepare($sql, $params_page), ARRAY_A);
|
||||||
|
|
||||||
|
// 渲染页面
|
||||||
|
echo '<div class="wrap">';
|
||||||
|
echo '<h1 class="wp-heading-inline">' . esc_html__('Subscriptions', 'yoone-subscriptions') . '</h1>';
|
||||||
|
echo '<hr class="wp-header-end">';
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
echo '<form method="get">';
|
||||||
|
echo '<input type="hidden" name="page" value="yoone-subscriptions" />';
|
||||||
|
echo '<div class="tablenav top">';
|
||||||
|
echo '<div class="alignleft actions">';
|
||||||
|
echo '<select name="status">';
|
||||||
|
$statuses = array('' => __('全部状态', 'yoone-subscriptions'), 'active' => __('Active', 'yoone-subscriptions'), 'paused' => __('Paused', 'yoone-subscriptions'), 'canceled' => __('Canceled', 'yoone-subscriptions'));
|
||||||
|
foreach ($statuses as $key => $label) {
|
||||||
|
echo '<option value="' . esc_attr($key) . '"' . selected($status, $key, false) . '>' . esc_html($label) . '</option>';
|
||||||
|
}
|
||||||
|
echo '</select> ';
|
||||||
|
echo '<input type="number" name="product_id" placeholder="' . esc_attr__('产品ID', 'yoone-subscriptions') . '" value="' . esc_attr($product_id) . '" style="width:120px" /> ';
|
||||||
|
echo '<input type="text" name="user" placeholder="' . esc_attr__('用户ID或邮箱', 'yoone-subscriptions') . '" value="' . esc_attr($user_query) . '" style="width:200px" /> ';
|
||||||
|
submit_button(__('筛选'), 'secondary', null, false);
|
||||||
|
echo '</div>';
|
||||||
|
echo '</div>';
|
||||||
|
echo '</form>';
|
||||||
|
|
||||||
|
// 列表表格
|
||||||
|
echo '<table class="wp-list-table widefat fixed striped">';
|
||||||
|
echo '<thead><tr>';
|
||||||
|
$cols = array(
|
||||||
|
__('ID', 'yoone-subscriptions'),
|
||||||
|
__('用户', 'yoone-subscriptions'),
|
||||||
|
__('产品', 'yoone-subscriptions'),
|
||||||
|
__('周期', 'yoone-subscriptions'),
|
||||||
|
__('数量', 'yoone-subscriptions'),
|
||||||
|
__('每周期金额', 'yoone-subscriptions'),
|
||||||
|
__('状态', 'yoone-subscriptions'),
|
||||||
|
__('开始时间', 'yoone-subscriptions'),
|
||||||
|
__('下次续费', 'yoone-subscriptions'),
|
||||||
|
__('操作', 'yoone-subscriptions'),
|
||||||
|
);
|
||||||
|
foreach ($cols as $c) echo '<th>' . esc_html($c) . '</th>';
|
||||||
|
echo '</tr></thead><tbody>';
|
||||||
|
|
||||||
|
if (empty($rows)) {
|
||||||
|
echo '<tr><td colspan="10">' . esc_html__('暂无订阅记录。', 'yoone-subscriptions') . '</td></tr>';
|
||||||
|
} else {
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$user = get_user_by('id', intval($r['user_id']));
|
||||||
|
$product = wc_get_product(intval($r['product_id']));
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<td>#' . intval($r['id']) . '</td>';
|
||||||
|
echo '<td>' . ($user ? esc_html($user->user_email) . ' (ID ' . intval($user->ID) . ')' : '-') . '</td>';
|
||||||
|
echo '<td>' . ($product ? esc_html($product->get_name()) . ' (ID ' . intval($product->get_id()) . ')' : 'ID ' . intval($r['product_id'])) . '</td>';
|
||||||
|
echo '<td>' . esc_html($r['period']) . '</td>';
|
||||||
|
echo '<td>' . intval($r['qty']) . '</td>';
|
||||||
|
echo '<td>' . wc_price(floatval($r['price_per_cycle'])) . '</td>';
|
||||||
|
echo '<td>' . esc_html($r['status']) . '</td>';
|
||||||
|
echo '<td>' . esc_html($r['start_date']) . '</td>';
|
||||||
|
echo '<td>' . esc_html($r['next_renewal_date']) . '</td>';
|
||||||
|
echo '<td>';
|
||||||
|
echo '<form method="post" style="display:inline-block;margin-right:6px;">' . wp_nonce_field('yoone_subscriptions_action', '_wpnonce', true, false) . '<input type="hidden" name="yoone_sub_id" value="' . intval($r['id']) . '" />';
|
||||||
|
if ($r['status'] !== 'paused') {
|
||||||
|
echo '<input type="hidden" name="yoone_sub_action" value="pause" />';
|
||||||
|
submit_button(__('暂停', 'yoone-subscriptions'), 'small', null, false);
|
||||||
|
}
|
||||||
|
echo '</form>';
|
||||||
|
echo '<form method="post" style="display:inline-block;margin-right:6px;">' . wp_nonce_field('yoone_subscriptions_action', '_wpnonce', true, false) . '<input type="hidden" name="yoone_sub_id" value="' . intval($r['id']) . '" />';
|
||||||
|
if ($r['status'] !== 'active') {
|
||||||
|
echo '<input type="hidden" name="yoone_sub_action" value="resume" />';
|
||||||
|
submit_button(__('恢复', 'yoone-subscriptions'), 'small', null, false);
|
||||||
|
}
|
||||||
|
echo '</form>';
|
||||||
|
echo '<form method="post" style="display:inline-block;">' . wp_nonce_field('yoone_subscriptions_action', '_wpnonce', true, false) . '<input type="hidden" name="yoone_sub_id" value="' . intval($r['id']) . '" />';
|
||||||
|
if ($r['status'] !== 'canceled') {
|
||||||
|
echo '<input type="hidden" name="yoone_sub_action" value="cancel" />';
|
||||||
|
submit_button(__('取消', 'yoone-subscriptions'), 'small', null, false);
|
||||||
|
}
|
||||||
|
echo '</form>';
|
||||||
|
echo '</td>';
|
||||||
|
echo '</tr>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '</tbody></table>';
|
||||||
|
|
||||||
|
// 分页导航
|
||||||
|
if ($total > $per_page) {
|
||||||
|
$total_pages = ceil($total / $per_page);
|
||||||
|
echo '<div class="tablenav bottom"><div class="tablenav-pages">';
|
||||||
|
echo paginate_links(array(
|
||||||
|
'base' => add_query_arg(array('paged' => '%#%')),
|
||||||
|
'format' => '',
|
||||||
|
'prev_text' => __('« 上一页', 'yoone-subscriptions'),
|
||||||
|
'next_text' => __('下一页 »', 'yoone-subscriptions'),
|
||||||
|
'total' => $total_pages,
|
||||||
|
'current' => $paged,
|
||||||
|
));
|
||||||
|
echo '</div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,6 +13,8 @@ class Yoone_Subscriptions {
|
||||||
const META_QTY_DEFAULT = '_yoone_sub_qty_default'; // int >=1
|
const META_QTY_DEFAULT = '_yoone_sub_qty_default'; // int >=1
|
||||||
const META_PRICE = '_yoone_sub_price'; // decimal string
|
const META_PRICE = '_yoone_sub_price'; // decimal string
|
||||||
const META_ALLOW_ONETIME = '_yoone_sub_allow_onetime'; // bool
|
const META_ALLOW_ONETIME = '_yoone_sub_allow_onetime'; // bool
|
||||||
|
const META_MIN_QTY = '_yoone_sub_min_qty'; // int >=1(最小起订量,仅订阅模式下生效)
|
||||||
|
const META_TIER_RULES = '_yoone_sub_tier_rules'; // string 逗号分隔“数量:折扣%”对,如 10:5,20:10
|
||||||
|
|
||||||
protected static $instance = null;
|
protected static $instance = null;
|
||||||
|
|
||||||
|
|
@ -43,6 +45,8 @@ class Yoone_Subscriptions {
|
||||||
$qty = absint(get_post_meta($pid, self::META_QTY_DEFAULT, true));
|
$qty = absint(get_post_meta($pid, self::META_QTY_DEFAULT, true));
|
||||||
$price = get_post_meta($pid, self::META_PRICE, true);
|
$price = get_post_meta($pid, self::META_PRICE, true);
|
||||||
$onetime = (bool) get_post_meta($pid, self::META_ALLOW_ONETIME, true);
|
$onetime = (bool) get_post_meta($pid, self::META_ALLOW_ONETIME, true);
|
||||||
|
$min_qty = absint(get_post_meta($pid, self::META_MIN_QTY, true));
|
||||||
|
$tiers = get_post_meta($pid, self::META_TIER_RULES, true);
|
||||||
$period = in_array($period, array('month','year'), true) ? $period : 'month';
|
$period = in_array($period, array('month','year'), true) ? $period : 'month';
|
||||||
$qty = max(1, $qty);
|
$qty = max(1, $qty);
|
||||||
$price = is_numeric($price) ? floatval($price) : 0.0; // 0 表示按产品原价
|
$price = is_numeric($price) ? floatval($price) : 0.0; // 0 表示按产品原价
|
||||||
|
|
@ -52,6 +56,8 @@ class Yoone_Subscriptions {
|
||||||
'qty_default' => $qty,
|
'qty_default' => $qty,
|
||||||
'price' => $price,
|
'price' => $price,
|
||||||
'allow_onetime' => $onetime,
|
'allow_onetime' => $onetime,
|
||||||
|
'min_qty' => max(1, $min_qty),
|
||||||
|
'tier_rules' => is_string($tiers) ? $tiers : '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,6 +71,8 @@ class Yoone_Subscriptions {
|
||||||
'qty_default' => 1,
|
'qty_default' => 1,
|
||||||
'price' => 0.0,
|
'price' => 0.0,
|
||||||
'allow_onetime' => true,
|
'allow_onetime' => true,
|
||||||
|
'min_qty' => 1,
|
||||||
|
'tier_rules' => '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,11 +124,8 @@ class Yoone_Subscriptions_Frontend {
|
||||||
$period = in_array($period, array('month','year'), true) ? $period : $cfg['period'];
|
$period = in_array($period, array('month','year'), true) ? $period : $cfg['period'];
|
||||||
$qty = max(1, $qty);
|
$qty = max(1, $qty);
|
||||||
|
|
||||||
|
// 如果选择一次性购买,则不写入订阅元数据,购物车中不显示任何订阅信息
|
||||||
if ($cfg['allow_onetime'] && $mode === 'onetime') {
|
if ($cfg['allow_onetime'] && $mode === 'onetime') {
|
||||||
// 标记为一次性购买,便于显示
|
|
||||||
$cart_item_data['yoone_subscriptions'] = array(
|
|
||||||
'mode' => 'onetime',
|
|
||||||
);
|
|
||||||
return $cart_item_data;
|
return $cart_item_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,8 +144,8 @@ class Yoone_Subscriptions_Frontend {
|
||||||
public function display_item_data($item_data, $cart_item) {
|
public function display_item_data($item_data, $cart_item) {
|
||||||
if (empty($cart_item['yoone_subscriptions'])) return $item_data;
|
if (empty($cart_item['yoone_subscriptions'])) return $item_data;
|
||||||
$data = $cart_item['yoone_subscriptions'];
|
$data = $cart_item['yoone_subscriptions'];
|
||||||
if ($data['mode'] === 'onetime') {
|
// 仅在选择订阅购买时展示订阅信息;一次性购买不展示任何订阅相关信息
|
||||||
$item_data[] = array('key' => __('购买方式', 'yoone-subscriptions'), 'value' => __('一次性购买', 'yoone-subscriptions'));
|
if (! isset($data['mode']) || $data['mode'] !== 'subscribe') {
|
||||||
return $item_data;
|
return $item_data;
|
||||||
}
|
}
|
||||||
$period_label = $data['period'] === 'year' ? __('年', 'yoone-subscriptions') : __('月', 'yoone-subscriptions');
|
$period_label = $data['period'] === 'year' ? __('年', 'yoone-subscriptions') : __('月', 'yoone-subscriptions');
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,14 @@ add_action('plugins_loaded', function() {
|
||||||
Yoone_Subscriptions::instance();
|
Yoone_Subscriptions::instance();
|
||||||
Yoone_Subscriptions_Admin::instance();
|
Yoone_Subscriptions_Admin::instance();
|
||||||
Yoone_Subscriptions_Frontend::instance();
|
Yoone_Subscriptions_Frontend::instance();
|
||||||
|
|
||||||
|
// 兜底:若订阅表不存在则安装(避免早期版本已激活但未创建表的情况)
|
||||||
|
global $wpdb;
|
||||||
|
$table = Yoone_Subscriptions_DB::table_name();
|
||||||
|
$exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table));
|
||||||
|
if ($exists !== $table) {
|
||||||
|
Yoone_Subscriptions_DB::install();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 资源
|
// 资源
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue