PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.2.0
MxChat – AI Chatbot & Content Generation for WordPress v3.2.0
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 +5 -215 3.2.63.2.0 View file →
@@ -2,9 +2,9 @@
2 2 /**
3 3 * Plugin Name: MxChat
4 4 * Plugin URI: https://mxchat.ai/
5 5 * Description: AI chatbot for WordPress with OpenAI, Claude, xAI, DeepSeek, live agent, PDF uploads, WooCommerce, and training on website data.
6 - * Version: 3.2.6
6 + * Version: 3.2.0
7 7 * Author: MxChat
8 8 * Author URI: https://mxchat.ai
9 9 * License: GPLv2 or later
10 10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -250,61 +250,8 @@
250 250 $rejected[] = 'wp-admin/admin-ajax.php';
251 251 return $rejected;
252 252 });
253 253
254 -// ── Page-cache bypass for chat AJAX (companion to the 3.2.6 nonce-race hotfix)
255 -// Each cache plugin gets its own filter export so that visitors hitting an
256 -// edge-cached page never receive cached chat-AJAX responses. The chat send /
257 -// stream send / file upload all POST to /wp-admin/admin-ajax.php with
258 -// `action=mxchat_*`. Without these exports, a cache plugin can stale a response
259 -// and break the per-session nonce flow on the first message.
260 -
261 -// WP Rocket — `rocket_cache_reject_uri` takes a flat array of regex strings.
262 -add_filter('rocket_cache_reject_uri', function($uris) {
263 - if (!is_array($uris)) $uris = array();
264 - $uris[] = '/wp-admin/admin-ajax\.php\?action=mxchat_.*';
265 - return $uris;
266 -});
267 -
268 -// LiteSpeed Cache — `litespeed_cache_no_cache_for_request` short-circuits
269 -// caching when the request matches our chat-AJAX pattern.
270 -add_filter('litespeed_cache_no_cache_for_request', function($no_cache) {
271 - if ($no_cache) return $no_cache;
272 - if (!empty($_SERVER['REQUEST_URI']) &&
273 - strpos($_SERVER['REQUEST_URI'], '/wp-admin/admin-ajax.php') !== false &&
274 - !empty($_REQUEST['action']) &&
275 - strpos((string) $_REQUEST['action'], 'mxchat_') === 0) {
276 - return true;
277 - }
278 - return $no_cache;
279 -});
280 -
281 -// W3 Total Cache — `w3tc_pgcache_request_skip_uri` flips page-cache off when
282 -// the URI matches.
283 -add_filter('w3tc_pgcache_request_skip_uri', function($skip) {
284 - if ($skip) return $skip;
285 - if (!empty($_SERVER['REQUEST_URI']) &&
286 - strpos($_SERVER['REQUEST_URI'], '/wp-admin/admin-ajax.php') !== false &&
287 - !empty($_REQUEST['action']) &&
288 - strpos((string) $_REQUEST['action'], 'mxchat_') === 0) {
289 - return true;
290 - }
291 - return $skip;
292 -});
293 -
294 -// FlyingPress — `flying_press_cacheable` takes a boolean and is run per
295 -// request. Same pattern as LiteSpeed / W3TC.
296 -add_filter('flying_press_cacheable', function($cacheable) {
297 - if (!$cacheable) return $cacheable;
298 - if (!empty($_SERVER['REQUEST_URI']) &&
299 - strpos($_SERVER['REQUEST_URI'], '/wp-admin/admin-ajax.php') !== false &&
300 - !empty($_REQUEST['action']) &&
301 - strpos((string) $_REQUEST['action'], 'mxchat_') === 0) {
302 - return false;
303 - }
304 - return $cacheable;
305 -});
306 -
307 254 // Include classes with error handling
308 255 function mxchat_include_classes() {
309 256 $class_files = array(
310 257 'includes/class-mxchat-integrator.php',
@@ -315,9 +262,8 @@
315 262 'includes/class-mxchat-meta-box.php',
316 263 'includes/class-mxchat-chunker.php',
317 264 'includes/class-mxchat-word-handler.php',
318 265 'includes/class-mxchat-content-generator.php',
319 - 'includes/class-rest-api.php',
320 266 'admin/class-ajax-handler.php',
321 267 'admin/class-pinecone-manager.php',
322 268 'admin/class-knowledge-manager.php'
323 269 );
@@ -329,16 +275,8 @@
329 275 } else {
330 276 //error_log('MxChat: Missing class file - ' . $file);
331 277 }
332 278 }
333 -
334 - // Admin pages that aren't classes (procedural include).
335 - if (is_admin()) {
336 - $admin_api_page = plugin_dir_path(__FILE__) . 'includes/admin-api-page.php';
337 - if (file_exists($admin_api_page)) {
338 - require_once $admin_api_page;
339 - }
340 - }
341 279 }
342 280
343 281 /**
344 282 * Lazy-load the PDF parser library only when needed.
@@ -670,33 +608,8 @@
670 608 update_option('mxchat_content_type_migration_version', '2.5.6');
671 609 }
672 610
673 611 /**
674 - * 3.2.4: Backfill the active embedding model option for installs that already
675 - * have KB content but no stamped model. The mismatch warning compares this
676 - * against the user's currently selected model — no per-row column needed.
677 - */
678 -function mxchat_backfill_active_embedding_model() {
679 - global $wpdb;
680 -
681 - if (get_option('mxchat_active_embedding_model', '') !== '') {
682 - return;
683 - }
684 -
685 - $kb_table = $wpdb->prefix . 'mxchat_system_prompt_content';
686 - if ($wpdb->get_var("SHOW TABLES LIKE '{$kb_table}'") !== $kb_table) {
687 - return;
688 - }
689 -
690 - $kb_count = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$kb_table}");
691 - if ($kb_count > 0) {
692 - $options = get_option('mxchat_options', array());
693 - $current_model = $options['embedding_model'] ?? 'text-embedding-ada-002';
694 - update_option('mxchat_active_embedding_model', $current_model, false);
695 - }
696 -}
697 -
698 -/**
699 612 * 2.5.2: Create queue processing tables for reliable background processing
700 613 */
701 614 function mxchat_create_queue_tables() {
702 615 global $wpdb;
@@ -768,34 +681,8 @@
768 681 dbDelta($sql);
769 682 }
770 683
771 684 /**
772 - * Create per-session satisfaction ratings table (v3.2.6)
773 - * Stores one 👍/👎 rating + optional feedback per chat session.
774 - */
775 -function mxchat_create_session_ratings_table() {
776 - global $wpdb;
777 - $charset_collate = $wpdb->get_charset_collate();
778 -
779 - $table_name = $wpdb->prefix . 'mxchat_session_ratings';
780 - $sql = "CREATE TABLE $table_name (
781 - id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
782 - session_id varchar(255) NOT NULL,
783 - bot_id varchar(50) NOT NULL DEFAULT 'default',
784 - rating_value tinyint(1) NOT NULL,
785 - rating_feedback text DEFAULT NULL,
786 - created_at datetime NOT NULL,
787 - PRIMARY KEY (id),
788 - UNIQUE KEY session_id (session_id),
789 - KEY bot_id (bot_id),
790 - KEY created_at (created_at)
791 - ) $charset_collate;";
792 -
793 - require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
794 - dbDelta($sql);
795 -}
796 -
797 -/**
798 685 * 2.5.2: Fix URL column size to support long URLs (especially with UTF-8 encoding)
799 686 * This fixes "url, source_url. The supplied values may be too long" errors
800 687 */
801 688 function mxchat_fix_url_column_size() {
@@ -981,11 +868,8 @@
981 868
982 869 // Create transcript translations table
983 870 mxchat_create_translations_table();
984 871
985 - // Create per-session satisfaction ratings table (v3.2.6)
986 - mxchat_create_session_ratings_table();
987 -
988 872 // Ensure additional columns in system prompt table
989 873 $existing_system_columns = $wpdb->get_results("SHOW COLUMNS FROM $system_prompt_table");
990 874 if (!empty($existing_system_columns)) {
991 875 $existing_system_column_names = array_column($existing_system_columns, 'Field');
@@ -1028,11 +912,8 @@
1028 912
1029 913 // Run migration for existing installations
1030 914 mxchat_migrate_pinecone_roles_add_bot_id();
1031 915
1032 - // 3.2.4: Backfill active embedding model option (replaces 3.2.3 column-based tracking)
1033 - mxchat_backfill_active_embedding_model();
1034 -
1035 916 // Setup cron jobs
1036 917 mxchat_setup_cron_jobs();
1037 918
1038 919 // Update version
@@ -1067,14 +948,13 @@
1067 948 // Clear fallback flags if cron scheduling succeeded
1068 949 delete_option('mxchat_use_fallback_rate_limits');
1069 950 }
1070 951
1071 - // Schedule transcript cleanup if configured (bucket dropdown OR custom retention-days > 0)
952 + // Schedule transcript cleanup if configured
1072 953 $transcript_options = get_option('mxchat_transcripts_options', array());
1073 954 $cleanup_interval = isset($transcript_options['mxchat_auto_delete_transcripts']) ? $transcript_options['mxchat_auto_delete_transcripts'] : 'never';
1074 - $custom_retention = isset($transcript_options['mxchat_retention_days']) ? (int) $transcript_options['mxchat_retention_days'] : 0;
1075 -
1076 - if ($cleanup_interval !== 'never' || $custom_retention > 0) {
955 +
956 + if ($cleanup_interval !== 'never') {
1077 957 // Check if not already scheduled
1078 958 if (!wp_next_scheduled('mxchat_cleanup_old_transcripts')) {
1079 959 // Schedule to run daily at 3 AM
1080 960 $next_run = strtotime('tomorrow 3:00 AM');
@@ -1208,14 +1088,8 @@
1208 1088 delete_option('mxchat_email_null');
1209 1089 delete_option('mxchat_name_null');
1210 1090 }
1211 1091
1212 - // 3.2.4: Backfill active embedding model option for the warning UI
1213 - // (replaces the per-row column tracking from 3.2.3, which was reverted)
1214 - if (version_compare($current_version, '3.2.4', '<')) {
1215 - mxchat_backfill_active_embedding_model();
1216 - }
1217 -
1218 1092 // Run full activation to ensure everything is up to date
1219 1093 mxchat_activate();
1220 1094
1221 1095 // Run migration functions
@@ -1440,16 +1314,8 @@
1440 1314 if (class_exists('MxChat_Content_Generator')) {
1441 1315 new MxChat_Content_Generator();
1442 1316 }
1443 1317
1444 - // Initialize REST API globally — endpoints must be registered on
1445 - // every request (admin and frontend) so they're reachable via /wp-json/.
1446 - // Endpoints are auth-gated and locked until the site owner generates
1447 - // a token in MxChat → API Access.
1448 - if (class_exists('MxChat_Rest_Api')) {
1449 - new MxChat_Rest_Api();
1450 - }
1451 -
1452 1318 // Initialize public classes
1453 1319 if (class_exists('MxChat_Public')) {
1454 1320 $mxchat_public = new MxChat_Public();
1455 1321 }
@@ -1494,25 +1360,11 @@
1494 1360
1495 1361 mxchat_migrate_pinecone_roles_add_bot_id();
1496 1362 mxchat_migrate_add_content_type_column();
1497 1363 mxchat_migrate_add_translations_table();
1498 - mxchat_migrate_add_session_ratings_table();
1499 1364 }
1500 1365
1501 1366 /**
1502 - * Migration: Create per-session satisfaction ratings table (v3.2.6)
1503 - * For users upgrading from versions before 3.2.6
1504 - */
1505 -function mxchat_migrate_add_session_ratings_table() {
1506 - $migration_key = 'mxchat_session_ratings_table_created';
1507 - if (get_option($migration_key)) {
1508 - return;
1509 - }
1510 - mxchat_create_session_ratings_table();
1511 - update_option($migration_key, '3.2.6');
1512 -}
1513 -
1514 -/**
1515 1367 * Migration: Create transcript translations table (v3.0.4)
1516 1368 * For users upgrading from versions before 3.0.4
1517 1369 */
1518 1370 function mxchat_migrate_add_translations_table() {
@@ -1555,67 +1407,5 @@
1555 1407 return $schedules;
1556 1408 });
1557 1409
1558 1410 // Register deactivation hook
1559 -register_deactivation_hook(__FILE__, 'mxchat_deactivate');
1560 -
1561 -/**
1562 - * Per-session satisfaction rating: AJAX save handler (v3.2.6).
1563 - * Records one 👍/👎 + optional feedback per chat session. The UNIQUE KEY on
1564 - * session_id makes this naturally idempotent — only the first rating per
1565 - * session is stored; duplicate POSTs are silent no-ops.
1566 - */
1567 -function mxchat_save_session_rating() {
1568 - global $wpdb;
1569 -
1570 - $session_id = isset($_POST['session_id']) ? sanitize_text_field(wp_unslash($_POST['session_id'])) : '';
1571 - $bot_id = isset($_POST['bot_id']) ? sanitize_text_field(wp_unslash($_POST['bot_id'])) : 'default';
1572 - $rating_raw = isset($_POST['rating']) ? (int) $_POST['rating'] : 0;
1573 - $feedback = isset($_POST['feedback']) ? sanitize_textarea_field(wp_unslash($_POST['feedback'])) : '';
1574 -
1575 - if ($session_id === '' || ($rating_raw !== 1 && $rating_raw !== -1)) {
1576 - wp_send_json_error(array('message' => 'invalid_input'), 400);
1577 - }
1578 -
1579 - if (strlen($feedback) > 1000) {
1580 - $feedback = substr($feedback, 0, 1000);
1581 - }
1582 -
1583 - $table_name = $wpdb->prefix . 'mxchat_session_ratings';
1584 - $existing = $wpdb->get_var($wpdb->prepare(
1585 - "SELECT id FROM $table_name WHERE session_id = %s LIMIT 1",
1586 - $session_id
1587 - ));
1588 -
1589 - if ($existing) {
1590 - if ($feedback !== '') {
1591 - $wpdb->update(
1592 - $table_name,
1593 - array('rating_feedback' => $feedback),
1594 - array('id' => (int) $existing),
1595 - array('%s'),
1596 - array('%d')
1597 - );
1598 - }
1599 - wp_send_json_success(array('updated' => true));
1600 - }
1601 -
1602 - $inserted = $wpdb->insert(
1603 - $table_name,
1604 - array(
1605 - 'session_id' => $session_id,
1606 - 'bot_id' => $bot_id !== '' ? $bot_id : 'default',
1607 - 'rating_value' => $rating_raw,
1608 - 'rating_feedback' => $feedback !== '' ? $feedback : null,
1609 - 'created_at' => current_time('mysql'),
1610 - ),
1611 - array('%s', '%s', '%d', '%s', '%s')
1612 - );
1613 -
1614 - if ($inserted === false) {
1615 - wp_send_json_error(array('message' => 'db_insert_failed'), 500);
1616 - }
1617 -
1618 - wp_send_json_success(array('saved' => true));
1619 -}
1620 -add_action('wp_ajax_mxchat_save_rating', 'mxchat_save_session_rating');
1621 -add_action('wp_ajax_nopriv_mxchat_save_rating', 'mxchat_save_session_rating');
1411 +register_deactivation_hook(__FILE__, 'mxchat_deactivate');