prefix . 'mxchat_url_clicks'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, session_id varchar(100) NOT NULL, clicked_url text NOT NULL, message_context text, click_timestamp datetime DEFAULT CURRENT_TIMESTAMP, user_ip varchar(45), user_agent text, PRIMARY KEY (id), KEY session_id (session_id), KEY click_timestamp (click_timestamp) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } function mxchat_activate() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); // Chat Transcripts Table $chat_transcripts_table = $wpdb->prefix . 'mxchat_chat_transcripts'; $sql_chat_transcripts = "CREATE TABLE $chat_transcripts_table ( id MEDIUMINT(9) NOT NULL AUTO_INCREMENT, user_id MEDIUMINT(9) DEFAULT 0, session_id VARCHAR(255) NOT NULL, role VARCHAR(255) NOT NULL, message TEXT NOT NULL, user_email VARCHAR(255) DEFAULT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // System Prompt Content Table $system_prompt_table = $wpdb->prefix . 'mxchat_system_prompt_content'; $sql_system_prompt = "CREATE TABLE $system_prompt_table ( id MEDIUMINT(9) NOT NULL AUTO_INCREMENT, url VARCHAR(255) NOT NULL, article_content LONGTEXT NOT NULL, embedding_vector LONGTEXT, source_url VARCHAR(255) DEFAULT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // Intents Table $intents_table = $wpdb->prefix . 'mxchat_intents'; $sql_intents_table = "CREATE TABLE $intents_table ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, intent_label VARCHAR(255) NOT NULL, phrases TEXT NOT NULL, embedding_vector LONGTEXT NOT NULL, callback_function VARCHAR(255) NOT NULL, similarity_threshold FLOAT DEFAULT 0.85, PRIMARY KEY (id) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // Create or update tables dbDelta($sql_chat_transcripts); dbDelta($sql_system_prompt); dbDelta($sql_intents_table); // NEW: Create URL click tracking table mxchat_create_url_clicks_table(); // Ensure additional columns in `mxchat_chat_transcripts` mxchat_add_missing_columns($chat_transcripts_table, 'user_identifier', 'VARCHAR(255)'); mxchat_add_missing_columns($chat_transcripts_table, 'user_email', 'VARCHAR(255) DEFAULT NULL'); // NEW: Add originating page tracking columns mxchat_add_missing_columns($chat_transcripts_table, 'originating_page_url', 'TEXT DEFAULT NULL'); mxchat_add_missing_columns($chat_transcripts_table, 'originating_page_title', 'VARCHAR(500) DEFAULT NULL'); // Ensure additional columns in `mxchat_system_prompt_content` mxchat_add_missing_columns($system_prompt_table, 'embedding_vector', 'LONGTEXT'); mxchat_add_missing_columns($system_prompt_table, 'source_url', 'VARCHAR(255) DEFAULT NULL'); // Set default thresholds for existing intents $wpdb->query("UPDATE {$intents_table} SET similarity_threshold = 0.85 WHERE similarity_threshold IS NULL"); mxchat_add_missing_columns($intents_table, 'enabled', 'TINYINT(1) NOT NULL DEFAULT 1'); // SETUP CRON JOB HERE (ONCE ON ACTIVATION) mxchat_setup_cron_jobs(); // Use the constant instead of hardcoded version update_option('mxchat_plugin_version', MXCHAT_VERSION); } /** * Setup cron jobs on plugin activation */ function mxchat_setup_cron_jobs() { // Clear any existing cron jobs first wp_clear_scheduled_hook('mxchat_reset_rate_limits'); // Check if WordPress cron is disabled if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) { // Set flag to use fallback system update_option('mxchat_use_fallback_rate_limits', true); update_option('mxchat_next_rate_limit_check', time() + 3600); //error_log('MxChat: WordPress cron disabled, using fallback system'); return; } // Schedule the rate limit reset cron job $result = wp_schedule_event(time() + 300, 'hourly', 'mxchat_reset_rate_limits'); if ($result === false) { // Fallback if scheduling fails update_option('mxchat_use_fallback_rate_limits', true); update_option('mxchat_next_rate_limit_check', time() + 3600); //error_log('MxChat: Failed to schedule cron on activation, using fallback'); } else { // Clear fallback flags if cron scheduling succeeded delete_option('mxchat_use_fallback_rate_limits'); //error_log('MxChat: Successfully scheduled cron on activation'); } } /** * Clean up on plugin deactivation */ function mxchat_deactivate() { // Clear scheduled cron jobs wp_clear_scheduled_hook('mxchat_reset_rate_limits'); // Clear fallback options delete_option('mxchat_use_fallback_rate_limits'); delete_option('mxchat_next_rate_limit_check'); delete_option('mxchat_fallback_check_interval'); //error_log('MxChat: Cleaned up cron jobs on deactivation'); } /** * Check if fallback rate limit cleanup is needed */ function mxchat_check_fallback_rate_limits() { $use_fallback = get_option('mxchat_use_fallback_rate_limits', false); if (!$use_fallback) { return; } $next_check = get_option('mxchat_next_rate_limit_check', 0); if (time() >= $next_check) { // Only run reset if the MxChat_Integrator class exists if (class_exists('MxChat_Integrator')) { $integrator = new MxChat_Integrator(); if (method_exists($integrator, 'mxchat_reset_rate_limits')) { $integrator->mxchat_reset_rate_limits(); update_option('mxchat_next_rate_limit_check', time() + 3600); } } } } function mxchat_add_missing_columns($table, $column_name, $column_type) { global $wpdb; $column_exists = $wpdb->get_results($wpdb->prepare("SHOW COLUMNS FROM $table LIKE %s", $column_name)); if (empty($column_exists)) { $wpdb->query("ALTER TABLE $table ADD COLUMN $column_name $column_type"); } } function mxchat_check_for_update() { try { $current_version = get_option('mxchat_plugin_version'); $plugin_version = MXCHAT_VERSION; if ($current_version !== $plugin_version) { // Run live agent update BEFORE updating the stored version mxchat_handle_live_agent_update(); // Run existing update processes mxchat_activate(); mxchat_migrate_live_agent_status(); // Add the new cleanup function for version 2.1.8 if (version_compare($current_version, '2.1.8', '<')) { $deleted = mxchat_cleanup_orphaned_chat_history(); } // Update version LAST so the live agent update logic can work update_option('mxchat_plugin_version', $plugin_version); } } catch (Exception $e) { //error_log('MxChat update error: ' . $e->getMessage()); // Don't update version if there was an error } } /** * Clean up orphaned chat history options from the wp_options table * @return int Number of options deleted */ function mxchat_cleanup_orphaned_chat_history() { global $wpdb; $count = 0; // Get all option keys that match our pattern $history_options = $wpdb->get_results( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE 'mxchat_history_%'" ); if (!empty($history_options)) { foreach ($history_options as $option) { // Extract the session ID from the option name $session_id = str_replace('mxchat_history_', '', $option->option_name); // Check if this session still exists in the custom table $table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; $exists = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table_name} WHERE session_id = %s", $session_id ) ); // If session doesn't exist in the main table, delete the option if ($exists == 0) { delete_option($option->option_name); // Also delete related metadata delete_option("mxchat_email_{$session_id}"); delete_option("mxchat_agent_name_{$session_id}"); $count++; } } } return $count; } function mxchat_migrate_live_agent_status() { $options = get_option('mxchat_options', []); // Check if live_agent_status exists if (isset($options['live_agent_status'])) { $current_status = $options['live_agent_status']; $needs_update = false; // Convert to new format if needed if ($current_status === 'online') { $options['live_agent_status'] = 'on'; $needs_update = true; } else if ($current_status === 'offline') { $options['live_agent_status'] = 'off'; $needs_update = true; } else if (!in_array($current_status, ['on', 'off'])) { // Default to off for any unexpected values $options['live_agent_status'] = 'off'; $needs_update = true; } // Only update if needed if ($needs_update) { update_option('mxchat_options', $options); } } else { // If status doesn't exist, set default to off $options['live_agent_status'] = 'off'; update_option('mxchat_options', $options); } } function mxchat_handle_live_agent_update() { // Get the CURRENT stored version (before it gets updated) $current_version = get_option('mxchat_plugin_version', '0.0.0'); $new_version = '2.2.2'; // Only run this once for the update to 2.2.2 $update_handled = get_option('mxchat_live_agent_update_2_2_2_handled', false); // Check if we're upgrading TO 2.2.2 and haven't handled this yet if (version_compare($current_version, $new_version, '<') && !$update_handled) { $options = get_option('mxchat_options', array()); // Check if live agent was previously enabled if (isset($options['live_agent_status']) && $options['live_agent_status'] === 'on') { // Disable live agent $options['live_agent_status'] = 'off'; update_option('mxchat_options', $options); // Set flag to show the notification banner update_option('mxchat_show_live_agent_disabled_notice', true); } // Mark this update as handled update_option('mxchat_live_agent_update_2_2_2_handled', true); } } // Initialize plugin safely function mxchat_init() { // Include all class files first mxchat_include_classes(); // Run update check mxchat_check_for_update(); // Add fallback rate limit check add_action('init', 'mxchat_check_fallback_rate_limits', 5); // Initialize classes with error handling try { // Initialize admin classes if (is_admin()) { if (class_exists('MxChat_Knowledge_Manager')) { $mxchat_knowledge_manager = new MxChat_Knowledge_Manager(); if (class_exists('MxChat_Admin')) { $mxchat_admin = new MxChat_Admin($mxchat_knowledge_manager); } } } // Initialize public classes if (class_exists('MxChat_Public')) { $mxchat_public = new MxChat_Public(); } if (class_exists('MxChat_Integrator')) { $mxchat_integrator = new MxChat_Integrator(); } } catch (Exception $e) { //error_log('MxChat initialization error: ' . $e->getMessage()); // Show admin notice if there's an error if (is_admin()) { add_action('admin_notices', function() use ($e) { echo '

'; echo 'MxChat Error: Plugin initialization failed. '; echo 'Please check error logs or contact support. Error: ' . esc_html($e->getMessage()); echo '

'; }); } } } // Run initialization on plugins_loaded add_action('plugins_loaded', 'mxchat_init'); // Register activation hook register_activation_hook(__FILE__, 'mxchat_activate'); // Add cron schedule add_filter('cron_schedules', function($schedules) { $schedules['one_minute'] = array( 'interval' => 60, 'display' => 'Every Minute' ); return $schedules; }); // Register deactivation hook register_deactivation_hook(__FILE__, 'mxchat_deactivate');