🔧 Bug Fixes: - Fixed download limits defaulting to 5 instead of 0 for unlimited downloads - Fixed software license filename sanitization (spaces→dashes, dots→underscores, proper .zip extension) - Software downloads now show as "Test-Plugin-v2-2-0.zip" instead of "Test Plugin v2.2.0" ✨ UI/UX Enhancements: - Redesigned license key display to span full table width with FontAwesome copy icons - Added responsive CSS styling for license key rows - Integrated FontAwesome CDN for modern copy icons 🏗️ Architecture Improvements: - Added comprehensive filename sanitization in both download handler and API paths - Enhanced software license product handling for local package files - Improved error handling and logging throughout download processes 📦 Infrastructure: - Added Gitea workflows for automated releases on push to main - Created comprehensive .gitignore excluding test files and browser automation - Updated documentation with all recent improvements and technical insights 🔍 Technical Details: - Software license products served from wp-content/uploads/wpdd-packages/ - Download flow: token → process_download_by_token() → process_download() → deliver_file() - Dual path coverage for both API downloads and regular file delivery - Version placeholder system for automated deployment 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			1307 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1307 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
if (!defined('ABSPATH')) {
 | 
						|
    exit;
 | 
						|
}
 | 
						|
 | 
						|
class WPDD_Admin {
 | 
						|
    
