PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 2.5.1
MxChat – AI Chatbot & Content Generation for WordPress v2.5.1
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
mxchat-basic / mxchat-basic.php

mxchat-basic.php in MxChat – AI Chatbot & Content Generation for WordPress 2.5.1, at mxchat-basic.php

748 lines 26.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: MxChat
4 * Plugin URI: https://mxchat.ai/
5 * Description: AI chatbot for WordPress with OpenAI, Claude, xAI, DeepSeek, live agent, PDF uploads, WooCommerce, and training on website data.
6 * Version: 2.5.1
7 * Author: MxChat
8 * Author URI: https://mxchat.ai
9 * License: GPLv2 or later
10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
11 * Text Domain: mxchat
12 * Domain Path: /languages
13 */
14
15 if (!defined('ABSPATH')) {
16 exit; // Exit if accessed directly.
17 }
18
19 // Define plugin version constant for asset versioning
20 define('MXCHAT_VERSION', '2.5.1');
21
22 function mxchat_load_textdomain() {
23 load_plugin_textdomain('mxchat', false, dirname(plugin_basename(__FILE__)) . '/languages');
24 }
25 add_action('init', 'mxchat_load_textdomain');
26
27 // Include classes with error handling
28 function mxchat_include_classes() {
29 $class_files = array(
30 'includes/class-mxchat-integrator.php',
31 'includes/class-mxchat-admin.php',
32 'includes/class-mxchat-public.php',
33 'includes/class-mxchat-utils.php',
34 'includes/class-mxchat-user.php',
35 'includes/class-mxchat-meta-box.php',
36 'includes/pdf-parser/alt_autoload.php',
37 'includes/class-mxchat-word-handler.php',
38 'admin/class-ajax-handler.php',
39 'admin/class-pinecone-manager.php',
40 'admin/class-knowledge-manager.php'
41 );
42
43 foreach ($class_files as $file) {
44 $file_path = plugin_dir_path(__FILE__) . $file;
45 if (file_exists($file_path)) {
46 require_once $file_path;
47 } else {
48 //error_log('MxChat: Missing class file - ' . $file);
49 }
50 }
51 }
52
53 /**
54 * Create URL click tracking table
55 */
56 function mxchat_create_url_clicks_table() {
57 global $wpdb;
58
59 $table_name = $wpdb->prefix . 'mxchat_url_clicks';
60
61 $charset_collate = $wpdb->get_charset_collate();
62
63 $sql = "CREATE TABLE $table_name (
64 id mediumint(9) NOT NULL AUTO_INCREMENT,
65 session_id varchar(100) NOT NULL,
66 clicked_url text NOT NULL,
67 message_context text,
68 click_timestamp datetime DEFAULT CURRENT_TIMESTAMP,
69 user_ip varchar(45),
70 user_agent text,
71 PRIMARY KEY (id),
72 KEY session_id (session_id),
73 KEY click_timestamp (click_timestamp)
74 ) $charset_collate;";
75
76 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
77 dbDelta($sql);
78 }
79
80 /**
81 * FIXED: Robust table creation and column management
82 */
83 function mxchat_create_chat_transcripts_table() {
84 global $wpdb;
85
86 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
87 $charset_collate = $wpdb->get_charset_collate();
88
89 // Create table with ALL columns including user_name from the start
90 $sql = "CREATE TABLE $table_name (
91 id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
92 user_id MEDIUMINT(9) DEFAULT 0,
93 session_id VARCHAR(255) NOT NULL,
94 role VARCHAR(255) NOT NULL,
95 message TEXT NOT NULL,
96 user_email VARCHAR(255) DEFAULT NULL,
97 user_name VARCHAR(100) DEFAULT NULL,
98 user_identifier VARCHAR(255) DEFAULT NULL,
99 originating_page_url TEXT DEFAULT NULL,
100 originating_page_title VARCHAR(500) DEFAULT NULL,
101 timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
102 PRIMARY KEY (id),
103 KEY session_id (session_id),
104 KEY user_email (user_email),
105 KEY timestamp (timestamp)
106 ) $charset_collate;";
107
108 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
109 $result = dbDelta($sql);
110
111 // Log the result for debugging
112 if (empty($result)) {
113 //error_log("MxChat: dbDelta returned empty result for chat transcripts table");
114 } else {
115 //error_log("MxChat: dbDelta result: " . print_r($result, true));
116 }
117
118 // IMPORTANT: Ensure all columns exist for existing installations
119 mxchat_ensure_all_columns($table_name);
120 }
121
122 /**
123 * Ensure all required columns exist (for upgrades)
124 */
125 function mxchat_ensure_all_columns($table_name) {
126 global $wpdb;
127
128 // First check if table exists
129 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name;
130 if (!$table_exists) {
131 //error_log("MxChat: Table $table_name does not exist, cannot add columns");
132 return;
133 }
134
135 // Define all required columns and their types
136 $required_columns = [
137 'user_identifier' => 'VARCHAR(255) DEFAULT NULL',
138 'user_email' => 'VARCHAR(255) DEFAULT NULL',
139 'user_name' => 'VARCHAR(100) DEFAULT NULL',
140 'originating_page_url' => 'TEXT DEFAULT NULL',
141 'originating_page_title' => 'VARCHAR(500) DEFAULT NULL'
142 ];
143
144 // Get existing columns
145 $existing_columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name");
146 if (empty($existing_columns)) {
147 //error_log("MxChat: Could not get columns for table $table_name");
148 return;
149 }
150
151 $existing_column_names = array_column($existing_columns, 'Field');
152
153 // Add missing columns
154 foreach ($required_columns as $column_name => $column_definition) {
155 if (!in_array($column_name, $existing_column_names)) {
156 $alter_sql = "ALTER TABLE $table_name ADD COLUMN $column_name $column_definition";
157 $result = $wpdb->query($alter_sql);
158
159 if ($result === false) {
160 //error_log("MxChat: Failed to add column $column_name to $table_name. Error: " . $wpdb->last_error);
161 } else {
162 //error_log("MxChat: Successfully added column $column_name to $table_name");
163 }
164 }
165 }
166 }
167
168 /**
169 * Add role restriction column to knowledge base table
170 */
171 function mxchat_add_role_restriction_column() {
172 global $wpdb;
173 $table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
174
175 // Check if table exists first
176 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name;
177 if (!$table_exists) {
178 //error_log("MxChat: System prompt content table does not exist, cannot add role_restriction column");
179 return;
180 }
181
182 // Check if column already exists
183 $column_exists = $wpdb->get_results(
184 $wpdb->prepare(
185 "SHOW COLUMNS FROM {$table_name} LIKE %s",
186 'role_restriction'
187 )
188 );
189
190 if (empty($column_exists)) {
191 $alter_sql = "ALTER TABLE {$table_name} ADD COLUMN role_restriction VARCHAR(50) DEFAULT 'public' AFTER source_url";
192 $result = $wpdb->query($alter_sql);
193
194 if ($result === false) {
195 //error_log("MxChat: Failed to add role_restriction column. Error: " . $wpdb->last_error);
196 } else {
197 //error_log("MxChat: Successfully added role_restriction column");
198
199 // Set all existing records to 'public' (everyone can access)
200 $update_result = $wpdb->query(
201 "UPDATE {$table_name}
202 SET role_restriction = 'public'
203 WHERE role_restriction IS NULL OR role_restriction = ''"
204 );
205
206 if ($update_result !== false) {
207 //error_log("MxChat: Updated {$update_result} existing records to public access");
208 }
209 }
210 }
211 }
212
213 /**
214 * NEW: Add enabled_bots column to intents table for multi-bot action filtering
215 */
216 function mxchat_add_enabled_bots_column() {
217 global $wpdb;
218 $table_name = $wpdb->prefix . 'mxchat_intents';
219
220 // Check if table exists first
221 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name;
222 if (!$table_exists) {
223 //error_log("MxChat: Intents table does not exist, cannot add enabled_bots column");
224 return;
225 }
226
227 // Check if column already exists
228 $column_exists = $wpdb->get_results(
229 $wpdb->prepare(
230 "SHOW COLUMNS FROM {$table_name} LIKE %s",
231 'enabled_bots'
232 )
233 );
234
235 if (empty($column_exists)) {
236 $alter_sql = "ALTER TABLE {$table_name} ADD COLUMN enabled_bots LONGTEXT DEFAULT NULL AFTER enabled";
237 $result = $wpdb->query($alter_sql);
238
239 if ($result === false) {
240 //error_log("MxChat: Failed to add enabled_bots column. Error: " . $wpdb->last_error);
241 } else {
242 //error_log("MxChat: Successfully added enabled_bots column");
243
244 // Set all existing actions to work with 'default' bot for backward compatibility
245 $default_bots = json_encode(['default']);
246 $update_result = $wpdb->query(
247 $wpdb->prepare(
248 "UPDATE {$table_name}
249 SET enabled_bots = %s
250 WHERE enabled_bots IS NULL OR enabled_bots = ''",
251 $default_bots
252 )
253 );
254
255 if ($update_result !== false) {
256 //error_log("MxChat: Updated {$update_result} existing actions to work with default bot");
257 }
258 }
259 }
260 }
261
262 /**
263 * Create Pinecone role restrictions table
264 */
265 function mxchat_create_pinecone_roles_table() {
266 global $wpdb;
267
268 $table_name = $wpdb->prefix . 'mxchat_pinecone_roles';
269 $charset_collate = $wpdb->get_charset_collate();
270
271 $sql = "CREATE TABLE $table_name (
272 id mediumint(9) NOT NULL AUTO_INCREMENT,
273 vector_id varchar(255) NOT NULL,
274 source_url text,
275 role_restriction varchar(50) DEFAULT 'public',
276 updated_at timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
277 PRIMARY KEY (id),
278 UNIQUE KEY vector_id (vector_id),
279 KEY role_restriction (role_restriction)
280 ) $charset_collate;";
281
282 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
283 dbDelta($sql);
284 }
285
286 /**
287 * Migrate deprecated AI models to their replacements
288 * Version 2.5.1: Migrate Claude 3.5 Sonnet (deprecated) to Claude 3.7 Sonnet
289 */
290 function mxchat_migrate_deprecated_models() {
291 $options = get_option('mxchat_options', array());
292
293 // Check if model is set and is the deprecated Claude 3.5 Sonnet
294 if (isset($options['model']) && $options['model'] === 'claude-3-5-sonnet-20241022') {
295 // Update to Claude 3.7 Sonnet (the replacement model)
296 $options['model'] = 'claude-3-7-sonnet-20250219';
297 update_option('mxchat_options', $options);
298
299 // Set a flag to show admin notice
300 update_option('mxchat_model_migrated_notice', true);
301
302 //error_log('MxChat: Migrated deprecated Claude 3.5 Sonnet to Claude 3.7 Sonnet');
303 }
304 }
305
306 /**
307 * Show admin notice after model migration
308 */
309 function mxchat_show_migration_notice() {
310 if (get_option('mxchat_model_migrated_notice')) {
311 ?>
312 <div class="notice notice-info is-dismissible">
313 <p>
314 <strong><?php esc_html_e('MxChat Model Updated', 'mxchat'); ?></strong><br>
315 <?php esc_html_e('Your chatbot model has been automatically updated from Claude 3.5 Sonnet to Claude 3.7 Sonnet due to the deprecation of the previous model by Anthropic. Claude 3.7 Sonnet offers improved performance and capabilities.', 'mxchat'); ?>
316 </p>
317 </div>
318 <?php
319 delete_option('mxchat_model_migrated_notice');
320 }
321 }
322
323 function mxchat_activate() {
324 global $wpdb;
325 $charset_collate = $wpdb->get_charset_collate();
326
327 //error_log("MxChat: Running activation function");
328
329 // Create chat transcripts table with improved function
330 mxchat_create_chat_transcripts_table();
331
332 // System Prompt Content Table
333 $system_prompt_table = $wpdb->prefix . 'mxchat_system_prompt_content';
334 $sql_system_prompt = "CREATE TABLE $system_prompt_table (
335 id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
336 url VARCHAR(255) NOT NULL,
337 article_content LONGTEXT NOT NULL,
338 embedding_vector LONGTEXT,
339 source_url VARCHAR(255) DEFAULT NULL,
340 role_restriction VARCHAR(50) DEFAULT 'public',
341 timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
342 PRIMARY KEY (id)
343 ) $charset_collate;";
344
345 // Intents Table - NOW INCLUDES enabled_bots column from the start
346 $intents_table = $wpdb->prefix . 'mxchat_intents';
347 $sql_intents_table = "CREATE TABLE $intents_table (
348 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
349 intent_label VARCHAR(255) NOT NULL,
350 phrases TEXT NOT NULL,
351 embedding_vector LONGTEXT NOT NULL,
352 callback_function VARCHAR(255) NOT NULL,
353 similarity_threshold FLOAT DEFAULT 0.85,
354 enabled TINYINT(1) NOT NULL DEFAULT 1,
355 enabled_bots LONGTEXT DEFAULT NULL,
356 PRIMARY KEY (id)
357 ) $charset_collate;";
358
359 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
360
361 // Create other tables
362 dbDelta($sql_system_prompt);
363 dbDelta($sql_intents_table);
364
365 // Create URL click tracking table
366 mxchat_create_url_clicks_table();
367
368 //Create Pinecone roles table
369 mxchat_create_pinecone_roles_table();
370
371 // Ensure additional columns in system prompt table
372 $existing_system_columns = $wpdb->get_results("SHOW COLUMNS FROM $system_prompt_table");
373 if (!empty($existing_system_columns)) {
374 $existing_system_column_names = array_column($existing_system_columns, 'Field');
375
376 if (!in_array('embedding_vector', $existing_system_column_names)) {
377 $wpdb->query("ALTER TABLE $system_prompt_table ADD COLUMN embedding_vector LONGTEXT");
378 }
379 if (!in_array('source_url', $existing_system_column_names)) {
380 $wpdb->query("ALTER TABLE $system_prompt_table ADD COLUMN source_url VARCHAR(255) DEFAULT NULL");
381 }
382 if (!in_array('role_restriction', $existing_system_column_names)) {
383 $wpdb->query("ALTER TABLE $system_prompt_table ADD COLUMN role_restriction VARCHAR(50) DEFAULT 'public' AFTER source_url");
384 }
385 }
386
387 // Set default thresholds for existing intents
388 $wpdb->query("UPDATE {$intents_table} SET similarity_threshold = 0.85 WHERE similarity_threshold IS NULL");
389
390 // Ensure enabled column exists in intents table
391 $existing_intent_columns = $wpdb->get_results("SHOW COLUMNS FROM $intents_table");
392 if (!empty($existing_intent_columns)) {
393 $existing_intent_column_names = array_column($existing_intent_columns, 'Field');
394
395 if (!in_array('enabled', $existing_intent_column_names)) {
396 $wpdb->query("ALTER TABLE $intents_table ADD COLUMN enabled TINYINT(1) NOT NULL DEFAULT 1");
397 }
398
399 // NEW: Ensure enabled_bots column exists for existing installations
400 if (!in_array('enabled_bots', $existing_intent_column_names)) {
401 $wpdb->query("ALTER TABLE $intents_table ADD COLUMN enabled_bots LONGTEXT DEFAULT NULL AFTER enabled");
402
403 // Set existing actions to work with default bot
404 $default_bots = json_encode(['default']);
405 $wpdb->query($wpdb->prepare(
406 "UPDATE {$intents_table} SET enabled_bots = %s WHERE enabled_bots IS NULL",
407 $default_bots
408 ));
409 }
410 }
411
412 // Setup cron jobs
413 mxchat_setup_cron_jobs();
414
415 // Update version
416 update_option('mxchat_plugin_version', MXCHAT_VERSION);
417
418 //error_log("MxChat: Activation function completed");
419 }
420
421 /**
422 * Setup cron jobs on plugin activation
423 */
424 function mxchat_setup_cron_jobs() {
425 // Clear any existing cron jobs first
426 wp_clear_scheduled_hook('mxchat_reset_rate_limits');
427
428 // Check if WordPress cron is disabled
429 if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) {
430 // Set flag to use fallback system
431 update_option('mxchat_use_fallback_rate_limits', true);
432 update_option('mxchat_next_rate_limit_check', time() + 3600);
433 return;
434 }
435
436 // Schedule the rate limit reset cron job
437 $result = wp_schedule_event(time() + 300, 'hourly', 'mxchat_reset_rate_limits');
438
439 if ($result === false) {
440 // Fallback if scheduling fails
441 update_option('mxchat_use_fallback_rate_limits', true);
442 update_option('mxchat_next_rate_limit_check', time() + 3600);
443 } else {
444 // Clear fallback flags if cron scheduling succeeded
445 delete_option('mxchat_use_fallback_rate_limits');
446 }
447 }
448
449 /**
450 * Clean up on plugin deactivation
451 */
452 function mxchat_deactivate() {
453 // Clear scheduled cron jobs
454 wp_clear_scheduled_hook('mxchat_reset_rate_limits');
455
456 // Clear fallback options
457 delete_option('mxchat_use_fallback_rate_limits');
458 delete_option('mxchat_next_rate_limit_check');
459 delete_option('mxchat_fallback_check_interval');
460 }
461
462 /**
463 * Check if fallback rate limit cleanup is needed
464 */
465 function mxchat_check_fallback_rate_limits() {
466 $use_fallback = get_option('mxchat_use_fallback_rate_limits', false);
467
468 if (!$use_fallback) {
469 return;
470 }
471
472 $next_check = get_option('mxchat_next_rate_limit_check', 0);
473
474 if (time() >= $next_check) {
475 // Only run reset if the MxChat_Integrator class exists
476 if (class_exists('MxChat_Integrator')) {
477 $integrator = new MxChat_Integrator();
478 if (method_exists($integrator, 'mxchat_reset_rate_limits')) {
479 $integrator->mxchat_reset_rate_limits();
480 update_option('mxchat_next_rate_limit_check', time() + 3600);
481 }
482 }
483 }
484 }
485
486 /**
487 * Robust update checking with role restriction migration and model deprecation handling
488 */
489 function mxchat_check_for_update() {
490 global $wpdb; // CRITICAL: Declare this at the top
491
492 try {
493 $current_version = get_option('mxchat_plugin_version', '0.0.0');
494 $plugin_version = MXCHAT_VERSION;
495
496 // Always run activation to ensure tables exist (safe for existing installations)
497 if ($current_version !== $plugin_version) {
498 //error_log("MxChat: Version change detected: $current_version -> $plugin_version");
499
500 // Run live agent update BEFORE updating the stored version
501 mxchat_handle_live_agent_update();
502
503 // Run role restriction migration for 2.4.1
504 if (version_compare($current_version, '2.4.1', '<')) {
505 mxchat_add_role_restriction_column();
506 }
507
508 // Run enabled_bots column migration for 2.4.4
509 if (version_compare($current_version, '2.4.4', '<')) {
510 mxchat_add_enabled_bots_column();
511 }
512
513 // NEW: Run model migration for 2.5.1 (Claude deprecation)
514 if (version_compare($current_version, '2.5.1', '<')) {
515 mxchat_migrate_deprecated_models();
516 }
517
518 // Run activation (this will create/update all tables and columns)
519 mxchat_activate();
520
521 // Run migration functions
522 mxchat_migrate_live_agent_status();
523
524 // Add the cleanup function for version 2.1.8
525 if (version_compare($current_version, '2.1.8', '<')) {
526 $deleted = mxchat_cleanup_orphaned_chat_history();
527 }
528
529 // Update version LAST
530 update_option('mxchat_plugin_version', $plugin_version);
531
532 //error_log("MxChat: Updated from version $current_version to $plugin_version");
533 }
534
535 // CRITICAL: Always ensure tables exist, even if version matches
536 // This handles cases where tables were manually deleted
537 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
538 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name;
539
540 if (!$table_exists) {
541 //error_log("MxChat: Chat transcripts table missing, recreating...");
542 mxchat_activate(); // Run full activation instead of just table creation
543 }
544
545 } catch (Exception $e) {
546 //error_log('MxChat update error: ' . $e->getMessage());
547 // Don't update version if there was an error
548 }
549 }
550
551 /**
552 * Ensure tables exist on every load for fresh installations
553 */
554 function mxchat_ensure_tables_exist() {
555 global $wpdb;
556
557 // Only run for admin users to avoid performance impact
558 if (!current_user_can('administrator')) {
559 return;
560 }
561
562 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
563 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name;
564
565 if (!$table_exists) {
566 //error_log("MxChat: Tables missing on admin load, running activation");
567 mxchat_activate();
568 }
569 }
570
571 /**
572 * Clean up orphaned chat history options from the wp_options table
573 * @return int Number of options deleted
574 */
575 function mxchat_cleanup_orphaned_chat_history() {
576 global $wpdb;
577 $count = 0;
578
579 // Get all option keys that match our pattern
580 $history_options = $wpdb->get_results(
581 "SELECT option_name FROM {$wpdb->options}
582 WHERE option_name LIKE 'mxchat_history_%'"
583 );
584
585 if (!empty($history_options)) {
586 foreach ($history_options as $option) {
587 // Extract the session ID from the option name
588 $session_id = str_replace('mxchat_history_', '', $option->option_name);
589
590 // Check if this session still exists in the custom table
591 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
592 $exists = $wpdb->get_var(
593 $wpdb->prepare(
594 "SELECT COUNT(*) FROM {$table_name} WHERE session_id = %s",
595 $session_id
596 )
597 );
598
599 // If session doesn't exist in the main table, delete the option
600 if ($exists == 0) {
601 delete_option($option->option_name);
602 // Also delete related metadata
603 delete_option("mxchat_email_{$session_id}");
604 delete_option("mxchat_name_{$session_id}");
605 delete_option("mxchat_agent_name_{$session_id}");
606 $count++;
607 }
608 }
609 }
610
611 return $count;
612 }
613
614 function mxchat_migrate_live_agent_status() {
615 $options = get_option('mxchat_options', []);
616
617 // Check if live_agent_status exists
618 if (isset($options['live_agent_status'])) {
619 $current_status = $options['live_agent_status'];
620 $needs_update = false;
621
622 // Convert to new format if needed
623 if ($current_status === 'online') {
624 $options['live_agent_status'] = 'on';
625 $needs_update = true;
626 } else if ($current_status === 'offline') {
627 $options['live_agent_status'] = 'off';
628 $needs_update = true;
629 } else if (!in_array($current_status, ['on', 'off'])) {
630 // Default to off for any unexpected values
631 $options['live_agent_status'] = 'off';
632 $needs_update = true;
633 }
634
635 // Only update if needed
636 if ($needs_update) {
637 update_option('mxchat_options', $options);
638 }
639 } else {
640 // If status doesn't exist, set default to off
641 $options['live_agent_status'] = 'off';
642 update_option('mxchat_options', $options);
643 }
644 }
645
646 function mxchat_handle_live_agent_update() {
647 // Get the CURRENT stored version (before it gets updated)
648 $current_version = get_option('mxchat_plugin_version', '0.0.0');
649 $new_version = '2.2.2';
650
651 // Only run this once for the update to 2.2.2
652 $update_handled = get_option('mxchat_live_agent_update_2_2_2_handled', false);
653
654 // Check if we're upgrading TO 2.2.2 and haven't handled this yet
655 if (version_compare($current_version, $new_version, '<') && !$update_handled) {
656 $options = get_option('mxchat_options', array());
657
658 // Check if live agent was previously enabled
659 if (isset($options['live_agent_status']) && $options['live_agent_status'] === 'on') {
660 // Disable live agent
661 $options['live_agent_status'] = 'off';
662 update_option('mxchat_options', $options);
663
664 // Set flag to show the notification banner
665 update_option('mxchat_show_live_agent_disabled_notice', true);
666 }
667
668 // Mark this update as handled
669 update_option('mxchat_live_agent_update_2_2_2_handled', true);
670 }
671 }
672
673 // Initialize plugin safely
674 function mxchat_init() {
675 // Include all class files first
676 mxchat_include_classes();
677
678 // Run update check
679 mxchat_check_for_update();
680
681 // CRITICAL: Ensure tables exist (for fresh installations that don't trigger activation hook)
682 add_action('admin_init', 'mxchat_ensure_tables_exist', 1);
683
684 // Add fallback rate limit check
685 add_action('init', 'mxchat_check_fallback_rate_limits', 5);
686
687 // Add migration notice hook
688 add_action('admin_notices', 'mxchat_show_migration_notice');
689
690 // Initialize classes with error handling
691 try {
692 // Initialize admin classes
693 if (is_admin()) {
694 if (class_exists('MxChat_Knowledge_Manager')) {
695 $mxchat_knowledge_manager = new MxChat_Knowledge_Manager();
696
697 if (class_exists('MxChat_Admin')) {
698 $mxchat_admin = new MxChat_Admin($mxchat_knowledge_manager);
699 }
700 }
701
702 // Initialize meta box class
703 if (class_exists('MxChat_Meta_Box')) {
704 new MxChat_Meta_Box();
705 }
706 }
707
708 // Initialize public classes
709 if (class_exists('MxChat_Public')) {
710 $mxchat_public = new MxChat_Public();
711 }
712
713 if (class_exists('MxChat_Integrator')) {
714 $mxchat_integrator = new MxChat_Integrator();
715 }
716
717 } catch (Exception $e) {
718 //error_log('MxChat initialization error: ' . $e->getMessage());
719
720 // Show admin notice if there's an error
721 if (is_admin()) {
722 add_action('admin_notices', function() use ($e) {
723 echo '<div class="notice notice-error"><p>';
724 echo '<strong>MxChat Error:</strong> Plugin initialization failed. ';
725 echo 'Please check error logs or contact support. Error: ' . esc_html($e->getMessage());
726 echo '</p></div>';
727 });
728 }
729 }
730 }
731
732 // Run initialization on plugins_loaded
733 add_action('plugins_loaded', 'mxchat_init');
734
735 // Register activation hook
736 register_activation_hook(__FILE__, 'mxchat_activate');
737
738 // Add cron schedule
739 add_filter('cron_schedules', function($schedules) {
740 $schedules['one_minute'] = array(
741 'interval' => 60,
742 'display' => 'Every Minute'
743 );
744 return $schedules;
745 });
746
747 // Register deactivation hook
748 register_deactivation_hook(__FILE__, 'mxchat_deactivate');