PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 2.6.2
MxChat – AI Chatbot & Content Generation for WordPress v2.6.2
3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 2.0.3 2.0.4 2.0.5 2.0.6 All 152 releases
← All changes | admin/class-ajax-handler.php +51 -478 3.2.72.6.2 View file →
@@ -40,90 +40,10 @@
40 40 add_action('wp_ajax_mxchat_update_intent_threshold', array($this, 'mxchat_update_intent_threshold'));
41 41
42 42 add_action('wp_ajax_mxchat_save_selected_bot', array($this, 'mxchat_save_selected_bot'));
43 43 add_action('wp_ajax_mxchat_check_api_keys', array($this, 'mxchat_check_api_keys'));
44 -
45 - // Debug & Optimization AJAX
46 - add_action('wp_ajax_mxchat_toggle_debug_mode', array($this, 'mxchat_toggle_debug_mode_callback'));
47 - add_action('wp_ajax_mxchat_get_debug_log', array($this, 'mxchat_get_debug_log_callback'));
48 - add_action('wp_ajax_mxchat_clear_debug_log', array($this, 'mxchat_clear_debug_log_callback'));
49 - add_action('wp_ajax_mxchat_export_settings', array($this, 'mxchat_export_settings_callback'));
50 - add_action('wp_ajax_mxchat_reset_all_settings', array($this, 'mxchat_reset_all_settings_callback'));
51 -
52 - // Custom (OpenAI-compatible) Provider connection test
53 - add_action('wp_ajax_mxchat_test_custom_provider', array($this, 'mxchat_test_custom_provider_callback'));
54 44 }
55 45
56 -/**
57 - * Test connection to a Custom (OpenAI-compatible) provider by hitting its /models endpoint
58 - * with whichever auth scheme the user configured. Reports model count or a clean error.
59 - */
60 -public function mxchat_test_custom_provider_callback() {
61 - check_ajax_referer('mxchat_test_custom_provider');
62 - if (!current_user_can('manage_options')) {
63 - wp_send_json_error(array('message' => esc_html__('Unauthorized', 'mxchat')));
64 - }
65 -
66 - $options = get_option('mxchat_options', array());
67 - $base_url = isset($options['custom_provider_base_url']) ? trim((string) $options['custom_provider_base_url']) : '';
68 - $api_key = isset($options['custom_provider_api_key']) ? trim((string) $options['custom_provider_api_key']) : '';
69 - $auth = isset($options['custom_provider_auth_scheme']) ? $options['custom_provider_auth_scheme'] : 'bearer';
70 - $api_version = isset($options['custom_provider_api_version']) ? trim((string) $options['custom_provider_api_version']) : '';
71 -
72 - if (empty($base_url)) {
73 - wp_send_json_error(array('message' => esc_html__('Base URL is empty. Save it first.', 'mxchat')));
74 - }
75 -
76 - $url = rtrim($base_url, '/') . '/models';
77 - if (!empty($api_version)) {
78 - $url = add_query_arg('api-version', $api_version, $url);
79 - }
80 -
81 - $headers = array('Content-Type' => 'application/json');
82 - if (!empty($api_key)) {
83 - if ($auth === 'api-key') {
84 - $headers['api-key'] = $api_key;
85 - } else {
86 - $headers['Authorization'] = 'Bearer ' . $api_key;
87 - }
88 - }
89 -
90 - $response = wp_remote_get($url, array(
91 - 'headers' => $headers,
92 - 'timeout' => 10,
93 - ));
94 -
95 - if (is_wp_error($response)) {
96 - wp_send_json_error(array('message' => sprintf(esc_html__('Network error: %s', 'mxchat'), esc_html($response->get_error_message()))));
97 - }
98 -
99 - $code = (int) wp_remote_retrieve_response_code($response);
100 - if ($code === 401 || $code === 403) {
101 - wp_send_json_error(array('message' => sprintf(esc_html__('Auth rejected (HTTP %d). Check API key and auth scheme.', 'mxchat'), $code)));
102 - }
103 - if ($code === 404) {
104 - wp_send_json_error(array('message' => esc_html__('Endpoint not found (HTTP 404). Check the Base URL.', 'mxchat')));
105 - }
106 - if ($code < 200 || $code >= 300) {
107 - wp_send_json_error(array('message' => sprintf(esc_html__('Upstream returned HTTP %d.', 'mxchat'), $code)));
108 - }
109 -
110 - $body = json_decode(wp_remote_retrieve_body($response), true);
111 - $count = 0;
112 - if (is_array($body)) {
113 - if (isset($body['data']) && is_array($body['data'])) {
114 - $count = count($body['data']);
115 - } elseif (isset($body['models']) && is_array($body['models'])) {
116 - $count = count($body['models']);
117 - }
118 - }
119 -
120 - wp_send_json_success(array(
121 - 'message' => sprintf(esc_html__('Connection OK — %d model(s) reported.', 'mxchat'), $count),
122 - 'count' => $count,
123 - ));
124 -}
125 -
126 46 // ========================================
127 47 // SETTINGS AJAX HANDLERS
128 48 // ========================================
129 49
@@ -152,17 +72,10 @@
152 72 // Load the full options array
153 73 $options = get_option('mxchat_options', []);
154 74 //error_log('MXChat Save: Current options array: ' . print_r($options, true));
155 75
156 - // Extract field name from mxchat_options[field_name] format if present
157 - // But preserve the full name for special cases like rate_limits that need the full path
158 - $field_name = $name;
159 - if (preg_match('/^mxchat_options\[([^\[\]]+)\]$/', $name, $matches)) {
160 - $field_name = $matches[1];
161 - }
162 -
163 76 // Handle special cases
164 - switch ($field_name) {
77 + switch ($name) {
165 78 case 'model':
166 79 //error_log('MXChat Save: Processing model selection');
167 80 //error_log('MXChat Save: Model value received: ' . $value);
168 81 //error_log('MXChat Save: Value type: ' . gettype($value));
@@ -174,15 +87,20 @@
174 87 //error_log('MXChat Save: Setting model to openrouter');
175 88 $options['model'] = 'openrouter';
176 89 } else {
177 90 //error_log('MXChat Save: Checking against whitelist');
178 - // Catalog refactor (plan-d14e89): canonical allowlist lives in
179 - // includes/class-mxchat-model-catalog.php. A new chat model
180 - // added there is automatically accepted by autosave.
181 - if (!class_exists('MxChat_Model_Catalog')) {
182 - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-mxchat-model-catalog.php';
183 - }
184 - $allowed_models = MxChat_Model_Catalog::chat_model_ids();
91 + $allowed_models = array(
92 + 'gemini-2.0-flash', 'gemini-2.0-flash-lite', 'gemini-1.5-pro', 'gemini-1.5-flash',
93 + 'grok-4-0709', 'grok-4-1-fast-reasoning', 'grok-4-1-fast-non-reasoning', 'grok-3-beta', 'grok-3-fast-beta', 'grok-3-mini-beta',
94 + 'grok-3-mini-fast-beta', 'grok-2',
95 + 'deepseek-chat',
96 + 'claude-sonnet-4-5-20250929', 'claude-opus-4-1-20250805', 'claude-haiku-4-5-20251001',
97 + 'claude-opus-4-20250514', 'claude-sonnet-4-20250514', 'claude-3-7-sonnet-20250219',
98 + 'claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-sonnet-20240229',
99 + 'claude-3-haiku-20240307',
100 + 'gpt-5.2', 'gpt-5.1-2025-11-13', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano', 'gpt-4.1-2025-04-14',
101 + 'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo',
102 + );
185 103
186 104 //error_log('MXChat Save: in_array result: ' . (in_array($value, $allowed_models) ? 'YES' : 'NO'));
187 105
188 106 if (in_array($value, $allowed_models)) {
@@ -221,9 +139,9 @@
221 139 case 'additional_popular_questions':
222 140 //error_log('MXChat Save: Processing additional_popular_questions');
223 141 $questions = json_decode($value, true); // No need for stripslashes here
224 142 if (is_array($questions)) {
225 - $options[$field_name] = $questions;
143 + $options[$name] = $questions;
226 144 // Also update old option for backwards compatibility
227 145 update_option('additional_popular_questions', $questions);
228 146 //error_log('MXChat Save: Saved ' . count($questions) . ' additional questions');
229 147 } else {
@@ -232,59 +150,56 @@
232 150 break;
233 151 case 'email_blocker_header_content':
234 152 //error_log('MXChat Save: Processing email_blocker_header_content');
235 153 // Allow HTML content but sanitize it safely
236 - $options[$field_name] = wp_kses_post($value);
154 + $options[$name] = wp_kses_post($value);
237 155 break;
238 156 case 'email_blocker_button_text':
239 157 //error_log('MXChat Save: Processing email_blocker_button_text');
240 - $options[$field_name] = sanitize_text_field($value);
158 + $options[$name] = sanitize_text_field($value);
241 159 break;
242 160 case 'name_field_placeholder':
243 161 //error_log('MXChat Save: Processing name_field_placeholder');
244 - $options[$field_name] = sanitize_text_field($value);
162 + $options[$name] = sanitize_text_field($value);
245 163 break;
246 164 case 'similarity_threshold':
247 165 //error_log('MXChat Save: Processing similarity_threshold');
248 - // Validate and save - enforce min 20, max 85
249 - $threshold = intval($value);
250 - if ($threshold < 20) $threshold = 20;
251 - if ($threshold > 85) $threshold = 85;
252 - $options[$field_name] = $threshold;
166 + // Save to the options array
167 + $options[$name] = $value;
253 168 break;
254 - case 'rag_sources_limit':
255 - //error_log('MXChat Save: Processing rag_sources_limit');
256 - // Validate and save - enforce min 3, max 10, default 6
257 - $rag_limit = intval($value);
258 - if ($rag_limit < 3) $rag_limit = 3;
259 - if ($rag_limit > 10) $rag_limit = 10;
260 - $options[$field_name] = $rag_limit;
169 + case 'user_message_bg_color':
170 + case 'user_message_font_color':
171 + case 'bot_message_bg_color':
172 + case 'bot_message_font_color':
173 + case 'top_bar_bg_color':
174 + case 'send_button_font_color':
175 + case 'chatbot_background_color':
176 + case 'icon_color':
177 + case 'chat_input_font_color':
178 + case 'live_agent_message_bg_color':
179 + case 'live_agent_message_font_color':
180 + case 'mode_indicator_bg_color':
181 + case 'mode_indicator_font_color':
182 + case 'toolbar_icon_color':
183 + case 'quick_questions_toggle_color':
184 + //error_log('MXChat Save: Processing color value: ' . $name);
185 + // Store color values directly
186 + $options[$name] = $value;
261 187 break;
262 - case 'rag_chunks_limit':
263 - // Validate and save - enforce min 8, max 20, default 15
264 - $chunks_limit = intval($value);
265 - if ($chunks_limit < 8) $chunks_limit = 8;
266 - if ($chunks_limit > 20) $chunks_limit = 20;
267 - $options[$field_name] = $chunks_limit;
268 - break;
269 188 case 'live_agent_status':
270 189 //error_log('MXChat Save: Processing live_agent_status');
271 190 // Set the new value
272 - $options[$field_name] = ($value === 'on') ? 'on' : 'off';
191 + $options[$name] = ($value === 'on') ? 'on' : 'off';
273 192 break;
274 - case 'enable_web_search':
275 - //error_log('MXChat Save: Processing enable_web_search');
276 - $options[$field_name] = ($value === 'on') ? 'on' : 'off';
277 - break;
278 193 case 'enable_woocommerce_integration':
279 194 //error_log('MXChat Save: Processing enable_woocommerce_integration');
280 195 // Handle values that used to be 1/0
281 - $options[$field_name] = ($value === 'on' || $value === '1') ? 'on' : 'off';
196 + $options[$name] = ($value === 'on' || $value === '1') ? 'on' : 'off';
282 197 break;
283 198 case 'post_type_visibility_mode':
284 199 // Validate mode value
285 200 $allowed_modes = array('all', 'include', 'exclude');
286 - $options[$field_name] = in_array($value, $allowed_modes) ? $value : 'all';
201 + $options[$name] = in_array($value, $allowed_modes) ? $value : 'all';
287 202 break;
288 203 case 'post_type_visibility_list':
289 204 // Handle JSON array of post types
290 205 $post_types = json_decode($value, true);
@@ -289,93 +204,16 @@
289 204 // Handle JSON array of post types
290 205 $post_types = json_decode($value, true);
291 206 if (is_array($post_types)) {
292 207 // Sanitize each post type slug
293 - $options[$field_name] = array_map('sanitize_key', $post_types);
208 + $options[$name] = array_map('sanitize_key', $post_types);
294 209 } else {
295 - $options[$field_name] = array();
210 + $options[$name] = array();
296 211 }
297 212 break;
298 - case 'script_loading_strategy':
299 - // Validate script loading strategy value
300 - $allowed_strategies = array('default', 'defer', 'delay_1s', 'delay_3s', 'delay_5s', 'on_interaction');
301 - $options[$field_name] = in_array($value, $allowed_strategies) ? $value : 'default';
302 - break;
303 - case 'auto_retry_on_transient_error':
304 - // Boolean toggle — accept 1/0/on/off, default to '1' if any truthy value.
305 - $options[$field_name] = ($value === '1' || $value === 'on' || $value === 1 || $value === true) ? '1' : '0';
306 - break;
307 213 default:
308 - // Handle transcripts options
309 - if (strpos($name, 'mxchat_transcripts_options') !== false) {
310 - // Extract field name from mxchat_transcripts_options[field_name]
311 - if (preg_match('/mxchat_transcripts_options\[([^\]]+)\]/', $name, $matches)) {
312 - $field_name = $matches[1];
313 -
314 - // Get current transcripts options
315 - $transcripts_options = get_option('mxchat_transcripts_options', array());
316 -
317 - // Ensure it's an array
318 - if (!is_array($transcripts_options)) {
319 - $transcripts_options = array();
320 - }
321 -
322 - // Handle checkbox values (convert 'on'/'off' to 1/0)
323 - if ($value === 'on' || $value === '1') {
324 - $transcripts_options[$field_name] = 1;
325 - } else if ($value === 'off' || $value === '0' || $value === '') {
326 - $transcripts_options[$field_name] = 0;
327 - } else {
328 - // For text/select fields, sanitize appropriately
329 - if ($field_name === 'mxchat_notification_email') {
330 - $transcripts_options[$field_name] = sanitize_email($value);
331 - } else {
332 - $transcripts_options[$field_name] = sanitize_text_field($value);
333 - }
334 - }
335 -
336 - // Use direct database update to bypass any filters
337 - global $wpdb;
338 -
339 - // Serialize the options array
340 - $serialized = maybe_serialize($transcripts_options);
341 -
342 - // Check if the option already exists in the database
343 - $existing = $wpdb->get_var("SELECT option_id FROM {$wpdb->options} WHERE option_name = 'mxchat_transcripts_options'");
344 -
345 - if ($existing) {
346 - // Option exists, do an update
347 - $result = $wpdb->update(
348 - $wpdb->options,
349 - array('option_value' => $serialized),
350 - array('option_name' => 'mxchat_transcripts_options'),
351 - array('%s'),
352 - array('%s')
353 - );
354 - } else {
355 - // Option doesn't exist (new install), do an insert
356 - $result = $wpdb->insert(
357 - $wpdb->options,
358 - array(
359 - 'option_name' => 'mxchat_transcripts_options',
360 - 'option_value' => $serialized,
361 - 'autoload' => 'yes'
362 - ),
363 - array('%s', '%s', '%s')
364 - );
365 - }
366 -
367 - // Clear all caches after direct DB update
368 - wp_cache_delete('mxchat_transcripts_options', 'options');
369 - wp_cache_delete('alloptions', 'options');
370 - wp_cache_flush();
371 -
372 - wp_send_json_success(['message' => esc_html__('Setting saved', 'mxchat')]);
373 - return;
374 - }
375 - }
376 214 // First check for rate limits settings
377 - else if (strpos($name, 'mxchat_options[rate_limits]') !== false) {
215 + if (strpos($name, 'mxchat_options[rate_limits]') !== false) {
378 216 //error_log('MXChat Save: Detected rate_limits field: ' . $name);
379 217
380 218 // Extract role ID and setting from the name
381 219 preg_match('/\[rate_limits\]\[(.*?)\]\[(.*?)\]/', $name, $matches);
@@ -430,10 +268,10 @@
430 268 } else {
431 269 //error_log('MXChat Save: Failed to parse role_rate_limits pattern: ' . $name);
432 270 }
433 271 }
434 - // Handle toggles - check both extracted field_name and original name for toggle detection
435 - else if (strpos($field_name, 'toggle') !== false || in_array($field_name, [
272 + // Handle toggles
273 + else if (strpos($name, 'toggle') !== false || in_array($name, [
436 274 'chat_persistence_toggle',
437 275 'privacy_toggle',
438 276 'complianz_toggle',
439 277 'chat_toolbar_toggle',
@@ -440,20 +278,17 @@
440 278 'show_pdf_upload_button',
441 279 'show_word_upload_button',
442 280 'enable_streaming_toggle',
443 281 'contextual_awareness_toggle',
444 - 'citation_links_toggle',
445 282 'enable_email_block',
446 - 'enable_name_field',
447 - 'custom_provider_for_embeddings',
448 - 'custom_provider_for_images'
283 + 'enable_name_field'
449 284 ])) {
450 - //error_log('MXChat Save: Processing toggle: ' . $field_name);
451 - $options[$field_name] = ($value === 'on') ? 'on' : 'off';
285 + //error_log('MXChat Save: Processing toggle: ' . $name);
286 + $options[$name] = ($value === 'on') ? 'on' : 'off';
452 287 } else {
453 - //error_log('MXChat Save: Processing standard field: ' . $field_name);
454 - // Store all other values directly using the extracted field name
455 - $options[$field_name] = $value;
288 + //error_log('MXChat Save: Processing standard field: ' . $name);
289 + // Store all other values directly
290 + $options[$name] = $value;
456 291 }
457 292 break;
458 293 }
459 294
@@ -461,20 +296,8 @@
461 296 $updated = update_option('mxchat_options', $options);
462 297 //error_log('MXChat Save: Update result: ' . ($updated ? 'success' : 'unchanged') . ' for field: ' . $name);
463 298 //error_log('MXChat Save: Updated options array: ' . print_r($options, true));
464 299
465 - // Log the save action if debug mode is enabled
466 - if ( class_exists( 'MxChat_Admin' ) ) {
467 - MxChat_Admin::mxchat_log_debug(
468 - 'settings_save',
469 - sprintf( 'Field saved: %s', $field_name ),
470 - array(
471 - 'field' => $field_name,
472 - 'updated' => $updated,
473 - )
474 - );
475 - }
476 -
477 300 // Always return success even if WordPress says nothing changed
478 301 // (which happens when the value is the same as before)
479 302 wp_send_json_success(['message' => esc_html__('Setting saved', 'mxchat')]);
480 303 }
@@ -678,123 +501,8 @@
678 501 wp_send_json_error(['message' => esc_html__('No changes detected', 'mxchat')]);
679 502 }
680 503 }
681 504
682 - // Handle chunking settings - use direct DB access to bypass WordPress filters
683 - if (strpos($name, 'mxchat_chunk') === 0 || $name === 'mxchat_chunking_enabled') {
684 - global $wpdb;
685 -
686 - // Get current options directly from database
687 - $current_options_raw = $wpdb->get_var(
688 - $wpdb->prepare(
689 - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s",
690 - 'mxchat_options'
691 - )
692 - );
693 -
694 - $options = $current_options_raw !== null ? maybe_unserialize($current_options_raw) : array();
695 - if (!is_array($options)) {
696 - $options = array();
697 - }
698 -
699 - // Update the specific chunking field
700 - if ($name === 'mxchat_chunking_enabled') {
701 - $options['chunking_enabled'] = in_array($value, array('on', '1', 'true', true), true);
702 - } elseif ($name === 'mxchat_chunk_size') {
703 - $options['chunk_size'] = max(1000, min(10000, intval($value)));
704 - }
705 -
706 - // Save directly to database
707 - $serialized_options = maybe_serialize($options);
708 -
709 - $option_exists = $wpdb->get_var(
710 - $wpdb->prepare(
711 - "SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name = %s",
712 - 'mxchat_options'
713 - )
714 - );
715 -
716 - if ($option_exists > 0) {
717 - $save_result = $wpdb->update(
718 - $wpdb->options,
719 - array('option_value' => $serialized_options),
720 - array('option_name' => 'mxchat_options'),
721 - array('%s'),
722 - array('%s')
723 - );
724 - } else {
725 - $save_result = $wpdb->insert(
726 - $wpdb->options,
727 - array(
728 - 'option_name' => 'mxchat_options',
729 - 'option_value' => $serialized_options,
730 - 'autoload' => 'yes'
731 - ),
732 - array('%s', '%s', '%s')
733 - );
734 - }
735 -
736 - // Clear object cache for this option
737 - wp_cache_delete('mxchat_options', 'options');
738 -
739 - if ($save_result !== false) {
740 - wp_send_json_success(['message' => esc_html__('Chunking setting saved', 'mxchat')]);
741 - } else {
742 - wp_send_json_error(['message' => esc_html__('Failed to save chunking setting', 'mxchat')]);
743 - }
744 - return;
745 - }
746 -
747 - // Handle ACF field exclusion toggles
748 - if (strpos($name, 'mxchat_acf_field_') === 0) {
749 - // Extract field name from the input name (e.g., mxchat_acf_field_private_notes -> private_notes)
750 - $field_name = str_replace('mxchat_acf_field_', '', $name);
751 - $is_enabled = ($value === 'on' || $value === '1');
752 -
753 - // Get current excluded fields
754 - $excluded_fields = get_option('mxchat_acf_excluded_fields', array());
755 - if (!is_array($excluded_fields)) {
756 - $excluded_fields = array();
757 - }
758 -
759 - if ($is_enabled) {
760 - // Remove from exclusion list (field should be included)
761 - $excluded_fields = array_values(array_diff($excluded_fields, array($field_name)));
762 - } else {
763 - // Add to exclusion list (field should be excluded)
764 - if (!in_array($field_name, $excluded_fields)) {
765 - $excluded_fields[] = $field_name;
766 - }
767 - }
768 -
769 - $updated = update_option('mxchat_acf_excluded_fields', $excluded_fields);
770 -
771 - if ($updated || true) { // Always report success since the state may already be correct
772 - wp_send_json_success([
773 - 'message' => $is_enabled
774 - ? sprintf(esc_html__('Field "%s" will be included in imports', 'mxchat'), $field_name)
775 - : sprintf(esc_html__('Field "%s" will be excluded from imports', 'mxchat'), $field_name)
776 - ]);
777 - } else {
778 - wp_send_json_error(['message' => esc_html__('Failed to save ACF field setting', 'mxchat')]);
779 - }
780 - return;
781 - }
782 -
783 - // Handle custom post meta whitelist
784 - if ($name === 'mxchat_custom_meta_whitelist') {
785 - $updated = update_option('mxchat_custom_meta_whitelist', sanitize_textarea_field($value));
786 -
787 - if ($updated || true) { // Always report success since the state may already be correct
788 - wp_send_json_success([
789 - 'message' => esc_html__('Custom meta whitelist saved', 'mxchat')
790 - ]);
791 - } else {
792 - wp_send_json_error(['message' => esc_html__('Failed to save custom meta whitelist', 'mxchat')]);
793 - }
794 - return;
795 - }
796 -
797 505 // Handle other prompts options
798 506 $options = get_option('mxchat_prompts_options', []);
799 507 $options[$name] = $value;
800 508 $updated = update_option('mxchat_prompts_options', $options);
@@ -1208,143 +916,8 @@
1208 916 'voyage' => !empty($options['voyage_api_key'])
1209 917 );
1210 918
1211 919 wp_send_json_success($api_key_status);
1212 - }
1213 -
1214 - // ========================================
1215 - // DEBUG & OPTIMIZATION AJAX HANDLERS
1216 - // ========================================
1217 -
1218 - /**
1219 - * Toggle debug mode on/off
1220 - */
1221 - public function mxchat_toggle_debug_mode_callback() {
1222 - // Verify nonce
1223 - if ( ! check_ajax_referer( 'mxchat_save_setting_nonce', '_ajax_nonce', false ) ) {
1224 - wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'mxchat' ) ) );
1225 - }
1226 -
1227 - // Check permissions
1228 - if ( ! current_user_can( 'manage_options' ) ) {
1229 - wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'mxchat' ) ) );
1230 - }
1231 -
1232 - $enabled = isset( $_POST['enabled'] ) && $_POST['enabled'] === 'on';
1233 -
1234 - $options = get_option( 'mxchat_options', array() );
1235 -
1236 - if ( $enabled ) {
1237 - $options['debug_mode'] = 'on';
1238 - update_option( 'mxchat_options', $options );
1239 - MxChat_Admin::mxchat_log_debug( 'debug_mode', 'Debug mode enabled' );
1240 - } else {
1241 - // Log before disabling
1242 - MxChat_Admin::mxchat_log_debug( 'debug_mode', 'Debug mode disabled' );
1243 - $options['debug_mode'] = 'off';
1244 - update_option( 'mxchat_options', $options );
1245 - }
1246 -
1247 - wp_send_json_success( array(
1248 - 'message' => $enabled ? esc_html__( 'Debug mode enabled', 'mxchat' ) : esc_html__( 'Debug mode disabled', 'mxchat' ),
1249 - 'enabled' => $enabled,
1250 - ) );
1251 - }
1252 -
1253 - /**
1254 - * Get the debug log entries
1255 - */
1256 - public function mxchat_get_debug_log_callback() {
1257 - // Verify nonce
1258 - if ( ! check_ajax_referer( 'mxchat_save_setting_nonce', '_ajax_nonce', false ) ) {
1259 - wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'mxchat' ) ) );
1260 - }
1261 -
1262 - // Check permissions
1263 - if ( ! current_user_can( 'manage_options' ) ) {
1264 - wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'mxchat' ) ) );
1265 - }
1266 -
1267 - $log = MxChat_Admin::mxchat_get_debug_log();
1268 -
1269 - wp_send_json_success( array(
1270 - 'log' => $log,
1271 - 'count' => count( $log ),
1272 - ) );
1273 - }
1274 -
1275 - /**
1276 - * Clear the debug log
1277 - */
1278 - public function mxchat_clear_debug_log_callback() {
1279 - // Verify nonce
1280 - if ( ! check_ajax_referer( 'mxchat_save_setting_nonce', '_ajax_nonce', false ) ) {
1281 - wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'mxchat' ) ) );
1282 - }
1283 -
1284 - // Check permissions
1285 - if ( ! current_user_can( 'manage_options' ) ) {
1286 - wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'mxchat' ) ) );
1287 - }
1288 -
1289 - MxChat_Admin::mxchat_clear_debug_log();
1290 -
1291 - // Log that the log was cleared (this will be the first entry in the new log)
1292 - MxChat_Admin::mxchat_log_debug( 'debug_log', 'Debug log cleared by user' );
1293 -
1294 - wp_send_json_success( array( 'message' => esc_html__( 'Debug log cleared', 'mxchat' ) ) );
1295 - }
1296 -
1297 - /**
1298 - * Export settings as JSON
1299 - */
1300 - public function mxchat_export_settings_callback() {
1301 - // Verify nonce
1302 - if ( ! check_ajax_referer( 'mxchat_save_setting_nonce', '_ajax_nonce', false ) ) {
1303 - wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'mxchat' ) ) );
1304 - }
1305 -
1306 - // Check permissions
1307 - if ( ! current_user_can( 'manage_options' ) ) {
1308 - wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'mxchat' ) ) );
1309 - }
1310 -
1311 - $export = MxChat_Admin::mxchat_export_settings();
1312 -
1313 - // Log the export
1314 - MxChat_Admin::mxchat_log_debug( 'settings_export', 'Settings exported by user' );
1315 -
1316 - wp_send_json_success( array(
1317 - 'settings' => $export,
1318 - 'filename' => 'mxchat-settings-' . gmdate( 'Y-m-d-His' ) . '.json',
1319 - ) );
1320 - }
1321 -
1322 - /**
1323 - * Reset all settings to defaults
1324 - */
1325 - public function mxchat_reset_all_settings_callback() {
1326 - // Verify nonce
1327 - if ( ! check_ajax_referer( 'mxchat_save_setting_nonce', '_ajax_nonce', false ) ) {
1328 - wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'mxchat' ) ) );
1329 - }
1330 -
1331 - // Check permissions
1332 - if ( ! current_user_can( 'manage_options' ) ) {
1333 - wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'mxchat' ) ) );
1334 - }
1335 -
1336 - // Require confirmation code
1337 - $confirmation = isset( $_POST['confirmation'] ) ? sanitize_text_field( wp_unslash( $_POST['confirmation'] ) ) : '';
1338 -
1339 - if ( strtoupper( $confirmation ) !== 'RESET' ) {
1340 - wp_send_json_error( array( 'message' => esc_html__( 'Invalid confirmation code. Please type RESET to confirm.', 'mxchat' ) ) );
1341 - }
1342 -
1343 - // Perform the reset
1344 - MxChat_Admin::mxchat_reset_all_settings();
1345 -
1346 - wp_send_json_success( array( 'message' => esc_html__( 'All settings have been reset to defaults. The page will reload.', 'mxchat' ) ) );
1347 920 }
1348 921
1349 922 }
1350 923