PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.1.3
MxChat – AI Chatbot & Content Generation for WordPress v3.1.3
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 | includes/class-mxchat-public.php +129 -78 3.2.73.1.3 View file →
@@ -10,38 +10,92 @@
10 10 // Simply get the options without defining duplicated defaults
11 11 $this->options = get_option('mxchat_options', array());
12 12 add_shortcode('mxchat_chatbot', array($this, 'render_chatbot_shortcode'));
13 13 add_action('wp_footer', array($this, 'append_chatbot_to_body'));
14 +
15 + // Initialize testing panel for admins
16 + add_action('wp_enqueue_scripts', array($this, 'enqueue_testing_assets'));
17 +
18 + // Add debug hook
19 + add_action('wp_footer', array($this, 'debug_display_logic'));
14 20 }
15 21
22 + /**
23 + * Enqueue testing panel assets for admin users
24 + */
25 + public function enqueue_testing_assets() {
26 + // Check if frontend debugger is enabled in settings
27 + $options = get_option('mxchat_options', array());
28 + $show_debugger = isset($options['show_frontend_debugger']) ? $options['show_frontend_debugger'] : 'on';
29 +
30 + // Only load if setting is enabled AND (user is admin or testing parameter is present)
31 + if ($show_debugger === 'on' && (current_user_can('administrator') || isset($_GET['mxchat_test']))) {
32 +
33 + // Get plugin URL for assets
34 + $plugin_url = plugin_dir_url(dirname(__FILE__));
35 +
36 + // Enqueue test panel CSS
37 + wp_enqueue_style(
38 + 'mxchat-test-panel',
39 + $plugin_url . 'css/test-panel.css',
40 + array(),
41 + '2.5.2'
42 + );
43 +
44 + // Enqueue test panel JS
45 + wp_enqueue_script(
46 + 'mxchat-test-panel',
47 + $plugin_url . 'js/test-panel.js',
48 + array('jquery'),
49 + '2.5.2',
50 + true
51 + );
52 +
53 + // Pass data to JavaScript
54 + wp_localize_script('mxchat-test-panel', 'mxchatTestData', array(
55 + 'ajaxUrl' => admin_url('admin-ajax.php'),
56 + 'nonce' => wp_create_nonce('mxchat_test_nonce'),
57 + 'isAdmin' => current_user_can('administrator'),
58 + 'testingEnabled' => true
59 + ));
60 +
61 + // Add JavaScript flag to enable testing
62 + add_action('wp_footer', array($this, 'add_testing_flag'));
63 + }
64 + }
65 +
66 + /**
67 + * Add JavaScript flag to enable testing panel
68 + */
69 + public function add_testing_flag() {
70 + echo '<script>window.mxchatTestingEnabled = true;</script>';
71 + }
72 +
73 + /**
74 + * Check if testing mode should be enabled
75 + */
76 + private function is_testing_mode_enabled() {
77 + return (current_user_can('administrator') || isset($_GET['mxchat_test']));
78 + }
79 +
16 80 /**
17 81 * UPDATED: Enhanced should_hide_chatbot method - only blocks auto-append, not shortcodes
18 82 */
19 83 private function should_hide_chatbot($context = 'auto') {
20 84 global $post;
21 -
85 +
22 86 if (!$post) {
23 87 return false;
24 88 }
25 -
89 +
90 + $hide_chatbot = get_post_meta($post->ID, '_mxchat_hide_chatbot', true);
91 +
26 92 // Only hide if it's the auto-append context (floating="yes" from global setting)
27 93 // Allow shortcodes to work regardless of this setting
28 - if ($context === 'auto') {
29 - // Check new visibility field first
30 - $visibility = get_post_meta($post->ID, '_mxchat_page_visibility', true);
31 - if ($visibility === 'hide') {
32 - return true;
33 - }
34 -
35 - // Backward compat: check legacy field if new field not set
36 - if (empty($visibility)) {
37 - $hide_chatbot = get_post_meta($post->ID, '_mxchat_hide_chatbot', true);
38 - if ($hide_chatbot === '1') {
39 - return true;
40 - }
41 - }
94 + if ($context === 'auto' && $hide_chatbot === '1') {
95 + return true;
42 96 }
43 -
97 +
44 98 return false;
45 99 }
46 100
47 101 /**
@@ -176,9 +230,9 @@
176 230 $email_state = $this->determine_email_collection_state();
177 231 $show_email_form = $email_state['show_email_form'];
178 232 $user_email = $email_state['user_email'] ?? '';
179 233 $user_name = $email_state['user_name'] ?? '';
180 - // Pre-chat dismissal now handled client-side via localStorage (zero server load)
234 + $transient_key = 'mxchat_pre_chat_message_dismissed_' . $user_id;
181 235 $input_copy = isset($current_options['input_copy']) ? esc_attr($current_options['input_copy']) : esc_attr__('How can I assist?', 'mxchat');
182 236 $rate_limit_message = isset($current_options['rate_limit_message']) ? esc_attr($current_options['rate_limit_message']) : esc_attr__('Rate limit exceeded. Please try again later.', 'mxchat');
183 237 $mode_indicator_bg_color = $current_options['mode_indicator_bg_color'] ?? '#212121';
184 238 $mode_indicator_font_color = $current_options['mode_indicator_font_color'] ?? '#fff';
@@ -230,25 +284,14 @@
230 284 if (!empty(trim($ai_agent_text))) {
231 285 echo '<span class="chat-mode-indicator" id="chat-mode-indicator-' . esc_attr($bot_id) . '" data-ai-text="' . esc_attr($ai_agent_text) . '"' . ($skip_inline_colors ? '' : ' style="color: ' . esc_attr($mode_indicator_font_color) . '; background-color: ' . esc_attr($mode_indicator_bg_color) . ';"') . '>' . esc_html($ai_agent_text) . '</span>';
232 286 }
233 287 echo ' </div>';
234 - // Overflow menu (3-dot) trigger + dropdown container.
235 - // Sibling of .exit-chat, rendered to its left. JS hides the trigger
236 - // if no menu items are enabled; outer click + Escape close the menu.
237 - echo ' <div class="mxchat-header-menu-wrap" data-bot-id="' . esc_attr($bot_id) . '"' . ($skip_inline_colors ? '' : ' style="--mxchat-menu-bg: ' . esc_attr($bot_message_bg_color) . '; --mxchat-menu-fg: ' . esc_attr($bot_message_font_color) . ';"') . '>';
238 - echo ' <button class="mxchat-header-btn mxchat-menu-trigger" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="' . esc_attr__('More options', 'mxchat') . '"' . ($skip_inline_colors ? '' : ' style="color: ' . esc_attr($close_button_color) . ';"') . '>';
239 - echo ' <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">';
240 - echo ' <circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/>';
241 - echo ' </svg>';
242 - echo ' </button>';
243 - echo ' <div class="mxchat-header-menu" role="menu" aria-hidden="true" hidden></div>';
244 - echo ' </div>';
245 - echo ' <button class="exit-chat" type="button" aria-label="' . esc_attr__('Close', 'mxchat') . '"' . ($skip_inline_colors ? '' : ' style="color: ' . esc_attr($close_button_color) . ';"') . '>';
246 - echo ' <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" id="ic-close" aria-hidden="true">';
247 - echo ' <line x1="6" y1="6" x2="18" y2="18"></line>';
248 - echo ' <line x1="18" y1="6" x2="6" y2="18"></line>';
288 + echo ' <button class="exit-chat" type="button" aria-label="' . esc_attr__('Minimize', 'mxchat') . '"' . ($skip_inline_colors ? '' : ' style="color: ' . esc_attr($close_button_color) . ';"') . '>';
289 + echo ' <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" id="ic-minimize"' . ($skip_inline_colors ? '' : ' style="fill: ' . esc_attr($close_button_color) . ';"') . '>';
290 + echo ' <path d="M0 0h24v24H0z" fill="none"></path>';
291 + echo ' <path d="M11.67 3.87L9.9 2.1 0 12l9.9 9.9 1.77-1.77L3.54 12z"></path>';
249 292 echo ' </svg>';
250 - echo ' <span>' . esc_html__('Close', 'mxchat') . '</span>';
293 + echo ' <span>' . esc_html__('Minimize', 'mxchat') . '</span>';
251 294 echo ' </button>';
252 295 echo ' </div>';
253 296
254 297 // 3b) Main chatbot container
@@ -283,14 +326,8 @@
283 326 echo ' </form>';
284 327 echo '</div>';
285 328 }
286 329
287 - echo ' <div id="mxchat-init-loader-' . esc_attr($bot_id) . '" class="mxchat-init-loader" style="display:none;">';
288 - echo ' <div class="mxchat-init-loader-dots">';
289 - echo ' <span class="dot"></span><span class="dot"></span><span class="dot"></span>';
290 - echo ' </div>';
291 - echo ' </div>';
292 -
293 330 echo ' <div id="chat-container-' . esc_attr($bot_id) . '" class="chat-container" style="' . ($enable_email_block && $show_email_form ? 'display: none;' : '') . '">';
294 331 echo ' <div id="chat-box-' . esc_attr($bot_id) . '" class="chat-box">';
295 332 echo ' <div class="bot-message"' . ($skip_inline_colors ? '' : ' style="background: ' . esc_attr($bot_message_bg_color) . ';"') . '>';
296 333 echo ' <div dir="auto"' . ($skip_inline_colors ? '' : ' style="color: ' . esc_attr($bot_message_font_color) . ';"') . '>';
@@ -437,19 +474,16 @@
437 474
438 475 if ($is_floating) {
439 476 echo '</div>';
440 477
441 - if (!empty($pre_chat_message)) {
442 - // Rendered hidden by default — JS checkPreChatDismissal() handles show/hide via localStorage
443 - echo '<div id="pre-chat-message-' . esc_attr($bot_id) . '" class="pre-chat-message" style="display:none;">';
478 + if (!empty($pre_chat_message) && !get_transient($transient_key)) {
479 + echo '<div id="pre-chat-message-' . esc_attr($bot_id) . '" class="pre-chat-message">';
444 480 echo nl2br(esc_html($pre_chat_message));
445 481 echo '<button class="close-pre-chat-message" aria-label="' . esc_attr__('Close', 'mxchat') . '">&times;</button>';
446 482 echo '</div>';
447 483 }
448 484
449 - $is_initially_hidden = (strpos($visibility_class, 'hidden') !== false);
450 - $aria_expanded = $is_initially_hidden ? 'false' : 'true';
451 - echo '<div class="floating-chatbot-button ' . esc_attr($visibility_class) . '" id="floating-chatbot-button-' . esc_attr($bot_id) . '" role="button" tabindex="0" aria-label="' . esc_attr__('Open chat', 'mxchat') . '" aria-expanded="' . esc_attr($aria_expanded) . '" aria-controls="floating-chatbot-' . esc_attr($bot_id) . '"' . ($skip_inline_colors ? '' : ' style="background: ' . esc_attr($chatbot_background_color) . '; color: ' . esc_attr($send_button_font_color) . ';"') . '>';
485 + echo '<div class="floating-chatbot-button ' . esc_attr($visibility_class) . '" id="floating-chatbot-button-' . esc_attr($bot_id) . '"' . ($skip_inline_colors ? '' : ' style="background: ' . esc_attr($chatbot_background_color) . '; color: ' . esc_attr($send_button_font_color) . ';"') . '>';
452 486 echo '<div id="chat-notification-badge-' . esc_attr($bot_id) . '" class="chat-notification-badge" style="display: none; position: absolute; top: -8px; right: -8px; background-color: #ff4444; color: white; border-radius: 50%; padding: 4px 8px; font-size: 12px; font-weight: bold; z-index: 10001;">1</div>';
453 487
454 488 if (!empty($custom_icon)) {
455 489 echo '<img src="' . $custom_icon . '" alt="' . esc_attr__('Chatbot Icon', 'mxchat') . '" style="height: 48px; width: 48px; object-fit: contain;" />';
@@ -508,9 +542,12 @@
508 542 }
509 543
510 544
511 545 private function determine_email_collection_state() {
512 - // Logged-in users skip the email form
546 + // Get session ID
547 + $session_id = 'mxchat_chat_' . wp_generate_uuid4(); // You'll need to use your actual session generation logic
548 +
549 + // Check if user is logged in first
513 550 if (is_user_logged_in()) {
514 551 $current_user = wp_get_current_user();
515 552 return [
516 553 'show_email_form' => false,
@@ -517,16 +554,26 @@
517 554 'user_email' => $current_user->user_email,
518 555 'user_name' => $current_user->display_name ?: $current_user->first_name ?: ''
519 556 ];
520 557 }
521 -
522 - // For guests, default to showing the email form.
523 - // The session-based check happens client-side via AJAX since the
524 - // session ID lives in the browser cookie/localStorage.
558 +
559 + // Check stored email for session
560 + $stored_email = get_option("mxchat_email_{$session_id}", '');
561 + $stored_name = get_option("mxchat_name_{$session_id}", '');
562 +
563 + // Check if name is required
564 + $name_field_enabled = isset($this->options['enable_name_field']) &&
565 + ($this->options['enable_name_field'] === '1' || $this->options['enable_name_field'] === 'on');
566 +
567 + $has_required_info = !empty($stored_email);
568 + if ($name_field_enabled) {
569 + $has_required_info = $has_required_info && !empty($stored_name);
570 + }
571 +
525 572 return [
526 - 'show_email_form' => true,
527 - 'user_email' => '',
528 - 'user_name' => ''
573 + 'show_email_form' => !$has_required_info,
574 + 'user_email' => $stored_email,
575 + 'user_name' => $stored_name
529 576 ];
530 577 }
531 578
532 579
@@ -641,46 +688,31 @@
641 688 return '';
642 689 }
643 690
644 691 /**
645 - * Get page-specific bot setting using new visibility field with backward compat
692 + * NEW: Get page-specific bot setting
646 693 */
647 694 private function get_page_bot_setting($post_id = null) {
648 695 if (!$post_id) {
649 696 $post_id = get_the_ID();
650 697 }
651 -
698 +
652 699 if (!$post_id) {
653 700 return null;
654 701 }
655 -
656 - // Check new visibility field first
657 - $visibility = get_post_meta($post_id, '_mxchat_page_visibility', true);
658 -
659 - if ($visibility === 'hide') {
702 +
703 + // Check if chatbot is hidden on this page
704 + $hide_chatbot = get_post_meta($post_id, '_mxchat_hide_chatbot', true);
705 + if ($hide_chatbot === '1') {
660 706 return array('action' => 'hide');
661 707 }
662 -
663 - if ($visibility === 'show') {
664 - $selected_bot = get_post_meta($post_id, '_mxchat_selected_bot', true);
665 - $bot_id = !empty($selected_bot) ? $selected_bot : 'default';
666 - return array('action' => 'show', 'bot_id' => $bot_id);
667 - }
668 -
669 - // Backward compat: check legacy hide checkbox if no new field set
670 - if (empty($visibility)) {
671 - $hide_chatbot = get_post_meta($post_id, '_mxchat_hide_chatbot', true);
672 - if ($hide_chatbot === '1') {
673 - return array('action' => 'hide');
674 - }
675 - }
676 -
677 - // Check if specific bot is selected (legacy path)
708 +
709 + // Check if specific bot is selected
678 710 $selected_bot = get_post_meta($post_id, '_mxchat_selected_bot', true);
679 711 if (!empty($selected_bot)) {
680 712 return array('action' => 'show', 'bot_id' => $selected_bot);
681 713 }
682 -
714 +
683 715 // Use global setting
684 716 return array('action' => 'global');
685 717 }
686 718
@@ -712,8 +744,27 @@
712 744
713 745 /**
714 746 * UPDATED: Debug function with new context info
715 747 */
748 +public function debug_display_logic() {
749 + if (current_user_can('manage_options') && isset($_GET['mxchat_debug'])) {
750 + $bot_to_show = $this->get_display_bot();
751 + $page_setting = $this->get_page_bot_setting();
752 + $global_autoshow = isset($this->options['append_to_body']) && $this->options['append_to_body'] === 'on';
753 + $hide_auto = $this->should_hide_chatbot('auto');
754 +
755 + echo '<div style="position: fixed; top: 50px; right: 20px; background: white; border: 2px solid red; padding: 10px; z-index: 9999; max-width: 300px; font-size: 12px;">';
756 + echo '<h4 style="margin: 0 0 10px 0;">MxChat Debug Info</h4>';
757 + echo '<p><strong>Raw append_to_body value:</strong> "' . ($this->options['append_to_body'] ?? 'NOT SET') . '"</p>';
758 + echo '<p><strong>Page Setting:</strong><br><pre>' . print_r($page_setting, true) . '</pre></p>';
759 + echo '<p><strong>Global Auto-show:</strong> ' . ($global_autoshow ? 'ON' : 'OFF') . '</p>';
760 + echo '<p><strong>Hide Auto-Append:</strong> ' . ($hide_auto ? 'YES' : 'NO') . '</p>';
761 + echo '<p><strong>Bot to Show:</strong> ' . ($bot_to_show === false ? 'NONE' : $bot_to_show) . '</p>';
762 + echo '<p><strong>Shortcodes:</strong> floating="no" always works</p>';
763 + echo '<p><small>Add ?mxchat_debug=1 to URL to see this</small></p>';
764 + echo '</div>';
765 + }
766 +}
716 767
717 768 /**
718 769 * NEW: Helper method to get available bots (for admin notices, etc.)
719 770 */