admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('ability_admin'), 'tier' => function_exists('ability_get_tier') ? ability_get_tier() : 'basic', 'isPro' => function_exists('ability_is_pro') ? ability_is_pro() : false, 'i18n' => [ 'saveStepFailed' => __('Failed to save step', 'ability'), 'unknownError' => __('Unknown error', 'ability'), 'completeSetup' => __('Completing setup...', 'ability'), 'completeSetupFailed' => __('Failed to complete setup.', 'ability'), 'skipConfirm' => __('Are you sure you want to skip the setup wizard? Default settings will be used.', 'ability'), 'skippingWizard' => __('Skipping wizard...', 'ability'), 'skipWizardFailed' => __('Failed to skip wizard.', 'ability'), 'working' => __('Working...', 'ability'), 'updating' => __('Updating...', 'ability'), 'settingsUpdated' => __('Settings Updated!', 'ability'), 'defaultsApplied' => __('Defaults applied.', 'ability'), ], ]); } public function maybe_redirect_to_wizard() { if (is_network_admin() || (defined('DOING_AJAX') && DOING_AJAX)) return; if (get_transient('ability_activation_redirect') && current_user_can('manage_options')) { delete_transient('ability_activation_redirect'); if (get_option('ability_wizard_done', 'no') === 'no') { wp_safe_redirect(admin_url('admin.php?page=ability-wizard')); exit; } } } /** * Adjust top-level wizard menu icon HTML to match requested markup. */ public function adjust_menu_icon_markup() { ?> render_limited_wizard(); return; } $wizard_done = get_option('ability_wizard_done', 'no') === 'yes'; if ($wizard_done) { $this->render_completed_prompt(); return; } // Load previously saved settings $wizard_settings = get_option('ability_wizard_settings', []); $is_pro = function_exists('ability_is_pro') ? ability_is_pro() : false; $free_scan_limit = class_exists('ABILITY\Config') ? \ABILITY\Config::get_free_scan_limit() : 5; ?>

>

✅

