# king-addons/51.1.44/includes/extensions/Maintenance_Mode/Maintenance_Mode.php

King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder, version 51.1.44. 1,043 lines.

- Page: https://pluginprobe.com/plugins/king-addons/51.1.44/code/includes/extensions/Maintenance_Mode/Maintenance_Mode.php
- Raw: https://pluginprobe.com/plugins/king-addons/51.1.44/raw/includes/extensions/Maintenance_Mode/Maintenance_Mode.php
- Modified: 2025-12-27T05:19:20+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/king-addons/51.1.44/code/includes/extensions/Maintenance_Mode/Maintenance_Mode.php#L10-L20`.

```php
<?php
/**
 * Maintenance Mode extension.
 *
 * @package King_Addons
 */

namespace King_Addons\Maintenance_Mode;

if (!defined('ABSPATH')) {
    exit;
}

class Maintenance_Mode
{
    private const OPTION_NAME = 'kng_maintenance_settings';

    private static ?Maintenance_Mode $instance = null;

    /**
     * Cached settings.
     *
     * @var array<string, mixed>
     */
    private array $settings = [];

    public static function instance(): Maintenance_Mode
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    private function __construct()
    {
        $this->settings = $this->get_settings();

        add_action('admin_menu', [$this, 'register_admin_menu']);
        add_action('admin_init', [$this, 'register_settings']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
        add_action('template_redirect', [$this, 'maybe_render_maintenance'], 1);

        add_action('admin_post_kng_maintenance_export', [$this, 'handle_export']);
        add_action('admin_post_kng_maintenance_import', [$this, 'handle_import']);

        add_shortcode('kng_maintenance_page', [$this, 'render_shortcode']);
    }

    public function register_admin_menu(): void
    {
        add_submenu_page(
            'king-addons',
            __('Maintenance Mode', 'king-addons'),
            __('Maintenance Mode', 'king-addons'),
            'manage_options',
            'king-addons-maintenance-mode',
            [$this, 'render_admin_page']
        );
    }

    public function register_settings(): void
    {
        register_setting(
            'kng_maintenance_settings_group',
            self::OPTION_NAME,
            [
                'type' => 'array',
                'sanitize_callback' => [$this, 'sanitize_settings'],
                'default' => $this->get_default_settings(),
            ]
        );
    }

    public function enqueue_admin_assets(string $hook): void
    {
        if ($hook !== 'king-addons_page_king-addons-maintenance-mode') {
            return;
        }

        $shared_css = KING_ADDONS_URL . 'includes/admin/layouts/shared/admin-v3-styles.css';
        $shared_path = KING_ADDONS_PATH . 'includes/admin/layouts/shared/admin-v3-styles.css';
        $shared_version = file_exists($shared_path) ? filemtime($shared_path) : KING_ADDONS_VERSION;
        wp_enqueue_style('king-addons-admin-v3', $shared_css, [], $shared_version);

        $admin_css = KING_ADDONS_URL . 'includes/extensions/Maintenance_Mode/assets/admin.css';
        $admin_path = KING_ADDONS_PATH . 'includes/extensions/Maintenance_Mode/assets/admin.css';
        $admin_version = file_exists($admin_path) ? filemtime($admin_path) : KING_ADDONS_VERSION;
        wp_enqueue_style('king-addons-maintenance-admin', $admin_css, ['king-addons-admin-v3'], $admin_version);

        $admin_js = KING_ADDONS_URL . 'includes/extensions/Maintenance_Mode/assets/admin.js';
        $admin_path_js = KING_ADDONS_PATH . 'includes/extensions/Maintenance_Mode/assets/admin.js';
        $admin_js_version = file_exists($admin_path_js) ? filemtime($admin_path_js) : KING_ADDONS_VERSION;
        wp_enqueue_script('king-addons-maintenance-admin', $admin_js, ['jquery'], $admin_js_version, true);

        wp_localize_script('king-addons-maintenance-admin', 'KNGMaintenance', [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'themeNonce' => wp_create_nonce('king_addons_dashboard_ui'),
        ]);
    }

    public function render_admin_page(): void
    {
        if (!current_user_can('manage_options')) {
            return;
        }

        $view = isset($_GET['view']) ? sanitize_key($_GET['view']) : 'dashboard';
        $is_pro = $this->is_pro();
        $settings = $this->get_settings();
        $templates = $this->get_builtin_templates();

        include __DIR__ . '/templates/admin-page.php';
    }

    public function maybe_render_maintenance(): void
    {
        if ($this->is_preview_request()) {
            $this->render_maintenance_response(true);
            exit;
        }

        if (!$this->is_mode_active()) {
            return;
        }

        if ($this->should_bypass_request()) {
            return;
        }

        $this->render_maintenance_response(false);
        exit;
    }

    private function is_mode_active(): bool
    {
        if (empty($this->settings['enabled'])) {
            return false;
        }

        if (empty($this->settings['schedule_enabled'])) {
            return true;
        }

        $start = $this->parse_schedule_time($this->settings['schedule_start'] ?? '');
        $end = $this->parse_schedule_time($this->settings['schedule_end'] ?? '');
        $now = current_time('timestamp', true);

        if ($start && $end) {
            return $now >= $start && $now <= $end;
        }

        if ($start && !$end) {
            return $now >= $start;
        }

        if (!$start && $end) {
            return $now <= $end;
        }

        return false;
    }

    private function should_bypass_request(): bool
    {
        if (defined('WP_CLI') && WP_CLI) {
            return true;
        }

        if (wp_doing_cron()) {
            return true;
        }

        if (is_admin()) {
            return true;
        }

        if (wp_doing_ajax() && !empty($this->settings['allow_admin_ajax'])) {
            return true;
        }

        if ($this->is_login_request()) {
            return true;
        }

        if (!empty($this->settings['disable_elementor_editor']) && $this->is_elementor_editor()) {
            return true;
        }

        if ($this->is_rest_request()) {
            if (is_user_logged_in()) {
                return true;
            }
            return !empty($this->settings['allow_rest']);
        }

        if ($this->is_user_allowed()) {
            return true;
        }

        if ($this->is_ip_whitelisted()) {
            return true;
        }

        if ($this->is_path_whitelisted()) {
            return true;
        }

        return false;
    }

    private function is_user_allowed(): bool
    {
        if (!is_user_logged_in()) {
            return false;
        }

        $user = wp_get_current_user();
        if (!$user || !$user->ID) {
            return false;
        }

        if (!empty($this->settings['exclude_admin']) && user_can($user, 'manage_options')) {
            return true;
        }

        if ($this->is_pro()) {
            $allowed_roles = $this->settings['allowed_roles'] ?? [];
            if (!empty($allowed_roles) && array_intersect((array) $user->roles, $allowed_roles)) {
                return true;
            }
        }

        return false;
    }

    private function is_ip_whitelisted(): bool
    {
        $whitelist = $this->settings['whitelist_ips'] ?? [];
        if (empty($whitelist)) {
            return false;
        }

        $ip = $this->get_client_ip();
        if ($ip === '') {
            return false;
        }

        return in_array($ip, $whitelist, true);
    }

    private function is_path_whitelisted(): bool
    {
        $paths = $this->settings['whitelist_paths'] ?? [];
        if (empty($paths)) {
            return false;
        }

        $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) wp_unslash($_SERVER['REQUEST_URI']) : '';
        $path = wp_parse_url($request_uri, PHP_URL_PATH);
        $path = $path ? '/' . ltrim($path, '/') : '/';

        foreach ($paths as $allowed) {
            if ($allowed !== '/' && strpos($path, $allowed) === 0) {
                return true;
            }
            if ($allowed === $path) {
                return true;
            }
        }

        return false;
    }

    private function is_login_request(): bool
    {
        $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) wp_unslash($_SERVER['REQUEST_URI']) : '';
        return strpos($request_uri, 'wp-login.php') !== false || strpos($request_uri, 'wp-register.php') !== false;
    }

    private function is_rest_request(): bool
    {
        return defined('REST_REQUEST') && REST_REQUEST;
    }

    private function is_elementor_editor(): bool
    {
        if (isset($_GET['elementor-preview'])) {
            return true;
        }

        if (class_exists('\\Elementor\\Plugin')) {
            $plugin = \Elementor\Plugin::instance();
            if ($plugin->editor && $plugin->editor->is_edit_mode()) {
                return true;
            }
        }

        return false;
    }

    private function render_maintenance_response(bool $is_preview): void
    {
        $mode = $this->settings['mode'] ?? 'coming_soon';
        $status = $mode === 'maintenance' ? 503 : 200;

        if ($is_preview) {
            $status = 200;
        }

        status_header($status);
        nocache_headers();
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');

        $retry_after = (int) ($this->settings['retry_after'] ?? 0);
        if ($status === 503 && $retry_after > 0) {
            header('Retry-After: ' . $retry_after);
        }

        if (!empty($this->settings['noindex'])) {
            header('X-Robots-Tag: noindex, nofollow', true);
        }

        $title = $mode === 'maintenance' ? __('Maintenance Mode', 'king-addons') : __('Coming Soon', 'king-addons');
        $content = $this->get_rendered_page_content();

        $this->enqueue_frontend_assets();

        echo '<!doctype html>';
        echo '<html ' . get_language_attributes() . '>';
        echo '<head>';
        echo '<meta charset="' . esc_attr(get_bloginfo('charset')) . '">';
        echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
        echo '<title>' . esc_html($title) . '</title>';
        if (!empty($this->settings['noindex'])) {
            echo '<meta name="robots" content="noindex, nofollow">';
        }
        wp_head();
        echo '</head>';
        echo '<body class="kng-maintenance-body">';
        echo $content;
        wp_footer();
        echo '</body></html>';
    }

    private function enqueue_frontend_assets(): void
    {
        wp_enqueue_style(
            'king-addons-maintenance-frontend',
            KING_ADDONS_URL . 'includes/extensions/Maintenance_Mode/assets/frontend.css',
            [],
            KING_ADDONS_VERSION
        );

        wp_enqueue_script(
            'king-addons-maintenance-frontend',
            KING_ADDONS_URL . 'includes/extensions/Maintenance_Mode/assets/frontend.js',
            [],
            KING_ADDONS_VERSION,
            true
        );
    }

    private function get_rendered_page_content(): string
    {
        $theme = $this->settings['theme'] ?? 'dark';
        $mode = $this->settings['mode'] ?? 'coming_soon';
        $template_source = $this->settings['template_source'] ?? 'built_in';

        $wrapper_classes = [
            'kng-maintenance',
            $theme === 'light' ? 'kng-maintenance-theme-light' : 'kng-maintenance-theme-dark',
            $mode === 'maintenance' ? 'kng-maintenance-mode-maintenance' : 'kng-maintenance-mode-coming-soon',
        ];

        $content = '';
        if ($template_source === 'page' && !empty($this->settings['page_id'])) {
            $content = $this->get_page_content((int) $this->settings['page_id']);
        } elseif ($template_source === 'elementor' && !empty($this->settings['elementor_id'])) {
            $content = $this->get_elementor_content((int) $this->settings['elementor_id']);
        } else {
            $content = $this->render_builtin_template((string) $this->settings['template_id']);
        }

        return '<main class="' . esc_attr(implode(' ', $wrapper_classes)) . '">' . $content . '</main>';
    }

    public function render_shortcode(array $atts): string
    {
        $atts = shortcode_atts([
            'id' => '',
            'type' => '',
            'theme' => '',
            'full_height' => 'false',
        ], $atts, 'kng_maintenance_page');

        $theme = $atts['theme'] !== '' ? sanitize_key($atts['theme']) : ($this->settings['theme'] ?? 'dark');
        $theme = $theme === 'light' ? 'light' : 'dark';

        $template_source = $this->settings['template_source'] ?? 'built_in';
        $template_id = $this->settings['template_id'] ?? 'minimal';
        $page_id = (int) ($this->settings['page_id'] ?? 0);
        $elementor_id = (int) ($this->settings['elementor_id'] ?? 0);

        if ($atts['id'] !== '') {
            if (is_numeric($atts['id'])) {
                $template_source = 'page';
                $page_id = absint($atts['id']);
            } else {
                $template_source = 'built_in';
                $template_id = sanitize_key($atts['id']);
            }
        }

        if ($atts['type'] !== '') {
            $template_source = sanitize_key($atts['type']);
            if ($template_source === 'elementor' && is_numeric($atts['id'])) {
                $elementor_id = absint($atts['id']);
            }
        }

        $content = '';
        if ($template_source === 'page' && $page_id) {
            $content = $this->get_page_content($page_id);
        } elseif ($template_source === 'elementor' && $elementor_id) {
            $content = $this->get_elementor_content($elementor_id);
        } else {
            $content = $this->render_builtin_template($this->ensure_template_allowed($template_id));
        }

        $this->enqueue_frontend_assets();

        $classes = [
            'kng-maintenance',
            $theme === 'light' ? 'kng-maintenance-theme-light' : 'kng-maintenance-theme-dark',
        ];

        if (filter_var($atts['full_height'], FILTER_VALIDATE_BOOLEAN)) {
            $classes[] = 'kng-maintenance-full';
        }

        return '<div class="' . esc_attr(implode(' ', $classes)) . '">' . $content . '</div>';
    }

    private function get_page_content(int $page_id): string
    {
        $page = get_post($page_id);
        if (!$page) {
            return $this->render_builtin_template('minimal');
        }

        $old_post = $GLOBALS['post'] ?? null;
        $GLOBALS['post'] = $page;
        setup_postdata($page);

        $content = apply_filters('the_content', $page->post_content);

        wp_reset_postdata();
        $GLOBALS['post'] = $old_post;

        return $content;
    }

    private function get_elementor_content(int $template_id): string
    {
        if (!class_exists('\\Elementor\\Plugin')) {
            return $this->render_builtin_template('minimal');
        }

        $plugin = \Elementor\Plugin::instance();
        if (!$plugin->frontend) {
            return $this->render_builtin_template('minimal');
        }

        $plugin->frontend->enqueue_styles();
        $plugin->frontend->enqueue_scripts();

        return $plugin->frontend->get_builder_content_for_display($template_id, true);
    }

    private function render_builtin_template(string $template_id): string
    {
        $templates = $this->get_builtin_templates();
        $template_id = isset($templates[$template_id]) ? $template_id : 'minimal';
        $template_id = $this->ensure_template_allowed($template_id);

        $mode = $this->settings['mode'] ?? 'coming_soon';
        $site_name = get_bloginfo('name');
        $tagline = get_bloginfo('description');
        $schedule_end = $this->settings['schedule_end'] ?? '';
        $content = $this->get_template_content($template_id);

        $headline = $mode === 'maintenance'
            ? __('We are upgrading the experience.', 'king-addons')
            : __('A new experience is on the horizon.', 'king-addons');

        $subhead = $tagline !== '' ? $tagline : __('Our team is preparing something beautiful. Stay tuned.', 'king-addons');

        $mode_label = $mode === 'maintenance' ? __('Maintenance Mode', 'king-addons') : __('Coming Soon', 'king-addons');

        $badge = $content['badge'] !== '' ? $content['badge'] : $mode_label;
        $headline = $content['headline'] !== '' ? $content['headline'] : $headline;
        $subhead = $content['subhead'] !== '' ? $content['subhead'] : $subhead;

        $launch_label = '';
        if ($content['launch_label'] !== '') {
            $launch_label = $content['launch_label'];
        }
        if ($schedule_end !== '') {
            $local_end = get_date_from_gmt($schedule_end, 'Y-m-d H:i');
            if ($launch_label === '') {
                $launch_label = sprintf(__('Estimated return: %s', 'king-addons'), esc_html($local_end));
            }
        }

        $footer_left = $content['footer_left'] !== '' ? $content['footer_left'] : $site_name;
        $footer_right = $content['footer_right'] !== '' ? $content['footer_right'] : __('Powered by King Addons', 'king-addons');

        $countdown_days = str_pad((string) (int) ($content['countdown_days'] ?? 0), 2, '0', STR_PAD_LEFT);
        $countdown_hours = str_pad((string) (int) ($content['countdown_hours'] ?? 0), 2, '0', STR_PAD_LEFT);
        $countdown_minutes = str_pad((string) (int) ($content['countdown_minutes'] ?? 0), 2, '0', STR_PAD_LEFT);
        $progress_percent = isset($content['progress_percent']) ? min(100, max(0, (int) $content['progress_percent'])) : 0;
        $progress_label = $content['progress_label'] ?? '';
        if ($progress_label === '') {
            $progress_label = sprintf(__('%d%% complete', 'king-addons'), $progress_percent);
        }
        $form_placeholder = $content['form_placeholder'] ?? '';
        if ($form_placeholder === '') {
            $form_placeholder = __('Email address', 'king-addons');
        }
        $form_button = $content['form_button'] ?? '';
        if ($form_button === '') {
            $form_button = __('Notify me', 'king-addons');
        }

        ob_start();
        ?>
        <section class="kng-maintenance-shell kng-maintenance-template-<?php echo esc_attr($template_id); ?>">
            <div class="kng-maintenance-card">
                <div class="kng-maintenance-badge"><?php echo esc_html($badge); ?></div>
                <h1><?php echo esc_html($headline); ?></h1>
                <p class="kng-maintenance-subhead"><?php echo esc_html($subhead); ?></p>

                <?php if ($launch_label !== '') : ?>
                    <p class="kng-maintenance-launch"><?php echo esc_html($launch_label); ?></p>
                <?php endif; ?>

                <?php if ($template_id === 'countdown') : ?>
                    <div class="kng-maintenance-countdown">
                        <div><strong><?php echo esc_html($countdown_days); ?></strong><span><?php esc_html_e('Days', 'king-addons'); ?></span></div>
                        <div><strong><?php echo esc_html($countdown_hours); ?></strong><span><?php esc_html_e('Hours', 'king-addons'); ?></span></div>
                        <div><strong><?php echo esc_html($countdown_minutes); ?></strong><span><?php esc_html_e('Minutes', 'king-addons'); ?></span></div>
                    </div>
                <?php endif; ?>

                <?php if ($template_id === 'progress') : ?>
                    <div class="kng-maintenance-progress">
                        <div class="kng-maintenance-progress-bar">
                            <span style="width: <?php echo esc_attr($progress_percent); ?>%;"></span>
                        </div>
                        <div class="kng-maintenance-progress-label"><?php echo esc_html($progress_label); ?></div>
                    </div>
                <?php endif; ?>

                <?php if (in_array($template_id, ['subscribe', 'product-launch'], true)) : ?>
                    <form class="kng-maintenance-form">
                        <input type="email" placeholder="<?php echo esc_attr($form_placeholder); ?>" aria-label="<?php echo esc_attr($form_placeholder); ?>">
                        <button type="button"><?php echo esc_html($form_button); ?></button>
                    </form>
                <?php endif; ?>

                <?php if ($template_id === 'split') : ?>
                    <div class="kng-maintenance-split">
                        <div>
                            <h3><?php echo esc_html($content['split_title_a']); ?></h3>
                            <p><?php echo esc_html($content['split_text_a']); ?></p>
                        </div>
                        <div>
                            <h3><?php echo esc_html($content['split_title_b']); ?></h3>
                            <p><?php echo esc_html($content['split_text_b']); ?></p>
                        </div>
                    </div>
                <?php endif; ?>

                <div class="kng-maintenance-footer">
                    <span><?php echo esc_html($footer_left); ?></span>
                    <span class="kng-maintenance-dot"></span>
                    <span><?php echo esc_html($footer_right); ?></span>
                </div>
            </div>
            <div class="kng-maintenance-orb"></div>
            <div class="kng-maintenance-orb secondary"></div>
        </section>
        <?php
        return ob_get_clean();
    }

    private function get_builtin_templates(): array
    {
        return [
            'minimal' => __('Minimal', 'king-addons'),
            'dark' => __('Dark', 'king-addons'),
            'gradient' => __('Gradient', 'king-addons'),
            'countdown' => __('Coming Soon Countdown', 'king-addons'),
            'progress' => __('Maintenance Progress', 'king-addons'),
            'subscribe' => __('Simple Subscribe', 'king-addons'),
            'product-launch' => __('Product Launch', 'king-addons'),
            'construction' => __('Under Construction', 'king-addons'),
            'split' => __('Split Layout', 'king-addons'),
            'logo' => __('Centered Logo', 'king-addons'),
        ];
    }

    public function get_pro_templates(): array
    {
        return [
            'countdown',
            'progress',
            'product-launch',
            'split',
        ];
    }

    public function handle_export(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('Unauthorized request.', 'king-addons'));
        }

        check_admin_referer('kng_maintenance_export');

        $settings = $this->get_settings();

        header('Content-Type: application/json; charset=utf-8');
        header('Content-Disposition: attachment; filename=maintenance-mode-settings.json');
        echo wp_json_encode($settings);
        exit;
    }

    public function handle_import(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('Unauthorized request.', 'king-addons'));
        }

        check_admin_referer('kng_maintenance_import');

        if (empty($_FILES['import_file']) || !isset($_FILES['import_file']['tmp_name'])) {
            $this->redirect_with_message('import-export', 'error_import');
        }

        $file = $_FILES['import_file'];
        if (!empty($file['error'])) {
            $this->redirect_with_message('import-export', 'error_import');
        }

        $contents = file_get_contents($file['tmp_name']);
        if ($contents === false) {
            $this->redirect_with_message('import-export', 'error_import');
        }

        $decoded = json_decode($contents, true);
        if (!is_array($decoded)) {
            $this->redirect_with_message('import-export', 'error_import');
        }

        $sanitized = $this->sanitize_settings($decoded);
        update_option(self::OPTION_NAME, $sanitized);

        $this->redirect_with_message('import-export', 'imported');
    }

    private function get_default_settings(): array
    {
        return [
            'enabled' => false,
            'mode' => 'coming_soon',
            'template_source' => 'built_in',
            'template_id' => 'minimal',
            'template_content' => [],
            'page_id' => 0,
            'elementor_id' => 0,
            'theme' => 'dark',
            'noindex' => true,
            'retry_after' => 3600,
            'whitelist_ips' => [],
            'whitelist_paths' => [],
            'exclude_admin' => true,
            'allowed_roles' => [],
            'schedule_enabled' => false,
            'schedule_start' => '',
            'schedule_end' => '',
            'allow_rest' => true,
            'allow_admin_ajax' => true,
            'disable_elementor_editor' => true,
            'custom_css' => '',
            'custom_js' => '',
        ];
    }

    public function get_settings(): array
    {
        $defaults = $this->get_default_settings();
        $saved = get_option(self::OPTION_NAME, []);

        $settings = wp_parse_args($saved, $defaults);
        if (!is_array($settings['template_content'])) {
            $settings['template_content'] = $defaults['template_content'];
        }
        if (!is_array($settings['whitelist_ips'])) {
            $settings['whitelist_ips'] = $defaults['whitelist_ips'];
        }
        if (!is_array($settings['whitelist_paths'])) {
            $settings['whitelist_paths'] = $defaults['whitelist_paths'];
        }
        if (!is_array($settings['allowed_roles'])) {
            $settings['allowed_roles'] = $defaults['allowed_roles'];
        }

        return $settings;
    }

    public function sanitize_settings(array $settings): array
    {
        $defaults = $this->get_default_settings();
        $existing = $this->get_settings();
        $settings = wp_parse_args($settings, $existing);
        $templates = array_keys($this->get_builtin_templates());
        $pro_templates = $this->get_pro_templates();

        $source = isset($settings['template_source']) ? sanitize_key($settings['template_source']) : $defaults['template_source'];
        if (!in_array($source, ['built_in', 'page', 'elementor'], true)) {
            $source = 'built_in';
        }

        $template_id = isset($settings['template_id']) ? sanitize_key($settings['template_id']) : $defaults['template_id'];
        if (!in_array($template_id, $templates, true)) {
            $template_id = $defaults['template_id'];
        }
        if (!$this->is_pro() && in_array($template_id, $pro_templates, true)) {
            $template_id = 'minimal';
        }

        $mode = isset($settings['mode']) ? sanitize_key($settings['mode']) : $defaults['mode'];
        if (!in_array($mode, ['coming_soon', 'maintenance'], true)) {
            $mode = $defaults['mode'];
        }

        $theme = isset($settings['theme']) ? sanitize_key($settings['theme']) : $defaults['theme'];
        $theme = $theme === 'light' ? 'light' : 'dark';

        $whitelist_ips = $this->sanitize_list($settings['whitelist_ips'] ?? []);
        $whitelist_paths = $this->sanitize_list($settings['whitelist_paths'] ?? []);

        if (!$this->is_pro()) {
            $whitelist_ips = array_slice($whitelist_ips, 0, 10);
            $whitelist_paths = array_slice($whitelist_paths, 0, 10);
        }

        $clean = [
            'enabled' => !empty($settings['enabled']),
            'mode' => $mode,
            'template_source' => $source,
            'template_id' => $template_id,
            'template_content' => $this->sanitize_template_content($settings['template_content'] ?? []),
            'page_id' => absint($settings['page_id'] ?? 0),
            'elementor_id' => absint($settings['elementor_id'] ?? 0),
            'theme' => $theme,
            'noindex' => !empty($settings['noindex']),
            'retry_after' => max(0, absint($settings['retry_after'] ?? $defaults['retry_after'])),
            'whitelist_ips' => $whitelist_ips,
            'whitelist_paths' => $this->normalize_paths($whitelist_paths),
            'exclude_admin' => !empty($settings['exclude_admin']),
            'allowed_roles' => $this->sanitize_list($settings['allowed_roles'] ?? []),
            'schedule_enabled' => !empty($settings['schedule_enabled']),
            'schedule_start' => $this->sanitize_datetime($settings['schedule_start'] ?? ''),
            'schedule_end' => $this->sanitize_datetime($settings['schedule_end'] ?? ''),
            'allow_rest' => !empty($settings['allow_rest']),
            'allow_admin_ajax' => !empty($settings['allow_admin_ajax']),
            'disable_elementor_editor' => !empty($settings['disable_elementor_editor']),
            'custom_css' => '',
            'custom_js' => '',
        ];

        if (!$this->is_pro()) {
            $clean['allowed_roles'] = [];
        }

        return $clean;
    }

    public function get_template_content(string $template_id): array
    {
        $templates = $this->get_builtin_templates();
        $template_id = isset($templates[$template_id]) ? $template_id : 'minimal';
        $template_id = $this->ensure_template_allowed($template_id);

        $defaults = $this->get_template_content_defaults($template_id);
        $saved = $this->settings['template_content'][$template_id] ?? [];
        if (!is_array($saved)) {
            $saved = [];
        }

        return wp_parse_args($saved, $defaults);
    }

    private function get_template_content_defaults(string $template_id): array
    {
        $mode = $this->settings['mode'] ?? 'coming_soon';
        $site_name = get_bloginfo('name');
        $tagline = get_bloginfo('description');

        $headline = $mode === 'maintenance'
            ? __('We are upgrading the experience.', 'king-addons')
            : __('A new experience is on the horizon.', 'king-addons');

        $subhead = $tagline !== '' ? $tagline : __('Our team is preparing something beautiful. Stay tuned.', 'king-addons');

        $base = [
            'badge' => '',
            'headline' => $headline,
            'subhead' => $subhead,
            'launch_label' => '',
            'footer_left' => $site_name,
            'footer_right' => __('Powered by King Addons', 'king-addons'),
        ];

        if ($template_id === 'countdown') {
            $base['countdown_days'] = '14';
            $base['countdown_hours'] = '06';
            $base['countdown_minutes'] = '42';
        }

        if ($template_id === 'progress') {
            $base['progress_percent'] = 68;
            $base['progress_label'] = __('68% complete', 'king-addons');
        }

        if (in_array($template_id, ['subscribe', 'product-launch'], true)) {
            $base['form_placeholder'] = __('Email address', 'king-addons');
            $base['form_button'] = __('Notify me', 'king-addons');
        }

        if ($template_id === 'split') {
            $base['split_title_a'] = __('What is happening', 'king-addons');
            $base['split_text_a'] = __('We are refining the experience with faster performance and new visuals.', 'king-addons');
            $base['split_title_b'] = __('Stay connected', 'king-addons');
            $base['split_text_b'] = __('Follow our updates while we prepare the launch.', 'king-addons');
        }

        return $base;
    }

    private function sanitize_template_content(array $content): array
    {
        $fields = $this->get_template_content_fields();
        $clean = [];

        foreach ($fields as $template_id => $template_fields) {
            $values = isset($content[$template_id]) && is_array($content[$template_id]) ? $content[$template_id] : [];
            $template_clean = [];

            foreach ($template_fields as $field => $type) {
                $value = $values[$field] ?? '';
                if ($type === 'int') {
                    $int = absint($value);
                    if ($field === 'progress_percent') {
                        $int = min(100, max(0, $int));
                    }
                    if ($field === 'countdown_hours') {
                        $int = min(23, max(0, $int));
                    }
                    if ($field === 'countdown_minutes') {
                        $int = min(59, max(0, $int));
                    }
                    $template_clean[$field] = $int;
                } else {
                    $template_clean[$field] = sanitize_text_field((string) $value);
                }
            }

            $clean[$template_id] = $template_clean;
        }

        return $clean;
    }

    private function get_template_content_fields(): array
    {
        $base = [
            'badge' => 'text',
            'headline' => 'text',
            'subhead' => 'text',
            'launch_label' => 'text',
            'footer_left' => 'text',
            'footer_right' => 'text',
        ];

        return [
            'minimal' => $base,
            'dark' => $base,
            'gradient' => $base,
            'construction' => $base,
            'logo' => $base,
            'countdown' => $base + [
                'countdown_days' => 'int',
                'countdown_hours' => 'int',
                'countdown_minutes' => 'int',
            ],
            'progress' => $base + [
                'progress_percent' => 'int',
                'progress_label' => 'text',
            ],
            'subscribe' => $base + [
                'form_placeholder' => 'text',
                'form_button' => 'text',
            ],
            'product-launch' => $base + [
                'form_placeholder' => 'text',
                'form_button' => 'text',
            ],
            'split' => $base + [
                'split_title_a' => 'text',
                'split_text_a' => 'text',
                'split_title_b' => 'text',
                'split_text_b' => 'text',
            ],
        ];
    }

    private function ensure_template_allowed(string $template_id): string
    {
        if (!$this->is_pro() && in_array($template_id, $this->get_pro_templates(), true)) {
            return 'minimal';
        }

        return $template_id;
    }

    private function sanitize_list($value): array
    {
        if (is_array($value)) {
            $items = $value;
        } else {
            $items = preg_split('/\\r\\n|\\r|\\n|,/', (string) $value);
        }

        $items = array_map('trim', $items);
        $items = array_filter($items, static function ($item) {
            return $item !== '';
        });
        $items = array_map('sanitize_text_field', $items);

        return array_values(array_unique($items));
    }

    private function normalize_paths(array $paths): array
    {
        $normalized = [];
        foreach ($paths as $path) {
            $path = wp_parse_url($path, PHP_URL_PATH) ?: $path;
            $path = '/' . ltrim((string) $path, '/');
            $normalized[] = $path === '' ? '/' : $path;
        }

        return array_values(array_unique($normalized));
    }

    private function sanitize_datetime(string $value): string
    {
        $value = sanitize_text_field($value);
        if ($value === '') {
            return '';
        }

        $value = str_replace('T', ' ', $value);
        if (strlen($value) === 16) {
            $value .= ':00';
        }

        $timestamp = strtotime($value);
        if (!$timestamp) {
            return '';
        }

        return get_gmt_from_date($value, 'Y-m-d H:i:s');
    }

    private function parse_schedule_time(string $value): int
    {
        if ($value === '') {
            return 0;
        }

        return (int) strtotime($value . ' UTC');
    }

    private function get_client_ip(): string
    {
        if (!empty($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP)) {
            return (string) $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    private function is_preview_request(): bool
    {
        if (empty($_GET['kng_maintenance_preview'])) {
            return false;
        }

        if (!current_user_can('manage_options')) {
            return false;
        }

        $nonce = isset($_GET['_kng_preview_nonce']) ? sanitize_text_field(wp_unslash($_GET['_kng_preview_nonce'])) : '';
        if ($nonce === '' || !wp_verify_nonce($nonce, 'kng_maintenance_preview')) {
            return false;
        }

        return true;
    }

    private function is_pro(): bool
    {
        return function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code__premium_only();
    }

    private function redirect_with_message(string $view, string $message): void
    {
        $args = [
            'page' => 'king-addons-maintenance-mode',
            'view' => $view,
            'message' => $message,
        ];

        wp_safe_redirect(add_query_arg($args, admin_url('admin.php')));
        exit;
    }
}

```
