Adding more functionality

This commit is contained in:
2025-08-29 18:54:14 -07:00
parent 5aa0777fd3
commit 6d797ef686
17 changed files with 4237 additions and 85 deletions

View File

@@ -10,6 +10,10 @@ class WPDD_Admin_Payouts {
add_action('admin_menu', array(__CLASS__, 'add_menu_page'));
add_action('admin_post_wpdd_process_payout', array(__CLASS__, 'process_payout'));
add_action('admin_post_wpdd_bulk_payouts', array(__CLASS__, 'process_bulk_payouts'));
add_action('admin_post_wpdd_process_payout_request', array(__CLASS__, 'process_payout_request'));
add_action('admin_post_wpdd_reject_payout_request', array(__CLASS__, 'reject_payout_request'));
add_action('admin_post_wpdd_manual_payout', array(__CLASS__, 'process_manual_payout'));
add_action('admin_post_wpdd_adjust_balance', array(__CLASS__, 'adjust_creator_balance'));
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'));
}
@@ -50,6 +54,15 @@ class WPDD_Admin_Payouts {
$currency = get_option('wpdd_currency', 'USD');
$threshold = floatval(get_option('wpdd_payout_threshold', 0));
// Get payout requests (requested status)
$payout_requests = $wpdb->get_results(
"SELECT p.*, u.display_name, u.user_email
FROM {$wpdb->prefix}wpdd_payouts p
INNER JOIN {$wpdb->users} u ON p.creator_id = u.ID
WHERE p.status = 'requested'
ORDER BY p.created_at ASC"
);
// Get payout history
$query = "SELECT p.*, u.display_name, u.user_email
FROM {$wpdb->prefix}wpdd_payouts p
@@ -81,9 +94,172 @@ class WPDD_Admin_Payouts {
<div class="notice notice-error is-dismissible">
<p><?php _e('Error processing payout. Please try again.', 'wp-digital-download'); ?></p>
</div>
<?php elseif ($_GET['message'] === 'balance_adjusted') : ?>
<div class="notice notice-success is-dismissible">
<p><?php _e('Creator balance adjusted successfully.', 'wp-digital-download'); ?></p>
</div>
<?php endif; ?>
<?php endif; ?>
<?php if (!empty($payout_requests)) : ?>
<div class="wpdd-payout-requests" style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px; padding: 20px; margin: 20px 0;">
<h2 style="margin-top: 0;"><?php _e('Payout Requests', 'wp-digital-download'); ?> <span class="count">(<?php echo count($payout_requests); ?>)</span></h2>
<p><?php _e('Creators have requested the following payouts:', 'wp-digital-download'); ?></p>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Creator', 'wp-digital-download'); ?></th>
<th><?php _e('Amount', 'wp-digital-download'); ?></th>
<th><?php _e('PayPal Email', 'wp-digital-download'); ?></th>
<th><?php _e('Request Date', 'wp-digital-download'); ?></th>
<th><?php _e('Actions', 'wp-digital-download'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($payout_requests as $request) : ?>
<tr>
<td>
<strong><?php echo esc_html($request->display_name); ?></strong><br>
<small><?php echo esc_html($request->user_email); ?></small>
</td>
<td><strong><?php echo wpdd_format_price($request->amount, $request->currency); ?></strong></td>
<td><?php echo esc_html($request->paypal_email); ?></td>
<td><?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($request->created_at))); ?></td>
<td>
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>" style="display: inline;">
<input type="hidden" name="action" value="wpdd_process_payout_request">
<input type="hidden" name="payout_id" value="<?php echo esc_attr($request->id); ?>">
<?php wp_nonce_field('wpdd_process_payout_request_' . $request->id, 'wpdd_nonce'); ?>
<button type="submit" class="button button-primary">
<?php _e('Process Now', 'wp-digital-download'); ?>
</button>
</form>
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>" style="display: inline; margin-left: 5px;">
<input type="hidden" name="action" value="wpdd_reject_payout_request">
<input type="hidden" name="payout_id" value="<?php echo esc_attr($request->id); ?>">
<?php wp_nonce_field('wpdd_reject_payout_request_' . $request->id, 'wpdd_nonce'); ?>
<button type="submit" class="button button-secondary" onclick="return confirm('<?php _e('Are you sure you want to reject this payout request?', 'wp-digital-download'); ?>')">
<?php _e('Reject', 'wp-digital-download'); ?>
</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<!-- Manual Actions Section -->
<div class="wpdd-manual-actions" style="display: flex; gap: 20px; margin: 20px 0;">
<!-- Manual Payout Form -->
<div style="background: white; border: 1px solid #ddd; border-radius: 4px; padding: 20px; flex: 1;">
<h3 style="margin-top: 0;"><?php _e('Manual Payout', 'wp-digital-download'); ?></h3>
<p><?php _e('Process a payout for off-site sales or manual adjustments.', 'wp-digital-download'); ?></p>
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
<input type="hidden" name="action" value="wpdd_manual_payout">
<?php wp_nonce_field('wpdd_manual_payout', 'wpdd_nonce'); ?>
<table class="form-table" style="margin: 0;">
<tr>
<th><label for="creator_id"><?php _e('Creator', 'wp-digital-download'); ?></label></th>
<td>
<select name="creator_id" id="creator_id" required style="width: 100%;">
<option value=""><?php _e('Select Creator', 'wp-digital-download'); ?></option>
<?php
$all_creators = get_users(array('role' => 'wpdd_creator'));
foreach ($all_creators as $creator) :
$paypal_email = get_user_meta($creator->ID, 'wpdd_paypal_email', true);
?>
<option value="<?php echo esc_attr($creator->ID); ?>" <?php echo empty($paypal_email) ? 'disabled' : ''; ?>>
<?php echo esc_html($creator->display_name); ?>
<?php echo empty($paypal_email) ? ' (' . __('No PayPal email', 'wp-digital-download') . ')' : ' (' . esc_html($paypal_email) . ')'; ?>
</option>
<?php endforeach; ?>
</select>
</td>
</tr>
<tr>
<th><label for="payout_amount"><?php _e('Amount', 'wp-digital-download'); ?></label></th>
<td>
<input type="number" name="payout_amount" id="payout_amount" step="0.01" min="0.01" required style="width: 150px;">
<span><?php echo esc_html($currency); ?></span>
</td>
</tr>
<tr>
<th><label for="payout_reason"><?php _e('Reason/Note', 'wp-digital-download'); ?></label></th>
<td>
<textarea name="payout_reason" id="payout_reason" rows="3" style="width: 100%;" placeholder="<?php _e('e.g., Off-site sale, manual adjustment, etc.', 'wp-digital-download'); ?>"></textarea>
</td>
</tr>
</table>
<p class="submit" style="margin: 15px 0 0 0;">
<button type="submit" class="button button-primary">
<?php _e('Process Manual Payout', 'wp-digital-download'); ?>
</button>
</p>
</form>
</div>
<!-- Balance Adjustment Form -->
<div style="background: white; border: 1px solid #ddd; border-radius: 4px; padding: 20px; flex: 1;">
<h3 style="margin-top: 0;"><?php _e('Adjust Creator Balance', 'wp-digital-download'); ?></h3>
<p><?php _e('Add or subtract funds from a creator\'s balance.', 'wp-digital-download'); ?></p>
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
<input type="hidden" name="action" value="wpdd_adjust_balance">
<?php wp_nonce_field('wpdd_adjust_balance', 'wpdd_nonce'); ?>
<table class="form-table" style="margin: 0;">
<tr>
<th><label for="adj_creator_id"><?php _e('Creator', 'wp-digital-download'); ?></label></th>
<td>
<select name="creator_id" id="adj_creator_id" required style="width: 100%;">
<option value=""><?php _e('Select Creator', 'wp-digital-download'); ?></option>
<?php foreach ($all_creators as $creator) : ?>
<option value="<?php echo esc_attr($creator->ID); ?>">
<?php echo esc_html($creator->display_name); ?>
</option>
<?php endforeach; ?>
</select>
</td>
</tr>
<tr>
<th><label for="adjustment_type"><?php _e('Type', 'wp-digital-download'); ?></label></th>
<td>
<select name="adjustment_type" id="adjustment_type" required>
<option value="add"><?php _e('Add Funds', 'wp-digital-download'); ?></option>
<option value="subtract"><?php _e('Subtract Funds', 'wp-digital-download'); ?></option>
</select>
</td>
</tr>
<tr>
<th><label for="adjustment_amount"><?php _e('Amount', 'wp-digital-download'); ?></label></th>
<td>
<input type="number" name="adjustment_amount" id="adjustment_amount" step="0.01" min="0.01" required style="width: 150px;">
<span><?php echo esc_html($currency); ?></span>
</td>
</tr>
<tr>
<th><label for="adjustment_reason"><?php _e('Reason/Note', 'wp-digital-download'); ?></label></th>
<td>
<textarea name="adjustment_reason" id="adjustment_reason" rows="3" style="width: 100%;" placeholder="<?php _e('e.g., Manual adjustment, refund, bonus, etc.', 'wp-digital-download'); ?>" required></textarea>
</td>
</tr>
</table>
<p class="submit" style="margin: 15px 0 0 0;">
<button type="submit" class="button button-secondary">
<?php _e('Adjust Balance', 'wp-digital-download'); ?>
</button>
</p>
</form>
</div>
</div>
<div class="wpdd-payout-stats">
<h2><?php _e('Pending Payouts', 'wp-digital-download'); ?></h2>
@@ -432,4 +608,241 @@ class WPDD_Admin_Payouts {
return false;
}
}
public static function process_payout_request() {
if (!current_user_can('manage_options')) {
wp_die(__('You do not have permission to perform this action.', 'wp-digital-download'));
}
$payout_id = isset($_POST['payout_id']) ? intval($_POST['payout_id']) : 0;
if (!$payout_id || !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_process_payout_request_' . $payout_id)) {
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
exit;
}
global $wpdb;
// Get the payout request
$payout = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE id = %d AND status = 'requested'",
$payout_id
));
if (!$payout) {
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
exit;
}
// Process via PayPal API
$result = WPDD_PayPal_Payouts::process_payout($payout_id);
if ($result['success']) {
// Update payout status
$wpdb->update(
$wpdb->prefix . 'wpdd_payouts',
array(
'status' => 'completed',
'transaction_id' => $result['transaction_id'],
'processed_by' => get_current_user_id(),
'processed_at' => current_time('mysql')
),
array('id' => $payout_id),
array('%s', '%s', '%d', '%s'),
array('%d')
);
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=success'));
} else {
// Update with error
$wpdb->update(
$wpdb->prefix . 'wpdd_payouts',
array(
'status' => 'failed',
'notes' => $result['error']
),
array('id' => $payout_id),
array('%s', '%s'),
array('%d')
);
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
}
exit;
}
public static function reject_payout_request() {
if (!current_user_can('manage_options')) {
wp_die(__('You do not have permission to perform this action.', 'wp-digital-download'));
}
$payout_id = isset($_POST['payout_id']) ? intval($_POST['payout_id']) : 0;
if (!$payout_id || !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_reject_payout_request_' . $payout_id)) {
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
exit;
}
global $wpdb;
// Get the payout request
$payout = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE id = %d AND status = 'requested'",
$payout_id
));
if (!$payout) {
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
exit;
}
// Update status to failed/rejected
$wpdb->update(
$wpdb->prefix . 'wpdd_payouts',
array(
'status' => 'failed',
'notes' => 'Request rejected by administrator',
'processed_by' => get_current_user_id(),
'processed_at' => current_time('mysql')
),
array('id' => $payout_id),
array('%s', '%s', '%d', '%s'),
array('%d')
);
// Restore balance to creator
update_user_meta($payout->creator_id, 'wpdd_creator_balance', $payout->amount);
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=success'));
exit;
}
public static function process_manual_payout() {
if (!current_user_can('manage_options') ||
!wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_manual_payout')) {
wp_die(__('Security check failed', 'wp-digital-download'));
}
$creator_id = intval($_POST['creator_id']);
$amount = floatval($_POST['payout_amount']);
$reason = sanitize_textarea_field($_POST['payout_reason']);
if (!$creator_id || $amount <= 0) {
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
exit;
}
$creator = get_userdata($creator_id);
if (!$creator || !in_array('wpdd_creator', $creator->roles)) {
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
exit;
}
$paypal_email = get_user_meta($creator_id, 'wpdd_paypal_email', true);
if (empty($paypal_email)) {
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
exit;
}
global $wpdb;
// Create the payout record
$result = $wpdb->insert(
$wpdb->prefix . 'wpdd_payouts',
array(
'creator_id' => $creator_id,
'amount' => $amount,
'currency' => get_option('wpdd_currency', 'USD'),
'paypal_email' => $paypal_email,
'status' => 'pending',
'payout_method' => 'manual',
'notes' => $reason,
'created_at' => current_time('mysql'),
'processed_by' => get_current_user_id()
),
array('%d', '%f', '%s', '%s', '%s', '%s', '%s', '%s', '%d')
);
if (!$result) {
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
exit;
}
$payout_id = $wpdb->insert_id;
// Try to process via PayPal
if (class_exists('WPDD_PayPal_Payouts')) {
$paypal_result = WPDD_PayPal_Payouts::process_payout($payout_id);
if (!$paypal_result) {
// Update status to failed
$wpdb->update(
$wpdb->prefix . 'wpdd_payouts',
array('status' => 'failed'),
array('id' => $payout_id),
array('%s'),
array('%d')
);
}
}
wp_redirect(add_query_arg('message', 'success', wp_get_referer()));
exit;
}
public static function adjust_creator_balance() {
if (!current_user_can('manage_options') ||
!wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_adjust_balance')) {
wp_die(__('Security check failed', 'wp-digital-download'));
}
$creator_id = intval($_POST['creator_id']);
$adjustment_type = sanitize_text_field($_POST['adjustment_type']);
$amount = floatval($_POST['adjustment_amount']);
$reason = sanitize_textarea_field($_POST['adjustment_reason']);
if (!$creator_id || $amount <= 0 || !in_array($adjustment_type, array('add', 'subtract'))) {
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
exit;
}
$creator = get_userdata($creator_id);
if (!$creator || !in_array('wpdd_creator', $creator->roles)) {
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
exit;
}
// Get current balance
$current_balance = floatval(get_user_meta($creator_id, 'wpdd_balance', true));
// Calculate new balance
if ($adjustment_type === 'add') {
$new_balance = $current_balance + $amount;
} else {
$new_balance = max(0, $current_balance - $amount); // Don't allow negative balance
}
// Update the balance
update_user_meta($creator_id, 'wpdd_balance', $new_balance);
// Create a record of this adjustment
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'wpdd_balance_adjustments',
array(
'creator_id' => $creator_id,
'adjustment_type' => $adjustment_type,
'amount' => $amount,
'previous_balance' => $current_balance,
'new_balance' => $new_balance,
'reason' => $reason,
'adjusted_by' => get_current_user_id(),
'created_at' => current_time('mysql')
),
array('%d', '%s', '%f', '%f', '%f', '%s', '%d', '%s')
);
wp_redirect(add_query_arg('message', 'balance_adjusted', wp_get_referer()));
exit;
}
}