__('Insufficient permissions', 'ability')]); } if (!wp_verify_nonce(wp_unslash($_POST['nonce'] ?? ''), 'ability_admin')) { wp_send_json_error(['message' => __('Invalid nonce', 'ability')]); } $is_pro = function_exists('ability_is_pro') ? ability_is_pro() : false; $free_scan_limit = class_exists('ABILITY\Config') ? \ABILITY\Config::get_free_scan_limit() : 5; $requested_scan_limit = absint(wp_unslash($_POST['max_files_per_scan'] ?? $free_scan_limit)); $settings = [ 'scan_enabled' => !empty($_POST['scan_enabled']), 'scan_schedule' => sanitize_text_field(wp_unslash($_POST['scan_schedule'] ?? 'daily')), // Align with Config::get_defaults() and enforce edition limits server-side. 'max_files_per_scan' => $is_pro ? max(1, min(999, $requested_scan_limit ?: 999)) : max(1, min($free_scan_limit, $requested_scan_limit ?: $free_scan_limit)), 'auto_fix_enabled' => $is_pro && !empty($_POST['auto_fix_enabled']), 'widget_enabled' => !empty($_POST['widget_enabled']), 'widget_position' => sanitize_text_field(wp_unslash($_POST['widget_position'] ?? 'bottom-right')), 'widget_style' => sanitize_text_field(wp_unslash($_POST['widget_style'] ?? 'modern')), 'compliance_level' => sanitize_text_field(wp_unslash($_POST['compliance_level'] ?? 'wcag_2_1_aa')), 'generate_reports' => $is_pro && !empty($_POST['generate_reports']), ]; update_option('ability_wizard_settings', $settings, false); update_option('ability_wizard_done', 'yes'); // Update the authoritative runtime settings model. Keep the wizard's // generate_reports key for wizard-state compatibility while mapping it to // the canonical compliance_reports option used by the runtime/admin UI. if (class_exists('ABILITY\Config')) { $runtime_settings = $settings; $runtime_settings['compliance_reports'] = !empty($settings['generate_reports']); unset($runtime_settings['generate_reports']); \ABILITY\Config::update_settings($runtime_settings); } wp_send_json_success([ 'message' => __('Settings saved successfully.', 'ability'), 'redirect' => admin_url('admin.php?page=ability-dashboard'), ]); } public function ajax_skip_wizard() { if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Insufficient permissions', 'ability')]); } if (!wp_verify_nonce(wp_unslash($_POST['nonce'] ?? ''), 'ability_admin')) { wp_send_json_error(['message' => __('Invalid nonce', 'ability')]); } update_option('ability_wizard_done', 'yes'); wp_send_json_success([ 'message' => __('Wizard skipped. Using default settings.', 'ability'), 'redirect' => admin_url('admin.php?page=ability-dashboard'), ]); } public function ajax_save_wizard() { if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Insufficient permissions', 'ability')]); } if (!wp_verify_nonce(wp_unslash($_POST['nonce'] ?? ''), 'ability_admin')) { wp_send_json_error(['message' => __('Invalid nonce', 'ability')]); } $step = intval(wp_unslash($_POST['step'] ?? 0)); $raw = wp_unslash($_POST['data'] ?? '{}'); $data = is_string($raw) ? json_decode($raw, true) : (array)$raw; if (!is_array($data)) $data = []; if ($step < 1 || $step > 4) { wp_send_json_error(['message' => __('Invalid step number', 'ability')]); } $wizard_settings = get_option('ability_wizard_settings', []); switch ($step) { case 1: if (array_key_exists('scan_enabled', $data)) { $wizard_settings['scan_enabled'] = !empty($data['scan_enabled']); } if (array_key_exists('scan_schedule', $data)) { $wizard_settings['scan_schedule'] = sanitize_text_field($data['scan_schedule']); } if (array_key_exists('max_files_per_scan', $data)) { $is_pro = function_exists('ability_is_pro') ? ability_is_pro() : false; $free_scan_limit = class_exists('ABILITY\Config') ? \ABILITY\Config::get_free_scan_limit() : 5; $requested_scan_limit = absint($data['max_files_per_scan']); $wizard_settings['max_files_per_scan'] = $is_pro ? max(1, min(999, $requested_scan_limit ?: 999)) : max(1, min($free_scan_limit, $requested_scan_limit ?: $free_scan_limit)); } break; case 2: if (array_key_exists('widget_enabled', $data)) { $wizard_settings['widget_enabled'] = !empty($data['widget_enabled']); } if (array_key_exists('widget_position', $data)) { $wizard_settings['widget_position'] = sanitize_text_field($data['widget_position']); } break; case 3: if (array_key_exists('compliance_level', $data)) { $wizard_settings['compliance_level'] = sanitize_text_field($data['compliance_level']); } break; } update_option('ability_wizard_settings', $wizard_settings, false); wp_send_json_success([ 'message' => __('Step saved successfully', 'ability'), 'step' => $step, ]); } public function ajax_reset_wizard() { if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Insufficient permissions', 'ability')]); } if (!wp_verify_nonce(wp_unslash($_POST['nonce'] ?? ''), 'ability_admin')) { wp_send_json_error(['message' => __('Invalid nonce', 'ability')]); } update_option('ability_wizard_done', 'no'); delete_option('ability_wizard_settings'); wp_send_json_success([ 'message' => __('Wizard reset successfully. Page will refresh.', 'ability'), ]); } public function ajax_apply_defaults() { if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Insufficient permissions', 'ability')]); } if (!wp_verify_nonce(wp_unslash($_POST['nonce'] ?? ''), 'ability_admin')) { wp_send_json_error(['message' => __('Invalid nonce', 'ability')]); } $defaults = [ 'scan_enabled' => true, 'scan_schedule' => 'daily', 'max_files_per_scan' => class_exists('ABILITY\Config') ? \ABILITY\Config::get_scan_limit() : 5, 'auto_fix_enabled' => false, 'widget_enabled' => true, 'widget_position' => 'bottom-right', 'widget_style' => 'modern', 'compliance_level' => 'wcag_2_1_aa', 'generate_reports' => false, ]; update_option('ability_wizard_settings', $defaults, false); update_option('ability_wizard_done', 'yes'); if (class_exists('ABILITY\Config')) { $runtime_defaults = $defaults; $runtime_defaults['compliance_reports'] = false; unset($runtime_defaults['generate_reports']); \ABILITY\Config::update_settings($runtime_defaults); } wp_send_json_success([ 'message' => __('Defaults applied successfully. Page will refresh.', 'ability'), ]); } }