409 lines
14 KiB
PHP
409 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* 订阅列表表格类
|
|
*
|
|
* 处理后台订阅列表显示
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
if (!class_exists('WP_List_Table')) {
|
|
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
|
}
|
|
|
|
/**
|
|
* 订阅列表表格类
|
|
*/
|
|
class Yoone_Subscriptions_List_Table extends WP_List_Table {
|
|
|
|
/**
|
|
* 构造函数
|
|
*/
|
|
public function __construct() {
|
|
parent::__construct(array(
|
|
'singular' => 'subscription',
|
|
'plural' => 'subscriptions',
|
|
'ajax' => false,
|
|
));
|
|
}
|
|
|
|
/**
|
|
* 获取列
|
|
*/
|
|
public function get_columns() {
|
|
return array(
|
|
'cb' => '<input type="checkbox" />',
|
|
'id' => __('ID', 'yoone-subscriptions'),
|
|
'customer' => __('客户', 'yoone-subscriptions'),
|
|
'status' => __('状态', 'yoone-subscriptions'),
|
|
'total' => __('金额', 'yoone-subscriptions'),
|
|
'billing_period' => __('计费周期', 'yoone-subscriptions'),
|
|
'next_payment' => __('下次付款', 'yoone-subscriptions'),
|
|
'created_date' => __('创建日期', 'yoone-subscriptions'),
|
|
'actions' => __('操作', 'yoone-subscriptions'),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 获取可排序列
|
|
*/
|
|
public function get_sortable_columns() {
|
|
return array(
|
|
'id' => array('id', false),
|
|
'status' => array('status', false),
|
|
'total' => array('total', false),
|
|
'next_payment' => array('next_payment_date', false),
|
|
'created_date' => array('created_at', false),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 获取批量操作
|
|
*/
|
|
public function get_bulk_actions() {
|
|
return array(
|
|
'activate' => __('激活', 'yoone-subscriptions'),
|
|
'pause' => __('暂停', 'yoone-subscriptions'),
|
|
'cancel' => __('取消', 'yoone-subscriptions'),
|
|
'delete' => __('删除', 'yoone-subscriptions'),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 准备项目
|
|
*/
|
|
public function prepare_items() {
|
|
global $wpdb;
|
|
|
|
$per_page = 20;
|
|
$current_page = $this->get_pagenum();
|
|
|
|
// 处理搜索
|
|
$search = isset($_REQUEST['s']) ? sanitize_text_field($_REQUEST['s']) : '';
|
|
|
|
// 处理状态过滤
|
|
$status_filter = isset($_REQUEST['status']) ? sanitize_text_field($_REQUEST['status']) : '';
|
|
|
|
// 构建查询
|
|
$where_conditions = array('1=1');
|
|
$where_values = array();
|
|
|
|
if (!empty($search)) {
|
|
$where_conditions[] = "(s.id LIKE %s OR u.display_name LIKE %s OR u.user_email LIKE %s)";
|
|
$where_values[] = '%' . $wpdb->esc_like($search) . '%';
|
|
$where_values[] = '%' . $wpdb->esc_like($search) . '%';
|
|
$where_values[] = '%' . $wpdb->esc_like($search) . '%';
|
|
}
|
|
|
|
if (!empty($status_filter)) {
|
|
$where_conditions[] = "s.status = %s";
|
|
$where_values[] = $status_filter;
|
|
}
|
|
|
|
$where_clause = implode(' AND ', $where_conditions);
|
|
|
|
// 排序
|
|
$allowed_orderby = array('id', 'status', 'total', 'next_payment_date', 'created_at');
|
|
$orderby = isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], $allowed_orderby) ? $_REQUEST['orderby'] : 'id';
|
|
$order = isset($_REQUEST['order']) && $_REQUEST['order'] === 'asc' ? 'ASC' : 'DESC';
|
|
|
|
// 获取总数
|
|
$total_query = "
|
|
SELECT COUNT(*)
|
|
FROM {$wpdb->prefix}yoone_subscriptions s
|
|
LEFT JOIN {$wpdb->users} u ON s.customer_id = u.ID
|
|
WHERE {$where_clause}
|
|
";
|
|
|
|
if (!empty($where_values)) {
|
|
$total_items = $wpdb->get_var($wpdb->prepare($total_query, $where_values));
|
|
} else {
|
|
$total_items = $wpdb->get_var($total_query);
|
|
}
|
|
|
|
// 获取数据
|
|
$offset = ($current_page - 1) * $per_page;
|
|
|
|
$items_query = "
|
|
SELECT s.*, u.display_name, u.user_email
|
|
FROM {$wpdb->prefix}yoone_subscriptions s
|
|
LEFT JOIN {$wpdb->users} u ON s.customer_id = u.ID
|
|
WHERE {$where_clause}
|
|
ORDER BY s.{$orderby} {$order}
|
|
LIMIT %d OFFSET %d
|
|
";
|
|
|
|
$query_values = array_merge($where_values, array($per_page, $offset));
|
|
$this->items = $wpdb->get_results($wpdb->prepare($items_query, $query_values));
|
|
|
|
// 设置分页
|
|
$this->set_pagination_args(array(
|
|
'total_items' => $total_items,
|
|
'per_page' => $per_page,
|
|
'total_pages' => ceil($total_items / $per_page),
|
|
));
|
|
|
|
$this->_column_headers = array(
|
|
$this->get_columns(),
|
|
array(),
|
|
$this->get_sortable_columns(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 默认列显示
|
|
*/
|
|
public function column_default($item, $column_name) {
|
|
switch ($column_name) {
|
|
case 'id':
|
|
return '#' . $item->id;
|
|
|
|
case 'customer':
|
|
$customer_link = admin_url('user-edit.php?user_id=' . $item->customer_id);
|
|
return '<a href="' . $customer_link . '">' . $item->display_name . '</a><br><small>' . $item->user_email . '</small>';
|
|
|
|
case 'status':
|
|
return $this->get_status_badge($item->status);
|
|
|
|
case 'total':
|
|
return wc_price($item->total);
|
|
|
|
case 'billing_period':
|
|
return $this->format_billing_period($item->billing_period, $item->billing_interval);
|
|
|
|
case 'next_payment':
|
|
if ($item->next_payment_date && $item->status === 'active') {
|
|
$date = new DateTime($item->next_payment_date);
|
|
return $date->format('Y-m-d H:i');
|
|
}
|
|
return '-';
|
|
|
|
case 'created_date':
|
|
$date = new DateTime($item->created_at);
|
|
return $date->format('Y-m-d H:i');
|
|
|
|
case 'actions':
|
|
return $this->get_row_actions($item);
|
|
|
|
default:
|
|
return isset($item->$column_name) ? $item->$column_name : '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 复选框列
|
|
*/
|
|
public function column_cb($item) {
|
|
return sprintf('<input type="checkbox" name="subscription[]" value="%s" />', $item->id);
|
|
}
|
|
|
|
/**
|
|
* 获取状态徽章
|
|
*/
|
|
private function get_status_badge($status) {
|
|
$statuses = array(
|
|
'active' => array('label' => __('活跃', 'yoone-subscriptions'), 'color' => 'green'),
|
|
'paused' => array('label' => __('暂停', 'yoone-subscriptions'), 'color' => 'orange'),
|
|
'cancelled' => array('label' => __('已取消', 'yoone-subscriptions'), 'color' => 'red'),
|
|
'expired' => array('label' => __('已过期', 'yoone-subscriptions'), 'color' => 'gray'),
|
|
'pending' => array('label' => __('待处理', 'yoone-subscriptions'), 'color' => 'blue'),
|
|
);
|
|
|
|
$status_info = isset($statuses[$status]) ? $statuses[$status] : array('label' => $status, 'color' => 'gray');
|
|
|
|
return sprintf(
|
|
'<span class="yoone-status-badge yoone-status-%s" style="background-color: %s; color: white; padding: 2px 8px; border-radius: 3px; font-size: 11px;">%s</span>',
|
|
$status,
|
|
$status_info['color'],
|
|
$status_info['label']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 格式化计费周期
|
|
*/
|
|
private function format_billing_period($period, $interval) {
|
|
$periods = array(
|
|
'day' => __('天', 'yoone-subscriptions'),
|
|
'week' => __('周', 'yoone-subscriptions'),
|
|
'month' => __('月', 'yoone-subscriptions'),
|
|
'year' => __('年', 'yoone-subscriptions'),
|
|
);
|
|
|
|
$period_name = isset($periods[$period]) ? $periods[$period] : $period;
|
|
|
|
if ($interval > 1) {
|
|
return sprintf(__('每 %d %s', 'yoone-subscriptions'), $interval, $period_name);
|
|
} else {
|
|
return sprintf(__('每%s', 'yoone-subscriptions'), $period_name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取行操作
|
|
*/
|
|
private function get_row_actions($item) {
|
|
$actions = array();
|
|
|
|
$edit_url = admin_url('admin.php?page=yoone-subscriptions&action=edit&id=' . $item->id);
|
|
$actions['edit'] = '<a href="' . $edit_url . '">' . __('编辑', 'yoone-subscriptions') . '</a>';
|
|
|
|
if ($item->status === 'active') {
|
|
$pause_url = wp_nonce_url(
|
|
admin_url('admin.php?page=yoone-subscriptions&action=pause&id=' . $item->id),
|
|
'pause_subscription_' . $item->id
|
|
);
|
|
$actions['pause'] = '<a href="' . $pause_url . '">' . __('暂停', 'yoone-subscriptions') . '</a>';
|
|
}
|
|
|
|
if ($item->status === 'paused') {
|
|
$resume_url = wp_nonce_url(
|
|
admin_url('admin.php?page=yoone-subscriptions&action=resume&id=' . $item->id),
|
|
'resume_subscription_' . $item->id
|
|
);
|
|
$actions['resume'] = '<a href="' . $resume_url . '">' . __('恢复', 'yoone-subscriptions') . '</a>';
|
|
}
|
|
|
|
if (in_array($item->status, array('active', 'paused'))) {
|
|
$cancel_url = wp_nonce_url(
|
|
admin_url('admin.php?page=yoone-subscriptions&action=cancel&id=' . $item->id),
|
|
'cancel_subscription_' . $item->id
|
|
);
|
|
$actions['cancel'] = '<a href="' . $cancel_url . '" style="color: red;">' . __('取消', 'yoone-subscriptions') . '</a>';
|
|
}
|
|
|
|
$delete_url = wp_nonce_url(
|
|
admin_url('admin.php?page=yoone-subscriptions&action=delete&id=' . $item->id),
|
|
'delete_subscription_' . $item->id
|
|
);
|
|
$actions['delete'] = '<a href="' . $delete_url . '" style="color: red;" onclick="return confirm(\'' . __('确定要删除这个订阅吗?', 'yoone-subscriptions') . '\')">' . __('删除', 'yoone-subscriptions') . '</a>';
|
|
|
|
return implode(' | ', $actions);
|
|
}
|
|
|
|
/**
|
|
* 显示状态过滤器
|
|
*/
|
|
protected function get_views() {
|
|
global $wpdb;
|
|
|
|
$status_counts = $wpdb->get_results("
|
|
SELECT status, COUNT(*) as count
|
|
FROM {$wpdb->prefix}yoone_subscriptions
|
|
GROUP BY status
|
|
", ARRAY_A);
|
|
|
|
$total_count = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}yoone_subscriptions");
|
|
|
|
$views = array();
|
|
$current_status = isset($_REQUEST['status']) ? $_REQUEST['status'] : '';
|
|
|
|
// 全部
|
|
$class = empty($current_status) ? 'current' : '';
|
|
$views['all'] = sprintf(
|
|
'<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
|
|
admin_url('admin.php?page=yoone-subscriptions'),
|
|
$class,
|
|
__('全部', 'yoone-subscriptions'),
|
|
$total_count
|
|
);
|
|
|
|
// 各状态
|
|
$status_labels = array(
|
|
'active' => __('活跃', 'yoone-subscriptions'),
|
|
'paused' => __('暂停', 'yoone-subscriptions'),
|
|
'cancelled' => __('已取消', 'yoone-subscriptions'),
|
|
'expired' => __('已过期', 'yoone-subscriptions'),
|
|
'pending' => __('待处理', 'yoone-subscriptions'),
|
|
);
|
|
|
|
foreach ($status_counts as $status_data) {
|
|
$status = $status_data['status'];
|
|
$count = $status_data['count'];
|
|
|
|
if (isset($status_labels[$status])) {
|
|
$class = $current_status === $status ? 'current' : '';
|
|
$views[$status] = sprintf(
|
|
'<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
|
|
admin_url('admin.php?page=yoone-subscriptions&status=' . $status),
|
|
$class,
|
|
$status_labels[$status],
|
|
$count
|
|
);
|
|
}
|
|
}
|
|
|
|
return $views;
|
|
}
|
|
|
|
/**
|
|
* 处理批量操作
|
|
*/
|
|
public function process_bulk_action() {
|
|
$action = $this->current_action();
|
|
|
|
if (!$action) {
|
|
return;
|
|
}
|
|
|
|
$subscription_ids = isset($_REQUEST['subscription']) ? array_map('intval', $_REQUEST['subscription']) : array();
|
|
|
|
if (empty($subscription_ids)) {
|
|
return;
|
|
}
|
|
|
|
foreach ($subscription_ids as $subscription_id) {
|
|
$subscription = new Yoone_Subscription($subscription_id);
|
|
|
|
if (!$subscription->get_id()) {
|
|
continue;
|
|
}
|
|
|
|
switch ($action) {
|
|
case 'activate':
|
|
$subscription->activate();
|
|
break;
|
|
|
|
case 'pause':
|
|
$subscription->pause();
|
|
break;
|
|
|
|
case 'cancel':
|
|
$subscription->cancel();
|
|
break;
|
|
|
|
case 'delete':
|
|
$subscription->delete();
|
|
break;
|
|
}
|
|
}
|
|
|
|
wp_redirect(admin_url('admin.php?page=yoone-subscriptions&bulk_action=' . $action . '&processed=' . count($subscription_ids)));
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* 显示批量操作通知
|
|
*/
|
|
public function admin_notices() {
|
|
if (isset($_GET['bulk_action']) && isset($_GET['processed'])) {
|
|
$action = sanitize_text_field($_GET['bulk_action']);
|
|
$processed = intval($_GET['processed']);
|
|
|
|
$messages = array(
|
|
'activate' => __('已激活 %d 个订阅', 'yoone-subscriptions'),
|
|
'pause' => __('已暂停 %d 个订阅', 'yoone-subscriptions'),
|
|
'cancel' => __('已取消 %d 个订阅', 'yoone-subscriptions'),
|
|
'delete' => __('已删除 %d 个订阅', 'yoone-subscriptions'),
|
|
);
|
|
|
|
if (isset($messages[$action])) {
|
|
echo '<div class="notice notice-success is-dismissible">';
|
|
echo '<p>' . sprintf($messages[$action], $processed) . '</p>';
|
|
echo '</div>';
|
|
}
|
|
}
|
|
}
|
|
} |