<?php
/**
 * Name: Force SSL Admin
 * Description: Force SSL and HTTPS protocol for admin area and login pages with automatic redirect for security but requires valid SSL certificate to avoid lockout
 * Category: Security
 * Icon: -
 * UseCases: [
 *   {
 *     "title": "Secure Admin Access",
 *     "description": "Force HTTPS for wp-admin to encrypt login credentials and prevent session hijacking on public WiFi networks."
 *   },
 *   {
 *     "title": "PCI Compliance",
 *     "description": "Meet payment card industry requirements by enforcing SSL encryption for all admin area and login traffic."
 *   },
 *   {
 *     "title": "Prevent Password Sniffing",
 *     "description": "Protect admin passwords from being intercepted on insecure networks by requiring encrypted HTTPS connections."
 *   }
 * ]
 * Added: 2025-07-30
 * Tags: ssl, https, security, admin, encryption
 * WhereToFind: {
 *   "location": "Admin Area (URL Bar)",
 *   "url": "admin.php",
 *   "instructions": "Admin URLs should force HTTPS protocol",
 *   "newTab": false
 * }
 */

// Prevent direct access
if (!defined('ABSPATH')) exit;

// EMERGENCY BYPASS CHECK - checked at file load time on frontend
// When user visits frontend with ?switchboard_disable_ssl=true, SSL forcing is disabled
// This allows recovery if user gets locked out of admin
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Emergency bypass check at load time, display-only
$switchboard_ssl_bypass_active = isset($_GET['switchboard_disable_ssl']) && $_GET['switchboard_disable_ssl'] === 'true';

class SwitchboardForceSSLAdmin {

    private $bypass_param = 'switchboard_disable_ssl';

    public function __construct() {
        global $switchboard_ssl_bypass_active;

        // If bypass is active (frontend URL with param), don't force SSL
        if ($switchboard_ssl_bypass_active) {
            add_action('admin_notices', [$this, 'bypass_active_notice']);
            return;
        }

        // Show admin notice if SSL is not available
        add_action('admin_notices', [$this, 'ssl_warning_notice']);

        if (!defined('FORCE_SSL_ADMIN')) {
            define('FORCE_SSL_ADMIN', true);
        }

        add_action('admin_init', [$this, 'force_ssl_redirect']);
    }

    /**
     * Show notice when bypass is active
     */
    public function bypass_active_notice() {
        if (!current_user_can('manage_options')) {
            return;
        }

        echo '<div class="notice notice-warning">';
        echo '<p><strong>' . esc_html__('Force SSL Admin Bypassed:', 'wpswitchboard') . '</strong> ';
        echo esc_html__('SSL forcing is temporarily disabled for this request. To fully disable, turn off the module in Switchboard settings.', 'wpswitchboard') . '</p>';
        echo '</div>';
    }

    /**
     * Register data locations for cleanup system
     *
     * @return array Data storage locations
     */
    public function register_data_locations() {
        return [
            'options' => [],
            'option_patterns' => [],
            'tables' => [],
            'post_meta' => [],
            'user_meta' => [],
        ];
    }
    
    public function force_ssl_redirect() {
        // Don't redirect if doing AJAX or if bypass parameter is present
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display-only bypass parameter check
        if (wp_doing_ajax() || isset($_GET[$this->bypass_param])) {
            return;
        }
        
        // Check if SSL is actually available before redirecting
        if (!is_ssl()) {
            // Test if HTTPS is available
            $host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
            $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
            $https_url = 'https://' . $host . $request_uri;
            
            // Add bypass parameter to prevent infinite loops
            if (strpos($https_url, '?') !== false) {
                $test_url = $https_url . '&' . $this->bypass_param . '_test=1';
            } else {
                $test_url = $https_url . '?' . $this->bypass_param . '_test=1';
            }
            
            // Only redirect if we haven't already tried
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display-only redirect loop check
            if (!isset($_GET[$this->bypass_param . '_test'])) {
                wp_safe_redirect($https_url, 301);
                exit;
            }
        }
    }
    
