Files
wp-digital-download/admin/class-wpdd-settings.php
jknapp 4731637f33
Some checks failed
Create Release / build (push) Failing after 3s
Major improvements: Fix download limits, enhance license display, fix software filenames
🔧 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>
2025-09-09 19:16:57 -07:00

1074 lines
41 KiB
PHP

<?php
if (!defined('ABSPATH')) {
exit;
}
class WPDD_Settings {
public static function init() {
add_action('admin_menu', array(__CLASS__, 'add_settings_page'));
add_action('admin_init', array(__CLASS__, 'register_settings'));
// Ensure default settings are set
self::ensure_default_settings();
}
public static function ensure_default_settings() {
$defaults = array(
'wpdd_paypal_mode' => 'sandbox',
'wpdd_currency' => 'USD',
'wpdd_commission_rate' => 0,
'wpdd_payout_threshold' => 0,
'wpdd_earnings_holding_days' => 15,
'wpdd_enable_guest_checkout' => 1,
'wpdd_default_download_limit' => 5,
'wpdd_default_download_expiry' => 7,
'wpdd_enable_watermark' => 0,
'wpdd_file_access_method' => 'direct',
'wpdd_smtp_enabled' => 0,
'wpdd_smtp_port' => 587,
'wpdd_smtp_encryption' => 'tls'
);
foreach ($defaults as $option_name => $default_value) {
if (get_option($option_name) === false) {
add_option($option_name, $default_value);
}
}
// Ensure critical settings exist (but don't set default values)
$critical_settings = array(
'wpdd_paypal_client_id',
'wpdd_paypal_secret',
'wpdd_admin_email',
'wpdd_from_name',
'wpdd_from_email',
'wpdd_smtp_host',
'wpdd_smtp_username',
'wpdd_smtp_password',
'wpdd_watermark_text',
'wpdd_terms_page',
'wpdd_privacy_page'
);
foreach ($critical_settings as $setting) {
if (get_option($setting) === false) {
add_option($setting, '');
}
}
}
public static function add_settings_page() {
add_submenu_page(
'edit.php?post_type=wpdd_product',
__('Settings', 'wp-digital-download'),
__('Settings', 'wp-digital-download'),
'manage_options',
'wpdd-settings',
array(__CLASS__, 'render_settings_page')
);
}
public static function register_settings() {
// General Settings
register_setting('wpdd_general_settings', 'wpdd_currency');
register_setting('wpdd_general_settings', 'wpdd_enable_guest_checkout');
register_setting('wpdd_general_settings', 'wpdd_commission_rate', array(
'sanitize_callback' => array(__CLASS__, 'sanitize_commission_rate')
));
register_setting('wpdd_general_settings', 'wpdd_payout_threshold', array(
'sanitize_callback' => array(__CLASS__, 'sanitize_payout_threshold')
));
register_setting('wpdd_general_settings', 'wpdd_earnings_holding_days', array(
'sanitize_callback' => array(__CLASS__, 'sanitize_holding_days')
));
register_setting('wpdd_general_settings', 'wpdd_terms_page');
register_setting('wpdd_general_settings', 'wpdd_privacy_page');
// PayPal Settings
register_setting('wpdd_paypal_settings', 'wpdd_paypal_mode');
register_setting('wpdd_paypal_settings', 'wpdd_paypal_client_id');
register_setting('wpdd_paypal_settings', 'wpdd_paypal_secret');
// Email Settings
register_setting('wpdd_email_settings', 'wpdd_admin_email');
register_setting('wpdd_email_settings', 'wpdd_from_name');
register_setting('wpdd_email_settings', 'wpdd_from_email');
register_setting('wpdd_email_settings', 'wpdd_smtp_enabled');
register_setting('wpdd_email_settings', 'wpdd_smtp_host');
register_setting('wpdd_email_settings', 'wpdd_smtp_port');
register_setting('wpdd_email_settings', 'wpdd_smtp_username');
register_setting('wpdd_email_settings', 'wpdd_smtp_password');
register_setting('wpdd_email_settings', 'wpdd_smtp_encryption');
// Download Settings
register_setting('wpdd_download_settings', 'wpdd_default_download_limit');
register_setting('wpdd_download_settings', 'wpdd_default_download_expiry');
register_setting('wpdd_download_settings', 'wpdd_file_access_method');
register_setting('wpdd_download_settings', 'wpdd_disable_admin_bar');
// Watermark Settings
register_setting('wpdd_watermark_settings', 'wpdd_enable_watermark');
register_setting('wpdd_watermark_settings', 'wpdd_watermark_text');
add_settings_section(
'wpdd_general_settings',
__('General Settings', 'wp-digital-download'),
array(__CLASS__, 'general_section_callback'),
'wpdd_general_settings'
);
add_settings_section(
'wpdd_paypal_settings',
__('PayPal Settings', 'wp-digital-download'),
array(__CLASS__, 'paypal_section_callback'),
'wpdd_paypal_settings'
);
add_settings_section(
'wpdd_email_settings',
__('Email Settings', 'wp-digital-download'),
array(__CLASS__, 'email_section_callback'),
'wpdd_email_settings'
);
add_settings_section(
'wpdd_download_settings',
__('Download Settings', 'wp-digital-download'),
array(__CLASS__, 'download_section_callback'),
'wpdd_download_settings'
);
add_settings_section(
'wpdd_watermark_settings',
__('Watermark Settings', 'wp-digital-download'),
array(__CLASS__, 'watermark_section_callback'),
'wpdd_watermark_settings'
);
self::add_general_fields();
self::add_paypal_fields();
self::add_email_fields();
self::add_download_fields();
self::add_watermark_fields();
}
private static function add_general_fields() {
add_settings_field(
'wpdd_currency',
__('Currency', 'wp-digital-download'),
array(__CLASS__, 'currency_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array(
'name' => 'wpdd_currency'
)
);
add_settings_field(
'wpdd_enable_guest_checkout',
__('Guest Checkout', 'wp-digital-download'),
array(__CLASS__, 'checkbox_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array(
'name' => 'wpdd_enable_guest_checkout',
'label' => __('Allow guest customers to purchase without creating an account', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_commission_rate',
__('Platform Commission Rate (%)', 'wp-digital-download'),
array(__CLASS__, 'number_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array(
'name' => 'wpdd_commission_rate',
'description' => __('Platform commission rate from sales (0-100). Creators receive the remainder.', 'wp-digital-download'),
'min' => 0,
'max' => 100,
'step' => 0.01
)
);
add_settings_field(
'wpdd_payout_threshold',
__('Automatic Payout Threshold ($)', 'wp-digital-download'),
array(__CLASS__, 'number_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array(
'name' => 'wpdd_payout_threshold',
'description' => __('Minimum balance for automatic payouts (0 to disable)', 'wp-digital-download'),
'min' => 0,
'step' => 0.01
)
);
add_settings_field(
'wpdd_earnings_holding_days',
__('Earnings Holding Period (Days)', 'wp-digital-download'),
array(__CLASS__, 'number_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array(
'name' => 'wpdd_earnings_holding_days',
'description' => __('Number of days to hold earnings before making them available for payout (0 for immediate, 15 recommended for fraud protection)', 'wp-digital-download'),
'min' => 0,
'max' => 365,
'step' => 1,
'default' => 15
)
);
add_settings_field(
'wpdd_terms_page',
__('Terms & Conditions Page', 'wp-digital-download'),
array(__CLASS__, 'page_dropdown_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array('name' => 'wpdd_terms_page')
);
add_settings_field(
'wpdd_privacy_page',
__('Privacy Policy Page', 'wp-digital-download'),
array(__CLASS__, 'page_dropdown_field'),
'wpdd_general_settings',
'wpdd_general_settings',
array('name' => 'wpdd_privacy_page')
);
}
private static function add_paypal_fields() {
add_settings_field(
'wpdd_paypal_mode',
__('PayPal Mode', 'wp-digital-download'),
array(__CLASS__, 'select_field'),
'wpdd_paypal_settings',
'wpdd_paypal_settings',
array(
'name' => 'wpdd_paypal_mode',
'options' => array(
'sandbox' => __('Sandbox (Testing)', 'wp-digital-download'),
'live' => __('Live (Production)', 'wp-digital-download')
)
)
);
add_settings_field(
'wpdd_paypal_client_id',
__('PayPal Client ID', 'wp-digital-download'),
array(__CLASS__, 'text_field'),
'wpdd_paypal_settings',
'wpdd_paypal_settings',
array('name' => 'wpdd_paypal_client_id')
);
add_settings_field(
'wpdd_paypal_secret',
__('PayPal Secret', 'wp-digital-download'),
array(__CLASS__, 'password_field'),
'wpdd_paypal_settings',
'wpdd_paypal_settings',
array('name' => 'wpdd_paypal_secret')
);
}
private static function add_email_fields() {
add_settings_field(
'wpdd_admin_email',
__('Admin Email', 'wp-digital-download'),
array(__CLASS__, 'email_field'),
'wpdd_email_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_admin_email',
'description' => __('Email address for admin notifications', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_from_name',
__('From Name', 'wp-digital-download'),
array(__CLASS__, 'text_field'),
'wpdd_email_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_from_name',
'description' => __('Name shown in email headers', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_from_email',
__('From Email', 'wp-digital-download'),
array(__CLASS__, 'email_field'),
'wpdd_email_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_from_email',
'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_email_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_email_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_email_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_email_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_email_settings',
'wpdd_email_settings',
array()
);
add_settings_field(
'wpdd_smtp_username',
__('SMTP Username', 'wp-digital-download'),
array(__CLASS__, 'text_field'),
'wpdd_email_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_email_settings',
'wpdd_email_settings',
array(
'name' => 'wpdd_smtp_password',
'description' => __('SMTP authentication password', 'wp-digital-download')
)
);
}
private static function add_download_fields() {
add_settings_field(
'wpdd_default_download_limit',
__('Default Download Limit', 'wp-digital-download'),
array(__CLASS__, 'number_field'),
'wpdd_download_settings',
'wpdd_download_settings',
array(
'name' => 'wpdd_default_download_limit',
'description' => __('Default number of downloads allowed per purchase (0 = unlimited)', 'wp-digital-download'),
'min' => 0
)
);
add_settings_field(
'wpdd_default_download_expiry',
__('Default Download Expiry (days)', 'wp-digital-download'),
array(__CLASS__, 'number_field'),
'wpdd_download_settings',
'wpdd_download_settings',
array(
'name' => 'wpdd_default_download_expiry',
'description' => __('Default number of days downloads remain available (0 = never expires)', 'wp-digital-download'),
'min' => 0
)
);
add_settings_field(
'wpdd_file_access_method',
__('File Access Method', 'wp-digital-download'),
array(__CLASS__, 'select_field'),
'wpdd_download_settings',
'wpdd_download_settings',
array(
'name' => 'wpdd_file_access_method',
'options' => array(
'direct' => __('Direct Download', 'wp-digital-download'),
'redirect' => __('Redirect to File', 'wp-digital-download'),
'force' => __('Force Download', 'wp-digital-download')
),
'description' => __('How files are delivered to customers', 'wp-digital-download')
)
);
}
private static function add_watermark_fields() {
add_settings_field(
'wpdd_enable_watermark',
__('Enable Watermarking', 'wp-digital-download'),
array(__CLASS__, 'checkbox_field'),
'wpdd_watermark_settings',
'wpdd_watermark_settings',
array(
'name' => 'wpdd_enable_watermark',
'label' => __('Enable watermarking for images and PDFs by default', 'wp-digital-download')
)
);
add_settings_field(
'wpdd_watermark_text',
__('Default Watermark Text', 'wp-digital-download'),
array(__CLASS__, 'text_field'),
'wpdd_watermark_settings',
'wpdd_watermark_settings',
array(
'name' => 'wpdd_watermark_text',
'description' => __('Available placeholders: {customer_name}, {customer_email}, {order_id}, {date}, {site_name}', 'wp-digital-download')
)
);
}
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>
<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
// Use appropriate settings group for each tab
switch ($active_tab) {
case 'general':
settings_fields('wpdd_general_settings');
self::render_general_tab();
break;
case 'paypal':
settings_fields('wpdd_paypal_settings');
self::render_paypal_tab();
break;
case 'email':
settings_fields('wpdd_email_settings');
self::render_email_tab();
break;
case 'downloads':
settings_fields('wpdd_download_settings');
self::render_downloads_tab();
break;
case 'watermark':
settings_fields('wpdd_watermark_settings');
self::render_watermark_tab();
break;
default:
settings_fields('wpdd_general_settings');
self::render_general_tab();
}
submit_button();
?>
</form>
</div>
<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>
</div>
<style>
.wpdd-settings-container {
display: flex;
gap: 20px;
margin-top: 20px;
}
.wpdd-settings-content {
flex: 1;
min-width: 0;
}
.wpdd-settings-sidebar {
width: 300px;
flex-shrink: 0;
}
.wpdd-settings-box {
background: white;
border: 1px solid #ccd0d4;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.wpdd-settings-box h3 {
margin-top: 0;
}
.wpdd-settings-box code {
background: #f1f1f1;
padding: 2px 5px;
font-size: 12px;
}
.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-container {
flex-direction: column;
}
.wpdd-settings-sidebar {
width: 100%;
order: 2;
}
}
</style>
<?php
}
public static function general_section_callback() {
echo '<p>' . __('Configure basic plugin settings.', 'wp-digital-download') . '</p>';
}
public static function paypal_section_callback() {
echo '<p>' . __('Configure PayPal payment settings. You can get your API credentials from the PayPal Developer Dashboard.', 'wp-digital-download') . '</p>';
}
public static function email_section_callback() {
echo '<p>' . __('Configure email settings for purchase notifications.', 'wp-digital-download') . '</p>';
}
public static function download_section_callback() {
echo '<p>' . __('Configure default download and file protection settings.', 'wp-digital-download') . '</p>';
}
public static function watermark_section_callback() {
echo '<p>' . __('Configure watermarking settings for images and PDF files.', 'wp-digital-download') . '</p>';
}
public static function text_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, '');
$description = isset($args['description']) ? $args['description'] : '';
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
printf(
'<input type="text" id="%s" name="%s" value="%s" class="regular-text" />',
esc_attr($name),
esc_attr($name),
esc_attr($value)
);
if ($description) {
printf('<p class="description">%s</p>', esc_html($description));
}
}
public static function password_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, '');
$description = isset($args['description']) ? $args['description'] : '';
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
printf(
'<input type="password" id="%s" name="%s" value="%s" class="regular-text" />',
esc_attr($name),
esc_attr($name),
esc_attr($value)
);
if ($description) {
printf('<p class="description">%s</p>', esc_html($description));
}
}
public static function email_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, '');
$description = isset($args['description']) ? $args['description'] : '';
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
printf(
'<input type="email" id="%s" name="%s" value="%s" class="regular-text" />',
esc_attr($name),
esc_attr($name),
esc_attr($value)
);
if ($description) {
printf('<p class="description">%s</p>', esc_html($description));
}
}
public static function number_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, '');
$description = isset($args['description']) ? $args['description'] : '';
$min = isset($args['min']) ? $args['min'] : 0;
$max = isset($args['max']) ? $args['max'] : '';
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
printf(
'<input type="number" id="%s" name="%s" value="%s" min="%s" %s />',
esc_attr($name),
esc_attr($name),
esc_attr($value),
esc_attr($min),
$max ? 'max="' . esc_attr($max) . '"' : ''
);
if ($description) {
printf('<p class="description">%s</p>', esc_html($description));
}
}
public static function checkbox_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, 0);
$label = $args['label'] ?? '';
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
printf(
'<label><input type="checkbox" id="%s" name="%s" value="1" %s /> %s</label>',
esc_attr($name),
esc_attr($name),
checked($value, 1, false),
esc_html($label)
);
}
public static function select_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, '');
$options = $args['options'] ?? array();
$description = isset($args['description']) ? $args['description'] : '';
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
printf('<select id="%s" name="%s">', esc_attr($name), esc_attr($name));
foreach ($options as $option_value => $option_label) {
printf(
'<option value="%s" %s>%s</option>',
esc_attr($option_value),
selected($value, $option_value, false),
esc_html($option_label)
);
}
echo '</select>';
if ($description) {
printf('<p class="description">%s</p>', esc_html($description));
}
}
public static function currency_field($args) {
$currencies = array(
'USD' => 'US Dollar ($)',
'EUR' => 'Euro (€)',
'GBP' => 'British Pound (£)',
'CAD' => 'Canadian Dollar (C$)',
'AUD' => 'Australian Dollar (A$)',
'JPY' => 'Japanese Yen (¥)'
);
$args['options'] = $currencies;
self::select_field($args);
}
public static function page_dropdown_field($args) {
$name = $args['name'] ?? '';
$value = get_option($name, '');
if (empty($name)) {
echo '<p>Error: Field name not provided</p>';
return;
}
wp_dropdown_pages(array(
'name' => $name,
'id' => $name,
'selected' => $value,
'show_option_none' => __('— Select —', 'wp-digital-download'),
'option_none_value' => ''
));
}
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;
if (is_writable($upload_dir['basedir'])) {
$status[] = array(
'label' => __('Upload Directory', 'wp-digital-download'),
'value' => __('Writable', 'wp-digital-download'),
'class' => 'wpdd-status-good'
);
} else {
$status[] = array(
'label' => __('Upload Directory', 'wp-digital-download'),
'value' => __('Not Writable', 'wp-digital-download'),
'class' => 'wpdd-status-error'
);
}
if (file_exists($protected_dir)) {
$status[] = array(
'label' => __('Protected Directory', 'wp-digital-download'),
'value' => __('Exists', 'wp-digital-download'),
'class' => 'wpdd-status-good'
);
} else {
$status[] = array(
'label' => __('Protected Directory', 'wp-digital-download'),
'value' => __('Missing', 'wp-digital-download'),
'class' => 'wpdd-status-warning'
);
}
if (function_exists('imagecreatefrompng')) {
$status[] = array(
'label' => __('GD Library', 'wp-digital-download'),
'value' => __('Available', 'wp-digital-download'),
'class' => 'wpdd-status-good'
);
} else {
$status[] = array(
'label' => __('GD Library', 'wp-digital-download'),
'value' => __('Not Available', 'wp-digital-download'),
'class' => 'wpdd-status-warning'
);
}
$paypal_client_id = get_option('wpdd_paypal_client_id');
if ($paypal_client_id) {
$status[] = array(
'label' => __('PayPal', 'wp-digital-download'),
'value' => __('Configured', 'wp-digital-download'),
'class' => 'wpdd-status-good'
);
} else {
$status[] = array(
'label' => __('PayPal', 'wp-digital-download'),
'value' => __('Not Configured', 'wp-digital-download'),
'class' => 'wpdd-status-warning'
);
}
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>';
}
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[$section_id][$section_id])) {
return;
}
$section = $wp_settings_sections[$section_id][$section_id];
if (isset($section['callback']) && $section['callback']) {
call_user_func($section['callback'], $section);
}
if (!isset($wp_settings_fields[$section_id][$section_id])) {
return;
}
echo '<table class="form-table" role="presentation">';
do_settings_fields($section_id, $section_id);
echo '</table>';
}
public static function sanitize_commission_rate($input) {
$value = floatval($input);
if ($value < 0) {
$value = 0;
add_settings_error('wpdd_commission_rate', 'invalid_rate', __('Commission rate cannot be less than 0%. Set to 0%.', 'wp-digital-download'));
} elseif ($value > 100) {
$value = 100;
add_settings_error('wpdd_commission_rate', 'invalid_rate', __('Commission rate cannot exceed 100%. Set to 100%.', 'wp-digital-download'));
}
return $value;
}
public static function sanitize_payout_threshold($input) {
$value = floatval($input);
if ($value < 0) {
$value = 0;
add_settings_error('wpdd_payout_threshold', 'invalid_threshold', __('Payout threshold cannot be negative. Set to 0 (disabled).', 'wp-digital-download'));
}
return $value;
}
public static function sanitize_holding_days($input) {
$value = intval($input);
if ($value < 0) {
$value = 15;
add_settings_error('wpdd_earnings_holding_days', 'invalid_holding_days', __('Holding days cannot be negative. Set to 15 (recommended).', 'wp-digital-download'));
} elseif ($value > 365) {
$value = 365;
add_settings_error('wpdd_earnings_holding_days', 'invalid_holding_days', __('Holding days cannot exceed 365. Set to maximum (365).', 'wp-digital-download'));
}
return $value;
}
}