init_hooks();
}
/**
* 初始化钩子
*/
private function init_hooks() {
// 管理菜单
add_action('admin_menu', array($this, 'add_admin_menus'));
// 产品数据面板
add_filter('woocommerce_product_data_tabs', array($this, 'add_product_data_tabs'));
add_action('woocommerce_product_data_panels', array($this, 'add_product_data_panels'));
add_action('woocommerce_process_product_meta', array($this, 'save_product_meta'));
// 产品类型
add_filter('product_type_selector', array($this, 'add_product_types'));
// 订单管理
add_action('add_meta_boxes', array($this, 'add_order_meta_boxes'));
add_action('woocommerce_order_status_changed', array($this, 'handle_order_status_change'), 10, 4);
// 列表表格
add_filter('manage_edit-product_columns', array($this, 'add_product_columns'));
add_action('manage_product_posts_custom_column', array($this, 'product_column_content'), 10, 2);
// 设置页面
add_filter('woocommerce_settings_tabs_array', array($this, 'add_settings_tab'), 50);
add_action('woocommerce_settings_tabs_yoone_subscriptions', array($this, 'settings_tab_content'));
add_action('woocommerce_update_options_yoone_subscriptions', array($this, 'update_settings'));
// 通知
add_action('admin_notices', array($this, 'admin_notices'));
}
/**
* 添加管理菜单
*/
public function add_admin_menus() {
// 主菜单
add_menu_page(
__('Yoone 订阅', 'yoone-subscriptions'),
__('Yoone 订阅', 'yoone-subscriptions'),
'manage_woocommerce',
'yoone-subscriptions',
array($this, 'subscriptions_page'),
'dashicons-update',
56
);
// 订阅管理
add_submenu_page(
'yoone-subscriptions',
__('订阅管理', 'yoone-subscriptions'),
__('订阅管理', 'yoone-subscriptions'),
'manage_woocommerce',
'yoone-subscriptions',
array($this, 'subscriptions_page')
);
// 混装产品
add_submenu_page(
'yoone-subscriptions',
__('混装产品', 'yoone-subscriptions'),
__('混装产品', 'yoone-subscriptions'),
'manage_woocommerce',
'yoone-bundles',
array($this, 'bundles_page')
);
// 支付设置
add_submenu_page(
'yoone-subscriptions',
__('支付设置', 'yoone-subscriptions'),
__('支付设置', 'yoone-subscriptions'),
'manage_woocommerce',
'yoone-payment-settings',
array($this, 'payment_settings_page')
);
// 报告
add_submenu_page(
'yoone-subscriptions',
__('报告', 'yoone-subscriptions'),
__('报告', 'yoone-subscriptions'),
'manage_woocommerce',
'yoone-reports',
array($this, 'reports_page')
);
}
/**
* 订阅管理页面
*/
public function subscriptions_page() {
$action = isset($_GET['action']) ? $_GET['action'] : 'list';
switch ($action) {
case 'view':
$this->view_subscription();
break;
case 'edit':
$this->edit_subscription();
break;
default:
$this->list_subscriptions();
break;
}
}
/**
* 订阅列表
*/
private function list_subscriptions() {
global $wpdb;
$per_page = 20;
$current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
$offset = ($current_page - 1) * $per_page;
$status_filter = isset($_GET['status']) ? $_GET['status'] : '';
$search = isset($_GET['s']) ? $_GET['s'] : '';
$where_conditions = array('1=1');
$params = array();
if ($status_filter) {
$where_conditions[] = 'status = %s';
$params[] = $status_filter;
}
if ($search) {
$where_conditions[] = '(id LIKE %s OR customer_id IN (SELECT ID FROM ' . $wpdb->users . ' WHERE display_name LIKE %s OR user_email LIKE %s))';
$params[] = '%' . $search . '%';
$params[] = '%' . $search . '%';
$params[] = '%' . $search . '%';
}
$where_clause = implode(' AND ', $where_conditions);
// 获取总数
$total_query = "SELECT COUNT(*) FROM {$wpdb->prefix}yoone_subscriptions WHERE {$where_clause}";
$total_items = $wpdb->get_var($wpdb->prepare($total_query, $params));
// 获取订阅列表
$params[] = $per_page;
$params[] = $offset;
$subscriptions_query = "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE {$where_clause} ORDER BY created_at DESC LIMIT %d OFFSET %d";
$subscriptions = $wpdb->get_results($wpdb->prepare($subscriptions_query, $params));
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/subscriptions-list.php';
}
/**
* 查看订阅
*/
private function view_subscription() {
$subscription_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$subscription_id) {
wp_die(__('无效的订阅ID', 'yoone-subscriptions'));
}
global $wpdb;
$subscription = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE id = %d",
$subscription_id
));
if (!$subscription) {
wp_die(__('订阅不存在', 'yoone-subscriptions'));
}
// 获取订阅项目
$items = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_subscription_items WHERE subscription_id = %d",
$subscription_id
));
// 获取日志
$logs = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_subscription_logs WHERE subscription_id = %d ORDER BY created_at DESC LIMIT 50",
$subscription_id
));
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/subscription-view.php';
}
/**
* 编辑订阅
*/
private function edit_subscription() {
$subscription_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$subscription_id) {
wp_die(__('无效的订阅ID', 'yoone-subscriptions'));
}
// 处理表单提交
if (isset($_POST['submit'])) {
$this->save_subscription($subscription_id);
}
global $wpdb;
$subscription = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE id = %d",
$subscription_id
));
if (!$subscription) {
wp_die(__('订阅不存在', 'yoone-subscriptions'));
}
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/subscription-edit.php';
}
/**
* 保存订阅
*/
private function save_subscription($subscription_id) {
if (!wp_verify_nonce($_POST['_wpnonce'], 'edit_subscription_' . $subscription_id)) {
wp_die(__('安全验证失败', 'yoone-subscriptions'));
}
global $wpdb;
$update_data = array(
'status' => sanitize_text_field($_POST['status']),
'next_payment_date' => sanitize_text_field($_POST['next_payment_date']),
'updated_at' => current_time('mysql')
);
$result = $wpdb->update(
$wpdb->prefix . 'yoone_subscriptions',
$update_data,
array('id' => $subscription_id)
);
if ($result !== false) {
add_action('admin_notices', function() {
echo '
' . __('订阅已更新', 'yoone-subscriptions') . '
';
});
}
}
/**
* 混装产品页面
*/
public function bundles_page() {
$action = isset($_GET['action']) ? $_GET['action'] : 'list';
switch ($action) {
case 'add':
$this->add_bundle();
break;
case 'edit':
$this->edit_bundle();
break;
case 'delete':
$this->delete_bundle();
break;
default:
$this->list_bundles();
break;
}
}
/**
* 添加混装产品
*/
private function add_bundle() {
if (isset($_POST['submit'])) {
$this->save_bundle();
}
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/bundle-add.php';
}
/**
* 编辑混装产品
*/
private function edit_bundle() {
$bundle_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$bundle_id) {
wp_die(__('无效的混装产品ID', 'yoone-subscriptions'));
}
if (isset($_POST['submit'])) {
$this->save_bundle($bundle_id);
}
global $wpdb;
$bundle = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_bundles WHERE id = %d",
$bundle_id
));
if (!$bundle) {
wp_die(__('混装产品不存在', 'yoone-subscriptions'));
}
$items = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_bundle_items WHERE bundle_id = %d ORDER BY sort_order",
$bundle_id
));
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/bundle-edit.php';
}
/**
* 删除混装产品
*/
private function delete_bundle() {
$bundle_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$bundle_id) {
wp_die(__('无效的混装产品ID', 'yoone-subscriptions'));
}
if (!wp_verify_nonce($_GET['_wpnonce'], 'delete_bundle_' . $bundle_id)) {
wp_die(__('安全验证失败', 'yoone-subscriptions'));
}
global $wpdb;
// 删除混装项目
$wpdb->delete(
$wpdb->prefix . 'yoone_bundle_items',
array('bundle_id' => $bundle_id)
);
// 删除混装产品
$result = $wpdb->delete(
$wpdb->prefix . 'yoone_bundles',
array('id' => $bundle_id)
);
if ($result) {
wp_redirect(admin_url('admin.php?page=yoone-bundles&deleted=1'));
exit;
} else {
wp_die(__('删除失败', 'yoone-subscriptions'));
}
}
/**
* 保存混装产品
*/
private function save_bundle($bundle_id = 0) {
$nonce_action = $bundle_id ? 'edit_bundle_' . $bundle_id : 'add_bundle';
if (!wp_verify_nonce($_POST['_wpnonce'], $nonce_action)) {
wp_die(__('安全验证失败', 'yoone-subscriptions'));
}
global $wpdb;
$bundle_data = array(
'name' => sanitize_text_field($_POST['name']),
'description' => sanitize_textarea_field($_POST['description']),
'discount_type' => sanitize_text_field($_POST['discount_type']),
'discount_value' => floatval($_POST['discount_value']),
'status' => sanitize_text_field($_POST['status']),
'updated_at' => current_time('mysql')
);
if ($bundle_id) {
// 更新现有混装产品
$result = $wpdb->update(
$wpdb->prefix . 'yoone_bundles',
$bundle_data,
array('id' => $bundle_id)
);
} else {
// 创建新混装产品
$bundle_data['created_at'] = current_time('mysql');
$result = $wpdb->insert(
$wpdb->prefix . 'yoone_bundles',
$bundle_data
);
$bundle_id = $wpdb->insert_id;
}
if ($result !== false) {
// 保存混装项目
if (isset($_POST['bundle_items']) && is_array($_POST['bundle_items'])) {
// 删除现有项目
$wpdb->delete(
$wpdb->prefix . 'yoone_bundle_items',
array('bundle_id' => $bundle_id)
);
// 添加新项目
foreach ($_POST['bundle_items'] as $sort_order => $item) {
$wpdb->insert(
$wpdb->prefix . 'yoone_bundle_items',
array(
'bundle_id' => $bundle_id,
'product_id' => intval($item['product_id']),
'quantity' => intval($item['quantity']),
'sort_order' => intval($sort_order)
)
);
}
}
wp_redirect(admin_url('admin.php?page=yoone-bundles&saved=1'));
exit;
} else {
wp_die(__('保存失败', 'yoone-subscriptions'));
}
}
/**
* 混装产品列表
*/
private function list_bundles() {
global $wpdb;
$bundles = $wpdb->get_results(
"SELECT * FROM {$wpdb->prefix}yoone_bundles ORDER BY created_at DESC"
);
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/bundles-list.php';
}
/**
* 支付设置页面
*/
public function payment_settings_page() {
if (isset($_POST['submit'])) {
$this->save_payment_settings();
}
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/payment-settings.php';
}
/**
* 保存支付设置
*/
private function save_payment_settings() {
if (!wp_verify_nonce($_POST['_wpnonce'], 'yoone_payment_settings')) {
wp_die(__('安全验证失败', 'yoone-subscriptions'));
}
$settings = array(
'yoone_moneris_enabled' => isset($_POST['moneris_enabled']) ? 'yes' : 'no',
'yoone_moneris_testmode' => isset($_POST['moneris_testmode']) ? 'yes' : 'no',
'yoone_moneris_store_id' => sanitize_text_field($_POST['moneris_store_id']),
'yoone_moneris_api_token' => sanitize_text_field($_POST['moneris_api_token']),
);
foreach ($settings as $key => $value) {
update_option($key, $value);
}
add_action('admin_notices', function() {
echo '' . __('设置已保存', 'yoone-subscriptions') . '
';
});
}
/**
* 报告页面
*/
public function reports_page() {
include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/reports.php';
}
/**
* 添加产品数据标签
*/
public function add_product_data_tabs($tabs) {
$tabs['yoone_subscription'] = array(
'label' => __('订阅设置', 'yoone-subscriptions'),
'target' => 'yoone_subscription_data',
'class' => array('show_if_simple', 'show_if_variable'),
);
$tabs['yoone_bundle'] = array(
'label' => __('混装设置', 'yoone-subscriptions'),
'target' => 'yoone_bundle_data',
'class' => array('show_if_yoone_bundle'),
);
return $tabs;
}
/**
* 添加产品数据面板
*/
public function add_product_data_panels() {
global $post;
// 订阅设置面板
echo '';
woocommerce_wp_checkbox(array(
'id' => '_yoone_subscription_enabled',
'label' => __('启用订阅', 'yoone-subscriptions'),
'description' => __('将此产品设置为订阅产品', 'yoone-subscriptions'),
));
woocommerce_wp_select(array(
'id' => '_yoone_subscription_trial_period',
'label' => __('试用期', 'yoone-subscriptions'),
'options' => array(
'' => __('无试用期', 'yoone-subscriptions'),
'7' => __('7天', 'yoone-subscriptions'),
'14' => __('14天', 'yoone-subscriptions'),
'30' => __('30天', 'yoone-subscriptions'),
),
));
echo '
';
echo '
' . __('订阅周期', 'yoone-subscriptions') . '
';
$periods = get_post_meta($post->ID, '_yoone_subscription_periods', true);
if (!is_array($periods)) {
$periods = array();
}
echo '
';
foreach ($periods as $key => $period) {
$this->render_subscription_period_row($key, $period);
}
echo '
';
echo '
';
echo '
';
echo '
';
// 混装设置面板
echo '';
woocommerce_wp_text_input(array(
'id' => '_yoone_bundle_min_quantity',
'label' => __('最小数量', 'yoone-subscriptions'),
'type' => 'number',
'custom_attributes' => array('min' => '1'),
));
woocommerce_wp_select(array(
'id' => '_yoone_bundle_discount_type',
'label' => __('折扣类型', 'yoone-subscriptions'),
'options' => array(
'percentage' => __('百分比', 'yoone-subscriptions'),
'fixed' => __('固定金额', 'yoone-subscriptions'),
),
));
woocommerce_wp_text_input(array(
'id' => '_yoone_bundle_discount_value',
'label' => __('折扣值', 'yoone-subscriptions'),
'type' => 'number',
'custom_attributes' => array('step' => '0.01', 'min' => '0'),
));
echo '
';
echo '
' . __('混装项目', 'yoone-subscriptions') . '
';
echo '
';
echo '
';
echo '
';
echo '
';
}
/**
* 渲染订阅周期行
*/
private function render_subscription_period_row($key, $period) {
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '
';
}
/**
* 保存产品元数据
*/
public function save_product_meta($post_id) {
// 保存订阅设置
$subscription_enabled = isset($_POST['_yoone_subscription_enabled']) ? 'yes' : 'no';
update_post_meta($post_id, '_yoone_subscription_enabled', $subscription_enabled);
if (isset($_POST['_yoone_subscription_trial_period'])) {
update_post_meta($post_id, '_yoone_subscription_trial_period', sanitize_text_field($_POST['_yoone_subscription_trial_period']));
}
if (isset($_POST['_yoone_subscription_periods'])) {
update_post_meta($post_id, '_yoone_subscription_periods', $_POST['_yoone_subscription_periods']);
}
// 保存混装设置
if (isset($_POST['_yoone_bundle_min_quantity'])) {
update_post_meta($post_id, '_yoone_bundle_min_quantity', intval($_POST['_yoone_bundle_min_quantity']));
}
if (isset($_POST['_yoone_bundle_discount_type'])) {
update_post_meta($post_id, '_yoone_bundle_discount_type', sanitize_text_field($_POST['_yoone_bundle_discount_type']));
}
if (isset($_POST['_yoone_bundle_discount_value'])) {
update_post_meta($post_id, '_yoone_bundle_discount_value', floatval($_POST['_yoone_bundle_discount_value']));
}
}
/**
* 添加产品类型
*/
public function add_product_types($types) {
$types['yoone_bundle'] = __('混装产品', 'yoone-subscriptions');
return $types;
}
/**
* 添加订单元框
*/
public function add_order_meta_boxes() {
add_meta_box(
'yoone-subscription-info',
__('订阅信息', 'yoone-subscriptions'),
array($this, 'order_subscription_meta_box'),
'shop_order',
'side',
'default'
);
}
/**
* 订单订阅信息元框
*/
public function order_subscription_meta_box($post) {
global $wpdb;
$subscriptions = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE parent_order_id = %d",
$post->ID
));
if (empty($subscriptions)) {
echo '' . __('此订单没有关联的订阅', 'yoone-subscriptions') . '
';
return;
}
foreach ($subscriptions as $subscription) {
echo '';
echo '
' . __('订阅ID:', 'yoone-subscriptions') . ' ' . $subscription->id . '
';
echo '
' . __('状态:', 'yoone-subscriptions') . ' ' . Yoone_Frontend::get_subscription_status_label($subscription->status) . '
';
echo '
' . __('下次付款:', 'yoone-subscriptions') . ' ' . $subscription->next_payment_date . '
';
echo '
' . __('查看详情', 'yoone-subscriptions') . '
';
echo '
';
}
}
/**
* 处理订单状态变化
*/
public function handle_order_status_change($order_id, $old_status, $new_status, $order) {
if ($new_status === 'completed') {
$this->create_subscription_from_order($order);
}
}
/**
* 从订单创建订阅
*/
private function create_subscription_from_order($order) {
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$subscription_enabled = get_post_meta($product_id, '_yoone_subscription_enabled', true);
if ($subscription_enabled === 'yes') {
$subscription_period = $item->get_meta('_yoone_subscription_period');
if ($subscription_period) {
$this->create_subscription($order, $item, $subscription_period);
}
}
}
}
/**
* 创建订阅
*/
private function create_subscription($order, $item, $period) {
global $wpdb;
$subscription_data = array(
'customer_id' => $order->get_customer_id(),
'parent_order_id' => $order->get_id(),
'status' => 'active',
'billing_period' => $period['period'],
'billing_interval' => $period['interval'],
'total' => $item->get_total(),
'currency' => $order->get_currency(),
'payment_method' => $order->get_payment_method(),
'payment_method_title' => $order->get_payment_method_title(),
'next_payment_date' => $this->calculate_next_payment_date($period),
'start_date' => current_time('mysql'),
'created_at' => current_time('mysql'),
);
$result = $wpdb->insert(
$wpdb->prefix . 'yoone_subscriptions',
$subscription_data
);
if ($result) {
$subscription_id = $wpdb->insert_id;
// 创建订阅项目
$wpdb->insert(
$wpdb->prefix . 'yoone_subscription_items',
array(
'subscription_id' => $subscription_id,
'product_id' => $item->get_product_id(),
'variation_id' => $item->get_variation_id(),
'quantity' => $item->get_quantity(),
'price' => $item->get_total() / $item->get_quantity(),
)
);
// 记录日志
Yoone_Logger::info("从订单 {$order->get_id()} 创建订阅 {$subscription_id}");
}
}
/**
* 计算下次付款日期
*/
private function calculate_next_payment_date($period) {
$interval = $period['interval'];
$period_type = $period['period'];
switch ($period_type) {
case 'day':
return date('Y-m-d H:i:s', strtotime("+{$interval} days"));
case 'week':
return date('Y-m-d H:i:s', strtotime("+{$interval} weeks"));
case 'month':
return date('Y-m-d H:i:s', strtotime("+{$interval} months"));
case 'year':
return date('Y-m-d H:i:s', strtotime("+{$interval} years"));
default:
return date('Y-m-d H:i:s', strtotime("+1 month"));
}
}
/**
* 添加产品列
*/
public function add_product_columns($columns) {
$columns['yoone_subscription'] = __('订阅', 'yoone-subscriptions');
$columns['yoone_bundle'] = __('混装', 'yoone-subscriptions');
return $columns;
}
/**
* 产品列内容
*/
public function product_column_content($column, $post_id) {
switch ($column) {
case 'yoone_subscription':
$enabled = get_post_meta($post_id, '_yoone_subscription_enabled', true);
echo $enabled === 'yes' ? '' : '—';
break;
case 'yoone_bundle':
$product = wc_get_product($post_id);
echo $product && $product->get_type() === 'yoone_bundle' ? '' : '—';
break;
}
}
/**
* 添加设置标签
*/
public function add_settings_tab($settings_tabs) {
$settings_tabs['yoone_subscriptions'] = __('Yoone 订阅', 'yoone-subscriptions');
return $settings_tabs;
}
/**
* 设置标签内容
*/
public function settings_tab_content() {
woocommerce_admin_fields($this->get_settings());
}
/**
* 更新设置
*/
public function update_settings() {
woocommerce_update_options($this->get_settings());
}
/**
* 获取设置字段
*/
private function get_settings() {
return array(
'section_title' => array(
'name' => __('Yoone 订阅设置', 'yoone-subscriptions'),
'type' => 'title',
'desc' => '',
'id' => 'yoone_subscriptions_section_title'
),
'subscription_enabled' => array(
'name' => __('启用订阅功能', 'yoone-subscriptions'),
'type' => 'checkbox',
'desc' => __('启用订阅功能', 'yoone-subscriptions'),
'id' => 'yoone_subscriptions_enabled'
),
'bundle_enabled' => array(
'name' => __('启用混装功能', 'yoone-subscriptions'),
'type' => 'checkbox',
'desc' => __('启用混装产品功能', 'yoone-subscriptions'),
'id' => 'yoone_bundles_enabled'
),
'section_end' => array(
'type' => 'sectionend',
'id' => 'yoone_subscriptions_section_end'
)
);
}
/**
* 管理通知
*/
public function admin_notices() {
// 检查WooCommerce依赖
if (!class_exists('WooCommerce')) {
echo '';
echo __('Yoone Subscriptions 需要 WooCommerce 插件才能正常工作。', 'yoone-subscriptions');
echo '
';
}
}
}