    /**
     * Render settings panel for Force SSL Admin
     * 
     * Displays information and warnings about forcing HTTPS/SSL for admin area with:
     * - SSL detection status (warning if HTTP, success if HTTPS)
     * - Warning message about redirect loops if SSL not available
     * - Prerequisites checklist for enabling SSL
     * - Emergency disable instructions with example URL
     * 
     * This is a configuration-free module (no user settings to save). It automatically
     * forces HTTPS for all admin and login pages by defining the FORCE_SSL_ADMIN constant
     * and adding a redirect at admin_init. The module includes protection against redirect
     * loops using a bypass parameter and shows admin notices on the Switchboard page if
     * SSL is not detected.
     * 
     * The settings panel serves as an informational/warning UI to help users understand
     * the SSL requirement and provide emergency disable instructions if they get locked out.
     * The module detects current SSL status using is_ssl() and displays color-coded alerts.
     * 
     * @param array $settings Current module settings (unused - no settings saved)
     * @return void Outputs HTML directly
     */
    public function render_settings($settings = []) {
        $is_ssl = is_ssl();
        $bypass_url = add_query_arg('switchboard_disable_ssl', 'true', admin_url('admin.php?page=switchboard'));
        
        ?>
        <input type="hidden" name="module" value="force-ssl-admin">

        <div class="sb-sp-group" style="margin-bottom: 24px;">
            <h3 class="sb-sp-heading"><?php esc_html_e('Force SSL Admin', 'wpswitchboard'); ?></h3>
            <p class="sb-sp-description"><?php esc_html_e('Force SSL and HTTPS protocol for admin area and login pages with automatic redirect for security. Requires a valid SSL certificate to avoid lockout.', 'wpswitchboard'); ?></p>
        </div>

        <?php if (!$is_ssl): ?>
            <div class="sb-sp-info-box sb-sp-info-box-tip" style="margin-bottom: 24px;">
                <h4 class="sb-sp-heading-sm"><?php esc_html_e('Warning: SSL Not Detected', 'wpswitchboard'); ?></h4>
                <p class="sb-sp-description" style="margin: 0 0 12px 0;"><?php esc_html_e('Your site is currently accessed via HTTP (not HTTPS). Enabling this module without a valid SSL certificate will cause redirect loops and lock you out of your admin area.', 'wpswitchboard'); ?></p>
                <p class="sb-sp-description" style="margin: 0 0 8px 0;"><strong><?php esc_html_e('Before enabling:', 'wpswitchboard'); ?></strong></p>
                <ul class="sb-sp-list">
                    <li class="sb-sp-list-item"><?php esc_html_e('Install an SSL certificate on your server', 'wpswitchboard'); ?></li>
                    <li class="sb-sp-list-item"><?php esc_html_e('Ensure your site is accessible via HTTPS', 'wpswitchboard'); ?></li>
                    <li class="sb-sp-list-item"><?php
                    // translators: %s is the HTTPS URL of the site for testing SSL availability
                    printf(esc_html__('Test by visiting: %s', 'wpswitchboard'), '<code>' . esc_url(str_replace('http://', 'https://', home_url())) . '</code>'); ?></li>
                </ul>
            </div>
        <?php else: ?>
            <div class="sb-sp-info-box sb-sp-info-box-success" style="margin-bottom: 24px;">
                <h4 class="sb-sp-heading-sm"><?php esc_html_e('SSL Detected', 'wpswitchboard'); ?></h4>
                <p class="sb-sp-description" style="margin: 0;"><?php esc_html_e('Your site is currently using HTTPS. This module is safe to enable and will automatically force all admin and login pages to use SSL encryption.', 'wpswitchboard'); ?></p>
            </div>
        <?php endif; ?>

        <div class="sb-sp-info-box sb-sp-info-box-info">
            <h4 class="sb-sp-heading-sm"><?php esc_html_e('How It Works', 'wpswitchboard'); ?></h4>
            <ul class="sb-sp-list">
                <li class="sb-sp-list-item"><?php esc_html_e('Automatically redirects all admin area pages (wp-admin) to HTTPS', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Forces login pages to use SSL encryption', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Protects admin passwords from being intercepted on insecure networks', 'wpswitchboard'); ?></li>
                <li class="sb-sp-list-item"><?php esc_html_e('Helps meet PCI compliance requirements for secure admin access', 'wpswitchboard'); ?></li>
            </ul>
        </div>

        <div class="sb-sp-info-box sb-sp-info-box-tip" style="margin-top: 24px;">
            <h4 class="sb-sp-heading-sm"><?php esc_html_e('Emergency Disable', 'wpswitchboard'); ?></h4>
            <p class="sb-sp-description" style="margin: 0 0 12px 0;"><?php esc_html_e('If you get locked out, add this parameter to your homepage URL (not admin):', 'wpswitchboard'); ?></p>
            <div style="background: #ffffff; border: 1px solid #e5e7eb; border-radius: 6px; padding: 12px; margin-bottom: 12px;">
                <code style="font-family: 'Courier New', monospace; font-size: 13px; color: #111827; display: block; white-space: pre-wrap; word-break: break-all;"><?php echo esc_url(home_url('/')); ?>?switchboard_disable_ssl=true</code>
            </div>
            <p class="sb-sp-description" style="margin: 0;">
                <?php esc_html_e('Visit this URL first, then navigate to wp-admin from there to disable the module.', 'wpswitchboard'); ?>
            </p>
        </div>
        <?php
    }

    public function ssl_warning_notice() {
        // Only show on Switchboard page
        $screen = get_current_screen();
        if (!$screen || !is_object($screen) || !isset($screen->id) || $screen->id !== 'toplevel_page_switchboard') {
            return;
        }
        
        // Check if SSL is working
        if (!is_ssl()) {
            $disable_url = add_query_arg('switchboard_disable_ssl', 'true', admin_url('admin.php?page=switchboard'));
            echo '<div class="notice notice-error">';
            echo '<p><strong>' . esc_html__('Force SSL Admin Warning:', 'wpswitchboard') . '</strong> ' . esc_html__('Your site does not have SSL/HTTPS enabled. This module may cause redirect loops.', 'wpswitchboard') . '</p>';
            echo '<p><a href="' . esc_url($disable_url) . '" class="button button-primary">' . esc_html__('Disable Force SSL Admin Module', 'wpswitchboard') . '</a></p>';
            echo '<p><small>' . esc_html__('If you\'re locked out, add', 'wpswitchboard') . ' <code>?switchboard_disable_ssl=true</code> ' . esc_html__('to your admin URL.', 'wpswitchboard') . '</small></p>';
            echo '</div>';
        }
    }
}

// Initialize and register with data system
$switchboard_instance = new SwitchboardForceSSLAdmin();
Switchboard_Data_Registry::get_instance()->auto_register($switchboard_instance, __FILE__);
