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