| @@ -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') . '">×</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 | */ |