 | 
						|
    public static function init() {
 | 
						|
        add_action('admin_menu', array(__CLASS__, 'add_admin_menus'));
 | 
						|
        add_filter('manage_wpdd_product_posts_columns', array(__CLASS__, 'add_product_columns'));
 | 
						|
        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'));
 | 
						|
        add_action('wp_ajax_wpdd_sync_software_product', array(__CLASS__, 'handle_sync_software_product'));
 | 
						|
        add_action('wp_ajax_wpdd_regenerate_licenses', array(__CLASS__, 'handle_regenerate_licenses'));
 | 
						|
        
 | 
						|
        // Initialize admin payouts
 | 
						|
        if (class_exists('WPDD_Admin_Payouts')) {
 | 
						|
            WPDD_Admin_Payouts::init();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function add_admin_menus() {
 | 
						|
        // 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');
 | 
						|
        
 | 
						|
        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')
 | 
						|
            );
 | 
						|
        }
 | 
						|
        
 | 
						|
        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) {
 | 
						|
        $new_columns = array();
 | 
						|
        
 | 
						|
        foreach ($columns as $key => $value) {
 | 
						|
            $new_columns[$key] = $value;
 | 
						|
            
 | 
						|
            if ($key === 'title') {
 | 
						|
                $new_columns['wpdd_price'] = __('Price', 'wp-digital-download');
 | 
						|
                $new_columns['wpdd_sales'] = __('Sales', 'wp-digital-download');
 | 
						|
                $new_columns['wpdd_revenue'] = __('Revenue', 'wp-digital-download');
 | 
						|
                $new_columns['wpdd_files'] = __('Files', 'wp-digital-download');
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        return $new_columns;
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function render_product_columns($column, $post_id) {
 | 
						|
        switch ($column) {
 | 
						|
            case 'wpdd_price':
 | 
						|
                $price = get_post_meta($post_id, '_wpdd_price', true);
 | 
						|
                $sale_price = get_post_meta($post_id, '_wpdd_sale_price', true);
 | 
						|
                $is_free = get_post_meta($post_id, '_wpdd_is_free', true);
 | 
						|
                
 | 
						|
                if ($is_free) {
 | 
						|
                    echo '<span style="color: green;">' . __('Free', 'wp-digital-download') . '</span>';
 | 
						|
                } elseif ($sale_price && $sale_price < $price) {
 | 
						|
                    echo '<del>$' . number_format($price, 2) . '</del> ';
 | 
						|
                    echo '<strong>$' . number_format($sale_price, 2) . '</strong>';
 | 
						|
                } else {
 | 
						|
                    echo '$' . number_format($price, 2);
 | 
						|
                }
 | 
						|
                break;
 | 
						|
                
 | 
						|
            case 'wpdd_sales':
 | 
						|
                global $wpdb;
 | 
						|
                $sales = $wpdb->get_var($wpdb->prepare(
 | 
						|
                    "SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_orders 
 | 
						|
                     WHERE product_id = %d AND status = 'completed'",
 | 
						|
                    $post_id
 | 
						|
                ));
 | 
						|
                echo intval($sales);
 | 
						|
                break;
 | 
						|
                
 | 
						|
            case 'wpdd_revenue':
 | 
						|
                global $wpdb;
 | 
						|
                $revenue = $wpdb->get_var($wpdb->prepare(
 | 
						|
                    "SELECT SUM(amount) FROM {$wpdb->prefix}wpdd_orders 
 | 
						|
                     WHERE product_id = %d AND status = 'completed'",
 | 
						|
                    $post_id
 | 
						|
                ));
 | 
						|
                echo '$' . number_format($revenue ?: 0, 2);
 | 
						|
                break;
 | 
						|
                
 | 
						|
            case 'wpdd_files':
 | 
						|
                $files = get_post_meta($post_id, '_wpdd_files', true);
 | 
						|
                $count = is_array($files) ? count($files) : 0;
 | 
						|
                $product_type = get_post_meta($post_id, '_wpdd_product_type', true);
 | 
						|
                
 | 
						|
                echo $count;
 | 
						|
                
 | 
						|
                // Add sync button for software license products with no files
 | 
						|
                if ($product_type === 'software_license' && $count === 0) {
 | 
						|
                    $nonce = wp_create_nonce('wpdd_sync_product_' . $post_id);
 | 
						|
                    echo '<br><button type="button" class="button button-small wpdd-sync-product" data-product-id="' . $post_id . '" data-nonce="' . $nonce . '">';
 | 
						|
                    echo __('Sync Files', 'wp-digital-download');
 | 
						|
                    echo '</button>';
 | 
						|
                }
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function make_columns_sortable($columns) {
 | 
						|
        $columns['wpdd_price'] = 'wpdd_price';
 | 
						|
        $columns['wpdd_sales'] = 'wpdd_sales';
 | 
						|
        $columns['wpdd_revenue'] = 'wpdd_revenue';
 | 
						|
        return $columns;
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function sort_products_by_column($query) {
 | 
						|
        if (!is_admin() || !$query->is_main_query()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        
 | 
						|
        if ($query->get('post_type') !== 'wpdd_product') {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        
 | 
						|
        $orderby = $query->get('orderby');
 | 
						|
        
 | 
						|
        switch ($orderby) {
 | 
						|
            case 'wpdd_price':
 | 
						|
                $query->set('meta_key', '_wpdd_price');
 | 
						|
                $query->set('orderby', 'meta_value_num');
 | 
						|
                break;
 | 
						|
                
 | 
						|
            case 'wpdd_sales':
 | 
						|
                $query->set('meta_key', '_wpdd_sales_count');
 | 
						|
                $query->set('orderby', 'meta_value_num');
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function render_orders_page() {
 | 
						|
        global $wpdb;
 | 
						|
        
 | 
						|
        $page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
 | 
						|
        $per_page = 20;
 | 
						|
        $offset = ($page - 1) * $per_page;
 | 
						|
        
 | 
						|
        $where = array('1=1');
 | 
						|
        
 | 
						|
        if (isset($_GET['status']) && $_GET['status']) {
 | 
						|
            $where[] = $wpdb->prepare("o.status = %s", sanitize_text_field($_GET['status']));
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (isset($_GET['product_id']) && $_GET['product_id']) {
 | 
						|
            $where[] = $wpdb->prepare("o.product_id = %d", intval($_GET['product_id']));
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (isset($_GET['search']) && $_GET['search']) {
 | 
						|
            $search = '%' . $wpdb->esc_like($_GET['search']) . '%';
 | 
						|
            $where[] = $wpdb->prepare(
 | 
						|
                "(o.order_number LIKE %s OR o.customer_email LIKE %s OR o.customer_name LIKE %s)",
 | 
						|
                $search, $search, $search
 | 
						|
            );
 | 
						|
        }
 | 
						|
        
 | 
						|
        $where_clause = implode(' AND ', $where);
 | 
						|
        
 | 
						|
        $total = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_orders o WHERE {$where_clause}");
 | 
						|
        
 | 
						|
        $orders = $wpdb->get_results($wpdb->prepare(
 | 
						|
            "SELECT o.*, p.post_title as product_name 
 | 
						|
             FROM {$wpdb->prefix}wpdd_orders o
 | 
						|
             LEFT JOIN {$wpdb->posts} p ON o.product_id = p.ID
 | 
						|
             WHERE {$where_clause}
 | 
						|
             ORDER BY o.purchase_date DESC
 | 
						|
             LIMIT %d OFFSET %d",
 | 
						|
            $per_page,
 | 
						|
            $offset
 | 
						|
        ));
 | 
						|
        ?>
 | 
						|
        <div class="wrap">
 | 
						|
            <h1><?php _e('Orders', 'wp-digital-download'); ?></h1>
 | 
						|
            
 | 
						|
            <form method="get">
 | 
						|
                <input type="hidden" name="post_type" value="wpdd_product" />
 | 
						|
                <input type="hidden" name="page" value="wpdd-orders" />
 | 
						|
                
 | 
						|
                <div class="tablenav top">
 | 
						|
                    <div class="alignleft actions">
 | 
						|
                        <select name="status">
 | 
						|
                            <option value=""><?php _e('All Statuses', 'wp-digital-download'); ?></option>
 | 
						|
                            <option value="pending" <?php selected(isset($_GET['status']) && $_GET['status'] == 'pending'); ?>>
 | 
						|
                                <?php _e('Pending', 'wp-digital-download'); ?>
 | 
						|
                            </option>
 | 
						|
                            <option value="completed" <?php selected(isset($_GET['status']) && $_GET['status'] == 'completed'); ?>>
 | 
						|
                                <?php _e('Completed', 'wp-digital-download'); ?>
 | 
						|
                            </option>
 | 
						|
                            <option value="failed" <?php selected(isset($_GET['status']) && $_GET['status'] == 'failed'); ?>>
 | 
						|
                                <?php _e('Failed', 'wp-digital-download'); ?>
 | 
						|
                            </option>
 | 
						|
                        </select>
 | 
						|
                        
 | 
						|
                        <input type="text" name="search" placeholder="<?php _e('Search orders...', 'wp-digital-download'); ?>" 
 | 
						|
                               value="<?php echo isset($_GET['search']) ? esc_attr($_GET['search']) : ''; ?>" />
 | 
						|
                        
 | 
						|
                        <input type="submit" class="button" value="<?php _e('Filter', 'wp-digital-download'); ?>" />
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </form>
 | 
						|
            
 | 
						|
            <table class="wp-list-table widefat fixed striped">
 | 
						|
                <thead>
 | 
						|
                    <tr>
 | 
						|
                        <th><?php _e('Order', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Product', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Customer', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Amount', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Status', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Date', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Actions', 'wp-digital-download'); ?></th>
 | 
						|
                    </tr>
 | 
						|
                </thead>
 | 
						|
                <tbody>
 | 
						|
                    <?php if ($orders) : ?>
 | 
						|
                        <?php foreach ($orders as $order) : ?>
 | 
						|
                            <tr>
 | 
						|
                                <td><strong>#<?php echo esc_html($order->order_number); ?></strong></td>
 | 
						|
                                <td>
 | 
						|
                                    <a href="<?php echo get_edit_post_link($order->product_id); ?>">
 | 
						|
                                        <?php echo esc_html($order->product_name); ?>
 | 
						|
                                    </a>
 | 
						|
                                </td>
 | 
						|
                                <td>
 | 
						|
                                    <?php echo esc_html($order->customer_name); ?><br>
 | 
						|
                                    <small><?php echo esc_html($order->customer_email); ?></small>
 | 
						|
                                </td>
 | 
						|
                                <td>$<?php echo number_format($order->amount, 2); ?></td>
 | 
						|
                                <td>
 | 
						|
                                    <span class="wpdd-status wpdd-status-<?php echo esc_attr($order->status); ?>">
 | 
						|
                                        <?php echo ucfirst($order->status); ?>
 | 
						|
                                    </span>
 | 
						|
                                </td>
 | 
						|
                                <td><?php echo date_i18n(get_option('date_format'), strtotime($order->purchase_date)); ?></td>
 | 
						|
                                <td>
 | 
						|
                                    <a href="<?php echo wp_nonce_url(
 | 
						|
                                        add_query_arg(array(
 | 
						|
                                            'action' => 'wpdd_view_order',
 | 
						|
                                            'order_id' => $order->id
 | 
						|
                                        )),
 | 
						|
                                        'wpdd_view_order_' . $order->id
 | 
						|
                                    ); ?>" class="button button-small">
 | 
						|
                                        <?php _e('View', 'wp-digital-download'); ?>
 | 
						|
                                    </a>
 | 
						|
                                </td>
 | 
						|
                            </tr>
 | 
						|
                        <?php endforeach; ?>
 | 
						|
                    <?php else : ?>
 | 
						|
                        <tr>
 | 
						|
                            <td colspan="7"><?php _e('No orders found.', 'wp-digital-download'); ?></td>
 | 
						|
                        </tr>
 | 
						|
                    <?php endif; ?>
 | 
						|
                </tbody>
 | 
						|
            </table>
 | 
						|
            
 | 
						|
            <?php
 | 
						|
            $total_pages = ceil($total / $per_page);
 | 
						|
            if ($total_pages > 1) {
 | 
						|
                echo '<div class="tablenav bottom"><div class="tablenav-pages">';
 | 
						|
                echo paginate_links(array(
 | 
						|
                    'base' => add_query_arg('paged', '%#%'),
 | 
						|
                    'format' => '',
 | 
						|
                    'current' => $page,
 | 
						|
                    'total' => $total_pages
 | 
						|
                ));
 | 
						|
                echo '</div></div>';
 | 
						|
            }
 | 
						|
            ?>
 | 
						|
        </div>
 | 
						|
        
 | 
						|
        <style>
 | 
						|
            .wpdd-status {
 | 
						|
                padding: 3px 8px;
 | 
						|
                border-radius: 3px;
 | 
						|
                font-size: 12px;
 | 
						|
                font-weight: 600;
 | 
						|
            }
 | 
						|
            .wpdd-status-completed { background: #d4edda; color: #155724; }
 | 
						|
            .wpdd-status-pending { background: #fff3cd; color: #856404; }
 | 
						|
            .wpdd-status-failed { background: #f8d7da; color: #721c24; }
 | 
						|
        </style>
 | 
						|
        <?php
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function render_reports_page() {
 | 
						|
        global $wpdb;
 | 
						|
        
 | 
						|
        $date_range = isset($_GET['range']) ? sanitize_text_field($_GET['range']) : '30days';
 | 
						|
        
 | 
						|
        switch ($date_range) {
 | 
						|
            case '7days':
 | 
						|
                $start_date = date('Y-m-d', strtotime('-7 days'));
 | 
						|
                break;
 | 
						|
            case '30days':
 | 
						|
                $start_date = date('Y-m-d', strtotime('-30 days'));
 | 
						|
                break;
 | 
						|
            case '3months':
 | 
						|
                $start_date = date('Y-m-d', strtotime('-3 months'));
 | 
						|
                break;
 | 
						|
            case 'year':
 | 
						|
                $start_date = date('Y-m-d', strtotime('-1 year'));
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                $start_date = date('Y-m-d', strtotime('-30 days'));
 | 
						|
        }
 | 
						|
        
 | 
						|
        $stats = $wpdb->get_row($wpdb->prepare(
 | 
						|
            "SELECT 
 | 
						|
                COUNT(*) as total_orders,
 | 
						|
                SUM(amount) as total_revenue,
 | 
						|
                COUNT(DISTINCT customer_id) as unique_customers,
 | 
						|
                COUNT(DISTINCT product_id) as products_sold
 | 
						|
             FROM {$wpdb->prefix}wpdd_orders
 | 
						|
             WHERE status = 'completed' 
 | 
						|
             AND purchase_date >= %s",
 | 
						|
            $start_date
 | 
						|
        ));
 | 
						|
        
 | 
						|
        $top_products = $wpdb->get_results($wpdb->prepare(
 | 
						|
            "SELECT 
 | 
						|
                p.ID, 
 | 
						|
                p.post_title,
 | 
						|
                COUNT(o.id) as sales,
 | 
						|
                SUM(o.amount) as revenue
 | 
						|
             FROM {$wpdb->prefix}wpdd_orders o
 | 
						|
             INNER JOIN {$wpdb->posts} p ON o.product_id = p.ID
 | 
						|
             WHERE o.status = 'completed' 
 | 
						|
             AND o.purchase_date >= %s
 | 
						|
             GROUP BY p.ID
 | 
						|
             ORDER BY revenue DESC
 | 
						|
             LIMIT 10",
 | 
						|
            $start_date
 | 
						|
        ));
 | 
						|
        
 | 
						|
        $top_creators = $wpdb->get_results($wpdb->prepare(
 | 
						|
            "SELECT 
 | 
						|
                u.ID,
 | 
						|
                u.display_name,
 | 
						|
                COUNT(o.id) as sales,
 | 
						|
                SUM(o.amount) as revenue
 | 
						|
             FROM {$wpdb->prefix}wpdd_orders o
 | 
						|
             INNER JOIN {$wpdb->users} u ON o.creator_id = u.ID
 | 
						|
             WHERE o.status = 'completed' 
 | 
						|
             AND o.purchase_date >= %s
 | 
						|
             GROUP BY u.ID
 | 
						|
             ORDER BY revenue DESC
 | 
						|
             LIMIT 10",
 | 
						|
            $start_date
 | 
						|
        ));
 | 
						|
        ?>
 | 
						|
        <div class="wrap">
 | 
						|
            <h1><?php _e('Reports', 'wp-digital-download'); ?></h1>
 | 
						|
            
 | 
						|
            <div class="wpdd-date-filter">
 | 
						|
                <form method="get">
 | 
						|
                    <input type="hidden" name="post_type" value="wpdd_product" />
 | 
						|
                    <input type="hidden" name="page" value="wpdd-reports" />
 | 
						|
                    
 | 
						|
                    <select name="range" onchange="this.form.submit()">
 | 
						|
                        <option value="7days" <?php selected($date_range, '7days'); ?>>
 | 
						|
                            <?php _e('Last 7 Days', 'wp-digital-download'); ?>
 | 
						|
                        </option>
 | 
						|
                        <option value="30days" <?php selected($date_range, '30days'); ?>>
 | 
						|
                            <?php _e('Last 30 Days', 'wp-digital-download'); ?>
 | 
						|
                        </option>
 | 
						|
                        <option value="3months" <?php selected($date_range, '3months'); ?>>
 | 
						|
                            <?php _e('Last 3 Months', 'wp-digital-download'); ?>
 | 
						|
                        </option>
 | 
						|
                        <option value="year" <?php selected($date_range, 'year'); ?>>
 | 
						|
                            <?php _e('Last Year', 'wp-digital-download'); ?>
 | 
						|
                        </option>
 | 
						|
                    </select>
 | 
						|
                </form>
 | 
						|
            </div>
 | 
						|
            
 | 
						|
            <div class="wpdd-stats-grid">
 | 
						|
                <div class="wpdd-stat-box">
 | 
						|
                    <h3><?php _e('Total Revenue', 'wp-digital-download'); ?></h3>
 | 
						|
                    <p class="wpdd-stat-value">$<?php echo number_format($stats->total_revenue ?: 0, 2); ?></p>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <div class="wpdd-stat-box">
 | 
						|
                    <h3><?php _e('Total Orders', 'wp-digital-download'); ?></h3>
 | 
						|
                    <p class="wpdd-stat-value"><?php echo intval($stats->total_orders); ?></p>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <div class="wpdd-stat-box">
 | 
						|
                    <h3><?php _e('Unique Customers', 'wp-digital-download'); ?></h3>
 | 
						|
                    <p class="wpdd-stat-value"><?php echo intval($stats->unique_customers); ?></p>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <div class="wpdd-stat-box">
 | 
						|
                    <h3><?php _e('Products Sold', 'wp-digital-download'); ?></h3>
 | 
						|
                    <p class="wpdd-stat-value"><?php echo intval($stats->products_sold); ?></p>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            
 | 
						|
            <div class="wpdd-reports-tables">
 | 
						|
                <div class="wpdd-report-section">
 | 
						|
                    <h2><?php _e('Top Products', 'wp-digital-download'); ?></h2>
 | 
						|
                    <table class="wp-list-table widefat fixed striped">
 | 
						|
                        <thead>
 | 
						|
                            <tr>
 | 
						|
                                <th><?php _e('Product', 'wp-digital-download'); ?></th>
 | 
						|
                                <th><?php _e('Sales', 'wp-digital-download'); ?></th>
 | 
						|
                                <th><?php _e('Revenue', 'wp-digital-download'); ?></th>
 | 
						|
                            </tr>
 | 
						|
                        </thead>
 | 
						|
                        <tbody>
 | 
						|
                            <?php if ($top_products) : ?>
 | 
						|
                                <?php foreach ($top_products as $product) : ?>
 | 
						|
                                    <tr>
 | 
						|
                                        <td>
 | 
						|
                                            <a href="<?php echo get_edit_post_link($product->ID); ?>">
 | 
						|
                                                <?php echo esc_html($product->post_title); ?>
 | 
						|
                                            </a>
 | 
						|
                                        </td>
 | 
						|
                                        <td><?php echo intval($product->sales); ?></td>
 | 
						|
                                        <td>$<?php echo number_format($product->revenue, 2); ?></td>
 | 
						|
                                    </tr>
 | 
						|
                                <?php endforeach; ?>
 | 
						|
                            <?php else : ?>
 | 
						|
                                <tr>
 | 
						|
                                    <td colspan="3"><?php _e('No data available.', 'wp-digital-download'); ?></td>
 | 
						|
                                </tr>
 | 
						|
                            <?php endif; ?>
 | 
						|
                        </tbody>
 | 
						|
                    </table>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <div class="wpdd-report-section">
 | 
						|
                    <h2><?php _e('Top Creators', 'wp-digital-download'); ?></h2>
 | 
						|
                    <table class="wp-list-table widefat fixed striped">
 | 
						|
                        <thead>
 | 
						|
                            <tr>
 | 
						|
                                <th><?php _e('Creator', 'wp-digital-download'); ?></th>
 | 
						|
                                <th><?php _e('Sales', 'wp-digital-download'); ?></th>
 | 
						|
                                <th><?php _e('Revenue', 'wp-digital-download'); ?></th>
 | 
						|
                            </tr>
 | 
						|
                        </thead>
 | 
						|
                        <tbody>
 | 
						|
                            <?php if ($top_creators) : ?>
 | 
						|
                                <?php foreach ($top_creators as $creator) : ?>
 | 
						|
                                    <tr>
 | 
						|
                                        <td>
 | 
						|
                                            <a href="<?php echo get_edit_user_link($creator->ID); ?>">
 | 
						|
                                                <?php echo esc_html($creator->display_name); ?>
 | 
						|
                                            </a>
 | 
						|
                                        </td>
 | 
						|
                                        <td><?php echo intval($creator->sales); ?></td>
 | 
						|
                                        <td>$<?php echo number_format($creator->revenue, 2); ?></td>
 | 
						|
                                    </tr>
 | 
						|
                                <?php endforeach; ?>
 | 
						|
                            <?php else : ?>
 | 
						|
                                <tr>
 | 
						|
                                    <td colspan="3"><?php _e('No data available.', 'wp-digital-download'); ?></td>
 | 
						|
                                </tr>
 | 
						|
                            <?php endif; ?>
 | 
						|
                        </tbody>
 | 
						|
                    </table>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
        
 | 
						|
        <style>
 | 
						|
            .wpdd-date-filter {
 | 
						|
                margin: 20px 0;
 | 
						|
            }
 | 
						|
            .wpdd-stats-grid {
 | 
						|
                display: grid;
 | 
						|
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
 | 
						|
                gap: 20px;
 | 
						|
                margin: 30px 0;
 | 
						|
            }
 | 
						|
            .wpdd-stat-box {
 | 
						|
                background: white;
 | 
						|
                padding: 20px;
 | 
						|
                border: 1px solid #ccd0d4;
 | 
						|
                border-radius: 4px;
 | 
						|
            }
 | 
						|
            .wpdd-stat-box h3 {
 | 
						|
                margin: 0 0 10px 0;
 | 
						|
                color: #23282d;
 | 
						|
            }
 | 
						|
            .wpdd-stat-value {
 | 
						|
                font-size: 32px;
 | 
						|
                font-weight: 600;
 | 
						|
                color: #2271b1;
 | 
						|
                margin: 0;
 | 
						|
            }
 | 
						|
            .wpdd-reports-tables {
 | 
						|
                display: grid;
 | 
						|
                grid-template-columns: 1fr 1fr;
 | 
						|
                gap: 30px;
 | 
						|
                margin-top: 30px;
 | 
						|
            }
 | 
						|
            .wpdd-report-section h2 {
 | 
						|
                margin-bottom: 15px;
 | 
						|
            }
 | 
						|
            @media (max-width: 1200px) {
 | 
						|
                .wpdd-reports-tables {
 | 
						|
                    grid-template-columns: 1fr;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        </style>
 | 
						|
        <?php
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function render_customers_page() {
 | 
						|
        global $wpdb;
 | 
						|
        
 | 
						|
        // Get all users who have made purchases, regardless of their role
 | 
						|
        $customers = $wpdb->get_results(
 | 
						|
            "SELECT 
 | 
						|
                u.ID,
 | 
						|
                u.user_email,
 | 
						|
                u.display_name,
 | 
						|
                u.user_registered,
 | 
						|
                COUNT(o.id) as total_orders,
 | 
						|
                SUM(o.amount) as total_spent,
 | 
						|
                MAX(o.purchase_date) as last_order_date
 | 
						|
             FROM {$wpdb->users} u
 | 
						|
             INNER JOIN {$wpdb->prefix}wpdd_orders o ON u.ID = o.customer_id AND o.status = 'completed'
 | 
						|
             GROUP BY u.ID
 | 
						|
             ORDER BY total_spent DESC"
 | 
						|
        );
 | 
						|
        ?>
 | 
						|
        <div class="wrap">
 | 
						|
            <h1><?php _e('Customers', 'wp-digital-download'); ?></h1>
 | 
						|
            
 | 
						|
            <table class="wp-list-table widefat fixed striped">
 | 
						|
                <thead>
 | 
						|
                    <tr>
 | 
						|
                        <th><?php _e('Customer', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Email', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Orders', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Total Spent', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Registered', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Last Order', 'wp-digital-download'); ?></th>
 | 
						|
                        <th><?php _e('Actions', 'wp-digital-download'); ?></th>
 | 
						|
                    </tr>
 | 
						|
                </thead>
 | 
						|
                <tbody>
 | 
						|
                    <?php if ($customers) : ?>
 | 
						|
                        <?php foreach ($customers as $customer) : ?>
 | 
						|
                            <tr>
 | 
						|
                                <td>
 | 
						|
                                    <strong><?php echo esc_html($customer->display_name); ?></strong>
 | 
						|
                                </td>
 | 
						|
                                <td><?php echo esc_html($customer->user_email); ?></td>
 | 
						|
                                <td><?php echo intval($customer->total_orders); ?></td>
 | 
						|
                                <td>$<?php echo number_format($customer->total_spent ?: 0, 2); ?></td>
 | 
						|
                                <td><?php echo date_i18n(get_option('date_format'), strtotime($customer->user_registered)); ?></td>
 | 
						|
                                <td>
 | 
						|
                                    <?php 
 | 
						|
                                    echo $customer->last_order_date 
 | 
						|
                                        ? date_i18n(get_option('date_format'), strtotime($customer->last_order_date))
 | 
						|
                                        : '-';
 | 
						|
                                    ?>
 | 
						|
                                </td>
 | 
						|
                                <td>
 | 
						|
                                    <a href="<?php echo get_edit_user_link($customer->ID); ?>" class="button button-small">
 | 
						|
                                        <?php _e('Edit', 'wp-digital-download'); ?>
 | 
						|
                                    </a>
 | 
						|
                                    <a href="<?php echo add_query_arg(array(
 | 
						|
                                        'post_type' => 'wpdd_product',
 | 
						|
                                        'page' => 'wpdd-orders',
 | 
						|
                                        'customer_id' => $customer->ID
 | 
						|
                                    ), admin_url('edit.php')); ?>" class="button button-small">
 | 
						|
                                        <?php _e('View Orders', 'wp-digital-download'); ?>
 | 
						|
                                    </a>
 | 
						|
                                </td>
 | 
						|
                            </tr>
 | 
						|
                        <?php endforeach; ?>
 | 
						|
                    <?php else : ?>
 | 
						|
                        <tr>
 | 
						|
                            <td colspan="7"><?php _e('No customers found.', 'wp-digital-download'); ?></td>
 | 
						|
                        </tr>
 | 
						|
                    <?php endif; ?>
 | 
						|
                </tbody>
 | 
						|
            </table>
 | 
						|
        </div>
 | 
						|
        <?php
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function handle_admin_actions() {
 | 
						|
        if (isset($_GET['action']) && $_GET['action'] === 'wpdd_view_order') {
 | 
						|
            if (!isset($_GET['order_id']) || !wp_verify_nonce($_GET['_wpnonce'] ?? '', 'wpdd_view_order_' . $_GET['order_id'])) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            
 | 
						|
            self::view_order_details(intval($_GET['order_id']));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    private static function view_order_details($order_id) {
 | 
						|
        global $wpdb;
 | 
						|
        
 | 
						|
        $order = $wpdb->get_row($wpdb->prepare(
 | 
						|
            "SELECT o.*, p.post_title as product_name 
 | 
						|
             FROM {$wpdb->prefix}wpdd_orders o
 | 
						|
             LEFT JOIN {$wpdb->posts} p ON o.product_id = p.ID
 | 
						|
             WHERE o.id = %d",
 | 
						|
            $order_id
 | 
						|
        ));
 | 
						|
        
 | 
						|
        if (!$order) {
 | 
						|
            wp_die(__('Order not found.', 'wp-digital-download'));
 | 
						|
        }
 | 
						|
        
 | 
						|
        include WPDD_PLUGIN_PATH . 'admin/views/order-details.php';
 | 
						|
        exit;
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function render_shortcodes_page() {
 | 
						|
        ?>
 | 
						|
        <div class="wrap">
 | 
						|
            <h1><?php _e('Available Shortcodes', 'wp-digital-download'); ?></h1>
 | 
						|
            
 | 
						|
            <div class="wpdd-shortcodes-intro">
 | 
						|
                <p><?php _e('Use these shortcodes to display digital download content on your pages and posts. Simply copy and paste the shortcode into any page or post editor.', 'wp-digital-download'); ?></p>
 | 
						|
            </div>
 | 
						|
            
 | 
						|
            <div class="wpdd-shortcodes-grid">
 | 
						|
                
 | 
						|
                <!-- Shop Shortcode -->
 | 
						|
                <div class="wpdd-shortcode-card">
 | 
						|
                    <h3><?php _e('Shop Page', 'wp-digital-download'); ?></h3>
 | 
						|
                    <div class="wpdd-shortcode-example">
 | 
						|
                        <code>[wpdd_shop]</code>
 | 
						|
                    </div>
 | 
						|
                    <p><?php _e('Displays a grid of all available products with filtering and pagination.', 'wp-digital-download'); ?></p>
 | 
						|
                    
 | 
						|
                    <h4><?php _e('Available Parameters:', 'wp-digital-download'); ?></h4>
 | 
						|
                    <ul class="wpdd-params-list">
 | 
						|
                        <li><strong>posts_per_page</strong> - Number of products per page (default: 12)</li>
 | 
						|
                        <li><strong>columns</strong> - Grid columns (default: 3, options: 1-6)</li>
 | 
						|
                        <li><strong>orderby</strong> - Sort order (date, title, price, menu_order)</li>
 | 
						|
                        <li><strong>order</strong> - ASC or DESC (default: DESC)</li>
 | 
						|
                        <li><strong>category</strong> - Show only specific categories (comma separated slugs)</li>
 | 
						|
                        <li><strong>show_filters</strong> - Show search/filter form (yes/no, default: yes)</li>
 | 
						|
                    </ul>
 | 
						|
                    
 | 
						|
                    <h4><?php _e('Examples:', 'wp-digital-download'); ?></h4>
 | 
						|
                    <div class="wpdd-shortcode-examples">
 | 
						|
                        <code>[wpdd_shop posts_per_page="6" columns="2"]</code><br>
 | 
						|
                        <code>[wpdd_shop category="music,videos" show_filters="no"]</code><br>
 | 
						|
                        <code>[wpdd_shop orderby="price" order="ASC" columns="4"]</code>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <!-- Checkout Shortcode -->
 | 
						|
                <div class="wpdd-shortcode-card">
 | 
						|
                    <h3><?php _e('Checkout Page', 'wp-digital-download'); ?></h3>
 | 
						|
                    <div class="wpdd-shortcode-example">
 | 
						|
                        <code>[wpdd_checkout]</code>
 | 
						|
                    </div>
 | 
						|
                    <p><?php _e('Displays the checkout form for purchasing products. Typically used on a dedicated checkout page.', 'wp-digital-download'); ?></p>
 | 
						|
                    
 | 
						|
                    <p class="wpdd-note"><?php _e('Note: This shortcode automatically detects the product to purchase from the URL parameter.', 'wp-digital-download'); ?></p>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <!-- Customer Purchases Shortcode -->
 | 
						|
                <div class="wpdd-shortcode-card">
 | 
						|
                    <h3><?php _e('Customer Purchases', 'wp-digital-download'); ?></h3>
 | 
						|
                    <div class="wpdd-shortcode-example">
 | 
						|
                        <code>[wpdd_customer_purchases]</code>
 | 
						|
                    </div>
 | 
						|
                    <p><?php _e('Shows a table of customer\'s purchase history with download links. Requires user to be logged in.', 'wp-digital-download'); ?></p>
 | 
						|
                    
 | 
						|
                    <p class="wpdd-note"><?php _e('Note: This page also supports guest access via email links sent after purchase.', 'wp-digital-download'); ?></p>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <!-- Thank You Shortcode -->
 | 
						|
                <div class="wpdd-shortcode-card">
 | 
						|
                    <h3><?php _e('Thank You Page', 'wp-digital-download'); ?></h3>
 | 
						|
                    <div class="wpdd-shortcode-example">
 | 
						|
                        <code>[wpdd_thank_you]</code>
 | 
						|
                    </div>
 | 
						|
                    <p><?php _e('Displays order confirmation and download links after successful purchase. Used on the thank you page.', 'wp-digital-download'); ?></p>
 | 
						|
                    
 | 
						|
                    <p class="wpdd-note"><?php _e('Note: This shortcode requires an order_id parameter in the URL.', 'wp-digital-download'); ?></p>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <!-- Single Product Shortcode -->
 | 
						|
                <div class="wpdd-shortcode-card">
 | 
						|
                    <h3><?php _e('Single Product', 'wp-digital-download'); ?></h3>
 | 
						|
                    <div class="wpdd-shortcode-example">
 | 
						|
                        <code>[wpdd_single_product id="123"]</code>
 | 
						|
                    </div>
 | 
						|
                    <p><?php _e('Display a single product card anywhere on your site.', 'wp-digital-download'); ?></p>
 | 
						|
                    
 | 
						|
                    <h4><?php _e('Parameters:', 'wp-digital-download'); ?></h4>
 | 
						|
                    <ul class="wpdd-params-list">
 | 
						|
                        <li><strong>id</strong> - Product ID (required)</li>
 | 
						|
                    </ul>
 | 
						|
                    
 | 
						|
                    <h4><?php _e('Example:', 'wp-digital-download'); ?></h4>
 | 
						|
                    <div class="wpdd-shortcode-examples">
 | 
						|
                        <code>[wpdd_single_product id="456"]</code>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
                <!-- Buy Button Shortcode -->
 | 
						|
                <div class="wpdd-shortcode-card">
 | 
						|
                    <h3><?php _e('Buy Button', 'wp-digital-download'); ?></h3>
 | 
						|
                    <div class="wpdd-shortcode-example">
 | 
						|
                        <code>[wpdd_buy_button id="123"]</code>
 | 
						|
                    </div>
 | 
						|
                    <p><?php _e('Display just a buy button for a specific product.', 'wp-digital-download'); ?></p>
 | 
						|
                    
 | 
						|
                    <h4><?php _e('Parameters:', 'wp-digital-download'); ?></h4>
 | 
						|
                    <ul class="wpdd-params-list">
 | 
						|
                        <li><strong>id</strong> - Product ID (default: current post ID)</li>
 | 
						|
                        <li><strong>text</strong> - Button text (default: "Buy Now")</li>
 | 
						|
                        <li><strong>class</strong> - CSS class for styling</li>
 | 
						|
                    </ul>
 | 
						|
                    
 | 
						|
                    <h4><?php _e('Examples:', 'wp-digital-download'); ?></h4>
 | 
						|
                    <div class="wpdd-shortcode-examples">
 | 
						|
                        <code>[wpdd_buy_button id="789" text="Purchase Now"]</code><br>
 | 
						|
                        <code>[wpdd_buy_button text="Get This Product" class="my-custom-button"]</code>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
                
 | 
						|
            </div>
 | 
						|
            
 | 
						|
            <!-- Page Setup Section -->
 | 
						|
            <div class="wpdd-page-setup">
 | 
						|
                <h2><?php _e('Required Pages Setup', 'wp-digital-download'); ?></h2>
 | 
						|
                <p><?php _e('For the plugin to work correctly, you need these pages with their respective shortcodes:', 'wp-digital-download'); ?></p>
 | 
						|
                
 | 
						|
                <table class="wp-list-table widefat fixed striped">
 | 
						|
                    <thead>
 | 
						|
                        <tr>
 | 
						|
                            <th><?php _e('Page Name', 'wp-digital-download'); ?></th>
 | 
						|
                            <th><?php _e('Shortcode', 'wp-digital-download'); ?></th>
 | 
						|
                            <th><?php _e('Purpose', 'wp-digital-download'); ?></th>
 | 
						|
                            <th><?php _e('Status', 'wp-digital-download'); ?></th>
 | 
						|
                        </tr>
 | 
						|
                    </thead>
 | 
						|
                    <tbody>
 | 
						|
                        <tr>
 | 
						|
                            <td><strong><?php _e('Shop', 'wp-digital-download'); ?></strong></td>
 | 
						|
                            <td><code>[wpdd_shop]</code></td>
 | 
						|
                            <td><?php _e('Main product listing page', 'wp-digital-download'); ?></td>
 | 
						|
                            <td>
 | 
						|
                                <?php 
 | 
						|
                                $shop_page_id = get_option('wpdd_shop_page_id');
 | 
						|
                                if ($shop_page_id && get_post($shop_page_id)) {
 | 
						|
                                    echo '<span style="color: green;">✓ ' . __('Created', 'wp-digital-download') . '</span>';
 | 
						|
                                    echo ' (<a href="' . get_edit_post_link($shop_page_id) . '">' . __('Edit', 'wp-digital-download') . '</a>)';
 | 
						|
                                } else {
 | 
						|
                                    echo '<span style="color: red;">✗ ' . __('Missing', 'wp-digital-download') . '</span>';
 | 
						|
                                }
 | 
						|
                                ?>
 | 
						|
                            </td>
 | 
						|
                        </tr>
 | 
						|
                        <tr>
 | 
						|
                            <td><strong><?php _e('Checkout', 'wp-digital-download'); ?></strong></td>
 | 
						|
                            <td><code>[wpdd_checkout]</code></td>
 | 
						|
                            <td><?php _e('Purchase processing page', 'wp-digital-download'); ?></td>
 | 
						|
                            <td>
 | 
						|
                                <?php 
 | 
						|
                                $checkout_page_id = get_option('wpdd_checkout_page_id');
 | 
						|
                                if ($checkout_page_id && get_post($checkout_page_id)) {
 | 
						|
                                    echo '<span style="color: green;">✓ ' . __('Created', 'wp-digital-download') . '</span>';
 | 
						|
                                    echo ' (<a href="' . get_edit_post_link($checkout_page_id) . '">' . __('Edit', 'wp-digital-download') . '</a>)';
 | 
						|
                                } else {
 | 
						|
                                    echo '<span style="color: red;">✗ ' . __('Missing', 'wp-digital-download') . '</span>';
 | 
						|
                                }
 | 
						|
                                ?>
 | 
						|
                            </td>
 | 
						|
                        </tr>
 | 
						|
                        <tr>
 | 
						|
                            <td><strong><?php _e('My Purchases', 'wp-digital-download'); ?></strong></td>
 | 
						|
                            <td><code>[wpdd_customer_purchases]</code></td>
 | 
						|
                            <td><?php _e('Customer purchase history', 'wp-digital-download'); ?></td>
 | 
						|
                            <td>
 | 
						|
                                <?php 
 | 
						|
                                $purchases_page_id = get_option('wpdd_purchases_page_id');
 | 
						|
                                if ($purchases_page_id && get_post($purchases_page_id)) {
 | 
						|
                                    echo '<span style="color: green;">✓ ' . __('Created', 'wp-digital-download') . '</span>';
 | 
						|
                                    echo ' (<a href="' . get_edit_post_link($purchases_page_id) . '">' . __('Edit', 'wp-digital-download') . '</a>)';
 | 
						|
                                } else {
 | 
						|
                                    echo '<span style="color: red;">✗ ' . __('Missing', 'wp-digital-download') . '</span>';
 | 
						|
                                }
 | 
						|
                                ?>
 | 
						|
                            </td>
 | 
						|
                        </tr>
 | 
						|
                        <tr>
 | 
						|
                            <td><strong><?php _e('Thank You', 'wp-digital-download'); ?></strong></td>
 | 
						|
                            <td><code>[wpdd_thank_you]</code></td>
 | 
						|
                            <td><?php _e('Post-purchase confirmation', 'wp-digital-download'); ?></td>
 | 
						|
                            <td>
 | 
						|
                                <?php 
 | 
						|
                                $thank_you_page_id = get_option('wpdd_thank_you_page_id');
 | 
						|
                                if ($thank_you_page_id && get_post($thank_you_page_id)) {
 | 
						|
                                    echo '<span style="color: green;">✓ ' . __('Created', 'wp-digital-download') . '</span>';
 | 
						|
                                    echo ' (<a href="' . get_edit_post_link($thank_you_page_id) . '">' . __('Edit', 'wp-digital-download') . '</a>)';
 | 
						|
                                } else {
 | 
						|
                                    echo '<span style="color: red;">✗ ' . __('Missing', 'wp-digital-download') . '</span>';
 | 
						|
                                }
 | 
						|
                                ?>
 | 
						|
                            </td>
 | 
						|
                        </tr>
 | 
						|
                    </tbody>
 | 
						|
                </table>
 | 
						|
            </div>
 | 
						|
            
 | 
						|
        </div>
 | 
						|
        
 | 
						|
        <style>
 | 
						|
            .wpdd-shortcodes-intro {
 | 
						|
                background: #f1f1f1;
 | 
						|
                padding: 15px;
 | 
						|
                border-radius: 5px;
 | 
						|
                margin: 20px 0;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-shortcodes-grid {
 | 
						|
                display: grid;
 | 
						|
                grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
 | 
						|
                gap: 20px;
 | 
						|
                margin: 30px 0;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-shortcode-card {
 | 
						|
                background: #fff;
 | 
						|
                border: 1px solid #ccd0d4;
 | 
						|
                border-radius: 5px;
 | 
						|
                padding: 20px;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-shortcode-card h3 {
 | 
						|
                margin-top: 0;
 | 
						|
                color: #23282d;
 | 
						|
                border-bottom: 1px solid #eee;
 | 
						|
                padding-bottom: 10px;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-shortcode-example {
 | 
						|
                background: #f8f9fa;
 | 
						|
                padding: 10px;
 | 
						|
                border-radius: 3px;
 | 
						|
                margin: 10px 0;
 | 
						|
                font-family: monospace;
 | 
						|
                border-left: 4px solid #2271b1;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-shortcode-examples {
 | 
						|
                background: #f8f9fa;
 | 
						|
                padding: 10px;
 | 
						|
                border-radius: 3px;
 | 
						|
                margin: 10px 0;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-shortcode-examples code {
 | 
						|
                display: block;
 | 
						|
                margin: 5px 0;
 | 
						|
                color: #d63384;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-params-list {
 | 
						|
                background: #fafafa;
 | 
						|
                padding: 10px 30px;
 | 
						|
                border-radius: 3px;
 | 
						|
                margin: 10px 0;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-params-list li {
 | 
						|
                margin: 8px 0;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-note {
 | 
						|
                background: #fff3cd;
 | 
						|
                border: 1px solid #ffeaa7;
 | 
						|
                color: #856404;
 | 
						|
                padding: 10px;
 | 
						|
                border-radius: 3px;
 | 
						|
                font-style: italic;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-page-setup {
 | 
						|
                margin-top: 40px;
 | 
						|
                padding-top: 30px;
 | 
						|
                border-top: 2px solid #ddd;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .wpdd-page-setup h2 {
 | 
						|
                color: #23282d;
 | 
						|
                margin-bottom: 15px;
 | 
						|
            }
 | 
						|
        </style>
 | 
						|
        
 | 
						|
        <?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;
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function handle_sync_software_product() {
 | 
						|
        if (!current_user_can('edit_wpdd_products')) {
 | 
						|
            wp_die('Unauthorized');
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (!isset($_POST['product_id']) || !wp_verify_nonce($_POST['nonce'], 'wpdd_sync_product_' . $_POST['product_id'])) {
 | 
						|
            wp_die('Invalid nonce');
 | 
						|
        }
 | 
						|
        
 | 
						|
        $product_id = intval($_POST['product_id']);
 | 
						|
        
 | 
						|
        if (!class_exists('WPDD_API')) {
 | 
						|
            require_once WPDD_PLUGIN_PATH . 'includes/class-wpdd-api.php';
 | 
						|
        }
 | 
						|
        
 | 
						|
        $result = WPDD_API::sync_software_product($product_id, true);
 | 
						|
        
 | 
						|
        wp_send_json($result);
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static function handle_regenerate_licenses() {
 | 
						|
        if (!current_user_can('manage_options')) {
 | 
						|
            wp_die('Unauthorized');
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (!wp_verify_nonce($_POST['nonce'], 'wpdd_regenerate_licenses')) {
 | 
						|
            wp_die('Invalid nonce');
 | 
						|
        }
 | 
						|
        
 | 
						|
        global $wpdb;
 | 
						|
        
 | 
						|
        // Find completed orders for software license products that don't have license keys
 | 
						|
        $orders = $wpdb->get_results("
 | 
						|
            SELECT o.*, pm.meta_value as product_type 
 | 
						|
            FROM {$wpdb->prefix}wpdd_orders o
 | 
						|
            LEFT JOIN {$wpdb->postmeta} pm ON o.product_id = pm.post_id AND pm.meta_key = '_wpdd_product_type'
 | 
						|
            LEFT JOIN {$wpdb->prefix}wpdd_licenses l ON o.id = l.order_id
 | 
						|
            WHERE o.status = 'completed' 
 | 
						|
            AND pm.meta_value = 'software_license'
 | 
						|
            AND l.license_key IS NULL
 | 
						|
        ");
 | 
						|
        
 | 
						|
        $generated = 0;
 | 
						|
        
 | 
						|
        foreach ($orders as $order) {
 | 
						|
            if (class_exists('WPDD_License_Manager')) {
 | 
						|
                $license_key = WPDD_License_Manager::create_license($order->id);
 | 
						|
                if ($license_key) {
 | 
						|
                    $generated++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        wp_send_json(array(
 | 
						|
            'success' => true,
 | 
						|
            'message' => sprintf('Generated %d license keys for existing orders.', $generated),
 | 
						|
            'generated' => $generated
 | 
						|
        ));
 | 
						|
    }
 | 
						|
}
 |