View File

@@ -12,6 +12,7 @@ class WPDD_Admin {
add_action('manage_wpdd_product_posts_custom_column', array(__CLASS__, 'render_product_columns'), 10, 2);
add_filter('manage_edit-wpdd_product_sortable_columns', array(__CLASS__, 'make_columns_sortable'));
add_action('pre_get_posts', array(__CLASS__, 'sort_products_by_column'));
add_action('pre_get_posts', array(__CLASS__, 'filter_creator_products'));
add_action('admin_init', array(__CLASS__, 'handle_admin_actions'));
// Initialize admin payouts
@@ -21,41 +22,70 @@ class WPDD_Admin {
}
public static function add_admin_menus() {
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Orders', 'wp-digital-download'),
__('Orders', 'wp-digital-download'),
'wpdd_manage_orders',
'wpdd-orders',
array(__CLASS__, 'render_orders_page')
);
// Show different menus based on user role
$user = wp_get_current_user();
$is_creator = in_array('wpdd_creator', (array) $user->roles);
$is_admin = current_user_can('manage_options');
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Reports', 'wp-digital-download'),
__('Reports', 'wp-digital-download'),
'wpdd_view_reports',
'wpdd-reports',
array(__CLASS__, 'render_reports_page')
);
if ($is_admin) {
// Full admin menus
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Orders', 'wp-digital-download'),
__('Orders', 'wp-digital-download'),
'wpdd_manage_orders',
'wpdd-orders',
array(__CLASS__, 'render_orders_page')
);
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Reports', 'wp-digital-download'),
__('Reports', 'wp-digital-download'),
'wpdd_view_reports',
'wpdd-reports',
array(__CLASS__, 'render_reports_page')
);
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Customers', 'wp-digital-download'),
__('Customers', 'wp-digital-download'),
'wpdd_manage_orders',
'wpdd-customers',
array(__CLASS__, 'render_customers_page')
);
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Shortcodes', 'wp-digital-download'),
__('Shortcodes', 'wp-digital-download'),
'edit_wpdd_products',
'wpdd-shortcodes',
array(__CLASS__, 'render_shortcodes_page')
);
}
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Customers', 'wp-digital-download'),
__('Customers', 'wp-digital-download'),
'wpdd_manage_orders',
'wpdd-customers',
array(__CLASS__, 'render_customers_page')
);
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Shortcodes', 'wp-digital-download'),
__('Shortcodes', 'wp-digital-download'),
'edit_wpdd_products',
'wpdd-shortcodes',
array(__CLASS__, 'render_shortcodes_page')
);
if ($is_creator || $is_admin) {
// Creator-specific menus
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('My Sales', 'wp-digital-download'),
__('My Sales', 'wp-digital-download'),
'wpdd_view_own_sales',
'wpdd-creator-sales',
array(__CLASS__, 'render_creator_sales_page')
);
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('My Payouts', 'wp-digital-download'),
__('My Payouts', 'wp-digital-download'),
'wpdd_view_own_sales',
'wpdd-creator-payouts',
array(__CLASS__, 'render_creator_payouts_page')
);
}
}
public static function add_product_columns($columns) {
@@ -917,4 +947,289 @@ class WPDD_Admin {
<?php
}
public static function filter_creator_products($query) {
if (!is_admin() || !$query->is_main_query()) {
return;
}
if (!isset($_GET['post_type']) || $_GET['post_type'] !== 'wpdd_product') {
return;
}
$user = wp_get_current_user();
$is_creator = in_array('wpdd_creator', (array) $user->roles);
$is_admin = current_user_can('manage_options');
// Only filter for creators, not admins
if ($is_creator && !$is_admin) {
$query->set('author', get_current_user_id());
}
}
public static function render_creator_sales_page() {
global $wpdb;
$user_id = get_current_user_id();
$currency = get_option('wpdd_currency', 'USD');
$commission_rate = floatval(get_option('wpdd_commission_rate', 0));
// Get creator's sales data
$sales = $wpdb->get_results($wpdb->prepare(
"SELECT o.*, p.post_title as product_name,
(o.total * %f / 100) as platform_fee,
(o.total * (100 - %f) / 100) as creator_earning
FROM {$wpdb->prefix}wpdd_orders o
INNER JOIN {$wpdb->posts} p ON o.product_id = p.ID
WHERE p.post_author = %d
AND o.status = 'completed'
ORDER BY o.purchase_date DESC
LIMIT 100",
$commission_rate,
$commission_rate,
$user_id
));
// Get totals
$total_sales = $wpdb->get_var($wpdb->prepare(
"SELECT SUM(o.total)
FROM {$wpdb->prefix}wpdd_orders o
INNER JOIN {$wpdb->posts} p ON o.product_id = p.ID
WHERE p.post_author = %d
AND o.status = 'completed'",
$user_id
));
$total_earnings = $total_sales * (1 - ($commission_rate / 100));
$current_balance = WPDD_Creator::get_creator_balance($user_id);
?>
<div class="wrap">
<h1><?php _e('My Sales Report', 'wp-digital-download'); ?></h1>
<div class="wpdd-stats-row" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px;">
<div class="wpdd-stat-card" style="background: #fff; padding: 20px; border: 1px solid #ccd0d4; border-radius: 4px;">
<h3 style="margin: 0 0 10px; color: #646970;"><?php _e('Total Sales', 'wp-digital-download'); ?></h3>
<div style="font-size: 24px; font-weight: bold; color: #1d2327;"><?php echo wpdd_format_price($total_sales, $currency); ?></div>
</div>
<div class="wpdd-stat-card" style="background: #fff; padding: 20px; border: 1px solid #ccd0d4; border-radius: 4px;">
<h3 style="margin: 0 0 10px; color: #646970;"><?php _e('Your Earnings', 'wp-digital-download'); ?></h3>
<div style="font-size: 24px; font-weight: bold; color: #1d2327;"><?php echo wpdd_format_price($total_earnings, $currency); ?></div>
<small style="color: #646970;"><?php printf(__('After %s%% platform fee', 'wp-digital-download'), $commission_rate); ?></small>
</div>
<div class="wpdd-stat-card" style="background: #fff; padding: 20px; border: 1px solid #ccd0d4; border-radius: 4px;">
<h3 style="margin: 0 0 10px; color: #646970;"><?php _e('Available Balance', 'wp-digital-download'); ?></h3>
<div style="font-size: 24px; font-weight: bold; color: #1d2327;"><?php echo wpdd_format_price($current_balance, $currency); ?></div>
<small style="color: #646970;"><?php _e('Ready for payout', 'wp-digital-download'); ?></small>
</div>
</div>
<?php if (!empty($sales)) : ?>
<div class="wpdd-sales-table">
<h2><?php _e('Recent Sales', 'wp-digital-download'); ?></h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Date', 'wp-digital-download'); ?></th>
<th><?php _e('Product', 'wp-digital-download'); ?></th>
<th><?php _e('Customer', 'wp-digital-download'); ?></th>
<th><?php _e('Sale Amount', 'wp-digital-download'); ?></th>
<th><?php _e('Platform Fee', 'wp-digital-download'); ?></th>
<th><?php _e('Your Earning', 'wp-digital-download'); ?></th>
<th><?php _e('Status', 'wp-digital-download'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($sales as $sale) : ?>
<tr>
<td><?php echo esc_html(date_i18n(get_option('date_format'), strtotime($sale->purchase_date))); ?></td>
<td><?php echo esc_html($sale->product_name); ?></td>
<td><?php echo esc_html($sale->customer_name); ?></td>
<td><?php echo wpdd_format_price($sale->total, $currency); ?></td>
<td><?php echo wpdd_format_price($sale->platform_fee, $currency); ?></td>
<td><strong><?php echo wpdd_format_price($sale->creator_earning, $currency); ?></strong></td>
<td>
<span class="wpdd-status-<?php echo esc_attr($sale->status); ?>" style="padding: 2px 8px; border-radius: 3px; font-size: 12px; <?php echo $sale->status === 'completed' ? 'background: #d1e7dd; color: #0f5132;' : 'background: #f8d7da; color: #721c24;'; ?>">
<?php echo esc_html(ucfirst($sale->status)); ?>
</span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else : ?>
<div style="background: #fff; padding: 40px; border: 1px solid #ccd0d4; border-radius: 4px; text-align: center;">
<h3><?php _e('No sales yet', 'wp-digital-download'); ?></h3>
<p><?php _e('Once customers purchase your products, your sales data will appear here.', 'wp-digital-download'); ?></p>
</div>
<?php endif; ?>
</div>
<?php
}
public static function render_creator_payouts_page() {
global $wpdb;
if (isset($_POST['request_payout']) && wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_request_payout')) {
self::handle_payout_request();
}
$user_id = get_current_user_id();
$currency = get_option('wpdd_currency', 'USD');
$current_balance = WPDD_Creator::get_creator_balance($user_id);
$paypal_email = get_user_meta($user_id, 'wpdd_paypal_email', true);
$threshold = floatval(get_option('wpdd_payout_threshold', 0));
// Get payout history
$payouts = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_payouts
WHERE creator_id = %d
ORDER BY created_at DESC
LIMIT 50",
$user_id
));
?>
<div class="wrap">
<h1><?php _e('My Payouts', 'wp-digital-download'); ?></h1>
<?php if (isset($_GET['message']) && $_GET['message'] === 'payout_requested') : ?>
<div class="notice notice-success is-dismissible">
<p><?php _e('Payout request submitted successfully!', 'wp-digital-download'); ?></p>
</div>
<?php endif; ?>
<div class="wpdd-payout-request" style="background: #fff; padding: 20px; border: 1px solid #ccd0d4; border-radius: 4px; margin-bottom: 30px;">
<h2><?php _e('Request Payout', 'wp-digital-download'); ?></h2>
<div style="display: grid; grid-template-columns: 1fr 2fr; gap: 20px; align-items: start;">
<div>
<h3><?php _e('Current Balance', 'wp-digital-download'); ?></h3>
<div style="font-size: 32px; font-weight: bold; color: #1d2327; margin: 10px 0;">
<?php echo wpdd_format_price($current_balance, $currency); ?>
</div>
<?php if ($threshold > 0) : ?>
<p style="color: #646970; margin: 0;">
<?php printf(__('Minimum for automatic payout: %s', 'wp-digital-download'), wpdd_format_price($threshold, $currency)); ?>
</p>
<?php endif; ?>
</div>
<div>
<?php if (empty($paypal_email)) : ?>
<div class="notice notice-warning" style="margin: 0;">
<p><?php _e('Please add your PayPal email in your profile before requesting a payout.', 'wp-digital-download'); ?></p>
<p><a href="<?php echo esc_url(get_edit_profile_url($user_id)); ?>" class="button"><?php _e('Edit Profile', 'wp-digital-download'); ?></a></p>
</div>
<?php elseif ($current_balance <= 0) : ?>
<div class="notice notice-info" style="margin: 0;">
<p><?php _e('No balance available for payout.', 'wp-digital-download'); ?></p>
</div>
<?php else : ?>
<form method="post">
<?php wp_nonce_field('wpdd_request_payout', 'wpdd_nonce'); ?>
<p><?php _e('PayPal Email:', 'wp-digital-download'); ?> <strong><?php echo esc_html($paypal_email); ?></strong></p>
<p><?php _e('Requesting a payout will notify administrators to process your payment.', 'wp-digital-download'); ?></p>
<button type="submit" name="request_payout" class="button button-primary">
<?php printf(__('Request Payout of %s', 'wp-digital-download'), wpdd_format_price($current_balance, $currency)); ?>
</button>
</form>
<?php endif; ?>
</div>
</div>
</div>
<?php if (!empty($payouts)) : ?>
<div class="wpdd-payout-history">
<h2><?php _e('Payout History', 'wp-digital-download'); ?></h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Date Requested', 'wp-digital-download'); ?></th>
<th><?php _e('Amount', 'wp-digital-download'); ?></th>
<th><?php _e('PayPal Email', 'wp-digital-download'); ?></th>
<th><?php _e('Status', 'wp-digital-download'); ?></th>
<th><?php _e('Transaction ID', 'wp-digital-download'); ?></th>
<th><?php _e('Processed Date', 'wp-digital-download'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($payouts as $payout) : ?>
<tr>
<td><?php echo esc_html(date_i18n(get_option('date_format'), strtotime($payout->created_at))); ?></td>
<td><strong><?php echo wpdd_format_price($payout->amount, $payout->currency); ?></strong></td>
<td><?php echo esc_html($payout->paypal_email); ?></td>
<td>
<?php
$status_colors = array(
'pending' => '#fef3c7; color: #92400e;',
'completed' => '#d1fae5; color: #065f46;',
'failed' => '#fee2e2; color: #991b1b;',
'requested' => '#dbeafe; color: #1e40af;'
);
$status_color = isset($status_colors[$payout->status]) ? $status_colors[$payout->status] : '#f3f4f6; color: #374151;';
?>
<span style="padding: 2px 8px; border-radius: 3px; font-size: 12px; background: <?php echo $status_color; ?>">
<?php echo esc_html(ucfirst($payout->status)); ?>
</span>
</td>
<td><?php echo esc_html($payout->transaction_id ?: '-'); ?></td>
<td>
<?php
echo $payout->processed_at
? esc_html(date_i18n(get_option('date_format'), strtotime($payout->processed_at)))
: '-';
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else : ?>
<div style="background: #fff; padding: 40px; border: 1px solid #ccd0d4; border-radius: 4px; text-align: center;">
<h3><?php _e('No payout history', 'wp-digital-download'); ?></h3>
<p><?php _e('Your payout requests will appear here once you make them.', 'wp-digital-download'); ?></p>
</div>
<?php endif; ?>
</div>
<?php
}
private static function handle_payout_request() {
global $wpdb;
$user_id = get_current_user_id();
$balance = WPDD_Creator::get_creator_balance($user_id);
$paypal_email = get_user_meta($user_id, 'wpdd_paypal_email', true);
if ($balance <= 0 || empty($paypal_email)) {
return;
}
$currency = get_option('wpdd_currency', 'USD');
// Create payout request
$wpdb->insert(
$wpdb->prefix . 'wpdd_payouts',
array(
'creator_id' => $user_id,
'amount' => $balance,
'currency' => $currency,
'paypal_email' => $paypal_email,
'status' => 'requested',
'payout_method' => 'request',
'created_at' => current_time('mysql')
),
array('%d', '%f', '%s', '%s', '%s', '%s', '%s')
);
// Reset balance to 0 since it's now requested
update_user_meta($user_id, 'wpdd_creator_balance', 0);
// Redirect to avoid resubmission
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-creator-payouts&message=payout_requested'));
exit;
}
}

