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

422 lines 14.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 * Description: AI chatbot for WordPress with OpenAI, Claude, xAI, DeepSeek, live agent, PDF uploads, WooCommerce, and training on website data.
5 * Version: 2.3.7
6 * Author: MxChat
7 * Author URI: https://mxchat.ai
8 * License: GPLv2 or later
9 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
10 * Text Domain: mxchat
11 * Domain Path: /languages
12 */
13
14 if (!defined('ABSPATH')) {
15 exit; // Exit if accessed directly.
16 }
17
18 // Define plugin version constant for asset versioning
19 define('MXCHAT_VERSION', '2.3.7');
20
21 function mxchat_load_textdomain() {
22 load_plugin_textdomain('mxchat', false, dirname(plugin_basename(__FILE__)) . '/languages');
23 }
24 add_action('plugins_loaded', 'mxchat_load_textdomain');
25
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/pdf-parser/alt_autoload.php',
35 'includes/class-mxchat-word-handler.php',
36 'admin/class-ajax-handler.php',
37 'admin/class-pinecone-manager.php',
38 'admin/class-knowledge-manager.php'
39 );
40
41 foreach ($class_files as $file) {
42 $file_path = plugin_dir_path(__FILE__) . $file;
43 if (file_exists($file_path)) {
44 require_once $file_path;
45 } else {
46 //error_log('MxChat: Missing class file - ' . $file);
47 }
48 }
49 }
50
51 /**
52 * NEW: Create URL click tracking table
53 */
54 function mxchat_create_url_clicks_table() {
55 global $wpdb;
56
57 $table_name = $wpdb->prefix . 'mxchat_url_clicks';
58
59 $charset_collate = $wpdb->get_charset_collate();
60
61 $sql = "CREATE TABLE $table_name (
62 id mediumint(9) NOT NULL AUTO_INCREMENT,
63 session_id varchar(100) NOT NULL,
64 clicked_url text NOT NULL,
65 message_context text,
66 click_timestamp datetime DEFAULT CURRENT_TIMESTAMP,
67 user_ip varchar(45),
68 user_agent text,
69 PRIMARY KEY (id),
70 KEY session_id (session_id),
71 KEY click_timestamp (click_timestamp)
72 ) $charset_collate;";
73
74 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
75 dbDelta($sql);
76 }
77
78 function mxchat_activate() {
79 global $wpdb;
80 $charset_collate = $wpdb->get_charset_collate();
81
82 // Chat Transcripts Table
83 $chat_transcripts_table = $wpdb->prefix . 'mxchat_chat_transcripts';
84 $sql_chat_transcripts = "CREATE TABLE $chat_transcripts_table (
85 id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
86 user_id MEDIUMINT(9) DEFAULT 0,
87 session_id VARCHAR(255) NOT NULL,
88 role VARCHAR(255) NOT NULL,
89 message TEXT NOT NULL,
90 user_email VARCHAR(255) DEFAULT NULL,
91 timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
92 PRIMARY KEY (id)
93 ) $charset_collate;";
94
95 // System Prompt Content Table
96 $system_prompt_table = $wpdb->prefix . 'mxchat_system_prompt_content';
97 $sql_system_prompt = "CREATE TABLE $system_prompt_table (
98 id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
99 url VARCHAR(255) NOT NULL,
100 article_content LONGTEXT NOT NULL,
101 embedding_vector LONGTEXT,
102 source_url VARCHAR(255) DEFAULT NULL,
103 timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
104 PRIMARY KEY (id)
105 ) $charset_collate;";
106
107 // Intents Table
108 $intents_table = $wpdb->prefix . 'mxchat_intents';
109 $sql_intents_table = "CREATE TABLE $intents_table (
110 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
111 intent_label VARCHAR(255) NOT NULL,
112 phrases TEXT NOT NULL,
113 embedding_vector LONGTEXT NOT NULL,
114 callback_function VARCHAR(255) NOT NULL,
115 similarity_threshold FLOAT DEFAULT 0.85,
116 PRIMARY KEY (id)
117 ) $charset_collate;";
118
119 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
120
121 // Create or update tables
122 dbDelta($sql_chat_transcripts);
123 dbDelta($sql_system_prompt);
124 dbDelta($sql_intents_table);
125
126 // NEW: Create URL click tracking table
127 mxchat_create_url_clicks_table();
128
129 // Ensure additional columns in `mxchat_chat_transcripts`
130 mxchat_add_missing_columns($chat_transcripts_table, 'user_identifier', 'VARCHAR(255)');
131 mxchat_add_missing_columns($chat_transcripts_table, 'user_email', 'VARCHAR(255) DEFAULT NULL');
132
133 // NEW: Add originating page tracking columns
134 mxchat_add_missing_columns($chat_transcripts_table, 'originating_page_url', 'TEXT DEFAULT NULL');
135 mxchat_add_missing_columns($chat_transcripts_table, 'originating_page_title', 'VARCHAR(500) DEFAULT NULL');
136
137 // Ensure additional columns in `mxchat_system_prompt_content`
138 mxchat_add_missing_columns($system_prompt_table, 'embedding_vector', 'LONGTEXT');
139 mxchat_add_missing_columns($system_prompt_table, 'source_url', 'VARCHAR(255) DEFAULT NULL');
140
141 // Set default thresholds for existing intents
142 $wpdb->query("UPDATE {$intents_table} SET similarity_threshold = 0.85 WHERE similarity_threshold IS NULL");
143 mxchat_add_missing_columns($intents_table, 'enabled', 'TINYINT(1) NOT NULL DEFAULT 1');
144
145 // SETUP CRON JOB HERE (ONCE ON ACTIVATION)
146 mxchat_setup_cron_jobs();
147
148 // Use the constant instead of hardcoded version
149 update_option('mxchat_plugin_version', MXCHAT_VERSION);
150 }
151
152 /**
153 * Setup cron jobs on plugin activation
154 */
155 function mxchat_setup_cron_jobs() {
156 // Clear any existing cron jobs first
157 wp_clear_scheduled_hook('mxchat_reset_rate_limits');
158
159 // Check if WordPress cron is disabled
160 if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) {
161 // Set flag to use fallback system
162 update_option('mxchat_use_fallback_rate_limits', true);
163 update_option('mxchat_next_rate_limit_check', time() + 3600);
164 //error_log('MxChat: WordPress cron disabled, using fallback system');
165 return;
166 }
167
168 // Schedule the rate limit reset cron job
169 $result = wp_schedule_event(time() + 300, 'hourly', 'mxchat_reset_rate_limits');
170
171 if ($result === false) {
172 // Fallback if scheduling fails
173 update_option('mxchat_use_fallback_rate_limits', true);
174 update_option('mxchat_next_rate_limit_check', time() + 3600);
175 //error_log('MxChat: Failed to schedule cron on activation, using fallback');
176 } else {
177 // Clear fallback flags if cron scheduling succeeded
178 delete_option('mxchat_use_fallback_rate_limits');
179 //error_log('MxChat: Successfully scheduled cron on activation');
180 }
181 }
182
183 /**
184 * Clean up on plugin deactivation
185 */
186 function mxchat_deactivate() {
187 // Clear scheduled cron jobs
188 wp_clear_scheduled_hook('mxchat_reset_rate_limits');
189
190 // Clear fallback options
191 delete_option('mxchat_use_fallback_rate_limits');
192 delete_option('mxchat_next_rate_limit_check');
193 delete_option('mxchat_fallback_check_interval');
194
195 //error_log('MxChat: Cleaned up cron jobs on deactivation');
196 }
197
198 /**
199 * Check if fallback rate limit cleanup is needed
200 */
201 function mxchat_check_fallback_rate_limits() {
202 $use_fallback = get_option('mxchat_use_fallback_rate_limits', false);
203
204 if (!$use_fallback) {
205 return;
206 }
207
208 $next_check = get_option('mxchat_next_rate_limit_check', 0);
209
210 if (time() >= $next_check) {
211 // Only run reset if the MxChat_Integrator class exists
212 if (class_exists('MxChat_Integrator')) {
213 $integrator = new MxChat_Integrator();
214 if (method_exists($integrator, 'mxchat_reset_rate_limits')) {
215 $integrator->mxchat_reset_rate_limits();
216 update_option('mxchat_next_rate_limit_check', time() + 3600);
217 }
218 }
219 }
220 }
221
222 function mxchat_add_missing_columns($table, $column_name, $column_type) {
223 global $wpdb;
224 $column_exists = $wpdb->get_results($wpdb->prepare("SHOW COLUMNS FROM $table LIKE %s", $column_name));
225 if (empty($column_exists)) {
226 $wpdb->query("ALTER TABLE $table ADD COLUMN $column_name $column_type");
227 }
228 }
229
230 function mxchat_check_for_update() {
231 try {
232 $current_version = get_option('mxchat_plugin_version');
233 $plugin_version = MXCHAT_VERSION;
234
235 if ($current_version !== $plugin_version) {
236 // Run live agent update BEFORE updating the stored version
237 mxchat_handle_live_agent_update();
238
239 // Run existing update processes
240 mxchat_activate();
241 mxchat_migrate_live_agent_status();
242
243 // Add the new cleanup function for version 2.1.8
244 if (version_compare($current_version, '2.1.8', '<')) {
245 $deleted = mxchat_cleanup_orphaned_chat_history();
246 }
247
248 // Update version LAST so the live agent update logic can work
249 update_option('mxchat_plugin_version', $plugin_version);
250 }
251 } catch (Exception $e) {
252 //error_log('MxChat update error: ' . $e->getMessage());
253 // Don't update version if there was an error
254 }
255 }
256
257 /**
258 * Clean up orphaned chat history options from the wp_options table
259 * @return int Number of options deleted
260 */
261 function mxchat_cleanup_orphaned_chat_history() {
262 global $wpdb;
263 $count = 0;
264
265 // Get all option keys that match our pattern
266 $history_options = $wpdb->get_results(
267 "SELECT option_name FROM {$wpdb->options}
268 WHERE option_name LIKE 'mxchat_history_%'"
269 );
270
271 if (!empty($history_options)) {
272 foreach ($history_options as $option) {
273 // Extract the session ID from the option name
274 $session_id = str_replace('mxchat_history_', '', $option->option_name);
275
276 // Check if this session still exists in the custom table
277 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
278 $exists = $wpdb->get_var(
279 $wpdb->prepare(
280 "SELECT COUNT(*) FROM {$table_name} WHERE session_id = %s",
281 $session_id
282 )
283 );
284
285 // If session doesn't exist in the main table, delete the option
286 if ($exists == 0) {
287 delete_option($option->option_name);
288 // Also delete related metadata
289 delete_option("mxchat_email_{$session_id}");
290 delete_option("mxchat_agent_name_{$session_id}");
291 $count++;
292 }
293 }
294 }
295
296 return $count;
297 }
298
299 function mxchat_migrate_live_agent_status() {
300 $options = get_option('mxchat_options', []);
301
302 // Check if live_agent_status exists
303 if (isset($options['live_agent_status'])) {
304 $current_status = $options['live_agent_status'];
305 $needs_update = false;
306
307 // Convert to new format if needed
308 if ($current_status === 'online') {
309 $options['live_agent_status'] = 'on';
310 $needs_update = true;
311 } else if ($current_status === 'offline') {
312 $options['live_agent_status'] = 'off';
313 $needs_update = true;
314 } else if (!in_array($current_status, ['on', 'off'])) {
315 // Default to off for any unexpected values
316 $options['live_agent_status'] = 'off';
317 $needs_update = true;
318 }
319
320 // Only update if needed
321 if ($needs_update) {
322 update_option('mxchat_options', $options);
323 }
324 } else {
325 // If status doesn't exist, set default to off
326 $options['live_agent_status'] = 'off';
327 update_option('mxchat_options', $options);
328 }
329 }
330
331 function mxchat_handle_live_agent_update() {
332 // Get the CURRENT stored version (before it gets updated)
333 $current_version = get_option('mxchat_plugin_version', '0.0.0');
334 $new_version = '2.2.2';
335
336 // Only run this once for the update to 2.2.2
337 $update_handled = get_option('mxchat_live_agent_update_2_2_2_handled', false);
338
339 // Check if we're upgrading TO 2.2.2 and haven't handled this yet
340 if (version_compare($current_version, $new_version, '<') && !$update_handled) {
341 $options = get_option('mxchat_options', array());
342
343 // Check if live agent was previously enabled
344 if (isset($options['live_agent_status']) && $options['live_agent_status'] === 'on') {
345 // Disable live agent
346 $options['live_agent_status'] = 'off';
347 update_option('mxchat_options', $options);
348
349 // Set flag to show the notification banner
350 update_option('mxchat_show_live_agent_disabled_notice', true);
351 }
352
353 // Mark this update as handled
354 update_option('mxchat_live_agent_update_2_2_2_handled', true);
355 }
356 }
357
358 // Initialize plugin safely
359 function mxchat_init() {
360 // Include all class files first
361 mxchat_include_classes();
362
363 // Run update check
364 mxchat_check_for_update();
365
366 // Add fallback rate limit check
367 add_action('init', 'mxchat_check_fallback_rate_limits', 5);
368
369 // Initialize classes with error handling
370 try {
371 // Initialize admin classes
372 if (is_admin()) {
373 if (class_exists('MxChat_Knowledge_Manager')) {
374 $mxchat_knowledge_manager = new MxChat_Knowledge_Manager();
375
376 if (class_exists('MxChat_Admin')) {
377 $mxchat_admin = new MxChat_Admin($mxchat_knowledge_manager);
378 }
379 }
380 }
381
382 // Initialize public classes
383 if (class_exists('MxChat_Public')) {
384 $mxchat_public = new MxChat_Public();
385 }
386
387 if (class_exists('MxChat_Integrator')) {
388 $mxchat_integrator = new MxChat_Integrator();
389 }
390
391 } catch (Exception $e) {
392 //error_log('MxChat initialization error: ' . $e->getMessage());
393
394 // Show admin notice if there's an error
395 if (is_admin()) {
396 add_action('admin_notices', function() use ($e) {
397 echo '<div class="notice notice-error"><p>';
398 echo '<strong>MxChat Error:</strong> Plugin initialization failed. ';
399 echo 'Please check error logs or contact support. Error: ' . esc_html($e->getMessage());
400 echo '</p></div>';
401 });
402 }
403 }
404 }
405
406 // Run initialization on plugins_loaded
407 add_action('plugins_loaded', 'mxchat_init');
408
409 // Register activation hook
410 register_activation_hook(__FILE__, 'mxchat_activate');
411
412 // Add cron schedule
413 add_filter('cron_schedules', function($schedules) {
414 $schedules['one_minute'] = array(
415 'interval' => 60,
416 'display' => 'Every Minute'
417 );
418 return $schedules;
419 });
420
421 // Register deactivation hook
422 register_deactivation_hook(__FILE__, 'mxchat_deactivate');