View File

@@ -16,7 +16,7 @@ class WPDD_Settings {
'edit.php?post_type=wpdd_product',
__('Settings', 'wp-digital-download'),
__('Settings', 'wp-digital-download'),
'wpdd_manage_settings',
'manage_options',
'wpdd-settings',
array(__CLASS__, 'render_settings_page')
);
@@ -26,9 +26,16 @@ class WPDD_Settings {
register_setting('wpdd_settings', 'wpdd_paypal_mode');
register_setting('wpdd_settings', 'wpdd_paypal_client_id');
register_setting('wpdd_settings', 'wpdd_paypal_secret');
register_setting('wpdd_settings', 'wpdd_paypal_payout_email');
register_setting('wpdd_settings', 'wpdd_admin_email');
register_setting('wpdd_settings', 'wpdd_from_name');
register_setting('wpdd_settings', 'wpdd_from_email');
register_setting('wpdd_settings', 'wpdd_smtp_enabled');
register_setting('wpdd_settings', 'wpdd_smtp_host');
register_setting('wpdd_settings', 'wpdd_smtp_port');
register_setting('wpdd_settings', 'wpdd_smtp_username');
register_setting('wpdd_settings', 'wpdd_smtp_password');
register_setting('wpdd_settings', 'wpdd_smtp_encryption');
register_setting('wpdd_settings', 'wpdd_currency');
register_setting('wpdd_settings', 'wpdd_enable_guest_checkout');
register_setting('wpdd_settings', 'wpdd_default_download_limit');
@@ -193,6 +200,18 @@ class WPDD_Settings {
'wpdd_paypal_settings',
array('name' => 'wpdd_paypal_secret')
);
add_settings_field(
'wpdd_paypal_payout_email',
__('PayPal Payout Account Email', 'wp-digital-download'),
array(__CLASS__, 'email_field'),
'wpdd_settings',
'wpdd_paypal_settings',
array(
'name' => 'wpdd_paypal_payout_email',
'description' => __('PayPal account email that will send payouts to creators', 'wp-digital-download')
)
);
}
private static function add_email_fields() {
@@ -231,6 +250,94 @@ class WPDD_Settings {
'description' => __('Email address shown in email headers', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_smtp_enabled',
__('Enable SMTP', 'wp-digital-download'),
array(__CLASS__, 'checkbox_field'),
'wpdd_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_enabled',
'label' => __('Use SMTP for sending emails instead of PHP mail()', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_smtp_host',
__('SMTP Host', 'wp-digital-download'),
array(__CLASS__, 'text_field'),
'wpdd_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_host',
'description' => __('SMTP server hostname (e.g., smtp.gmail.com)', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_smtp_port',
__('SMTP Port', 'wp-digital-download'),
array(__CLASS__, 'number_field'),
'wpdd_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_port',
'description' => __('SMTP server port number (common ports: 25, 465, 587)', 'wp-digital-download'),
'min' => 1,
'max' => 65535
)
);
add_settings_field(
'wpdd_smtp_encryption',
__('SMTP Encryption', 'wp-digital-download'),
array(__CLASS__, 'select_field'),
'wpdd_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_encryption',
'options' => array(
'' => __('None', 'wp-digital-download'),
'tls' => __('TLS', 'wp-digital-download'),
'ssl' => __('SSL', 'wp-digital-download')
),
'description' => __('Select encryption method - TLS is recommended for most providers', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_smtp_autodetect',
__('Auto-Detect Settings', 'wp-digital-download'),
array(__CLASS__, 'smtp_autodetect_field'),
'wpdd_settings',
'wpdd_email_settings',
array()
);
add_settings_field(
'wpdd_smtp_username',
__('SMTP Username', 'wp-digital-download'),
array(__CLASS__, 'text_field'),
'wpdd_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_username',
'description' => __('SMTP authentication username', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_smtp_password',
__('SMTP Password', 'wp-digital-download'),
array(__CLASS__, 'password_field'),
'wpdd_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_password',
'description' => __('SMTP authentication password', 'wp-digital-download')
)
);
}
private static function add_download_fields() {
@@ -305,59 +412,101 @@ class WPDD_Settings {
}
public static function render_settings_page() {
$active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general';
?>
<div class="wrap">
<h1><?php _e('WP Digital Download Settings', 'wp-digital-download'); ?></h1>
<div class="wpdd-settings-sidebar">
<div class="wpdd-settings-box">
<h3><?php _e('Quick Setup', 'wp-digital-download'); ?></h3>
<p><?php _e('To get started quickly:', 'wp-digital-download'); ?></p>
<ol>
<li><?php _e('Configure PayPal settings above', 'wp-digital-download'); ?></li>
<li><?php _e('Create your first product', 'wp-digital-download'); ?></li>
<li><?php _e('Add the shop shortcode [wpdd_shop] to a page', 'wp-digital-download'); ?></li>
<li><?php _e('Test with a free product first', 'wp-digital-download'); ?></li>
</ol>
<h2 class="nav-tab-wrapper">
<a href="<?php echo admin_url('edit.php?post_type=wpdd_product&page=wpdd-settings&tab=general'); ?>"
class="nav-tab <?php echo $active_tab == 'general' ? 'nav-tab-active' : ''; ?>"><?php _e('General', 'wp-digital-download'); ?></a>
<a href="<?php echo admin_url('edit.php?post_type=wpdd_product&page=wpdd-settings&tab=paypal'); ?>"
class="nav-tab <?php echo $active_tab == 'paypal' ? 'nav-tab-active' : ''; ?>"><?php _e('PayPal', 'wp-digital-download'); ?></a>
<a href="<?php echo admin_url('edit.php?post_type=wpdd_product&page=wpdd-settings&tab=email'); ?>"
class="nav-tab <?php echo $active_tab == 'email' ? 'nav-tab-active' : ''; ?>"><?php _e('Email', 'wp-digital-download'); ?></a>
<a href="<?php echo admin_url('edit.php?post_type=wpdd_product&page=wpdd-settings&tab=downloads'); ?>"
class="nav-tab <?php echo $active_tab == 'downloads' ? 'nav-tab-active' : ''; ?>"><?php _e('Downloads', 'wp-digital-download'); ?></a>
<a href="<?php echo admin_url('edit.php?post_type=wpdd_product&page=wpdd-settings&tab=watermark'); ?>"
class="nav-tab <?php echo $active_tab == 'watermark' ? 'nav-tab-active' : ''; ?>"><?php _e('Watermark', 'wp-digital-download'); ?></a>
</h2>
<div class="wpdd-settings-container">
<div class="wpdd-settings-content">
<form method="post" action="options.php" class="wpdd-settings-form">
<?php
settings_fields('wpdd_settings');
switch ($active_tab) {
case 'general':
self::render_general_tab();
break;
case 'paypal':
self::render_paypal_tab();
break;
case 'email':
self::render_email_tab();
break;
case 'downloads':
self::render_downloads_tab();
break;
case 'watermark':
self::render_watermark_tab();
break;
default:
self::render_general_tab();
}
submit_button();
?>
</form>
</div>
<div class="wpdd-settings-box">
<h3><?php _e('Available Shortcodes', 'wp-digital-download'); ?></h3>
<ul>
<li><code>[wpdd_shop]</code> - <?php _e('Display product storefront', 'wp-digital-download'); ?></li>
<li><code>[wpdd_customer_purchases]</code> - <?php _e('Customer purchase history', 'wp-digital-download'); ?></li>
<li><code>[wpdd_checkout]</code> - <?php _e('Checkout page', 'wp-digital-download'); ?></li>
<li><code>[wpdd_thank_you]</code> - <?php _e('Thank you page', 'wp-digital-download'); ?></li>
<li><code>[wpdd_product id="123"]</code> - <?php _e('Single product display', 'wp-digital-download'); ?></li>
</ul>
</div>
<div class="wpdd-settings-box">
<h3><?php _e('System Status', 'wp-digital-download'); ?></h3>
<?php self::system_status(); ?>
<div class="wpdd-settings-sidebar">
<?php if ($active_tab == 'general') : ?>
<div class="wpdd-settings-box">
<h3><?php _e('Quick Setup', 'wp-digital-download'); ?></h3>
<p><?php _e('To get started quickly:', 'wp-digital-download'); ?></p>
<ol>
<li><?php _e('Configure PayPal settings', 'wp-digital-download'); ?></li>
<li><?php _e('Create your first product', 'wp-digital-download'); ?></li>
<li><?php _e('Add the shop shortcode [wpdd_shop] to a page', 'wp-digital-download'); ?></li>
<li><?php _e('Test with a free product first', 'wp-digital-download'); ?></li>
</ol>
</div>
<div class="wpdd-settings-box">
<h3><?php _e('Available Shortcodes', 'wp-digital-download'); ?></h3>
<ul>
<li><code>[wpdd_shop]</code> - <?php _e('Display product storefront', 'wp-digital-download'); ?></li>
<li><code>[wpdd_customer_purchases]</code> - <?php _e('Customer purchase history', 'wp-digital-download'); ?></li>
<li><code>[wpdd_checkout]</code> - <?php _e('Checkout page', 'wp-digital-download'); ?></li>
<li><code>[wpdd_thank_you]</code> - <?php _e('Thank you page', 'wp-digital-download'); ?></li>
<li><code>[wpdd_product id="123"]</code> - <?php _e('Single product display', 'wp-digital-download'); ?></li>
</ul>
</div>
<?php endif; ?>
<div class="wpdd-settings-box">
<h3><?php _e('System Status', 'wp-digital-download'); ?></h3>
<?php self::system_status(); ?>
</div>
</div>
</div>
<form method="post" action="options.php" class="wpdd-settings-form">
<?php
settings_fields('wpdd_settings');
do_settings_sections('wpdd_settings');
submit_button();
?>
</form>
</div>
<style>
.wpdd-settings-sidebar {
float: right;
width: 300px;
margin-left: 20px;
position: relative;
z-index: 10;
.wpdd-settings-container {
display: flex;
gap: 20px;
margin-top: 20px;
}
.wpdd-settings-form {
overflow: hidden;
margin-right: 340px;
.wpdd-settings-content {
flex: 1;
min-width: 0;
}
.wpdd-settings-sidebar {
width: 300px;
flex-shrink: 0;
}
.wpdd-settings-box {
background: white;
@@ -377,15 +526,21 @@ class WPDD_Settings {
.wpdd-status-good { color: #46b450; }
.wpdd-status-warning { color: #ffb900; }
.wpdd-status-error { color: #dc3232; }
.wpdd-tab-content {
background: white;
border: 1px solid #ccd0d4;
padding: 20px;
margin-top: -1px;
}
@media (max-width: 1200px) {
.wpdd-settings-sidebar {
float: none;
width: 100%;
margin-left: 0;
margin-top: 30px;
.wpdd-settings-container {
flex-direction: column;
}
.wpdd-settings-form {
margin-right: 0;
.wpdd-settings-sidebar {
width: 100%;
order: 2;
}
}
</style>
@@ -584,9 +739,98 @@ class WPDD_Settings {
));
}
public static function smtp_autodetect_field($args) {
?>
<button type="button" id="wpdd-smtp-autodetect" class="button button-secondary">
<?php _e('Auto-Detect SMTP Settings', 'wp-digital-download'); ?>
</button>
<span id="wpdd-smtp-autodetect-status" style="margin-left: 10px;"></span>
<p class="description">
<?php _e('Automatically detect port and encryption settings based on the SMTP host.', 'wp-digital-download'); ?>
</p>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#wpdd-smtp-autodetect').on('click', function() {
var $button = $(this);
var $status = $('#wpdd-smtp-autodetect-status');
var host = $('#wpdd_smtp_host').val();
if (!host) {
$status.html('<span style="color: #dc3232;"><?php _e('Please enter SMTP host first.', 'wp-digital-download'); ?></span>');
return;
}
$button.prop('disabled', true).text('<?php _e('Detecting...', 'wp-digital-download'); ?>');
$status.html('<span style="color: #0073aa;"><?php _e('Testing connection...', 'wp-digital-download'); ?></span>');
// Test common SMTP configurations
var configs = [
{ port: 587, encryption: 'tls' },
{ port: 465, encryption: 'ssl' },
{ port: 25, encryption: 'tls' },
{ port: 25, encryption: '' }
];
// Detect common providers
var detectedConfig = null;
var hostname = host.toLowerCase();
if (hostname.includes('gmail.com') || hostname.includes('google.com')) {
detectedConfig = { port: 587, encryption: 'tls' };
} else if (hostname.includes('outlook.com') || hostname.includes('hotmail.com') || hostname.includes('live.com')) {
detectedConfig = { port: 587, encryption: 'tls' };
} else if (hostname.includes('yahoo.com')) {
detectedConfig = { port: 587, encryption: 'tls' };
} else if (hostname.includes('smtp.') && hostname.includes('.com')) {
detectedConfig = { port: 587, encryption: 'tls' };
} else {
// Default to most common configuration
detectedConfig = { port: 587, encryption: 'tls' };
}
// Apply detected settings
setTimeout(function() {
$('#wpdd_smtp_port').val(detectedConfig.port);
$('#wpdd_smtp_encryption').val(detectedConfig.encryption);
$button.prop('disabled', false).text('<?php _e('Auto-Detect SMTP Settings', 'wp-digital-download'); ?>');
$status.html('<span style="color: #46b450;"><?php _e('Settings detected and applied!', 'wp-digital-download'); ?></span>');
// Clear status after 5 seconds
setTimeout(function() {
$status.html('');
}, 5000);
}, 1000);
});
});
</script>
<?php
}
private static function system_status() {
$status = array();
// Check if WPDD_UPLOADS_DIR is defined to prevent fatal errors
if (!defined('WPDD_UPLOADS_DIR')) {
$status[] = array(
'label' => __('Plugin Constants', 'wp-digital-download'),
'value' => __('Not Loaded', 'wp-digital-download'),
'class' => 'wpdd-status-error'
);
echo '<ul>';
foreach ($status as $item) {
printf(
'<li>%s: <span class="%s">%s</span></li>',
esc_html($item['label']),
esc_attr($item['class']),
esc_html($item['value'])
);
}
echo '</ul>';
return;
}
$upload_dir = wp_upload_dir();
$protected_dir = trailingslashit($upload_dir['basedir']) . WPDD_UPLOADS_DIR;
@@ -659,6 +903,73 @@ class WPDD_Settings {
echo '</ul>';
}
public static function render_general_tab() {
?>
<div class="wpdd-tab-content">
<h2><?php _e('General Settings', 'wp-digital-download'); ?></h2>
<?php self::do_settings_sections_for_tab('wpdd_general_settings'); ?>
</div>
<?php
}
public static function render_paypal_tab() {
?>
<div class="wpdd-tab-content">
<h2><?php _e('PayPal Settings', 'wp-digital-download'); ?></h2>
<?php self::do_settings_sections_for_tab('wpdd_paypal_settings'); ?>
</div>
<?php
}
public static function render_email_tab() {
?>
<div class="wpdd-tab-content">
<h2><?php _e('Email Settings', 'wp-digital-download'); ?></h2>
<?php self::do_settings_sections_for_tab('wpdd_email_settings'); ?>
</div>
<?php
}
public static function render_downloads_tab() {
?>
<div class="wpdd-tab-content">
<h2><?php _e('Download Settings', 'wp-digital-download'); ?></h2>
<?php self::do_settings_sections_for_tab('wpdd_download_settings'); ?>
</div>
<?php
}
public static function render_watermark_tab() {
?>
<div class="wpdd-tab-content">
<h2><?php _e('Watermark Settings', 'wp-digital-download'); ?></h2>
<?php self::do_settings_sections_for_tab('wpdd_watermark_settings'); ?>
</div>
<?php
}
private static function do_settings_sections_for_tab($section_id) {
global $wp_settings_sections, $wp_settings_fields;
if (!isset($wp_settings_sections['wpdd_settings'][$section_id])) {
return;
}
$section = $wp_settings_sections['wpdd_settings'][$section_id];
if (isset($section['callback']) && $section['callback']) {
call_user_func($section['callback'], $section);
}
if (!isset($wp_settings_fields['wpdd_settings'][$section_id])) {
return;
}
echo '<table class="form-table" role="presentation">';
do_settings_fields('wpdd_settings', $section_id);
echo '</table>';
}
public static function sanitize_commission_rate($input) {
$value = floatval($input);
if ($value < 0) {

View File

@@ -0,0 +1,261 @@
<?php
if (!defined('ABSPATH')) {
exit;
}
// $order variable is passed from the calling function
?>
<div class="wrap">
<h1><?php _e('Order Details', 'wp-digital-download'); ?></h1>
<div class="order-details-container" style="max-width: 800px;">
<div class="order-summary" style="background: #fff; border: 1px solid #ccd0d4; padding: 20px; margin-bottom: 20px;">
<h2><?php _e('Order Summary', 'wp-digital-download'); ?></h2>
<table class="widefat fixed">
<tbody>
<tr>
<td style="width: 200px;"><strong><?php _e('Order Number', 'wp-digital-download'); ?></strong></td>
<td><?php echo esc_html($order->order_number); ?></td>
</tr>
<tr>
<td><strong><?php _e('Status', 'wp-digital-download'); ?></strong></td>
<td>
<span class="order-status status-<?php echo esc_attr($order->status); ?>" style="padding: 4px 8px; border-radius: 3px; font-size: 12px; <?php
echo $order->status === 'completed' ? 'background: #d1e7dd; color: #0f5132;' :
($order->status === 'pending' ? 'background: #fff3cd; color: #856404;' :
'background: #f8d7da; color: #721c24;');
?>">
<?php echo esc_html(ucfirst($order->status)); ?>
</span>
</td>
</tr>
<tr>
<td><strong><?php _e('Purchase Date', 'wp-digital-download'); ?></strong></td>
<td><?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($order->purchase_date))); ?></td>
</tr>
<tr>
<td><strong><?php _e('Payment Method', 'wp-digital-download'); ?></strong></td>
<td>
<?php
$payment_methods = array(
'paypal' => 'PayPal',
'free' => 'Free Download',
'manual' => 'Manual Payment'
);
echo esc_html($payment_methods[$order->payment_method] ?? ucfirst($order->payment_method));
?>
</td>
</tr>
<?php if (!empty($order->transaction_id)) : ?>
<tr>
<td><strong><?php _e('Transaction ID', 'wp-digital-download'); ?></strong></td>
<td><code><?php echo esc_html($order->transaction_id); ?></code></td>
</tr>
<?php endif; ?>
<tr>
<td><strong><?php _e('Amount', 'wp-digital-download'); ?></strong></td>
<td>
<strong style="font-size: 16px;">
<?php echo wpdd_format_price($order->amount, $order->currency); ?>
</strong>
</td>
</tr>
</tbody>
</table>
</div>
<div class="customer-details" style="background: #fff; border: 1px solid #ccd0d4; padding: 20px; margin-bottom: 20px;">
<h2><?php _e('Customer Information', 'wp-digital-download'); ?></h2>
<table class="widefat fixed">
<tbody>
<tr>
<td style="width: 200px;"><strong><?php _e('Customer Name', 'wp-digital-download'); ?></strong></td>
<td><?php echo esc_html($order->customer_name); ?></td>
</tr>
<tr>
<td><strong><?php _e('Email Address', 'wp-digital-download'); ?></strong></td>
<td>
<a href="mailto:<?php echo esc_attr($order->customer_email); ?>">
<?php echo esc_html($order->customer_email); ?>
</a>
</td>
</tr>
<?php if ($order->customer_id > 0) : ?>
<tr>
<td><strong><?php _e('WordPress User', 'wp-digital-download'); ?></strong></td>
<td>
<a href="<?php echo admin_url('user-edit.php?user_id=' . $order->customer_id); ?>">
<?php _e('View User Profile', 'wp-digital-download'); ?>
</a>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<div class="product-details" style="background: #fff; border: 1px solid #ccd0d4; padding: 20px; margin-bottom: 20px;">
<h2><?php _e('Product Information', 'wp-digital-download'); ?></h2>
<table class="widefat fixed">
<tbody>
<tr>
<td style="width: 200px;"><strong><?php _e('Product', 'wp-digital-download'); ?></strong></td>
<td>
<a href="<?php echo admin_url('post.php?post=' . $order->product_id . '&action=edit'); ?>">
<?php echo esc_html($order->product_name); ?>
</a>
</td>
</tr>
<tr>
<td><strong><?php _e('Product ID', 'wp-digital-download'); ?></strong></td>
<td><?php echo esc_html($order->product_id); ?></td>
</tr>
<?php if ($order->creator_id > 0) : ?>
<tr>
<td><strong><?php _e('Creator', 'wp-digital-download'); ?></strong></td>
<td>
<?php
$creator = get_userdata($order->creator_id);
if ($creator) : ?>
<a href="<?php echo admin_url('user-edit.php?user_id=' . $order->creator_id); ?>">
<?php echo esc_html($creator->display_name); ?>
</a>
<?php else : ?>
<?php _e('Creator not found', 'wp-digital-download'); ?>
<?php endif; ?>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php
// Get download links for this order
global $wpdb;
$download_links = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_download_links WHERE order_id = %d ORDER BY created_at DESC",
$order->id
));
?>
<?php if (!empty($download_links)) : ?>
<div class="download-links" style="background: #fff; border: 1px solid #ccd0d4; padding: 20px; margin-bottom: 20px;">
<h2><?php _e('Download Links', 'wp-digital-download'); ?></h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Download Token', 'wp-digital-download'); ?></th>
<th><?php _e('Downloads', 'wp-digital-download'); ?></th>
<th><?php _e('Expires', 'wp-digital-download'); ?></th>
<th><?php _e('Created', 'wp-digital-download'); ?></th>
<th><?php _e('Status', 'wp-digital-download'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($download_links as $link) :
$is_expired = strtotime($link->expires_at) < current_time('timestamp');
$is_used_up = $link->download_count >= $link->max_downloads;
?>
<tr>
<td>
<code style="font-size: 11px;"><?php echo esc_html(substr($link->token, 0, 20)) . '...'; ?></code>
</td>
<td>
<?php echo esc_html($link->download_count); ?> / <?php echo esc_html($link->max_downloads); ?>
</td>
<td>
<?php
if ($is_expired) : ?>
<span style="color: #d63384;"><?php _e('Expired', 'wp-digital-download'); ?></span>
<?php else : ?>
<?php echo esc_html(date_i18n(get_option('date_format'), strtotime($link->expires_at))); ?>
<?php endif; ?>
</td>
<td><?php echo esc_html(date_i18n(get_option('date_format'), strtotime($link->created_at))); ?></td>
<td>
<?php if ($is_expired) : ?>
<span style="color: #d63384;"><?php _e('Expired', 'wp-digital-download'); ?></span>
<?php elseif ($is_used_up) : ?>
<span style="color: #fd7e14;"><?php _e('Used Up', 'wp-digital-download'); ?></span>
<?php else : ?>
<span style="color: #198754;"><?php _e('Active', 'wp-digital-download'); ?></span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php
// Get download history for this order
$downloads = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_downloads WHERE order_id = %d ORDER BY download_date DESC LIMIT 20",
$order->id
));
?>
<?php if (!empty($downloads)) : ?>
<div class="download-history" style="background: #fff; border: 1px solid #ccd0d4; padding: 20px; margin-bottom: 20px;">
<h2><?php _e('Download History', 'wp-digital-download'); ?>
<small>(<?php printf(__('Last %d downloads', 'wp-digital-download'), count($downloads)); ?>)</small>
</h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Date', 'wp-digital-download'); ?></th>
<th><?php _e('IP Address', 'wp-digital-download'); ?></th>
<th><?php _e('User Agent', 'wp-digital-download'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($downloads as $download) : ?>
<tr>
<td><?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($download->download_date))); ?></td>
<td><code><?php echo esc_html($download->ip_address); ?></code></td>
<td style="font-size: 11px;">
<?php echo esc_html(wp_trim_words($download->user_agent, 10)); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<div class="order-actions" style="margin-top: 30px;">
<a href="<?php echo admin_url('edit.php?post_type=wpdd_product&page=wpdd-orders'); ?>" class="button">
<?php _e('← Back to Orders', 'wp-digital-download'); ?>
</a>
<?php if ($order->status === 'completed') : ?>
<a href="mailto:<?php echo esc_attr($order->customer_email); ?>?subject=<?php echo urlencode('Your Order: ' . $order->order_number); ?>" class="button button-secondary">
<?php _e('Email Customer', 'wp-digital-download'); ?>
</a>
<?php endif; ?>
</div>
</div>
</div>
<style>
.order-details-container table.widefat td {
padding: 12px;
border-bottom: 1px solid #f0f0f1;
}
.order-details-container table.widefat td:first-child {
background-color: #f6f7f7;
}
.order-status {
font-weight: bold;
text-transform: uppercase;
}
</style>