| @@ -43,16 +43,14 @@ | ||
| 43 | 43 | add_action('admin_post_mxchat_edit_intent', array($this, 'handle_edit_intent')); |
| 44 | 44 | add_action('save_post', array($this, 'handle_post_update'), 10, 3); |
| 45 | 45 | add_action('post_updated', array($this, 'handle_post_update'), 10, 3); |
| 46 | 46 | add_action('wp_ajax_mxchat_save_setting', array($this, 'mxchat_save_setting_callback')); |
| 47 | - add_action('wp_trash_post', array($this, 'mxchat_handle_post_delete')); | |
| 48 | - add_action('before_delete_post', array($this, 'mxchat_handle_post_delete')); | |
| 49 | - add_action('wp_ajax_mxchat_export_transcripts', array($this, 'export_chat_transcripts')); | |
| 47 | + | |
| 50 | 48 | add_action('wp_ajax_mxchat_save_prompts_setting', array($this, 'mxchat_save_prompts_setting_callback')); |
| 51 | 49 | if (isset($this->options['enable_woocommerce_integration']) && |
| 52 | 50 | ($this->options['enable_woocommerce_integration'] === '1' || |
| 53 | 51 | $this->options['enable_woocommerce_integration'] === 'on')) { |
| 54 | - | |
| 52 | + | |
| 55 | 53 | //error_log('MxChat Admin: WooCommerce integration is enabled, adding hooks'); |
| 56 | 54 | add_action('wp_insert_post', array($this, 'mxchat_handle_product_change'), 10, 3); |
| 57 | 55 | add_action('wp_trash_post', array($this, 'mxchat_handle_product_delete')); |
| 58 | 56 | add_action('before_delete_post', array($this, 'mxchat_handle_product_delete')); |
| @@ -71,14 +69,12 @@ | ||
| 71 | 69 | 'api_key' => '', |
| 72 | 70 | 'xai_api_key' => '', |
| 73 | 71 | 'claude_api_key' => '', |
| 74 | 72 | 'deepseek_api_key' => '', |
| 75 | - 'voyage_api_key' => '', | |
| 76 | - 'embedding_model' => 'text-embedding-ada-002', | |
| 77 | 73 | 'system_prompt_instructions' => esc_html__('[EXAMPLE INSTRUCTIONS] You are an AI Chatbot assistant for this website. The primary subject you should focus on is [insert proper subject here]. Your main goal is to assist visitors with questions related to this specific topic. Here are some key things to keep in mind: |
| 78 | 74 | - Your name is [Chatbot Name]. |
| 79 | 75 | - Stay focused on topics related to [insert proper subject here]. If a visitor asks about an unrelated topic, politely redirect the conversation to how you can assist them with this subject. |
| 80 | - - Do not make up links to pages. Only use specific links you see in your knowledgebase from [insert your domain]. Do not make assumptions or make up URLs. | |
| 76 | + - Do not make up links to pages. Only use specific links you see in your knowledgebase. | |
| 81 | 77 | - Keep your responses short, concise, and to the point. Provide clear and direct answers suitable for a chatbot interaction. |
| 82 | 78 | - Provide answers based on the knowledge available to you. If you do not have an answer to a specific question, let the visitor know that you don’t have the information.', 'mxchat'), |
| 83 | 79 | 'model' => esc_html__('gpt-4o', 'mxchat'), |
| 84 | 80 | 'rate_limit_logged_out' => esc_html__('100', 'mxchat'), |
| @@ -176,26 +172,28 @@ | ||
| 176 | 172 | 'mxchat-prompts', |
| 177 | 173 | array($this, 'mxchat_create_prompts_page') |
| 178 | 174 | ); |
| 179 | 175 | |
| 176 | + // Submenu page for Chat Transcripts | |
| 180 | 177 | add_submenu_page( |
| 181 | - 'mxchat-max', | |
| 178 | + 'mxchat-max', // Corrected parent slug to match the main menu | |
| 182 | 179 | esc_html__('Chat Transcripts', 'mxchat'), |
| 183 | 180 | esc_html__('Transcripts', 'mxchat'), |
| 184 | 181 | 'manage_options', |
| 185 | 182 | 'mxchat-transcripts', |
| 186 | - array($this, 'mxchat_create_transcripts_page') | |
| 183 | + array($this, 'mxchat_create_transcripts_page') // Prefixed function name with mxchat_ | |
| 187 | 184 | ); |
| 188 | 185 | |
| 186 | + // Submenu page for Intents | |
| 189 | 187 | add_submenu_page( |
| 190 | - 'mxchat-max', | |
| 191 | - esc_html__('MxChat Intents', 'mxchat'), | |
| 192 | - esc_html__('Intents', 'mxchat'), | |
| 193 | - 'manage_options', | |
| 194 | - 'mxchat-intents', | |
| 195 | - array($this, 'mxchat_intents_page_html') | |
| 188 | + 'mxchat-max', // Parent slug | |
| 189 | + esc_html__('MxChat Intents', 'mxchat'), // Page title | |
| 190 | + esc_html__('Intents', 'mxchat'), // Menu title | |
| 191 | + 'manage_options', // Capability | |
| 192 | + 'mxchat-intents', // Menu slug | |
| 193 | + array($this, 'mxchat_intents_page_html') // Callback function | |
| 196 | 194 | ); |
| 197 | - | |
| 195 | + | |
| 198 | 196 | add_submenu_page( |
| 199 | 197 | 'mxchat-max', |
| 200 | 198 | esc_html__('Add Ons', 'mxchat'), |
| 201 | 199 | esc_html__('Add Ons', 'mxchat'), |
| @@ -243,8 +241,9 @@ | ||
| 243 | 241 | // Also update old option for backwards compatibility |
| 244 | 242 | update_option('additional_popular_questions', $questions); |
| 245 | 243 | } |
| 246 | 244 | break; |
| 245 | + case 'close_button_color': | |
| 247 | 246 | case 'user_message_bg_color': |
| 248 | 247 | case 'user_message_font_color': |
| 249 | 248 | case 'bot_message_bg_color': |
| 250 | 249 | case 'bot_message_font_color': |
| @@ -411,15 +410,16 @@ | ||
| 411 | 410 | <?php endif; ?> |
| 412 | 411 | |
| 413 | 412 | <div class="mxchat-agents-banner"> |
| 414 | 413 | <p> |
| 415 | - <strong><?php echo esc_html__('The MxChat Add-Ons Platform', 'mxchat'); ?></strong><?php echo esc_html__(' is here! Pro users get unlimited access to our growing collection of powerful add-ons. ', 'mxchat'); ?><a href="<?php echo admin_url('admin.php?page=mxchat-addons'); ?>"><?php echo esc_html__('Explore all add-ons', 'mxchat'); ?></a><?php echo esc_html__(' including Forms Builder, Theme Customizer, Content Moderation, and more – all included with your lifetime Pro license!', 'mxchat'); ?> | |
| 416 | - </p> | |
| 414 | + <?php echo esc_html__('Pro users get exclusive access to', 'mxchat'); ?> <a href="https://mxchat.ai/agents/" target="_blank"><?php echo esc_html__('MxChat AI Agents', 'mxchat'); ?></a> <?php echo esc_html__('– our groundbreaking platform to test, refine, and deploy your chatbot with confidence. Take your AI assistant to the next level!', 'mxchat'); ?> | |
| 415 | + </p> | |
| 417 | 416 | </div> |
| 418 | 417 | |
| 419 | 418 | <h2 class="mxchat-nav-tab-wrapper"> |
| 420 | 419 | <a href="#chatbot" class="mxchat-nav-tab mxchat-nav-tab-active" data-tab="chatbot"><?php echo esc_html__('Chatbot', 'mxchat'); ?></a> |
| 421 | 420 | <a href="#embed" class="mxchat-nav-tab" data-tab="embed"><?php echo esc_html__('Integrations', 'mxchat'); ?></a> |
| 421 | + <a href="#theme" class="mxchat-nav-tab" data-tab="theme"><?php echo esc_html__('Theme', 'mxchat'); ?></a> | |
| 422 | 422 | <a href="#general" class="mxchat-nav-tab" data-tab="general"><?php echo esc_html__('FAQ', 'mxchat'); ?></a> |
| 423 | 423 | </h2> |
| 424 | 424 | |
| 425 | 425 | <div id="chatbot" class="mxchat-tab-content active"> |
| @@ -429,8 +429,15 @@ | ||
| 429 | 429 | </div> |
| 430 | 430 | |
| 431 | 431 | <div id="embed" class="mxchat-tab-content"> |
| 432 | 432 | <div class="mxchat-autosave-section"> |
| 433 | + <div class="mxchat-settings-section"> | |
| 434 | + <h2><?php echo esc_html__('WooCommerce Settings', 'mxchat'); ?></h2> | |
| 435 | + <table class="form-table"> | |
| 436 | + <?php do_settings_fields('mxchat-embed', 'mxchat_woocommerce_section'); ?> | |
| 437 | + </table> | |
| 438 | + </div> | |
| 439 | + <div class="section-divider"></div> | |
| 433 | 440 | |
| 434 | 441 | <div class="mxchat-settings-section"> |
| 435 | 442 | <h2><?php echo esc_html__('Loops Settings', 'mxchat'); ?></h2> |
| 436 | 443 | <table class="form-table"> |
| @@ -468,8 +475,13 @@ | ||
| 468 | 475 | </div> |
| 469 | 476 | </div> |
| 470 | 477 | </div> |
| 471 | 478 | |
| 479 | + <div id="theme" class="mxchat-tab-content"> | |
| 480 | + <div class="mxchat-autosave-section"> | |
| 481 | + <?php do_settings_sections('mxchat-theme'); ?> | |
| 482 | + </div> | |
| 483 | + </div> | |
| 472 | 484 | |
| 473 | 485 | <div id="general" class="mxchat-tab-content"> |
| 474 | 486 | <?php do_settings_sections('mxchat-general'); ?> |
| 475 | 487 | <p> |
| @@ -578,8 +590,9 @@ | ||
| 578 | 590 | <?php |
| 579 | 591 | } |
| 580 | 592 | |
| 581 | 593 | |
| 594 | + | |
| 582 | 595 | public function mxchat_create_transcripts_page() { |
| 583 | 596 | global $wpdb; |
| 584 | 597 | $table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; |
| 585 | 598 | |
| @@ -585,341 +598,65 @@ | ||
| 585 | 598 | |
| 586 | 599 | // Get basic stats |
| 587 | 600 | $total_chats = $wpdb->get_var("SELECT COUNT(DISTINCT session_id) FROM $table_name"); |
| 588 | 601 | $total_messages = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); |
| 589 | - | |
| 590 | - // Count unique users with detailed breakdown | |
| 591 | - $total_users = $wpdb->get_var(" | |
| 592 | - SELECT COUNT(DISTINCT | |
| 593 | - CASE | |
| 594 | - WHEN user_email != '' AND user_email IS NOT NULL THEN user_email | |
| 595 | - WHEN user_id != 0 THEN CONCAT('user_', user_id) | |
| 596 | - WHEN user_identifier NOT LIKE 'Tech-Savvy User' | |
| 597 | - AND user_identifier NOT LIKE 'Detail-Oriented User' | |
| 598 | - AND user_identifier NOT LIKE 'Language Learner' | |
| 599 | - AND user_identifier NOT LIKE 'Casual Browser' | |
| 600 | - AND user_identifier NOT LIKE 'Policy Enforcer' | |
| 601 | - AND user_identifier NOT LIKE 'Researcher' | |
| 602 | - AND user_identifier NOT LIKE 'Loyalty Member' | |
| 603 | - AND user_identifier NOT LIKE 'Gift Buyer' | |
| 604 | - AND user_identifier NOT LIKE 'Parent or Caregiver' | |
| 605 | - THEN user_identifier | |
| 606 | - ELSE session_id | |
| 607 | - END | |
| 608 | - ) | |
| 609 | - FROM $table_name | |
| 610 | - WHERE role != 'assistant' | |
| 611 | - "); | |
| 612 | - | |
| 613 | - // Get user type breakdown | |
| 614 | - $registered_users = $wpdb->get_var(" | |
| 615 | - SELECT COUNT(DISTINCT user_email) | |
| 616 | - FROM $table_name | |
| 617 | - WHERE user_email != '' AND user_email IS NOT NULL | |
| 618 | - "); | |
| 619 | - | |
| 620 | - $guest_users = $wpdb->get_var(" | |
| 621 | - SELECT COUNT(DISTINCT user_identifier) | |
| 622 | - FROM $table_name | |
| 623 | - WHERE (user_email = '' OR user_email IS NULL) | |
| 624 | - AND role != 'assistant' | |
| 625 | - AND user_identifier NOT LIKE 'Tech-Savvy User' | |
| 626 | - AND user_identifier NOT LIKE 'Detail-Oriented User' | |
| 627 | - AND user_identifier NOT LIKE 'Language Learner' | |
| 628 | - AND user_identifier NOT LIKE 'Casual Browser' | |
| 629 | - AND user_identifier NOT LIKE 'Policy Enforcer' | |
| 630 | - AND user_identifier NOT LIKE 'Researcher' | |
| 631 | - AND user_identifier NOT LIKE 'Loyalty Member' | |
| 632 | - AND user_identifier NOT LIKE 'Gift Buyer' | |
| 633 | - AND user_identifier NOT LIKE 'Parent or Caregiver' | |
| 634 | - "); | |
| 635 | - | |
| 636 | - // Get agent test messages count | |
| 637 | - $agent_tests = $wpdb->get_var(" | |
| 638 | - SELECT COUNT(DISTINCT session_id) | |
| 639 | - FROM $table_name | |
| 640 | - WHERE user_identifier IN ( | |
| 641 | - 'Tech-Savvy User', | |
| 642 | - 'Detail-Oriented User', | |
| 643 | - 'Language Learner', | |
| 644 | - 'Casual Browser', | |
| 645 | - 'Policy Enforcer', | |
| 646 | - 'Researcher', | |
| 647 | - 'Loyalty Member', | |
| 648 | - 'Gift Buyer', | |
| 649 | - 'Parent or Caregiver' | |
| 650 | - ) | |
| 651 | - "); | |
| 602 | + $total_users = $wpdb->get_var("SELECT COUNT(DISTINCT user_email) FROM $table_name WHERE user_email != ''"); | |
| 652 | 603 | ?> |
| 653 | - <div class="wrap mxchat-transcripts-wrapper"> | |
| 654 | - <!-- Hero Section --> | |
| 655 | - <div class="mxchat-transcripts-hero"> | |
| 656 | - <h1 class="mxchat-main-title"> | |
| 657 | - Chat <span class="mxchat-gradient-text">Transcripts</span> | |
| 658 | - </h1> | |
| 659 | - <p class="mxchat-hero-subtitle"> | |
| 660 | - <?php esc_html_e('Review and manage your chatbot conversations with detailed message history.', 'mxchat'); ?> | |
| 661 | - </p> | |
| 662 | - </div> | |
| 663 | - <div class="mxchat-content"> | |
| 664 | - <!-- Stats Cards --> | |
| 665 | - <div class="mxchat-stats-grid"> | |
| 666 | - <div class="mxchat-stat-card"> | |
| 667 | - <div class="stat-icon">💬</div> | |
| 668 | - <div class="stat-content"> | |
| 669 | - <span class="stat-value"><?php echo esc_html($total_chats); ?></span> | |
| 670 | - <span class="stat-label"><?php esc_html_e('Total Chats', 'mxchat'); ?></span> | |
| 671 | - </div> | |
| 604 | + <div class="wrap mxchat-admin"> | |
| 605 | + <!-- Stats Cards --> | |
| 606 | + <div class="mxchat-stats-grid"> | |
| 607 | + <div class="mxchat-stat-card"> | |
| 608 | + <div class="stat-icon">💬</div> | |
| 609 | + <div class="stat-content"> | |
| 610 | + <span class="stat-value"><?php echo esc_html($total_chats); ?></span> | |
| 611 | + <span class="stat-label"><?php esc_html_e('Total Chats', 'mxchat'); ?></span> | |
| 672 | 612 | </div> |
| 673 | - <div class="mxchat-stat-card"> | |
| 674 | - <div class="stat-icon">📝</div> | |
| 675 | - <div class="stat-content"> | |
| 676 | - <span class="stat-value"><?php echo esc_html($total_messages); ?></span> | |
| 677 | - <span class="stat-label"><?php esc_html_e('Total Messages', 'mxchat'); ?></span> | |
| 678 | - </div> | |
| 613 | + </div> | |
| 614 | + <div class="mxchat-stat-card"> | |
| 615 | + <div class="stat-icon">📝</div> | |
| 616 | + <div class="stat-content"> | |
| 617 | + <span class="stat-value"><?php echo esc_html($total_messages); ?></span> | |
| 618 | + <span class="stat-label"><?php esc_html_e('Total Messages', 'mxchat'); ?></span> | |
| 679 | 619 | </div> |
| 680 | - <div class="mxchat-stat-card"> | |
| 681 | - <div class="stat-icon">👥</div> | |
| 682 | - <div class="stat-content"> | |
| 683 | - <span class="stat-value"><?php echo esc_html($total_users); ?></span> | |
| 684 | - <span class="stat-label"><?php esc_html_e('Unique Users', 'mxchat'); ?></span> | |
| 685 | - <span class="stat-sublabel"> | |
| 686 | - <?php | |
| 687 | - echo sprintf( | |
| 688 | - esc_html__('%d registered, %d guests, %d agent tests', 'mxchat'), | |
| 689 | - $registered_users, | |
| 690 | - $guest_users, | |
| 691 | - $agent_tests | |
| 692 | - ); | |
| 693 | - ?> | |
| 694 | - </span> | |
| 695 | - </div> | |
| 696 | - </div> | |
| 697 | 620 | </div> |
| 698 | - <!-- Search and Filter Controls --> | |
| 699 | - <div class="mxchat-controls-wrapper"> | |
| 700 | - <div class="mxchat-search-box"> | |
| 701 | - <input type="text" id="mxchat-search-transcripts" | |
| 702 | - placeholder="<?php esc_attr_e('Search transcripts...', 'mxchat'); ?>" | |
| 703 | - class="regular-text"> | |
| 621 | + <div class="mxchat-stat-card"> | |
| 622 | + <div class="stat-icon">👥</div> | |
| 623 | + <div class="stat-content"> | |
| 624 | + <span class="stat-value"><?php echo esc_html($total_users); ?></span> | |
| 625 | + <span class="stat-label"><?php esc_html_e('Unique Users', 'mxchat'); ?></span> | |
| 704 | 626 | </div> |
| 705 | - <form id="mxchat-delete-form" method="post"> | |
| 706 | - <?php wp_nonce_field('mxchat_delete_chat_history', 'mxchat_delete_chat_nonce'); ?> | |
| 707 | - <div class="mxchat-controls"> | |
| 708 | - <button type="button" id="mxchat-export-transcripts" class="mxchat-action-button"> | |
| 709 | - <span class="dashicons dashicons-download"></span> | |
| 710 | - <?php esc_html_e('Export All Chats', 'mxchat'); ?> | |
| 711 | - </button> | |
| 712 | - <button type="button" id="mxchat-select-all-transcripts" class="mxchat-select-button"> | |
| 713 | - <span class="dashicons dashicons-yes-alt"></span> | |
| 714 | - <span class="button-text"><?php esc_html_e('Select All', 'mxchat'); ?></span> | |
| 715 | - </button> | |
| 716 | - <button type="submit" class="button delete-chats-button"> | |
| 717 | - <span class="dashicons dashicons-trash"></span> | |
| 718 | - <?php esc_html_e('Delete Selected', 'mxchat'); ?> | |
| 719 | - </button> | |
| 720 | - </div> | |
| 721 | - </form> | |
| 722 | 627 | </div> |
| 723 | - <!-- Transcripts Container --> | |
| 724 | - <div id="mxchat-transcripts"></div> | |
| 725 | 628 | </div> |
| 726 | - </div> | |
| 727 | - <?php | |
| 728 | -} | |
| 729 | 629 | |
| 730 | -public function export_chat_transcripts() { | |
| 731 | - if (!current_user_can('manage_options')) { | |
| 732 | - wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'mxchat')); | |
| 733 | - } | |
| 630 | + <!-- Search and Filter Controls --> | |
| 631 | + <div class="mxchat-controls-wrapper"> | |
| 632 | + <div class="mxchat-search-box"> | |
| 633 | + <input type="text" id="mxchat-search-transcripts" | |
| 634 | + placeholder="<?php esc_attr_e('Search transcripts...', 'mxchat'); ?>" | |
| 635 | + class="regular-text"> | |
| 636 | + </div> | |
| 734 | 637 | |
| 735 | - check_ajax_referer('mxchat_export_transcripts', 'security'); | |
| 638 | + <form id="mxchat-delete-form" method="post"> | |
| 639 | + <?php wp_nonce_field('mxchat_delete_chat_history', 'mxchat_delete_chat_nonce'); ?> | |
| 640 | + <div class="mxchat-controls"> | |
| 641 | + <button type="button" id="mxchat-select-all-transcripts" class="mxchat-select-button"> | |
| 642 | + <span class="dashicons dashicons-yes-alt"></span> | |
| 643 | + <span class="button-text"><?php esc_html_e('Select All', 'mxchat'); ?></span> | |
| 644 | + </button> | |
| 645 | + <button type="submit" class="button delete-chats-button"> | |
| 646 | + <span class="dashicons dashicons-trash"></span> | |
| 647 | + <?php esc_html_e('Delete Selected', 'mxchat'); ?> | |
| 648 | + </button> | |
| 649 | + </div> | |
| 650 | + </form> | |
| 651 | + </div> | |
| 736 | 652 | |
| 737 | - global $wpdb; | |
| 738 | - $table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; | |
| 739 | - | |
| 740 | - // Get all transcripts ordered by session and timestamp | |
| 741 | - $results = $wpdb->get_results( | |
| 742 | - "SELECT session_id, user_email, user_identifier, role, message, timestamp | |
| 743 | - FROM {$table_name} | |
| 744 | - ORDER BY session_id, timestamp ASC" | |
| 745 | - ); | |
| 746 | - | |
| 747 | - if (empty($results)) { | |
| 748 | - wp_send_json_error(array('message' => 'No transcripts found.')); | |
| 749 | - wp_die(); | |
| 750 | - } | |
| 751 | - | |
| 752 | - // Set headers for CSV download | |
| 753 | - header('Content-Type: text/csv'); | |
| 754 | - header('Content-Disposition: attachment; filename="chat-transcripts-' . date('Y-m-d') . '.csv"'); | |
| 755 | - header('Pragma: no-cache'); | |
| 756 | - header('Expires: 0'); | |
| 757 | - | |
| 758 | - // Create output stream | |
| 759 | - $output = fopen('php://output', 'w'); | |
| 760 | - | |
| 761 | - // Add UTF-8 BOM for proper Excel encoding | |
| 762 | - fputs($output, "\xEF\xBB\xBF"); | |
| 763 | - | |
| 764 | - // Add CSV headers | |
| 765 | - fputcsv($output, array( | |
| 766 | - 'Session ID', | |
| 767 | - 'Email', | |
| 768 | - 'User Identifier', | |
| 769 | - 'Role', | |
| 770 | - 'Message', | |
| 771 | - 'Timestamp' | |
| 772 | - )); | |
| 773 | - | |
| 774 | - // Add data rows | |
| 775 | - foreach ($results as $row) { | |
| 776 | - fputcsv($output, array( | |
| 777 | - $row->session_id, | |
| 778 | - $row->user_email, | |
| 779 | - $row->user_identifier, | |
| 780 | - $row->role, | |
| 781 | - $row->message, | |
| 782 | - $row->timestamp | |
| 783 | - )); | |
| 784 | - } | |
| 785 | - | |
| 786 | - fclose($output); | |
| 787 | - wp_die(); | |
| 653 | + <!-- Transcripts Container --> | |
| 654 | + <div id="mxchat-transcripts"></div> | |
| 655 | + </div> | |
| 656 | + <?php | |
| 788 | 657 | } |
| 789 | 658 | |
| 790 | -public function mxchat_fetch_chat_history() { | |
| 791 | - global $wpdb; | |
| 792 | - $table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; | |
| 793 | - | |
| 794 | - if (!current_user_can('manage_options')) { | |
| 795 | - wp_die(esc_html__('You do not have sufficient permissions to view this page.', 'mxchat')); | |
| 796 | - } | |
| 797 | - | |
| 798 | - // First get unique session IDs ordered by most recent message in each session | |
| 799 | - $session_ids = $wpdb->get_col( | |
| 800 | - $wpdb->prepare( | |
| 801 | - "SELECT DISTINCT session_id | |
| 802 | - FROM {$table_name} | |
| 803 | - GROUP BY session_id | |
| 804 | - ORDER BY MAX(timestamp) DESC" | |
| 805 | - ) | |
| 806 | - ); | |
| 807 | - | |
| 808 | - if (empty($session_ids)) { | |
| 809 | - wp_die(esc_html__('No chat history available.', 'mxchat')); | |
| 810 | - } | |
| 811 | - | |
| 812 | - ob_start(); | |
| 813 | - echo '<div class="mxchat-transcript">'; | |
| 814 | - | |
| 815 | - // Iterate through sessions from newest to oldest | |
| 816 | - foreach ($session_ids as $session_id) { | |
| 817 | - // Get the email associated with this session (if available) | |
| 818 | - $email = $wpdb->get_var( | |
| 819 | - $wpdb->prepare( | |
| 820 | - "SELECT user_email | |
| 821 | - FROM {$table_name} | |
| 822 | - WHERE session_id = %s AND user_email != '' | |
| 823 | - ORDER BY timestamp ASC | |
| 824 | - LIMIT 1", | |
| 825 | - $session_id | |
| 826 | - ) | |
| 827 | - ); | |
| 828 | - | |
| 829 | - // Debug: Check email retrieval | |
| 830 | - if (empty($email)) { | |
| 831 | - //error_log("No email found for session {$session_id}"); | |
| 832 | - } else { | |
| 833 | - //error_log("Email for session {$session_id}: " . $email); | |
| 834 | - } | |
| 835 | - | |
| 836 | - // Get messages for this session ordered by timestamp | |
| 837 | - $messages = $wpdb->get_results( | |
| 838 | - $wpdb->prepare( | |
| 839 | - "SELECT * FROM {$table_name} | |
| 840 | - WHERE session_id = %s | |
| 841 | - ORDER BY timestamp ASC", | |
| 842 | - $session_id | |
| 843 | - ) | |
| 844 | - ); | |
| 845 | - | |
| 846 | - // Start session block | |
| 847 | - echo '<div class="mxchat-session">'; | |
| 848 | - echo '<div class="mxchat-session-header">'; | |
| 849 | - // Wrap checkbox and session ID in one block | |
| 850 | - echo '<div class="mxchat-session-id">'; | |
| 851 | - echo '<input type="checkbox" name="delete_session_ids[]" value="' . esc_attr($session_id) . '"> '; | |
| 852 | - echo '<strong>' . esc_html__('Session ID:', 'mxchat') . '</strong> ' . esc_html($session_id); | |
| 853 | - echo '</div>'; | |
| 854 | - | |
| 855 | - // Place email directly below the session ID block | |
| 856 | - if (!empty($email)) { | |
| 857 | - echo '<div class="mxchat-session-email">'; | |
| 858 | - echo '<strong>' . esc_html__('Email:', 'mxchat') . '</strong> ' . esc_html($email); | |
| 859 | - echo '</div>'; | |
| 860 | - } | |
| 861 | - echo '</div>'; | |
| 862 | - | |
| 863 | - echo '<div class="mxchat-messages">'; | |
| 864 | - | |
| 865 | - // Display messages for this session | |
| 866 | - foreach ($messages as $transcript) { | |
| 867 | - $formatted_timestamp = date_i18n('F j, Y g:i a', strtotime($transcript->timestamp)); | |
| 868 | - | |
| 869 | - // Determine message styling | |
| 870 | - switch ($transcript->role) { | |
| 871 | - case 'assistant': | |
| 872 | - case 'bot': | |
| 873 | - $message_class = 'bot-message'; | |
| 874 | - $display_role = esc_html__('Chatbot', 'mxchat'); | |
| 875 | - break; | |
| 876 | - case 'user': | |
| 877 | - $message_class = 'user-message'; | |
| 878 | - $display_role = !empty($transcript->user_identifier) | |
| 879 | - ? sanitize_text_field($transcript->user_identifier) | |
| 880 | - : esc_html__('User', 'mxchat'); | |
| 881 | - break; | |
| 882 | - case 'agent': | |
| 883 | - $message_class = 'agent-message'; | |
| 884 | - $display_role = esc_html__('Agent', 'mxchat'); | |
| 885 | - break; | |
| 886 | - default: | |
| 887 | - $message_class = 'unknown-message'; | |
| 888 | - $display_role = esc_html__('Unknown', 'mxchat'); | |
| 889 | - } | |
| 890 | - | |
| 891 | - // Process message content | |
| 892 | - $message_content = wp_kses( | |
| 893 | - stripslashes($transcript->message), | |
| 894 | - [ | |
| 895 | - 'b' => [], 'strong' => [], 'i' => [], 'em' => [], 'u' => [], | |
| 896 | - 'br' => [], 'p' => [], 'ul' => [], 'ol' => [], 'li' => [], | |
| 897 | - 'a' => ['href' => [], 'title' => []] | |
| 898 | - ] | |
| 899 | - ); | |
| 900 | - $message_content = nl2br($message_content); | |
| 901 | - | |
| 902 | - // Render message | |
| 903 | - echo '<div class="mxchat-message ' . esc_attr($message_class) . '">'; | |
| 904 | - echo '<div class="mxchat-message-header">' . esc_html($display_role) . '</div>'; | |
| 905 | - echo '<div class="mxchat-message-content">' . $message_content . '</div>'; | |
| 906 | - echo '<div class="mxchat-timestamp">' . esc_html($formatted_timestamp) . '</div>'; | |
| 907 | - echo '</div>'; | |
| 908 | - } | |
| 909 | - | |
| 910 | - // Close session block | |
| 911 | - echo '</div></div>'; | |
| 912 | - } | |
| 913 | - | |
| 914 | - echo '</div>'; | |
| 915 | - $output = ob_get_clean(); | |
| 916 | - echo $output; | |
| 917 | - wp_die(); | |
| 918 | -} | |
| 919 | - | |
| 920 | - | |
| 921 | - | |
| 922 | 659 | public function mxchat_create_prompts_page() { |
| 923 | 660 | global $wpdb; |
| 924 | 661 | $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 925 | 662 | |
| @@ -952,9 +689,9 @@ | ||
| 952 | 689 | $per_page, |
| 953 | 690 | $offset |
| 954 | 691 | ) |
| 955 | 692 | ); |
| 956 | - | |
| 693 | + | |
| 957 | 694 | // Add the pagination links generation here |
| 958 | 695 | $page_links = paginate_links(array( |
| 959 | 696 | 'base' => add_query_arg(array( |
| 960 | 697 | 'paged' => '%#%', |
| @@ -1010,9 +747,9 @@ | ||
| 1010 | 747 | <!-- Auto-Sync Settings --> |
| 1011 | 748 | <div class="mxchat-settings-section"> |
| 1012 | 749 | <h3><?php esc_html_e('Auto-Sync Settings', 'mxchat'); ?></h3> |
| 1013 | 750 | <p class="mxchat-description"> |
| 1014 | - <?php esc_html_e('Note: Auto-sync works only for newly published content. Existing posts and pages must be imported manually below. Works with Pinecone if enabled', 'mxchat'); ?> | |
| 751 | + <?php esc_html_e('Note: Auto-sync works only for newly published content. Existing posts and pages must be imported manually below.', 'mxchat'); ?> | |
| 1015 | 752 | </p> |
| 1016 | 753 | <div class="mxchat-autosave-section"> <!-- Add this wrapper --> |
| 1017 | 754 | <div class="mxchat-toggle-group"> |
| 1018 | 755 | <div class="mxchat-toggle-container"> |
| @@ -1018,11 +755,11 @@ | ||
| 1018 | 755 | <div class="mxchat-toggle-container"> |
| 1019 | 756 | <label class="mxchat-toggle-switch"> |
| 1020 | 757 | <input type="checkbox" |
| 1021 | 758 | name="mxchat_auto_sync_posts" |
| 1022 | - class="mxchat-autosave-field" | |
| 759 | + class="mxchat-autosave-field" | |
| 1023 | 760 | value="1" |
| 1024 | - data-nonce="<?php echo wp_create_nonce('mxchat_prompts_setting_nonce'); ?>" | |
| 761 | + data-nonce="<?php echo wp_create_nonce('mxchat_prompts_setting_nonce'); ?>" | |
| 1025 | 762 | <?php checked(get_option('mxchat_auto_sync_posts', '0'), '1'); ?>> |
| 1026 | 763 | <span class="mxchat-toggle-slider"></span> |
| 1027 | 764 | </label> |
| 1028 | 765 | <span class="mxchat-toggle-label"> |
| @@ -1034,9 +771,9 @@ | ||
| 1034 | 771 | <input type="checkbox" |
| 1035 | 772 | name="mxchat_auto_sync_pages" |
| 1036 | 773 | class="mxchat-autosave-field" |
| 1037 | 774 | value="1" |
| 1038 | - data-nonce="<?php echo wp_create_nonce('mxchat_prompts_setting_nonce'); ?>" | |
| 775 | + data-nonce="<?php echo wp_create_nonce('mxchat_prompts_setting_nonce'); ?>" | |
| 1039 | 776 | <?php checked(get_option('mxchat_auto_sync_pages', '0'), '1'); ?>> |
| 1040 | 777 | <span class="mxchat-toggle-slider"></span> |
| 1041 | 778 | </label> |
| 1042 | 779 | <span class="mxchat-toggle-label"> |
| @@ -1050,9 +787,10 @@ | ||
| 1050 | 787 | <!-- Import Methods --> |
| 1051 | 788 | <div class="mxchat-import-methods"> |
| 1052 | 789 | <div class="mxchat-method-card"> |
| 1053 | 790 | <h4><?php esc_html_e('Sitemap Import', 'mxchat'); ?></h4> |
| 1054 | - <p><span class="red-warning">IMPORTANT:</span> <?php esc_html_e('Use a content-specific sub-sitemap, not the sitemap index.', 'mxchat'); ?></p> </div> | |
| 791 | + <p><?php esc_html_e('Import all content from your sitemap automatically.', 'mxchat'); ?></p> | |
| 792 | + </div> | |
| 1055 | 793 | <div class="mxchat-method-card"> |
| 1056 | 794 | <h4><?php esc_html_e('PDF Import', 'mxchat'); ?></h4> |
| 1057 | 795 | <p><?php esc_html_e('Import knowledge directly from PDF documents.', 'mxchat'); ?></p> |
| 1058 | 796 | </div> |
| @@ -1068,9 +806,9 @@ | ||
| 1068 | 806 | |
| 1069 | 807 | <!-- Import Form --> |
| 1070 | 808 | <?php if (!$is_processing) : ?> |
| 1071 | 809 | <div class="mxchat-import-form"> |
| 1072 | - <form id="mxchat-sitemap-form" method="post" | |
| 810 | + <form id="mxchat-sitemap-form" method="post" | |
| 1073 | 811 | action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_submit_sitemap')); ?>"> |
| 1074 | 812 | <?php wp_nonce_field('mxchat_submit_sitemap_action', 'mxchat_submit_sitemap_nonce'); ?> |
| 1075 | 813 | <div class="mxchat-url-input-group"> |
| 1076 | 814 | <input type="url" |
| @@ -1127,9 +865,9 @@ | ||
| 1127 | 865 | |
| 1128 | 866 | <?php if ($sitemap_status && $sitemap_status['status'] !== 'complete') : ?> |
| 1129 | 867 | <div class="mxchat-status-card"> |
| 1130 | 868 | <div class="mxchat-status-header"> |
| 1131 | - <h4><?php esc_html_e('Sitemap Processing Status (Refresh for update)', 'mxchat'); ?></h4> | |
| 869 | + <h4><?php esc_html_e('Sitemap Processing Status', 'mxchat'); ?></h4> | |
| 1132 | 870 | <?php if ($is_processing) : ?> |
| 1133 | 871 | <form method="post" class="mxchat-stop-form" |
| 1134 | 872 | action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_stop_processing')); ?>"> |
| 1135 | 873 | <?php wp_nonce_field('mxchat_stop_processing_action', 'mxchat_stop_processing_nonce'); ?> |
| @@ -1172,19 +910,19 @@ | ||
| 1172 | 910 | <div class="mxchat-card"> |
| 1173 | 911 | <div class="mxchat-card-header"> |
| 1174 | 912 | <h2><?php esc_html_e('Submit Direct Content', 'mxchat'); ?></h2> |
| 1175 | 913 | </div> |
| 1176 | - <form id="mxchat-content-form" method="post" | |
| 914 | + <form id="mxchat-content-form" method="post" | |
| 1177 | 915 | action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_submit_content')); ?>"> |
| 1178 | 916 | <?php wp_nonce_field('mxchat_submit_content_action', 'mxchat_submit_content_nonce'); ?> |
| 1179 | 917 | <div class="mxchat-form-group"> |
| 1180 | 918 | <label for="article_content"><?php esc_html_e('Content:', 'mxchat'); ?></label> |
| 1181 | - <textarea name="article_content" id="article_content" required | |
| 919 | + <textarea name="article_content" id="article_content" required | |
| 1182 | 920 | placeholder="<?php esc_attr_e('Enter your content here...', 'mxchat'); ?>"></textarea> |
| 1183 | 921 | </div> |
| 1184 | 922 | <div class="mxchat-form-group"> |
| 1185 | 923 | <label for="article_url"><?php esc_html_e('Source URL (Optional):', 'mxchat'); ?></label> |
| 1186 | - <input type="url" name="article_url" id="article_url" | |
| 924 | + <input type="url" name="article_url" id="article_url" | |
| 1187 | 925 | placeholder="<?php esc_attr_e('Enter source URL', 'mxchat'); ?>"> |
| 1188 | 926 | </div> |
| 1189 | 927 | <button type="submit" name="submit_content" class="mxchat-button-primary"> |
| 1190 | 928 | <?php esc_html_e('Submit Content', 'mxchat'); ?> |
| @@ -1258,13 +996,13 @@ | ||
| 1258 | 996 | <span class="mxchat-na"><?php esc_html_e('N/A', 'mxchat'); ?></span> |
| 1259 | 997 | <?php endif; ?> |
| 1260 | 998 | </td> |
| 1261 | 999 | <td class="mxchat-actions-cell"> |
| 1262 | - <button class="mxchat-button-icon edit-button" | |
| 1000 | + <button class="mxchat-button-icon edit-button" | |
| 1263 | 1001 | data-id="<?php echo esc_attr($prompt->id); ?>"> |
| 1264 | 1002 | <span class="dashicons dashicons-edit"></span> |
| 1265 | 1003 | </button> |
| 1266 | - <button class="mxchat-button-icon save-button" | |
| 1004 | + <button class="mxchat-button-icon save-button" | |
| 1267 | 1005 | data-id="<?php echo esc_attr($prompt->id); ?>" |
| 1268 | 1006 | style="display:none;" |
| 1269 | 1007 | data-nonce="<?php echo wp_create_nonce('mxchat_save_inline_nonce'); ?>"> |
| 1270 | 1008 | <span class="dashicons dashicons-saved"></span> |
| @@ -1271,9 +1009,9 @@ | ||
| 1271 | 1009 | </button> |
| 1272 | 1010 | <a href="<?php echo esc_url(admin_url( |
| 1273 | 1011 | 'admin-post.php?action=mxchat_delete_prompt&id=' . esc_attr($prompt->id) |
| 1274 | 1012 | . '&_wpnonce=' . wp_create_nonce('mxchat_delete_prompt_nonce') |
| 1275 | - )); ?>" | |
| 1013 | + )); ?>" | |
| 1276 | 1014 | class="mxchat-button-icon delete-button" |
| 1277 | 1015 | onclick="return confirm('<?php esc_attr_e('Are you sure you want to delete this entry?', 'mxchat'); ?>');"> |
| 1278 | 1016 | <span class="dashicons dashicons-trash"></span> |
| 1279 | 1017 | </a> |
| @@ -1359,90 +1097,30 @@ | ||
| 1359 | 1097 | |
| 1360 | 1098 | wp_safe_redirect(add_query_arg(array('page' => 'mxchat-prompts', 'deleted' => 'true'), admin_url('admin.php'))); |
| 1361 | 1099 | exit; |
| 1362 | 1100 | } |
| 1363 | - | |
| 1364 | - | |
| 1365 | 1101 | public function mxchat_generate_embedding($text) { |
| 1366 | - //error_log('Starting embedding generation for text: ' . substr($text, 0, 100) . '...'); | |
| 1102 | + $options = get_option('mxchat_options'); | |
| 1103 | + $api_key = $options['api_key'] ?? esc_html__('default_api_key', 'mxchat'); | |
| 1367 | 1104 | |
| 1368 | - $options = get_option('mxchat_options'); | |
| 1369 | - $selected_model = $options['embedding_model'] ?? 'text-embedding-ada-002'; | |
| 1370 | - //error_log('Selected embedding model: ' . $selected_model); | |
| 1105 | + $response = wp_remote_post('https://api.openai.com/v1/embeddings', array( | |
| 1106 | + 'body' => wp_json_encode(array( | |
| 1107 | + 'model' => esc_html__('text-embedding-ada-002', 'mxchat'), | |
| 1108 | + 'input' => $text | |
| 1109 | + )), | |
| 1110 | + 'headers' => array( | |
| 1111 | + 'Authorization' => 'Bearer ' . $api_key, | |
| 1112 | + 'Content-Type' => esc_html__('application/json', 'mxchat') | |
| 1113 | + ), | |
| 1114 | + )); | |
| 1371 | 1115 | |
| 1372 | - // Determine provider and endpoint | |
| 1373 | - if (strpos($selected_model, 'voyage') === 0) { | |
| 1374 | - $api_key = $options['voyage_api_key'] ?? ''; | |
| 1375 | - $endpoint = 'https://api.voyageai.com/v1/embeddings'; | |
| 1376 | - } else { | |
| 1377 | - $api_key = $options['api_key'] ?? ''; | |
| 1378 | - $endpoint = 'https://api.openai.com/v1/embeddings'; | |
| 1379 | - } | |
| 1380 | - //error_log('Using endpoint: ' . $endpoint); | |
| 1116 | + if (is_wp_error($response)) { | |
| 1117 | + return null; | |
| 1118 | + } | |
| 1381 | 1119 | |
| 1382 | - if (empty($api_key)) { | |
| 1383 | - //error_log('Error: API key not configured'); | |
| 1384 | - return null; | |
| 1120 | + $response_data = json_decode(wp_remote_retrieve_body($response), true); | |
| 1121 | + return $response_data['data'][0]['embedding'] ?? null; | |
| 1385 | 1122 | } |
| 1386 | - | |
| 1387 | - // Prepare request body | |
| 1388 | - $request_body = array( | |
| 1389 | - 'model' => $selected_model, | |
| 1390 | - 'input' => $text | |
| 1391 | - ); | |
| 1392 | - | |
| 1393 | - // Add output_dimension for voyage-3-large model | |
| 1394 | - if ($selected_model === 'voyage-3-large') { | |
| 1395 | - $request_body['output_dimension'] = 2048; | |
| 1396 | - } | |
| 1397 | - | |
| 1398 | - //error_log('Request body prepared: ' . wp_json_encode($request_body)); | |
| 1399 | - | |
| 1400 | - // Make API request | |
| 1401 | - $response = wp_remote_post($endpoint, array( | |
| 1402 | - 'body' => wp_json_encode($request_body), | |
| 1403 | - 'headers' => array( | |
| 1404 | - 'Authorization' => 'Bearer ' . $api_key, | |
| 1405 | - 'Content-Type' => 'application/json' | |
| 1406 | - ), | |
| 1407 | - 'timeout' => 30 | |
| 1408 | - )); | |
| 1409 | - | |
| 1410 | - // Handle wp_remote_post errors | |
| 1411 | - if (is_wp_error($response)) { | |
| 1412 | - //error_log('WP Remote Post Error: ' . $response->get_error_message()); | |
| 1413 | - return null; | |
| 1414 | - } | |
| 1415 | - | |
| 1416 | - // Get and check HTTP response code | |
| 1417 | - $http_code = wp_remote_retrieve_response_code($response); | |
| 1418 | - //error_log('API Response Code: ' . $http_code); | |
| 1419 | - | |
| 1420 | - if ($http_code !== 200) { | |
| 1421 | - //error_log('API Error Response Body: ' . wp_remote_retrieve_body($response)); | |
| 1422 | - return null; | |
| 1423 | - } | |
| 1424 | - | |
| 1425 | - // Parse response body | |
| 1426 | - $response_data = json_decode(wp_remote_retrieve_body($response), true); | |
| 1427 | - | |
| 1428 | - if (json_last_error() !== JSON_ERROR_NONE) { | |
| 1429 | - //error_log('JSON Parse Error: ' . json_last_error_msg()); | |
| 1430 | - return null; | |
| 1431 | - } | |
| 1432 | - | |
| 1433 | - // Both APIs use the same structure, so we can extract the embedding the same way | |
| 1434 | - if (isset($response_data['data'][0]['embedding'])) { | |
| 1435 | - //error_log('Successfully extracted embedding'); | |
| 1436 | - //error_log('Embedding dimension: ' . count($response_data['data'][0]['embedding'])); | |
| 1437 | - return $response_data['data'][0]['embedding']; | |
| 1438 | - } else { | |
| 1439 | - //error_log('Error: No embedding found in response. Response structure: ' . wp_json_encode($response_data)); | |
| 1440 | - return null; | |
| 1441 | - } | |
| 1442 | -} | |
| 1443 | - | |
| 1444 | - | |
| 1445 | 1123 | public function mxchat_delete_chat_history() { |
| 1446 | 1124 | if (!current_user_can('manage_options')) { |
| 1447 | 1125 | echo wp_json_encode(['error' => esc_html__('You do not have sufficient permissions.', 'mxchat')]); |
| 1448 | 1126 | wp_die(); |
| @@ -1570,9 +1248,9 @@ | ||
| 1570 | 1248 | |
| 1571 | 1249 | if ($pinecone_settings && is_array($pinecone_settings)) { |
| 1572 | 1250 | // Check if Pinecone is enabled and all required settings are present |
| 1573 | 1251 | $use_pinecone = ( |
| 1574 | - isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 1252 | + isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 1575 | 1253 | $pinecone_settings['mxchat_use_pinecone'] === '1' && |
| 1576 | 1254 | !empty($pinecone_settings['mxchat_pinecone_api_key']) && |
| 1577 | 1255 | !empty($pinecone_settings['mxchat_pinecone_host']) && |
| 1578 | 1256 | !empty($pinecone_settings['mxchat_pinecone_index']) && |
| @@ -1591,9 +1269,9 @@ | ||
| 1591 | 1269 | $pinecone_settings['mxchat_pinecone_index'] |
| 1592 | 1270 | ); |
| 1593 | 1271 | |
| 1594 | 1272 | if (!$pinecone_result['success']) { |
| 1595 | - //error_log('MXChat: Pinecone sync failed - falling back to WordPress DB'); | |
| 1273 | + error_log('MXChat: Pinecone sync failed - falling back to WordPress DB'); | |
| 1596 | 1274 | $this->store_in_wordpress_db($content, $url, $embedding_vector); |
| 1597 | 1275 | } |
| 1598 | 1276 | } else { |
| 1599 | 1277 | // Fallback to WordPress DB storage |
| @@ -1599,25 +1277,28 @@ | ||
| 1599 | 1277 | // Fallback to WordPress DB storage |
| 1600 | 1278 | $this->store_in_wordpress_db($content, $url, $embedding_vector); |
| 1601 | 1279 | } |
| 1602 | 1280 | } |
| 1603 | -// Modified storage function to add type field | |
| 1281 | + | |
| 1604 | 1282 | private function store_in_pinecone_main($embedding_vector, $content, $url, $api_key, $environment, $index_name, $vector_id = null) { |
| 1283 | + // Generate vector ID based on URL for consistent updates/inserts | |
| 1605 | 1284 | $vector_id = $vector_id ?: md5($url); |
| 1285 | + | |
| 1286 | + // Get the Pinecone host from options | |
| 1606 | 1287 | $options = get_option('mxchat_pinecone_addon_options'); |
| 1607 | 1288 | $host = $options['mxchat_pinecone_host'] ?? ''; |
| 1608 | - | |
| 1289 | + | |
| 1609 | 1290 | if (empty($host)) { |
| 1291 | + //error_log('Pinecone host is not configured'); | |
| 1610 | 1292 | return array( |
| 1611 | 1293 | 'success' => false, |
| 1612 | 1294 | 'message' => 'Pinecone host is not configured. Please set the host in your settings.' |
| 1613 | 1295 | ); |
| 1614 | 1296 | } |
| 1615 | - | |
| 1616 | - // Determine if this is a product URL | |
| 1617 | - $is_product = (strpos($url, '/product/') !== false || strpos($url, '/shop/') !== false); | |
| 1618 | - | |
| 1297 | + | |
| 1298 | + // Build API endpoint using the configured host | |
| 1619 | 1299 | $api_endpoint = "https://{$host}/vectors/upsert"; |
| 1300 | + | |
| 1620 | 1301 | $request_body = array( |
| 1621 | 1302 | 'vectors' => array( |
| 1622 | 1303 | array( |
| 1623 | 1304 | 'id' => $vector_id, |
| @@ -1624,15 +1305,14 @@ | ||
| 1624 | 1305 | 'values' => $embedding_vector, |
| 1625 | 1306 | 'metadata' => array( |
| 1626 | 1307 | 'text' => $content, |
| 1627 | 1308 | 'source_url' => $url, |
| 1628 | - 'type' => $is_product ? 'product' : 'content', | |
| 1629 | 1309 | 'last_updated' => time() |
| 1630 | 1310 | ) |
| 1631 | 1311 | ) |
| 1632 | 1312 | ) |
| 1633 | 1313 | ); |
| 1634 | - | |
| 1314 | + | |
| 1635 | 1315 | $response = wp_remote_post($api_endpoint, array( |
| 1636 | 1316 | 'headers' => array( |
| 1637 | 1317 | 'Api-Key' => $api_key, |
| 1638 | 1318 | 'accept' => 'application/json', |
| @@ -1641,24 +1321,27 @@ | ||
| 1641 | 1321 | 'body' => wp_json_encode($request_body), |
| 1642 | 1322 | 'timeout' => 30, |
| 1643 | 1323 | 'data_format' => 'body' |
| 1644 | 1324 | )); |
| 1645 | - | |
| 1325 | + | |
| 1646 | 1326 | if (is_wp_error($response)) { |
| 1327 | + //error_log('Pinecone API WP Error: ' . $response->get_error_message()); | |
| 1647 | 1328 | return array( |
| 1648 | 1329 | 'success' => false, |
| 1649 | 1330 | 'message' => $response->get_error_message() |
| 1650 | 1331 | ); |
| 1651 | 1332 | } |
| 1652 | - | |
| 1333 | + | |
| 1653 | 1334 | $response_code = wp_remote_retrieve_response_code($response); |
| 1654 | 1335 | if ($response_code !== 200) { |
| 1655 | 1336 | $body = wp_remote_retrieve_body($response); |
| 1337 | + //error_log('Pinecone API Error Body: ' . $body); | |
| 1338 | + //error_log('Pinecone API Request: ' . wp_json_encode($request_body)); | |
| 1656 | 1339 | return array( |
| 1657 | 1340 | 'success' => false, |
| 1658 | 1341 | 'message' => sprintf( |
| 1659 | - 'Pinecone API error (HTTP %d): %s', | |
| 1660 | - $response_code, | |
| 1342 | + 'Pinecone API error (HTTP %d): %s', | |
| 1343 | + $response_code, | |
| 1661 | 1344 | $body |
| 1662 | 1345 | ) |
| 1663 | 1346 | ); |
| 1664 | 1347 | } |
| @@ -1667,8 +1350,10 @@ | ||
| 1667 | 1350 | 'success' => true, |
| 1668 | 1351 | 'message' => 'Successfully stored in Pinecone' |
| 1669 | 1352 | ); |
| 1670 | 1353 | } |
| 1354 | + | |
| 1355 | + | |
| 1671 | 1356 | // Helper method for WordPress DB storage |
| 1672 | 1357 | private function store_in_wordpress_db($content, $url, $embedding_vector) { |
| 1673 | 1358 | global $wpdb; |
| 1674 | 1359 | $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| @@ -1700,109 +1385,16 @@ | ||
| 1700 | 1385 | array('%s', '%s', '%s', '%s') |
| 1701 | 1386 | ); |
| 1702 | 1387 | } |
| 1703 | 1388 | } |
| 1704 | -/** | |
| 1705 | - * Handle deletion of posts and pages from both Pinecone and WordPress DB | |
| 1706 | - * | |
| 1707 | - * @param int $post_id The ID of the post being deleted | |
| 1708 | - * @return void | |
| 1709 | - */ | |
| 1710 | -public function mxchat_handle_post_delete($post_id) { | |
| 1711 | - // Get post data before it's deleted | |
| 1712 | - $post = get_post($post_id); | |
| 1713 | 1389 | |
| 1714 | - // Basic validation | |
| 1715 | - if (!$post || wp_is_post_revision($post_id)) { | |
| 1716 | - return; | |
| 1717 | - } | |
| 1718 | 1390 | |
| 1719 | - // Check post type | |
| 1720 | - $post_type = $post->post_type; | |
| 1721 | - if (!in_array($post_type, array('post', 'page'))) { | |
| 1722 | - return; | |
| 1723 | - } | |
| 1724 | - | |
| 1725 | - // Check if sync is enabled for this post type | |
| 1726 | - $sync_option = ($post_type === 'post') ? 'mxchat_auto_sync_posts' : 'mxchat_auto_sync_pages'; | |
| 1727 | - if (get_option($sync_option) != '1') { | |
| 1728 | - return; | |
| 1729 | - } | |
| 1730 | - | |
| 1731 | - // Get the URL before post is deleted | |
| 1732 | - $source_url = get_permalink($post_id); | |
| 1733 | - if (!$source_url) { | |
| 1734 | - //error_log('MXChat: Failed to get permalink for post ' . $post_id); | |
| 1735 | - return; | |
| 1736 | - } | |
| 1737 | - | |
| 1738 | - // Check for Pinecone addon and its settings | |
| 1739 | - $pinecone_settings = get_option('mxchat_pinecone_addon_options'); | |
| 1740 | - $use_pinecone = false; | |
| 1741 | - if ($pinecone_settings && is_array($pinecone_settings)) { | |
| 1742 | - $use_pinecone = ( | |
| 1743 | - isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 1744 | - $pinecone_settings['mxchat_use_pinecone'] === '1' && | |
| 1745 | - !empty($pinecone_settings['mxchat_pinecone_api_key']) && | |
| 1746 | - !empty($pinecone_settings['mxchat_pinecone_host']) && | |
| 1747 | - !empty($pinecone_settings['mxchat_pinecone_index']) && | |
| 1748 | - !empty($pinecone_settings['mxchat_pinecone_environment']) | |
| 1749 | - ); | |
| 1750 | - } | |
| 1751 | - | |
| 1752 | - $deletion_successful = false; | |
| 1753 | - | |
| 1754 | - if ($use_pinecone) { | |
| 1755 | - try { | |
| 1756 | - $pinecone_result = $this->delete_from_pinecone( | |
| 1757 | - array($source_url), | |
| 1758 | - $pinecone_settings['mxchat_pinecone_api_key'], | |
| 1759 | - $pinecone_settings['mxchat_pinecone_environment'], | |
| 1760 | - $pinecone_settings['mxchat_pinecone_index'] | |
| 1761 | - ); | |
| 1762 | - | |
| 1763 | - if (!$pinecone_result['success']) { | |
| 1764 | - //error_log('MXChat: Pinecone deletion failed for URL: ' . $source_url . ' - ' . $pinecone_result['message']); | |
| 1765 | - } else { | |
| 1766 | - $deletion_successful = true; | |
| 1767 | - } | |
| 1768 | - } catch (Exception $e) { | |
| 1769 | - //error_log('MXChat: Exception during Pinecone deletion - ' . $e->getMessage()); | |
| 1770 | - } | |
| 1771 | - } | |
| 1772 | - | |
| 1773 | - // Always attempt WordPress DB deletion, regardless of Pinecone status | |
| 1774 | - try { | |
| 1775 | - global $wpdb; | |
| 1776 | - $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; | |
| 1777 | - | |
| 1778 | - $result = $wpdb->delete( | |
| 1779 | - $table_name, | |
| 1780 | - array('source_url' => $source_url), | |
| 1781 | - array('%s') | |
| 1782 | - ); | |
| 1783 | - | |
| 1784 | - if ($result === false) { | |
| 1785 | - //error_log('MXChat: WordPress DB deletion failed for URL: ' . $source_url); | |
| 1786 | - } else { | |
| 1787 | - $deletion_successful = true; | |
| 1788 | - } | |
| 1789 | - } catch (Exception $e) { | |
| 1790 | - //error_log('MXChat: Exception during WordPress DB deletion - ' . $e->getMessage()); | |
| 1791 | - } | |
| 1792 | - | |
| 1793 | - if (!$deletion_successful) { | |
| 1794 | - //error_log('MXChat: Complete deletion failure for post ID: ' . $post_id . ' URL: ' . $source_url); | |
| 1795 | - } | |
| 1796 | -} | |
| 1797 | - | |
| 1798 | - | |
| 1799 | 1391 | public function mxchat_handle_content_submission() { |
| 1800 | 1392 | // Check if the form was submitted and the user has permission. |
| 1801 | 1393 | if (!isset($_POST['submit_content']) || !current_user_can('manage_options')) { |
| 1802 | 1394 | return; |
| 1803 | 1395 | } |
| 1804 | - | |
| 1396 | + | |
| 1805 | 1397 | // Verify the nonce. |
| 1806 | 1398 | $nonce = isset($_POST['mxchat_submit_content_nonce']) ? sanitize_text_field(wp_unslash($_POST['mxchat_submit_content_nonce'])) : ''; |
| 1807 | 1399 | if (!wp_verify_nonce($nonce, 'mxchat_submit_content_action')) { |
| 1808 | 1400 | wp_die(esc_html__('Nonce verification failed.', 'mxchat')); |
| @@ -1814,10 +1406,10 @@ | ||
| 1814 | 1406 | |
| 1815 | 1407 | // Generate the embedding vector. |
| 1816 | 1408 | $embedding_vector = $this->mxchat_generate_embedding($article_content); |
| 1817 | 1409 | if (!is_array($embedding_vector)) { |
| 1818 | - set_transient('mxchat_admin_notice_error', | |
| 1819 | - esc_html__('Embedding generation failed. Please ensure your API key is correct and try again.', 'mxchat'), | |
| 1410 | + set_transient('mxchat_admin_notice_error', | |
| 1411 | + esc_html__('Embedding generation failed. Please ensure your API key is correct and try again.', 'mxchat'), | |
| 1820 | 1412 | 30 |
| 1821 | 1413 | ); |
| 1822 | 1414 | wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1823 | 1415 | exit; |
| @@ -1844,15 +1436,15 @@ | ||
| 1844 | 1436 | array('%s', '%s', '%s') |
| 1845 | 1437 | ); |
| 1846 | 1438 | |
| 1847 | 1439 | if ($inserted === false) { |
| 1848 | - set_transient('mxchat_admin_notice_error', | |
| 1849 | - esc_html__('Error inserting content into the database. Please try again.', 'mxchat'), | |
| 1440 | + set_transient('mxchat_admin_notice_error', | |
| 1441 | + esc_html__('Error inserting content into the database. Please try again.', 'mxchat'), | |
| 1850 | 1442 | 30 |
| 1851 | 1443 | ); |
| 1852 | 1444 | } else { |
| 1853 | - set_transient('mxchat_admin_notice_success', | |
| 1854 | - esc_html__('Content successfully submitted!', 'mxchat'), | |
| 1445 | + set_transient('mxchat_admin_notice_success', | |
| 1446 | + esc_html__('Content successfully submitted!', 'mxchat'), | |
| 1855 | 1447 | 30 |
| 1856 | 1448 | ); |
| 1857 | 1449 | } |
| 1858 | 1450 | |
| @@ -2037,11 +1629,9 @@ | ||
| 2037 | 1629 | |
| 2038 | 1630 | return array( |
| 2039 | 1631 | 'total_pages' => absint($status['total_pages']), |
| 2040 | 1632 | 'processed_pages' => absint($status['processed_pages']), |
| 2041 | - 'percentage' => ($status['total_pages'] > 0) | |
| 2042 | - ? round((absint($status['processed_pages']) / absint($status['total_pages'])) * 100) | |
| 2043 | - : 0, | |
| 1633 | + 'percentage' => round((absint($status['processed_pages']) / absint($status['total_pages'])) * 100), | |
| 2044 | 1634 | 'status' => sanitize_text_field($status['status']), |
| 2045 | 1635 | 'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ' . esc_html__('ago', 'mxchat') |
| 2046 | 1636 | ); |
| 2047 | 1637 | } |
| @@ -2250,25 +1840,25 @@ | ||
| 2250 | 1840 | $sitemap_url = esc_url_raw($sitemap_url); |
| 2251 | 1841 | $total_urls = absint($total_urls); |
| 2252 | 1842 | $batch_size = absint($batch_size); |
| 2253 | 1843 | $batch_pause = absint($batch_pause); |
| 2254 | - | |
| 1844 | + | |
| 2255 | 1845 | if (!is_array($urls) || empty($urls)) { |
| 2256 | 1846 | return; |
| 2257 | 1847 | } |
| 2258 | - | |
| 1848 | + | |
| 2259 | 1849 | try { |
| 2260 | 1850 | $status_key = sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url)); |
| 2261 | 1851 | $status = get_transient($status_key); |
| 2262 | - | |
| 1852 | + | |
| 2263 | 1853 | if (!$status || !is_array($status)) { |
| 2264 | 1854 | throw new Exception('Invalid status data retrieved from transient'); |
| 2265 | 1855 | } |
| 2266 | - | |
| 1856 | + | |
| 2267 | 1857 | $start_url = absint($status['processed_urls']); |
| 2268 | 1858 | $end_url = min($start_url + $batch_size, $total_urls); |
| 2269 | 1859 | $instance = new self(); |
| 2270 | - | |
| 1860 | + | |
| 2271 | 1861 | // Track failures in batch |
| 2272 | 1862 | $batch_stats = [ |
| 2273 | 1863 | 'processed' => 0, |
| 2274 | 1864 | 'failed' => 0, |
| @@ -2277,43 +1867,43 @@ | ||
| 2277 | 1867 | |
| 2278 | 1868 | for ($i = $start_url; $i < $end_url; $i++) { |
| 2279 | 1869 | $page_url = esc_url_raw($urls[$i]); |
| 2280 | 1870 | $page_response = wp_remote_get($page_url); |
| 2281 | - | |
| 1871 | + | |
| 2282 | 1872 | if (is_wp_error($page_response) || wp_remote_retrieve_response_code($page_response) !== 200) { |
| 2283 | 1873 | $batch_stats['failed']++; |
| 2284 | 1874 | continue; |
| 2285 | 1875 | } |
| 2286 | - | |
| 1876 | + | |
| 2287 | 1877 | $page_html = wp_remote_retrieve_body($page_response); |
| 2288 | 1878 | $page_content = $instance->mxchat_extract_main_content($page_html); |
| 2289 | 1879 | $sanitized_content = $instance->mxchat_sanitize_content_for_api($page_content); |
| 2290 | - | |
| 1880 | + | |
| 2291 | 1881 | if (!empty($sanitized_content)) { |
| 2292 | 1882 | $embedding_vector = $instance->mxchat_generate_embedding($sanitized_content); |
| 2293 | - | |
| 1883 | + | |
| 2294 | 1884 | if (is_array($embedding_vector)) { |
| 2295 | 1885 | $options = get_option('mxchat_options'); |
| 2296 | 1886 | $submission_result = MxChat_Utils::submit_content_to_db($sanitized_content, $page_url, $options['api_key']); |
| 2297 | - | |
| 1887 | + | |
| 2298 | 1888 | if (is_wp_error($submission_result)) { |
| 2299 | 1889 | $batch_stats['failed']++; |
| 2300 | 1890 | $batch_stats['last_error'] = $submission_result->get_error_message(); |
| 2301 | 1891 | continue; |
| 2302 | 1892 | } |
| 2303 | - | |
| 1893 | + | |
| 2304 | 1894 | $batch_stats['processed']++; |
| 2305 | 1895 | } else { |
| 2306 | 1896 | $batch_stats['failed']++; |
| 2307 | - $batch_stats['last_error'] = 'Failed to generate embedding. Please check embedding API key.'; | |
| 1897 | + $batch_stats['last_error'] = 'Failed to generate embedding. Please check OpenAI API key.'; | |
| 2308 | 1898 | } |
| 2309 | 1899 | } |
| 2310 | - | |
| 1900 | + | |
| 2311 | 1901 | $status['processed_urls'] = absint($i + 1); |
| 2312 | 1902 | $status['last_update'] = time(); |
| 2313 | 1903 | $status['failed_urls'] = absint($status['failed_urls'] ?? 0) + $batch_stats['failed']; |
| 2314 | 1904 | $status['last_error'] = $batch_stats['last_error']; |
| 2315 | - | |
| 1905 | + | |
| 2316 | 1906 | set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 2317 | 1907 | } |
| 2318 | 1908 | |
| 2319 | 1909 | // If all URLs in this batch failed, stop processing |
| @@ -2349,20 +1939,18 @@ | ||
| 2349 | 1939 | |
| 2350 | 1940 | public function get_sitemap_processing_status($sitemap_url) { |
| 2351 | 1941 | $sitemap_url = esc_url_raw($sitemap_url); |
| 2352 | 1942 | $status = get_transient(sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url))); |
| 2353 | - | |
| 1943 | + | |
| 2354 | 1944 | if (!$status || !is_array($status)) { |
| 2355 | 1945 | return false; |
| 2356 | 1946 | } |
| 2357 | - | |
| 1947 | + | |
| 2358 | 1948 | return array( |
| 2359 | 1949 | 'total_urls' => absint($status['total_urls']), |
| 2360 | 1950 | 'processed_urls' => absint($status['processed_urls']), |
| 2361 | 1951 | 'failed_urls' => absint($status['failed_urls'] ?? 0), |
| 2362 | - 'percentage' => ($status['total_urls'] > 0) | |
| 2363 | - ? round((absint($status['processed_urls']) / absint($status['total_urls'])) * 100) | |
| 2364 | - : 0, | |
| 1952 | + 'percentage' => round((absint($status['processed_urls']) / absint($status['total_urls'])) * 100), | |
| 2365 | 1953 | 'status' => sanitize_text_field($status['status']), |
| 2366 | 1954 | 'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ' . esc_html__('ago', 'mxchat'), |
| 2367 | 1955 | 'error' => isset($status['error']) ? sanitize_text_field($status['error']) : '', |
| 2368 | 1956 | 'last_error' => isset($status['last_error']) ? sanitize_text_field($status['last_error']) : '' |
| @@ -2468,9 +2056,9 @@ | ||
| 2468 | 2056 | $use_pinecone = false; |
| 2469 | 2057 | |
| 2470 | 2058 | if ($pinecone_settings && is_array($pinecone_settings)) { |
| 2471 | 2059 | $use_pinecone = ( |
| 2472 | - isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 2060 | + isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 2473 | 2061 | $pinecone_settings['mxchat_use_pinecone'] === '1' && |
| 2474 | 2062 | !empty($pinecone_settings['mxchat_pinecone_api_key']) && |
| 2475 | 2063 | !empty($pinecone_settings['mxchat_pinecone_host']) && |
| 2476 | 2064 | !empty($pinecone_settings['mxchat_pinecone_index']) && |
| @@ -2501,11 +2089,11 @@ | ||
| 2501 | 2089 | public function mxchat_handle_product_delete($post_id) { |
| 2502 | 2090 | if (get_post_type($post_id) !== 'product') { |
| 2503 | 2091 | return; |
| 2504 | 2092 | } |
| 2505 | - | |
| 2093 | + | |
| 2506 | 2094 | $source_url = get_permalink($post_id); |
| 2507 | - | |
| 2095 | + | |
| 2508 | 2096 | // Check for Pinecone addon and its settings |
| 2509 | 2097 | $pinecone_settings = get_option('mxchat_pinecone_addon_options'); |
| 2510 | 2098 | $use_pinecone = false; |
| 2511 | 2099 | |
| @@ -2510,9 +2098,9 @@ | ||
| 2510 | 2098 | $use_pinecone = false; |
| 2511 | 2099 | |
| 2512 | 2100 | if ($pinecone_settings && is_array($pinecone_settings)) { |
| 2513 | 2101 | $use_pinecone = ( |
| 2514 | - isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 2102 | + isset($pinecone_settings['mxchat_use_pinecone']) && | |
| 2515 | 2103 | $pinecone_settings['mxchat_use_pinecone'] === '1' && |
| 2516 | 2104 | !empty($pinecone_settings['mxchat_pinecone_api_key']) && |
| 2517 | 2105 | !empty($pinecone_settings['mxchat_pinecone_host']) && |
| 2518 | 2106 | !empty($pinecone_settings['mxchat_pinecone_index']) && |
| @@ -2534,102 +2122,139 @@ | ||
| 2534 | 2122 | $wpdb->delete($table_name, array('source_url' => $source_url), array('%s')); |
| 2535 | 2123 | } |
| 2536 | 2124 | } |
| 2537 | 2125 | |
| 2126 | +public function mxchat_fetch_chat_history() { | |
| 2127 | + global $wpdb; | |
| 2128 | + $table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; | |
| 2538 | 2129 | |
| 2539 | -/** | |
| 2540 | - * Delete vectors from Pinecone by source URL | |
| 2541 | - * | |
| 2542 | - * @param array $urls Array of source URLs to delete | |
| 2543 | - * @param string $api_key Pinecone API key | |
| 2544 | - * @param string $environment Pinecone environment | |
| 2545 | - * @param string $index_name Pinecone index name | |
| 2546 | - * @return array Associative array with 'success' boolean and 'message' string | |
| 2547 | - */ | |
| 2548 | -private function delete_from_pinecone($urls, $api_key, $environment, $index_name) { | |
| 2549 | - // Get the Pinecone host from options (matching your store_in_pinecone_main pattern) | |
| 2550 | - $options = get_option('mxchat_pinecone_addon_options'); | |
| 2551 | - $host = $options['mxchat_pinecone_host'] ?? ''; | |
| 2552 | - | |
| 2553 | - if (empty($host)) { | |
| 2554 | - return array( | |
| 2555 | - 'success' => false, | |
| 2556 | - 'message' => 'Pinecone host is not configured. Please set the host in your settings.' | |
| 2557 | - ); | |
| 2130 | + if (!current_user_can('manage_options')) { | |
| 2131 | + wp_die(esc_html__('You do not have sufficient permissions to view this page.', 'mxchat')); | |
| 2558 | 2132 | } |
| 2559 | 2133 | |
| 2560 | - // Build API endpoint using the configured host | |
| 2561 | - $api_endpoint = "https://{$host}/vectors/delete"; | |
| 2562 | - | |
| 2563 | - // Create vector IDs from URLs (matching your store method's ID generation) | |
| 2564 | - $vector_ids = array_map('md5', $urls); | |
| 2565 | - | |
| 2566 | - // Prepare the delete request body | |
| 2567 | - $request_body = array( | |
| 2568 | - 'ids' => $vector_ids, | |
| 2569 | - 'filter' => array( | |
| 2570 | - 'source_url' => array( | |
| 2571 | - '$in' => $urls | |
| 2572 | - ) | |
| 2134 | + // First get unique session IDs ordered by most recent message in each session | |
| 2135 | + $session_ids = $wpdb->get_col( | |
| 2136 | + $wpdb->prepare( | |
| 2137 | + "SELECT DISTINCT session_id | |
| 2138 | + FROM {$table_name} | |
| 2139 | + GROUP BY session_id | |
| 2140 | + ORDER BY MAX(timestamp) DESC" | |
| 2573 | 2141 | ) |
| 2574 | 2142 | ); |
| 2575 | 2143 | |
| 2576 | - // Make the deletion request | |
| 2577 | - $response = wp_remote_post($api_endpoint, array( | |
| 2578 | - 'headers' => array( | |
| 2579 | - 'Api-Key' => $api_key, | |
| 2580 | - 'accept' => 'application/json', | |
| 2581 | - 'content-type' => 'application/json' | |
| 2582 | - ), | |
| 2583 | - 'body' => wp_json_encode($request_body), | |
| 2584 | - 'timeout' => 30, | |
| 2585 | - 'data_format' => 'body' | |
| 2586 | - )); | |
| 2144 | + if (empty($session_ids)) { | |
| 2145 | + wp_die(esc_html__('No chat history available.', 'mxchat')); | |
| 2146 | + } | |
| 2587 | 2147 | |
| 2588 | - // Handle WordPress HTTP API errors | |
| 2589 | - if (is_wp_error($response)) { | |
| 2590 | - return array( | |
| 2591 | - 'success' => false, | |
| 2592 | - 'message' => $response->get_error_message() | |
| 2148 | + ob_start(); | |
| 2149 | + echo '<div class="mxchat-transcript">'; | |
| 2150 | + | |
| 2151 | + // Iterate through sessions from newest to oldest | |
| 2152 | + foreach ($session_ids as $session_id) { | |
| 2153 | + // Get the email associated with this session (if available) | |
| 2154 | + $email = $wpdb->get_var( | |
| 2155 | + $wpdb->prepare( | |
| 2156 | + "SELECT user_email | |
| 2157 | + FROM {$table_name} | |
| 2158 | + WHERE session_id = %s AND user_email != '' | |
| 2159 | + ORDER BY timestamp ASC | |
| 2160 | + LIMIT 1", | |
| 2161 | + $session_id | |
| 2162 | + ) | |
| 2593 | 2163 | ); |
| 2594 | - } | |
| 2595 | 2164 | |
| 2596 | - // Check response status | |
| 2597 | - $response_code = wp_remote_retrieve_response_code($response); | |
| 2598 | - if ($response_code !== 200) { | |
| 2599 | - $body = wp_remote_retrieve_body($response); | |
| 2600 | - return array( | |
| 2601 | - 'success' => false, | |
| 2602 | - 'message' => sprintf( | |
| 2603 | - 'Pinecone API error (HTTP %d): %s', | |
| 2604 | - $response_code, | |
| 2605 | - $body | |
| 2165 | + // Debug: Check email retrieval | |
| 2166 | + if (empty($email)) { | |
| 2167 | + //error_log("No email found for session {$session_id}"); | |
| 2168 | + } else { | |
| 2169 | + //error_log("Email for session {$session_id}: " . $email); | |
| 2170 | + } | |
| 2171 | + | |
| 2172 | + // Get messages for this session ordered by timestamp | |
| 2173 | + $messages = $wpdb->get_results( | |
| 2174 | + $wpdb->prepare( | |
| 2175 | + "SELECT * FROM {$table_name} | |
| 2176 | + WHERE session_id = %s | |
| 2177 | + ORDER BY timestamp ASC", | |
| 2178 | + $session_id | |
| 2606 | 2179 | ) |
| 2607 | 2180 | ); |
| 2608 | - } | |
| 2609 | 2181 | |
| 2610 | - // Parse response body | |
| 2611 | - $body = wp_remote_retrieve_body($response); | |
| 2612 | - $response_data = json_decode($body, true); | |
| 2182 | + // Start session block | |
| 2183 | + echo '<div class="mxchat-session">'; | |
| 2184 | + echo '<div class="mxchat-session-header">'; | |
| 2185 | + // Wrap checkbox and session ID in one block | |
| 2186 | + echo '<div class="mxchat-session-id">'; | |
| 2187 | + echo '<input type="checkbox" name="delete_session_ids[]" value="' . esc_attr($session_id) . '"> '; | |
| 2188 | + echo '<strong>' . esc_html__('Session ID:', 'mxchat') . '</strong> ' . esc_html($session_id); | |
| 2189 | + echo '</div>'; | |
| 2613 | 2190 | |
| 2614 | - // Final validation of the response | |
| 2615 | - if (json_last_error() !== JSON_ERROR_NONE) { | |
| 2616 | - return array( | |
| 2617 | - 'success' => false, | |
| 2618 | - 'message' => 'Failed to parse Pinecone response: ' . json_last_error_msg() | |
| 2619 | - ); | |
| 2620 | - } | |
| 2191 | + // Place email directly below the session ID block | |
| 2192 | + if (!empty($email)) { | |
| 2193 | + echo '<div class="mxchat-session-email">'; | |
| 2194 | + echo '<strong>' . esc_html__('Email:', 'mxchat') . '</strong> ' . esc_html($email); | |
| 2195 | + echo '</div>'; | |
| 2196 | + } | |
| 2197 | + echo '</div>'; | |
| 2621 | 2198 | |
| 2622 | - return array( | |
| 2623 | - 'success' => true, | |
| 2624 | - 'message' => sprintf('Successfully deleted %d vectors from Pinecone', count($vector_ids)) | |
| 2625 | - ); | |
| 2626 | -} | |
| 2199 | + echo '<div class="mxchat-messages">'; | |
| 2627 | 2200 | |
| 2201 | + // Display messages for this session | |
| 2202 | + foreach ($messages as $transcript) { | |
| 2203 | + $formatted_timestamp = date_i18n('F j, Y g:i a', strtotime($transcript->timestamp)); | |
| 2628 | 2204 | |
| 2205 | + // Determine message styling | |
| 2206 | + switch ($transcript->role) { | |
| 2207 | + case 'assistant': | |
| 2208 | + case 'bot': | |
| 2209 | + $message_class = 'bot-message'; | |
| 2210 | + $display_role = esc_html__('Chatbot', 'mxchat'); | |
| 2211 | + break; | |
| 2212 | + case 'user': | |
| 2213 | + $message_class = 'user-message'; | |
| 2214 | + $display_role = !empty($transcript->user_identifier) | |
| 2215 | + ? sanitize_text_field($transcript->user_identifier) | |
| 2216 | + : esc_html__('User', 'mxchat'); | |
| 2217 | + break; | |
| 2218 | + case 'agent': | |
| 2219 | + $message_class = 'agent-message'; | |
| 2220 | + $display_role = esc_html__('Agent', 'mxchat'); | |
| 2221 | + break; | |
| 2222 | + default: | |
| 2223 | + $message_class = 'unknown-message'; | |
| 2224 | + $display_role = esc_html__('Unknown', 'mxchat'); | |
| 2225 | + } | |
| 2629 | 2226 | |
| 2227 | + // Process message content | |
| 2228 | + $message_content = wp_kses( | |
| 2229 | + stripslashes($transcript->message), | |
| 2230 | + [ | |
| 2231 | + 'b' => [], 'strong' => [], 'i' => [], 'em' => [], 'u' => [], | |
| 2232 | + 'br' => [], 'p' => [], 'ul' => [], 'ol' => [], 'li' => [], | |
| 2233 | + 'a' => ['href' => [], 'title' => []] | |
| 2234 | + ] | |
| 2235 | + ); | |
| 2236 | + $message_content = nl2br($message_content); | |
| 2630 | 2237 | |
| 2238 | + // Render message | |
| 2239 | + echo '<div class="mxchat-message ' . esc_attr($message_class) . '">'; | |
| 2240 | + echo '<div class="mxchat-message-header">' . esc_html($display_role) . '</div>'; | |
| 2241 | + echo '<div class="mxchat-message-content">' . $message_content . '</div>'; | |
| 2242 | + echo '<div class="mxchat-timestamp">' . esc_html($formatted_timestamp) . '</div>'; | |
| 2243 | + echo '</div>'; | |
| 2244 | + } | |
| 2631 | 2245 | |
| 2246 | + // Close session block | |
| 2247 | + echo '</div></div>'; | |
| 2248 | + } | |
| 2249 | + | |
| 2250 | + echo '</div>'; | |
| 2251 | + $output = ob_get_clean(); | |
| 2252 | + echo $output; | |
| 2253 | + wp_die(); | |
| 2254 | +} | |
| 2255 | + | |
| 2256 | + | |
| 2632 | 2257 | public function mxchat_create_activation_page() { |
| 2633 | 2258 | $license_status = get_option('mxchat_license_status', 'inactive'); |
| 2634 | 2259 | $license_error = get_option('mxchat_license_error', ''); |
| 2635 | 2260 | ?> |
| @@ -2674,15 +2299,15 @@ | ||
| 2674 | 2299 | </div> |
| 2675 | 2300 | </form> |
| 2676 | 2301 | <!-- License Status Display --> |
| 2677 | 2302 | <div class="mxchat-pro-status"> |
| 2678 | - <h3><?php esc_html_e('License Status:', 'mxchat'); ?> | |
| 2303 | + <h3><?php esc_html_e('License Status:', 'mxchat'); ?> | |
| 2679 | 2304 | <span id="mxchat-license-status" class="mxchat-status-badge <?php echo $license_status; ?>"> |
| 2680 | 2305 | <?php echo $license_status === 'active' ? esc_html__('Active', 'mxchat') : esc_html__('Inactive', 'mxchat'); ?> |
| 2681 | 2306 | </span> |
| 2682 | 2307 | </h3> |
| 2683 | 2308 | </div> |
| 2684 | - | |
| 2309 | + | |
| 2685 | 2310 | </div> |
| 2686 | 2311 | <?php |
| 2687 | 2312 | } |
| 2688 | 2313 | |
| @@ -2711,9 +2336,9 @@ | ||
| 2711 | 2336 | $callback_filter = isset($_GET['callback_filter']) ? sanitize_text_field($_GET['callback_filter']) : ''; |
| 2712 | 2337 | |
| 2713 | 2338 | if ($search_term) { |
| 2714 | 2339 | $search_term_like = '%' . $wpdb->esc_like($search_term) . '%'; |
| 2715 | - $where .= $wpdb->prepare(' AND (intent_label LIKE %s OR phrases LIKE %s)', | |
| 2340 | + $where .= $wpdb->prepare(' AND (intent_label LIKE %s OR phrases LIKE %s)', | |
| 2716 | 2341 | $search_term_like, $search_term_like); |
| 2717 | 2342 | } |
| 2718 | 2343 | |
| 2719 | 2344 | if ($callback_filter) { |
| @@ -2725,9 +2350,9 @@ | ||
| 2725 | 2350 | $total_pages = ceil($total_intents / $per_page); |
| 2726 | 2351 | |
| 2727 | 2352 | // Get intents |
| 2728 | 2353 | $intents = $wpdb->get_results($wpdb->prepare( |
| 2729 | - "SELECT * FROM $table_name WHERE $where LIMIT %d OFFSET %d", | |
| 2354 | + "SELECT * FROM $table_name WHERE $where LIMIT %d OFFSET %d", | |
| 2730 | 2355 | $per_page, $offset |
| 2731 | 2356 | )); |
| 2732 | 2357 | |
| 2733 | 2358 | // Get callbacks |
| @@ -2750,9 +2375,9 @@ | ||
| 2750 | 2375 | <div class="mxchat-card"> |
| 2751 | 2376 | <div class="mxchat-card-header"> |
| 2752 | 2377 | <h2><?php esc_html_e('Add New Intent', 'mxchat'); ?></h2> |
| 2753 | 2378 | </div> |
| 2754 | - | |
| 2379 | + | |
| 2755 | 2380 | <div class="mxchat-intent-documentation"> |
| 2756 | 2381 | <p> |
| 2757 | 2382 | <?php esc_html_e('We highly encourage users to quickly read our ', 'mxchat'); ?> |
| 2758 | 2383 | <a href="https://mxchat.ai/documentation/#intents" target="_blank" rel="noopener noreferrer"> |
| @@ -2761,9 +2386,9 @@ | ||
| 2761 | 2386 | <?php esc_html_e(' to better understand intents. Some intents require setup in the Integration tab. If your intent is not triggering lower similarity threshold test.', 'mxchat'); ?> |
| 2762 | 2387 | </p> |
| 2763 | 2388 | </div> |
| 2764 | 2389 | |
| 2765 | - <form id="mxchat-add-intent-form" method="post" | |
| 2390 | + <form id="mxchat-add-intent-form" method="post" | |
| 2766 | 2391 | action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> |
| 2767 | 2392 | <input type="hidden" name="action" value="mxchat_add_intent"> |
| 2768 | 2393 | <?php wp_nonce_field('mxchat_add_intent_nonce'); ?> |
| 2769 | 2394 | |
| @@ -2788,9 +2413,9 @@ | ||
| 2788 | 2413 | <div class="mxchat-form-group"> |
| 2789 | 2414 | <label for="callback_function"> |
| 2790 | 2415 | <?php esc_html_e('Callback Function', 'mxchat'); ?> |
| 2791 | 2416 | </label> |
| 2792 | - <select name="callback_function" id="callback_function" | |
| 2417 | + <select name="callback_function" id="callback_function" | |
| 2793 | 2418 | class="mxchat-intent-select" required> |
| 2794 | 2419 | <option value=""> |
| 2795 | 2420 | <?php esc_html_e('Select a Callback', 'mxchat'); ?> |
| 2796 | 2421 | </option> |
| @@ -2803,9 +2428,9 @@ | ||
| 2803 | 2428 | $pro_only = $data['pro_only']; |
| 2804 | 2429 | $disabled = (!$this->is_activated && $pro_only) ? 'disabled' : ''; |
| 2805 | 2430 | $label_suffix = (!$this->is_activated && $pro_only) ? ' (Pro Only)' : ''; |
| 2806 | 2431 | ?> |
| 2807 | - <option value="<?php echo esc_attr($function); ?>" | |
| 2432 | + <option value="<?php echo esc_attr($function); ?>" | |
| 2808 | 2433 | <?php echo $disabled; ?>> |
| 2809 | 2434 | <?php echo esc_html($label . $label_suffix); ?> |
| 2810 | 2435 | </option> |
| 2811 | 2436 | <?php |
| @@ -2830,9 +2455,9 @@ | ||
| 2830 | 2455 | <form method="get" class="mxchat-search-form"> |
| 2831 | 2456 | <input type="hidden" name="page" value="mxchat-intents"> |
| 2832 | 2457 | <div class="mxchat-search-group"> |
| 2833 | 2458 | <span class="dashicons dashicons-search"></span> |
| 2834 | - <input type="text" name="s" | |
| 2459 | + <input type="text" name="s" | |
| 2835 | 2460 | placeholder="<?php esc_attr_e('Search Intents', 'mxchat'); ?>" |
| 2836 | 2461 | value="<?php echo esc_attr($search_term); ?>"> |
| 2837 | 2462 | <select name="callback_filter" class="mxchat-intent-filter"> |
| 2838 | 2463 | <option value=""> |
| @@ -2839,9 +2464,9 @@ | ||
| 2839 | 2464 | <?php esc_html_e('All Callbacks', 'mxchat'); ?> |
| 2840 | 2465 | </option> |
| 2841 | 2466 | <?php foreach ($available_callbacks as $function => $callback_data) : |
| 2842 | 2467 | $label = $callback_data['label']; ?> |
| 2843 | - <option value="<?php echo esc_attr($function); ?>" | |
| 2468 | + <option value="<?php echo esc_attr($function); ?>" | |
| 2844 | 2469 | <?php selected($callback_filter, $function); ?>> |
| 2845 | 2470 | <?php echo esc_html($label); ?> |
| 2846 | 2471 | </option> |
| 2847 | 2472 | <?php endforeach; ?> |
| @@ -2864,123 +2489,83 @@ | ||
| 2864 | 2489 | <th><?php esc_html_e('Similarity Threshold', 'mxchat'); ?></th> |
| 2865 | 2490 | <th><?php esc_html_e('Actions', 'mxchat'); ?></th> |
| 2866 | 2491 | </tr> |
| 2867 | 2492 | </thead> |
| 2868 | - <tbody> | |
| 2869 | - <?php if ($intents) : | |
| 2870 | - foreach ($intents as $intent) : | |
| 2871 | - $callback_function = $intent->callback_function; | |
| 2872 | - $callback_label = isset($available_callbacks[$callback_function]['label']) | |
| 2873 | - ? $available_callbacks[$callback_function]['label'] | |
| 2874 | - : $callback_function; | |
| 2875 | - $threshold_value = isset($intent->similarity_threshold) | |
| 2876 | - ? round($intent->similarity_threshold * 100) | |
| 2877 | - : 85; | |
| 2878 | - | |
| 2879 | - // Check if this is a form intent (its intent_label starts with "Form ") | |
| 2880 | - $is_form_intent = strpos($intent->intent_label, 'Form ') === 0; | |
| 2881 | - ?> | |
| 2882 | - <tr<?php echo $is_form_intent ? ' class="mxchat-form-intent"' : ''; ?>> | |
| 2883 | - <td> | |
| 2884 | - <?php | |
| 2885 | - if ($is_form_intent) { | |
| 2886 | - // Attempt to extract the form ID from the intent_label. | |
| 2887 | - preg_match('/Form (\d+)/', $intent->intent_label, $matches); | |
| 2888 | - $form_id = isset($matches[1]) ? intval($matches[1]) : 0; | |
| 2889 | - if ($form_id) { | |
| 2890 | - global $wpdb; | |
| 2891 | - $forms_table = $wpdb->prefix . 'mxchat_forms'; | |
| 2892 | - $form = $wpdb->get_row($wpdb->prepare("SELECT title FROM $forms_table WHERE id = %d", $form_id)); | |
| 2893 | - if ($form && !empty($form->title)) { | |
| 2894 | - echo esc_html($form->title); | |
| 2895 | - } else { | |
| 2896 | - echo esc_html($intent->intent_label); | |
| 2897 | - } | |
| 2898 | - } else { | |
| 2899 | - echo esc_html($intent->intent_label); | |
| 2900 | - } | |
| 2901 | - echo ' <span class="mxchat-badge">Form Intent</span>'; | |
| 2902 | - } else { | |
| 2903 | - echo esc_html($intent->intent_label); | |
| 2904 | - } | |
| 2905 | - ?> | |
| 2906 | - </td> | |
| 2907 | - <td class="mxchat-content-cell"> | |
| 2908 | - <?php echo esc_html($intent->phrases); ?> | |
| 2909 | - </td> | |
| 2910 | - <td><?php echo esc_html($callback_label); ?></td> | |
| 2911 | - <td> | |
| 2912 | - <!-- Similarity threshold adjustment (shown for all intents) --> | |
| 2913 | - <form method="post" | |
| 2914 | - action="<?php echo esc_url(admin_url('admin-post.php')); ?>" | |
| 2915 | - class="mxchat-threshold-form"> | |
| 2916 | - <?php wp_nonce_field('mxchat_update_intent_threshold_nonce'); ?> | |
| 2917 | - <input type="hidden" name="action" | |
| 2918 | - value="mxchat_update_intent_threshold"> | |
| 2919 | - <input type="hidden" name="intent_id" | |
| 2920 | - value="<?php echo esc_attr($intent->id); ?>"> | |
| 2921 | - <div class="mxchat-slider-group"> | |
| 2922 | - <input type="range" | |
| 2923 | - name="intent_threshold" | |
| 2924 | - id="intent_threshold_<?php echo esc_attr($intent->id); ?>" | |
| 2925 | - min="70" | |
| 2926 | - max="95" | |
| 2927 | - value="<?php echo esc_attr($threshold_value); ?>" | |
| 2928 | - class="mxchat-intent-slider" | |
| 2929 | - oninput="document.getElementById('threshold_output_<?php echo esc_attr($intent->id); ?>').value = this.value + '%'"> | |
| 2930 | - <output id="threshold_output_<?php echo esc_attr($intent->id); ?>" | |
| 2931 | - class="mxchat-intent-output"> | |
| 2932 | - <?php echo esc_html($threshold_value); ?>% | |
| 2933 | - </output> | |
| 2934 | - </div> | |
| 2935 | - <button type="submit" class="mxchat-button-icon"> | |
| 2936 | - <span class="dashicons dashicons-saved"></span> | |
| 2937 | - </button> | |
| 2938 | - </form> | |
| 2939 | - </td> | |
| 2940 | - <td class="mxchat-actions-cell"> | |
| 2941 | - <?php if (!$is_form_intent) : ?> | |
| 2942 | - <!-- Standard intents: allow edit and delete --> | |
| 2943 | - <button type="button" | |
| 2944 | - class="mxchat-button-icon mxchat-edit-button" | |
| 2945 | - data-intent-id="<?php echo esc_attr($intent->id); ?>" | |
| 2946 | - data-phrases="<?php echo esc_attr($intent->phrases); ?>"> | |
| 2947 | - <span class="dashicons dashicons-edit"></span> | |
| 2948 | - </button> | |
| 2949 | - <form method="post" | |
| 2950 | - action="<?php echo esc_url(admin_url('admin-post.php')); ?>" | |
| 2951 | - class="mxchat-delete-form" | |
| 2952 | - onsubmit="return confirm('<?php esc_attr_e('Are you sure you want to delete this intent?', 'mxchat'); ?>');"> | |
| 2953 | - <?php wp_nonce_field('mxchat_delete_intent_nonce'); ?> | |
| 2954 | - <input type="hidden" name="action" value="mxchat_delete_intent"> | |
| 2955 | - <input type="hidden" name="intent_id" | |
| 2956 | - value="<?php echo esc_attr($intent->id); ?>"> | |
| 2957 | - <button type="submit" class="mxchat-button-icon"> | |
| 2958 | - <span class="dashicons dashicons-trash"></span> | |
| 2959 | - </button> | |
| 2960 | - </form> | |
| 2961 | - <?php else : ?> | |
| 2962 | - <!-- Form intents: show manage in forms button --> | |
| 2963 | - <?php | |
| 2964 | - preg_match('/Form (\d+)/', $intent->intent_label, $matches); | |
| 2965 | - $form_id = isset($matches[1]) ? $matches[1] : ''; | |
| 2966 | - ?> | |
| 2967 | - <a href="<?php echo esc_url(admin_url('admin.php?page=mxchat-forms&action=edit&form_id=' . $form_id)); ?>" | |
| 2968 | - class="mxchat-button-secondary"> | |
| 2969 | - <?php esc_html_e('Manage in Forms', 'mxchat'); ?> | |
| 2970 | - </a> | |
| 2971 | - <?php endif; ?> | |
| 2972 | - </td> | |
| 2973 | - </tr> | |
| 2974 | - <?php endforeach; | |
| 2975 | - else : ?> | |
| 2493 | + <tbody> | |
| 2494 | + <?php if ($intents) : | |
| 2495 | + foreach ($intents as $intent) : | |
| 2496 | + $callback_function = $intent->callback_function; | |
| 2497 | + $callback_label = isset($available_callbacks[$callback_function]['label']) | |
| 2498 | + ? $available_callbacks[$callback_function]['label'] | |
| 2499 | + : $callback_function; | |
| 2500 | + $threshold_value = isset($intent->similarity_threshold) | |
| 2501 | + ? round($intent->similarity_threshold * 100) | |
| 2502 | + : 85; | |
| 2503 | + ?> | |
| 2976 | 2504 | <tr> |
| 2977 | - <td colspan="5" class="mxchat-no-records"> | |
| 2978 | - <?php esc_html_e('No intents found.', 'mxchat'); ?> | |
| 2505 | + <td><?php echo esc_html($intent->intent_label); ?></td> | |
| 2506 | + <td class="mxchat-content-cell"> | |
| 2507 | + <?php echo esc_html($intent->phrases); ?> | |
| 2979 | 2508 | </td> |
| 2509 | + <td><?php echo esc_html($callback_label); ?></td> | |
| 2510 | + <td> | |
| 2511 | + <form method="post" | |
| 2512 | + action="<?php echo esc_url(admin_url('admin-post.php')); ?>" | |
| 2513 | + class="mxchat-threshold-form"> | |
| 2514 | + <?php wp_nonce_field('mxchat_update_intent_threshold_nonce'); ?> | |
| 2515 | + <input type="hidden" name="action" | |
| 2516 | + value="mxchat_update_intent_threshold"> | |
| 2517 | + <input type="hidden" name="intent_id" | |
| 2518 | + value="<?php echo esc_attr($intent->id); ?>"> | |
| 2519 | + <div class="mxchat-slider-group"> | |
| 2520 | + <input type="range" | |
| 2521 | + name="intent_threshold" | |
| 2522 | + id="intent_threshold_<?php echo esc_attr($intent->id); ?>" | |
| 2523 | + min="70" | |
| 2524 | + max="95" | |
| 2525 | + value="<?php echo esc_attr($threshold_value); ?>" | |
| 2526 | + class="mxchat-intent-slider" | |
| 2527 | + oninput="document.getElementById('threshold_output_<?php echo esc_attr($intent->id); ?>').value = this.value + '%'"> | |
| 2528 | + <output id="threshold_output_<?php echo esc_attr($intent->id); ?>" | |
| 2529 | + class="mxchat-intent-output"> | |
| 2530 | + <?php echo esc_html($threshold_value); ?>% | |
| 2531 | + </output> | |
| 2532 | + </div> | |
| 2533 | + <button type="submit" class="mxchat-button-icon"> | |
| 2534 | + <span class="dashicons dashicons-saved"></span> | |
| 2535 | + </button> | |
| 2536 | + </form> | |
| 2537 | + </td> | |
| 2538 | + <td class="mxchat-actions-cell"> | |
| 2539 | + <button type="button" | |
| 2540 | + class="mxchat-button-icon mxchat-edit-button" | |
| 2541 | + data-intent-id="<?php echo esc_attr($intent->id); ?>" | |
| 2542 | + data-phrases="<?php echo esc_attr($intent->phrases); ?>"> | |
| 2543 | + <span class="dashicons dashicons-edit"></span> | |
| 2544 | + </button> | |
| 2545 | + <form method="post" | |
| 2546 | + action="<?php echo esc_url(admin_url('admin-post.php')); ?>" | |
| 2547 | + class="mxchat-delete-form" | |
| 2548 | + onsubmit="return confirm('<?php esc_attr_e('Are you sure you want to delete this intent?', 'mxchat'); ?>');"> | |
| 2549 | + <?php wp_nonce_field('mxchat_delete_intent_nonce'); ?> | |
| 2550 | + <input type="hidden" name="action" value="mxchat_delete_intent"> | |
| 2551 | + <input type="hidden" name="intent_id" | |
| 2552 | + value="<?php echo esc_attr($intent->id); ?>"> | |
| 2553 | + <button type="submit" class="mxchat-button-icon"> | |
| 2554 | + <span class="dashicons dashicons-trash"></span> | |
| 2555 | + </button> | |
| 2556 | + </form> | |
| 2557 | + </td> | |
| 2980 | 2558 | </tr> |
| 2981 | - <?php endif; ?> | |
| 2982 | - </tbody> | |
| 2559 | + <?php endforeach; | |
| 2560 | + else : ?> | |
| 2561 | + <tr> | |
| 2562 | + <td colspan="5" class="mxchat-no-records"> | |
| 2563 | + <?php esc_html_e('No intents found.', 'mxchat'); ?> | |
| 2564 | + </td> | |
| 2565 | + </tr> | |
| 2566 | + <?php endif; ?> | |
| 2567 | + </tbody> | |
| 2983 | 2568 | </table> |
| 2984 | 2569 | </div> |
| 2985 | 2570 | |
| 2986 | 2571 | <?php if ($total_pages > 1) : ?> |
| @@ -3006,26 +2591,26 @@ | ||
| 3006 | 2591 | <span class="mxchat-modal-close">×</span> |
| 3007 | 2592 | <div class="mxchat-card-header"> |
| 3008 | 2593 | <h2><?php esc_html_e('Edit Intent Phrases', 'mxchat'); ?></h2> |
| 3009 | 2594 | </div> |
| 3010 | - | |
| 3011 | - <form id="mxchat-edit-intent-form" method="post" | |
| 2595 | + | |
| 2596 | + <form id="mxchat-edit-intent-form" method="post" | |
| 3012 | 2597 | action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> |
| 3013 | 2598 | <?php wp_nonce_field('mxchat_edit_intent_nonce'); ?> |
| 3014 | 2599 | <input type="hidden" name="action" value="mxchat_edit_intent"> |
| 3015 | 2600 | <input type="hidden" name="intent_id" id="edit_intent_id"> |
| 3016 | - | |
| 2601 | + | |
| 3017 | 2602 | <div class="mxchat-form-group"> |
| 3018 | 2603 | <label for="edit_phrases"> |
| 3019 | 2604 | <?php esc_html_e('Phrases (comma-separated)', 'mxchat'); ?> |
| 3020 | 2605 | </label> |
| 3021 | - <textarea name="phrases" | |
| 3022 | - id="edit_phrases" | |
| 3023 | - rows="5" | |
| 3024 | - class="mxchat-intent-textarea" | |
| 2606 | + <textarea name="phrases" | |
| 2607 | + id="edit_phrases" | |
| 2608 | + rows="5" | |
| 2609 | + class="mxchat-intent-textarea" | |
| 3025 | 2610 | required></textarea> |
| 3026 | 2611 | </div> |
| 3027 | - | |
| 2612 | + | |
| 3028 | 2613 | <div class="mxchat-modal-actions"> |
| 3029 | 2614 | <button type="submit" class="mxchat-button-primary"> |
| 3030 | 2615 | <?php esc_html_e('Update Phrases', 'mxchat'); ?> |
| 3031 | 2616 | </button> |
| @@ -3242,8 +2827,18 @@ | ||
| 3242 | 2827 | 'label' => __('Email Capture', 'mxchat'), |
| 3243 | 2828 | 'pro_only' => false, |
| 3244 | 2829 | 'group' => __('Customer Engagement', 'mxchat'), |
| 3245 | 2830 | ], |
| 2831 | + 'mxchat_handle_product_inquiry' => [ | |
| 2832 | + 'label' => __('Show Product Card', 'mxchat'), | |
| 2833 | + 'pro_only' => true, | |
| 2834 | + 'group' => __('WooCommerce Features', 'mxchat'), | |
| 2835 | + ], | |
| 2836 | + 'mxchat_handle_order_history' => [ | |
| 2837 | + 'label' => __('Order History', 'mxchat'), | |
| 2838 | + 'pro_only' => true, | |
| 2839 | + 'group' => __('WooCommerce Features', 'mxchat'), | |
| 2840 | + ], | |
| 3246 | 2841 | 'mxchat_generate_image' => [ |
| 3247 | 2842 | 'label' => __('Generate Image', 'mxchat'), |
| 3248 | 2843 | 'pro_only' => true, |
| 3249 | 2844 | 'group' => __('Other Features', 'mxchat'), |
| @@ -3257,13 +2852,28 @@ | ||
| 3257 | 2852 | 'label' => __('Brave Image Search', 'mxchat'), |
| 3258 | 2853 | 'pro_only' => false, |
| 3259 | 2854 | 'group' => __('Search Features', 'mxchat'), |
| 3260 | 2855 | ], |
| 2856 | + 'mxchat_handle_add_to_cart_intent' => [ | |
| 2857 | + 'label' => __('Add to Cart', 'mxchat'), | |
| 2858 | + 'pro_only' => true, | |
| 2859 | + 'group' => __('WooCommerce Features', 'mxchat'), | |
| 2860 | + ], | |
| 2861 | + 'mxchat_handle_checkout_intent' => [ | |
| 2862 | + 'label' => __('Proceed to Checkout', 'mxchat'), | |
| 2863 | + 'pro_only' => true, | |
| 2864 | + 'group' => __('WooCommerce Features', 'mxchat'), | |
| 2865 | + ], | |
| 3261 | 2866 | 'mxchat_handle_pdf_discussion' => [ |
| 3262 | 2867 | 'label' => __('Chat with PDF', 'mxchat'), |
| 3263 | 2868 | 'pro_only' => true, |
| 3264 | 2869 | 'group' => __('Other Features', 'mxchat'), |
| 3265 | 2870 | ], |
| 2871 | + 'mxchat_handle_product_recommendations' => [ | |
| 2872 | + 'label' => __('Product Recommendations', 'mxchat'), | |
| 2873 | + 'pro_only' => true, | |
| 2874 | + 'group' => __('WooCommerce Features', 'mxchat'), | |
| 2875 | + ], | |
| 3266 | 2876 | 'mxchat_live_agent_handover' => [ |
| 3267 | 2877 | 'label' => __('Live Agent', 'mxchat'), |
| 3268 | 2878 | 'pro_only' => true, |
| 3269 | 2879 | 'group' => __('Customer Engagement', 'mxchat'), |
| @@ -3274,11 +2884,8 @@ | ||
| 3274 | 2884 | 'group' => __('Customer Engagement', 'mxchat'), |
| 3275 | 2885 | ], |
| 3276 | 2886 | ]; |
| 3277 | 2887 | |
| 3278 | - // Allow other plugins to add their callbacks | |
| 3279 | - $callbacks = apply_filters('mxchat_available_callbacks', $callbacks); | |
| 3280 | - | |
| 3281 | 2888 | // Return grouped structure if requested |
| 3282 | 2889 | if ($grouped) { |
| 3283 | 2890 | $grouped_callbacks = []; |
| 3284 | 2891 | foreach ($callbacks as $key => $data) { |
| @@ -3289,12 +2896,14 @@ | ||
| 3289 | 2896 | ]; |
| 3290 | 2897 | } |
| 3291 | 2898 | return $grouped_callbacks; |
| 3292 | 2899 | } |
| 2900 | + | |
| 3293 | 2901 | return $callbacks; |
| 3294 | 2902 | } |
| 3295 | 2903 | |
| 3296 | 2904 | |
| 2905 | + | |
| 3297 | 2906 | private function mxchat_average_vectors($vectors) { |
| 3298 | 2907 | $vector_length = count($vectors[0]); |
| 3299 | 2908 | $sum_vector = array_fill(0, $vector_length, 0); |
| 3300 | 2909 | |
| @@ -3412,44 +3021,25 @@ | ||
| 3412 | 3021 | 'mxchat-chatbot', |
| 3413 | 3022 | 'mxchat_chatbot_section' |
| 3414 | 3023 | ); |
| 3415 | 3024 | |
| 3416 | - add_settings_field( | |
| 3417 | - 'voyage_api_key', | |
| 3418 | - esc_html__('Voyage AI API Key', 'mxchat'), | |
| 3419 | - array($this, 'voyage_api_key_callback'), | |
| 3420 | - 'mxchat-chatbot', | |
| 3421 | - 'mxchat_chatbot_section' | |
| 3422 | - ); | |
| 3423 | - | |
| 3424 | - | |
| 3425 | 3025 | add_settings_field( |
| 3426 | - 'model', | |
| 3427 | - esc_html__('Chat Model', 'mxchat'), | |
| 3428 | - array($this, 'mxchat_model_callback'), | |
| 3026 | + 'system_prompt_instructions', | |
| 3027 | + esc_html__('AI Instructions (Behavior)', 'mxchat'), | |
| 3028 | + array($this, 'system_prompt_instructions_callback'), | |
| 3429 | 3029 | 'mxchat-chatbot', |
| 3430 | 3030 | 'mxchat_chatbot_section' |
| 3431 | 3031 | ); |
| 3432 | 3032 | |
| 3433 | - // Add the settings field | |
| 3434 | 3033 | add_settings_field( |
| 3435 | - 'embedding_model', | |
| 3436 | - esc_html__('Embedding Model', 'mxchat'), | |
| 3437 | - array($this, 'embedding_model_callback'), | |
| 3034 | + 'model', | |
| 3035 | + esc_html__('Model', 'mxchat'), | |
| 3036 | + array($this, 'mxchat_model_callback'), | |
| 3438 | 3037 | 'mxchat-chatbot', |
| 3439 | 3038 | 'mxchat_chatbot_section' |
| 3440 | 3039 | ); |
| 3441 | 3040 | |
| 3442 | 3041 | add_settings_field( |
| 3443 | - 'system_prompt_instructions', | |
| 3444 | - esc_html__('AI Instructions (Behavior)', 'mxchat'), | |
| 3445 | - array($this, 'system_prompt_instructions_callback'), | |
| 3446 | - 'mxchat-chatbot', | |
| 3447 | - 'mxchat_chatbot_section' | |
| 3448 | - ); | |
| 3449 | - | |
| 3450 | - | |
| 3451 | - add_settings_field( | |
| 3452 | 3042 | 'top_bar_title', |
| 3453 | 3043 | esc_html__('Top Bar Title', 'mxchat'), |
| 3454 | 3044 | array($this, 'mxchat_top_bar_title_callback'), |
| 3455 | 3045 | 'mxchat-chatbot', |
| @@ -3561,9 +3151,9 @@ | ||
| 3561 | 3151 | ); |
| 3562 | 3152 | |
| 3563 | 3153 | add_settings_field( |
| 3564 | 3154 | 'popular_question_1', |
| 3565 | - esc_html__('Quick Question 1', 'mxchat'), | |
| 3155 | + esc_html__('Popular Question 1', 'mxchat'), | |
| 3566 | 3156 | array($this, 'mxchat_popular_question_1_callback'), |
| 3567 | 3157 | 'mxchat-chatbot', |
| 3568 | 3158 | 'mxchat_chatbot_section' |
| 3569 | 3159 | ); |
| @@ -3569,9 +3159,9 @@ | ||
| 3569 | 3159 | ); |
| 3570 | 3160 | |
| 3571 | 3161 | add_settings_field( |
| 3572 | 3162 | 'popular_question_2', |
| 3573 | - esc_html__('Quick Question 2', 'mxchat'), | |
| 3163 | + esc_html__('Popular Question 2', 'mxchat'), | |
| 3574 | 3164 | array($this, 'mxchat_popular_question_2_callback'), |
| 3575 | 3165 | 'mxchat-chatbot', |
| 3576 | 3166 | 'mxchat_chatbot_section' |
| 3577 | 3167 | ); |
| @@ -3577,9 +3167,9 @@ | ||
| 3577 | 3167 | ); |
| 3578 | 3168 | |
| 3579 | 3169 | add_settings_field( |
| 3580 | 3170 | 'popular_question_3', |
| 3581 | - esc_html__('Quick Question 3', 'mxchat'), | |
| 3171 | + esc_html__('Popular Question 3', 'mxchat'), | |
| 3582 | 3172 | array($this, 'mxchat_popular_question_3_callback'), |
| 3583 | 3173 | 'mxchat-chatbot', |
| 3584 | 3174 | 'mxchat_chatbot_section' |
| 3585 | 3175 | ); |
| @@ -3585,14 +3175,21 @@ | ||
| 3585 | 3175 | ); |
| 3586 | 3176 | |
| 3587 | 3177 | add_settings_field( |
| 3588 | 3178 | 'additional_popular_questions', |
| 3589 | - esc_html__('Additional Quick Questions', 'mxchat'), | |
| 3179 | + esc_html__('Additional Popular Questions', 'mxchat'), | |
| 3590 | 3180 | array($this, 'mxchat_additional_popular_questions_callback'), |
| 3591 | 3181 | 'mxchat-chatbot', |
| 3592 | 3182 | 'mxchat_chatbot_section' |
| 3593 | 3183 | ); |
| 3594 | 3184 | |
| 3185 | + // WooCommerce Settings Section | |
| 3186 | + add_settings_section( | |
| 3187 | + 'mxchat_woocommerce_section', | |
| 3188 | + esc_html__('WooCommerce Settings', 'mxchat'), | |
| 3189 | + null, | |
| 3190 | + 'mxchat-embed' | |
| 3191 | + ); | |
| 3595 | 3192 | |
| 3596 | 3193 | // Loops Settings Section |
| 3597 | 3194 | add_settings_section( |
| 3598 | 3195 | 'mxchat_loops_section', |
| @@ -3600,8 +3197,33 @@ | ||
| 3600 | 3197 | null, |
| 3601 | 3198 | 'mxchat-embed' |
| 3602 | 3199 | ); |
| 3603 | 3200 | |
| 3201 | + // WooCommerce Settings Fields | |
| 3202 | + add_settings_field( | |
| 3203 | + 'enable_woocommerce_integration', | |
| 3204 | + esc_html__('Automatically Embed Products', 'mxchat'), | |
| 3205 | + array($this, 'mxchat_enable_woocommerce_integration_callback'), | |
| 3206 | + 'mxchat-embed', | |
| 3207 | + 'mxchat_woocommerce_section' | |
| 3208 | + ); | |
| 3209 | + | |
| 3210 | + add_settings_field( | |
| 3211 | + 'woocommerce_consumer_key', | |
| 3212 | + esc_html__('WooCommerce Consumer Key', 'mxchat'), | |
| 3213 | + array($this, 'mxchat_woocommerce_consumer_key_callback'), | |
| 3214 | + 'mxchat-embed', | |
| 3215 | + 'mxchat_woocommerce_section' | |
| 3216 | + ); | |
| 3217 | + | |
| 3218 | + add_settings_field( | |
| 3219 | + 'woocommerce_consumer_secret', | |
| 3220 | + esc_html__('WooCommerce Consumer Secret', 'mxchat'), | |
| 3221 | + array($this, 'mxchat_woocommerce_consumer_secret_callback'), | |
| 3222 | + 'mxchat-embed', | |
| 3223 | + 'mxchat_woocommerce_section' | |
| 3224 | + ); | |
| 3225 | + | |
| 3604 | 3226 | // Loops Settings Fields |
| 3605 | 3227 | add_settings_field( |
| 3606 | 3228 | 'loops_api_key', |
| 3607 | 3229 | esc_html__('Loops API Key', 'mxchat'), |
| @@ -3796,11 +3418,162 @@ | ||
| 3796 | 3418 | 'mxchat-embed', |
| 3797 | 3419 | 'mxchat_live_agent_section' |
| 3798 | 3420 | ); |
| 3799 | 3421 | |
| 3422 | + // Theme Settings Section | |
| 3423 | + add_settings_section( | |
| 3424 | + 'mxchat_theme_section', | |
| 3425 | + esc_html__('Theme Settings', 'mxchat'), | |
| 3426 | + null, | |
| 3427 | + 'mxchat-theme' | |
| 3428 | + ); | |
| 3800 | 3429 | |
| 3430 | + add_settings_field( | |
| 3431 | + 'close_button_color', | |
| 3432 | + esc_html__('Close Button & Title Color', 'mxchat'), | |
| 3433 | + array($this, 'mxchat_close_button_color_callback'), | |
| 3434 | + 'mxchat-theme', | |
| 3435 | + 'mxchat_theme_section' | |
| 3436 | + ); | |
| 3801 | 3437 | |
| 3438 | + add_settings_field( | |
| 3439 | + 'chatbot_bg_color', | |
| 3440 | + esc_html__('Chatbot Background Color', 'mxchat'), | |
| 3441 | + array($this, 'mxchat_chatbot_bg_color_callback'), | |
| 3442 | + 'mxchat-theme', | |
| 3443 | + 'mxchat_theme_section' | |
| 3444 | + ); | |
| 3802 | 3445 | |
| 3446 | + add_settings_field( | |
| 3447 | + 'user_message_bg_color', | |
| 3448 | + esc_html__('User Message Background Color', 'mxchat'), | |
| 3449 | + array($this, 'mxchat_user_message_bg_color_callback'), | |
| 3450 | + 'mxchat-theme', | |
| 3451 | + 'mxchat_theme_section' | |
| 3452 | + ); | |
| 3453 | + | |
| 3454 | + add_settings_field( | |
| 3455 | + 'user_message_font_color', | |
| 3456 | + esc_html__('User Message Font Color', 'mxchat'), | |
| 3457 | + array($this, 'mxchat_user_message_font_color_callback'), | |
| 3458 | + 'mxchat-theme', | |
| 3459 | + 'mxchat_theme_section' | |
| 3460 | + ); | |
| 3461 | + | |
| 3462 | + add_settings_field( | |
| 3463 | + 'bot_message_bg_color', | |
| 3464 | + esc_html__('Bot Message Background Color', 'mxchat'), | |
| 3465 | + array($this, 'mxchat_bot_message_bg_color_callback'), | |
| 3466 | + 'mxchat-theme', | |
| 3467 | + 'mxchat_theme_section' | |
| 3468 | + ); | |
| 3469 | + | |
| 3470 | + add_settings_field( | |
| 3471 | + 'bot_message_font_color', | |
| 3472 | + esc_html__('Bot Message Font Color', 'mxchat'), | |
| 3473 | + array($this, 'mxchat_bot_message_font_color_callback'), | |
| 3474 | + 'mxchat-theme', | |
| 3475 | + 'mxchat_theme_section' | |
| 3476 | + ); | |
| 3477 | + | |
| 3478 | + add_settings_field( | |
| 3479 | + 'top_bar_bg_color', | |
| 3480 | + esc_html__('Top Bar Background Color', 'mxchat'), | |
| 3481 | + array($this, 'mxchat_top_bar_bg_color_callback'), | |
| 3482 | + 'mxchat-theme', | |
| 3483 | + 'mxchat_theme_section' | |
| 3484 | + ); | |
| 3485 | + | |
| 3486 | + add_settings_field( | |
| 3487 | + 'send_button_font_color', | |
| 3488 | + esc_html__('Send Button Color', 'mxchat'), | |
| 3489 | + array($this, 'mxchat_send_button_font_color_callback'), | |
| 3490 | + 'mxchat-theme', | |
| 3491 | + 'mxchat_theme_section' | |
| 3492 | + ); | |
| 3493 | + | |
| 3494 | + add_settings_field( | |
| 3495 | + 'chat_input_font_color', | |
| 3496 | + esc_html__('Chat Input Font Color', 'mxchat'), | |
| 3497 | + array($this, 'mxchat_chat_input_font_color_callback'), | |
| 3498 | + 'mxchat-theme', | |
| 3499 | + 'mxchat_theme_section' | |
| 3500 | + ); | |
| 3501 | + | |
| 3502 | + add_settings_field( | |
| 3503 | + 'chatbot_background_color', | |
| 3504 | + esc_html__('Floating Widget Background Color', 'mxchat'), | |
| 3505 | + array($this, 'mxchat_chatbot_background_color_callback'), | |
| 3506 | + 'mxchat-theme', | |
| 3507 | + 'mxchat_theme_section' | |
| 3508 | + ); | |
| 3509 | + | |
| 3510 | + add_settings_field( | |
| 3511 | + 'icon_color', | |
| 3512 | + esc_html__('Chatbot Icon Color', 'mxchat'), | |
| 3513 | + array($this, 'mxchat_icon_color_callback'), | |
| 3514 | + 'mxchat-theme', | |
| 3515 | + 'mxchat_theme_section' | |
| 3516 | + ); | |
| 3517 | + | |
| 3518 | + add_settings_field( | |
| 3519 | + 'custom_icon', | |
| 3520 | + esc_html__('Custom Chatbot Icon (PNG)', 'mxchat'), | |
| 3521 | + array($this, 'mxchat_custom_icon_callback'), | |
| 3522 | + 'mxchat-theme', | |
| 3523 | + 'mxchat_theme_section' | |
| 3524 | + ); | |
| 3525 | + | |
| 3526 | + add_settings_field( | |
| 3527 | + 'title_icon', | |
| 3528 | + esc_html__('Title Bar Icon (PNG)', 'mxchat'), | |
| 3529 | + array($this, 'mxchat_title_icon_callback'), | |
| 3530 | + 'mxchat-theme', | |
| 3531 | + 'mxchat_theme_section' | |
| 3532 | + ); | |
| 3533 | + | |
| 3534 | + add_settings_field( | |
| 3535 | + 'live_agent_message_bg_color', | |
| 3536 | + esc_html__('Live Agent Background Color', 'mxchat'), | |
| 3537 | + array($this, 'mxchat_live_agent_message_bg_color_callback'), | |
| 3538 | + 'mxchat-theme', | |
| 3539 | + 'mxchat_theme_section' | |
| 3540 | + ); | |
| 3541 | + | |
| 3542 | + add_settings_field( | |
| 3543 | + 'live_agent_message_font_color', | |
| 3544 | + esc_html__('Live Agent Font Color', 'mxchat'), | |
| 3545 | + array($this, 'mxchat_live_agent_message_font_color_callback'), | |
| 3546 | + 'mxchat-theme', | |
| 3547 | + 'mxchat_theme_section' | |
| 3548 | + ); | |
| 3549 | + | |
| 3550 | + // Mode Indicator Background Color | |
| 3551 | + add_settings_field( | |
| 3552 | + 'mode_indicator_bg_color', | |
| 3553 | + esc_html__('Mode Indicator Background Color', 'mxchat'), | |
| 3554 | + array($this, 'mxchat_mode_indicator_bg_color_callback'), | |
| 3555 | + 'mxchat-theme', | |
| 3556 | + 'mxchat_theme_section' | |
| 3557 | + ); | |
| 3558 | + | |
| 3559 | + // Mode Indicator Font Color | |
| 3560 | + add_settings_field( | |
| 3561 | + 'mode_indicator_font_color', | |
| 3562 | + esc_html__('Mode Indicator Font Color', 'mxchat'), | |
| 3563 | + array($this, 'mxchat_mode_indicator_font_color_callback'), | |
| 3564 | + 'mxchat-theme', | |
| 3565 | + 'mxchat_theme_section' | |
| 3566 | + ); | |
| 3567 | + | |
| 3568 | + add_settings_field( | |
| 3569 | + 'toolbar_icon_color', | |
| 3570 | + esc_html__('Toolbar Icon Color', 'mxchat'), | |
| 3571 | + array($this, 'mxchat_toolbar_icon_color_callback'), | |
| 3572 | + 'mxchat-theme', | |
| 3573 | + 'mxchat_theme_section' | |
| 3574 | + ); | |
| 3575 | + | |
| 3803 | 3576 | // General Settings Section |
| 3804 | 3577 | add_settings_section( |
| 3805 | 3578 | 'mxchat_general_section', |
| 3806 | 3579 | esc_html__('Frequently Asked Questions (FAQ)', 'mxchat'), |
| @@ -3835,9 +3608,9 @@ | ||
| 3835 | 3608 | } |
| 3836 | 3609 | |
| 3837 | 3610 | /** |
| 3838 | 3611 | * Sanitize all prompts options |
| 3839 | - * | |
| 3612 | + * | |
| 3840 | 3613 | * @param array $input The unsanitized options array |
| 3841 | 3614 | * @return array The sanitized options array |
| 3842 | 3615 | */ |
| 3843 | 3616 | public function sanitize_prompts_options($input) { |
| @@ -3842,16 +3615,16 @@ | ||
| 3842 | 3615 | */ |
| 3843 | 3616 | public function sanitize_prompts_options($input) { |
| 3844 | 3617 | // Log the incoming input. |
| 3845 | 3618 | //error_log('Sanitizing inputs: ' . print_r($input, true)); |
| 3846 | - | |
| 3619 | + | |
| 3847 | 3620 | $sanitized = array(); |
| 3848 | - | |
| 3621 | + | |
| 3849 | 3622 | // Boolean options |
| 3850 | 3623 | $sanitized['mxchat_auto_sync_posts'] = isset($input['mxchat_auto_sync_posts']) ? 1 : 0; |
| 3851 | 3624 | $sanitized['mxchat_auto_sync_pages'] = isset($input['mxchat_auto_sync_pages']) ? 1 : 0; |
| 3852 | 3625 | $sanitized['mxchat_use_pinecone'] = !empty($input['mxchat_use_pinecone']) ? 1 : 0; |
| 3853 | - | |
| 3626 | + | |
| 3854 | 3627 | // API Key: if less than 32 characters, flag as invalid. |
| 3855 | 3628 | $api_key = sanitize_text_field($input['mxchat_pinecone_api_key'] ?? ''); |
| 3856 | 3629 | if (!empty($api_key) && strlen($api_key) < 32) { |
| 3857 | 3630 | add_settings_error( |
| @@ -3863,13 +3636,13 @@ | ||
| 3863 | 3636 | $sanitized['mxchat_pinecone_api_key'] = $existing_options['mxchat_pinecone_api_key'] ?? ''; |
| 3864 | 3637 | } else { |
| 3865 | 3638 | $sanitized['mxchat_pinecone_api_key'] = $api_key; |
| 3866 | 3639 | } |
| 3867 | - | |
| 3640 | + | |
| 3868 | 3641 | // Environment and Index Name |
| 3869 | 3642 | $sanitized['mxchat_pinecone_environment'] = sanitize_text_field($input['mxchat_pinecone_environment'] ?? ''); |
| 3870 | 3643 | $sanitized['mxchat_pinecone_index'] = sanitize_text_field($input['mxchat_pinecone_index'] ?? ''); |
| 3871 | - | |
| 3644 | + | |
| 3872 | 3645 | // Host: Remove protocol and validate format. |
| 3873 | 3646 | $host = sanitize_text_field($input['mxchat_pinecone_host'] ?? ''); |
| 3874 | 3647 | $host = preg_replace('#^https?://#', '', $host); |
| 3875 | 3648 | //error_log('Host after removing protocol: ' . $host); |
| @@ -3887,11 +3660,11 @@ | ||
| 3887 | 3660 | } |
| 3888 | 3661 | } else { |
| 3889 | 3662 | $sanitized['mxchat_pinecone_host'] = ''; |
| 3890 | 3663 | } |
| 3891 | - | |
| 3664 | + | |
| 3892 | 3665 | //error_log('Final sanitized array: ' . print_r($sanitized, true)); |
| 3893 | - | |
| 3666 | + | |
| 3894 | 3667 | return $sanitized; |
| 3895 | 3668 | } |
| 3896 | 3669 | |
| 3897 | 3670 | |
| @@ -4047,8 +3820,52 @@ | ||
| 4047 | 3820 | echo '</div>'; |
| 4048 | 3821 | } |
| 4049 | 3822 | |
| 4050 | 3823 | |
| 3824 | +public function mxchat_enable_woocommerce_integration_callback() { | |
| 3825 | + // Load from mxchat_options array | |
| 3826 | + $options = get_option('mxchat_options', []); | |
| 3827 | + | |
| 3828 | + // Get WooCommerce integration status with backwards compatibility | |
| 3829 | + $woo_integration = isset($options['enable_woocommerce_integration']) | |
| 3830 | + ? $options['enable_woocommerce_integration'] | |
| 3831 | + : ''; | |
| 3832 | + | |
| 3833 | + // Support both old ('1') and new ('on') values | |
| 3834 | + $checked = ($woo_integration === 'on' || $woo_integration === '1') ? 'checked' : ''; | |
| 3835 | + | |
| 3836 | + // Check if the feature is activated (paid feature) | |
| 3837 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 3838 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 3839 | + | |
| 3840 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 3841 | + | |
| 3842 | + echo '<label class="toggle-switch">'; | |
| 3843 | + echo sprintf( | |
| 3844 | + '<input type="checkbox" id="enable_woocommerce_integration" name="enable_woocommerce_integration" value="on" %s %s />', | |
| 3845 | + esc_attr($checked), | |
| 3846 | + esc_attr($disabled) | |
| 3847 | + ); | |
| 3848 | + echo '<span class="slider"></span>'; | |
| 3849 | + echo '</label>'; | |
| 3850 | + | |
| 3851 | + echo '<p class="description">' . esc_html__('Automatically syncs new product additions, updates, and removals to the knowledge base. For existing products, submit your product sitemap in the Knowledge Base section to add them initially.', 'mxchat') . '</p>'; | |
| 3852 | + | |
| 3853 | + // Pro feature overlay for non-activated users | |
| 3854 | + if (!$this->is_activated) { | |
| 3855 | + echo '<div class="pro-feature-overlay">'; | |
| 3856 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 3857 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 3858 | + echo '</a>'; | |
| 3859 | + echo '</div>'; | |
| 3860 | + } | |
| 3861 | + | |
| 3862 | + echo '</div>'; | |
| 3863 | +} | |
| 3864 | + | |
| 3865 | + | |
| 3866 | + | |
| 3867 | + | |
| 4051 | 3868 | private function mxchat_add_option_field($id, $title, $callback = '') { |
| 4052 | 3869 | add_settings_field( |
| 4053 | 3870 | $id, |
| 4054 | 3871 | __($title, 'mxchat'), |
| @@ -4065,8 +3882,9 @@ | ||
| 4065 | 3882 | |
| 4066 | 3883 | // Notice we changed the name to "api_key" (no array notation). |
| 4067 | 3884 | echo '<input type="password" id="api_key" name="api_key" value="' . $apiKey . '" class="regular-text" />'; |
| 4068 | 3885 | echo '<button type="button" id="toggleApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; |
| 3886 | + echo '<p class="description">' . esc_html__('The OpenAI API key is required even when using other models as it is used for vector embedding functionality. You must add credits to your OpenAI billing account before use.', 'mxchat') . '</p>'; | |
| 4069 | 3887 | } |
| 4070 | 3888 | public function xai_api_key_callback() { |
| 4071 | 3889 | // Check if the feature is activated (paid feature) |
| 4072 | 3890 | $disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated |
| @@ -4094,15 +3912,15 @@ | ||
| 4094 | 3912 | echo '</div>'; |
| 4095 | 3913 | } |
| 4096 | 3914 | public function claude_api_key_callback() { |
| 4097 | 3915 | // Check if the feature is activated (paid feature) |
| 4098 | - $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4099 | - $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 3916 | + $disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated | |
| 3917 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; // CSS class to style the wrapper based on activation status | |
| 4100 | 3918 | |
| 4101 | - // Retrieve the Claude API key value directly like the others | |
| 3919 | + // Retrieve the Claude API key value | |
| 4102 | 3920 | $claudeApiKey = isset($this->options['claude_api_key']) ? esc_attr($this->options['claude_api_key']) : ''; |
| 4103 | 3921 | |
| 4104 | - // Use direct name field like the other working API keys | |
| 3922 | + // Render the input field for the Claude API key | |
| 4105 | 3923 | echo '<div class="' . esc_attr($class) . '">'; |
| 4106 | 3924 | printf( |
| 4107 | 3925 | '<input type="password" id="claude_api_key" name="claude_api_key" value="%s" class="regular-text" %s />', |
| 4108 | 3926 | $claudeApiKey, |
| @@ -4109,13 +3927,15 @@ | ||
| 4109 | 3927 | $disabled |
| 4110 | 3928 | ); |
| 4111 | 3929 | echo '<button type="button" id="toggleClaudeApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; |
| 4112 | 3930 | |
| 3931 | + // If the feature is not activated, show the overlay with a "Pro Only" message | |
| 4113 | 3932 | if (!$this->is_activated) { |
| 4114 | 3933 | echo '<div class="pro-feature-overlay">'; |
| 4115 | 3934 | echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="' . esc_attr__('Pro Only', 'mxchat') . '" /></a>'; |
| 4116 | 3935 | echo '</div>'; |
| 4117 | 3936 | } |
| 3937 | + | |
| 4118 | 3938 | echo '</div>'; |
| 4119 | 3939 | } |
| 4120 | 3940 | public function deepseek_api_key_callback() { |
| 4121 | 3941 | // Retrieve from your stored 'deepseek_api_key' in the mxchat_options array |
| @@ -4126,11 +3946,79 @@ | ||
| 4126 | 3946 | echo '<button type="button" id="toggleDeepSeekApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; |
| 4127 | 3947 | } |
| 4128 | 3948 | |
| 4129 | 3949 | |
| 3950 | +public function mxchat_woocommerce_consumer_key_callback() { | |
| 3951 | + // Load the entire 'mxchat_options' array | |
| 3952 | + $all_options = get_option('mxchat_options', []); | |
| 4130 | 3953 | |
| 3954 | + // Retrieve the WooCommerce consumer key or set a default | |
| 3955 | + $consumer_key = isset($all_options['woocommerce_consumer_key']) ? $all_options['woocommerce_consumer_key'] : ''; | |
| 4131 | 3956 | |
| 3957 | + // Check if the feature is activated (paid feature) | |
| 3958 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 3959 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4132 | 3960 | |
| 3961 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 3962 | + | |
| 3963 | + // Render the input field | |
| 3964 | + printf( | |
| 3965 | + '<input type="text" id="woocommerce_consumer_key" name="woocommerce_consumer_key" value="%s" class="regular-text" %s />', | |
| 3966 | + esc_attr($consumer_key), | |
| 3967 | + esc_attr($disabled) | |
| 3968 | + ); | |
| 3969 | + | |
| 3970 | + // Description for the input field | |
| 3971 | + echo '<p class="description">' . esc_html__('Enter your WooCommerce consumer key for integration.', 'mxchat') . '</p>'; | |
| 3972 | + | |
| 3973 | + // Pro feature overlay for non-activated users | |
| 3974 | + if (!$this->is_activated) { | |
| 3975 | + echo '<div class="pro-feature-overlay">'; | |
| 3976 | + echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="' . esc_attr__('Pro Only', 'mxchat') . '" /></a>'; | |
| 3977 | + echo '</div>'; | |
| 3978 | + } | |
| 3979 | + | |
| 3980 | + echo '</div>'; | |
| 3981 | +} | |
| 3982 | + | |
| 3983 | +public function mxchat_woocommerce_consumer_secret_callback() { | |
| 3984 | + // Get value with fallback | |
| 3985 | + $consumer_secret = isset($this->options['woocommerce_consumer_secret']) | |
| 3986 | + ? esc_attr($this->options['woocommerce_consumer_secret']) | |
| 3987 | + : ''; | |
| 3988 | + | |
| 3989 | + // Check if the feature is activated (paid feature) | |
| 3990 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 3991 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 3992 | + | |
| 3993 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 3994 | + | |
| 3995 | + // Output the password input | |
| 3996 | + echo sprintf( | |
| 3997 | + '<input type="password" | |
| 3998 | + id="woocommerce_consumer_secret" | |
| 3999 | + name="woocommerce_consumer_secret" | |
| 4000 | + value="%s" | |
| 4001 | + class="regular-text" | |
| 4002 | + %s />', | |
| 4003 | + $consumer_secret, | |
| 4004 | + esc_attr($disabled) | |
| 4005 | + ); | |
| 4006 | + | |
| 4007 | + // Add show/hide button | |
| 4008 | + echo '<button type="button" id="toggleWooCommerceSecretVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; | |
| 4009 | + | |
| 4010 | + // Pro feature overlay | |
| 4011 | + if (!$this->is_activated) { | |
| 4012 | + echo '<div class="pro-feature-overlay">'; | |
| 4013 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 4014 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 4015 | + echo '</a>'; | |
| 4016 | + echo '</div>'; | |
| 4017 | + } | |
| 4018 | + | |
| 4019 | + echo '</div>'; | |
| 4020 | +} | |
| 4133 | 4021 | public function mxchat_loops_api_key_callback() { |
| 4134 | 4022 | // Support both old and new format |
| 4135 | 4023 | $loops_api_key = isset($this->options['loops_api_key']) ? esc_attr($this->options['loops_api_key']) : ''; |
| 4136 | 4024 | |
| @@ -4291,46 +4179,13 @@ | ||
| 4291 | 4179 | // Close the select dropdown |
| 4292 | 4180 | echo '</select>'; |
| 4293 | 4181 | |
| 4294 | 4182 | // Add a description below the dropdown |
| 4295 | - echo '<p class="description">' . esc_html__('Select the AI model your chatbot will use for chatting. Pro-only models are marked accordingly.', 'mxchat') . '</p>'; | |
| 4183 | + echo '<p class="description">' . esc_html__('Select the AI model to use for your chatbot. Pro-only models are marked accordingly.', 'mxchat') . '</p>'; | |
| 4296 | 4184 | } |
| 4297 | 4185 | |
| 4298 | -public function voyage_api_key_callback() { | |
| 4299 | - $apiKey = isset($this->options['voyage_api_key']) ? esc_attr($this->options['voyage_api_key']) : ''; | |
| 4300 | - echo '<input type="password" id="voyage_api_key" name="voyage_api_key" value="' . $apiKey . '" class="regular-text" />'; | |
| 4301 | - echo '<button type="button" id="toggleVoyageAPIKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; | |
| 4302 | -} | |
| 4303 | 4186 | |
| 4304 | -// Callback function for embedding model selection | |
| 4305 | -public function embedding_model_callback() { | |
| 4306 | - $models = array( | |
| 4307 | - esc_html__('OpenAI Embeddings', 'mxchat') => array( | |
| 4308 | - 'text-embedding-3-small' => esc_html__('TE3 Small (1536, Efficient)', 'mxchat'), | |
| 4309 | - 'text-embedding-ada-002' => esc_html__('Ada 2 (1536, Original)', 'mxchat'), | |
| 4310 | - 'text-embedding-3-large' => esc_html__('TE3 Large (3072, Powerful)', 'mxchat'), | |
| 4311 | - ), | |
| 4312 | - esc_html__('Voyage AI Embeddings', 'mxchat') => array( | |
| 4313 | - 'voyage-3-large' => esc_html__('Voyage-3 Large (2048, Most Capable)', 'mxchat'), | |
| 4314 | - ) | |
| 4315 | - ); | |
| 4316 | 4187 | |
| 4317 | - $selected_model = isset($this->options['embedding_model']) ? esc_attr($this->options['embedding_model']) : 'text-embedding-ada-002'; | |
| 4318 | - | |
| 4319 | - echo '<select id="embedding_model" name="embedding_model">'; | |
| 4320 | - foreach ($models as $group_label => $group_models) { | |
| 4321 | - echo '<optgroup label="' . esc_attr($group_label) . '">'; | |
| 4322 | - foreach ($group_models as $model_value => $model_label) { | |
| 4323 | - echo '<option value="' . esc_attr($model_value) . '" ' . selected($selected_model, $model_value, false) . '>' . esc_html($model_label) . '</option>'; | |
| 4324 | - } | |
| 4325 | - echo '</optgroup>'; | |
| 4326 | - } | |
| 4327 | - echo '</select>'; | |
| 4328 | -echo '<p class="description"><span class="red-warning">IMPORTANT:</span> Select the model for vector embeddings. Changing models is not recommended; if you do, you must delete all existing knowledge & intent data and reconfigure them.</p>'; | |
| 4329 | - | |
| 4330 | -} | |
| 4331 | - | |
| 4332 | - | |
| 4333 | 4188 | public function mxchat_top_bar_title_callback() { |
| 4334 | 4189 | // Retrieve the current value of the top bar title from saved options |
| 4335 | 4190 | $top_bar_title = isset($this->options['top_bar_title']) ? esc_attr($this->options['top_bar_title']) : ''; |
| 4336 | 4191 | |
| @@ -4443,8 +4298,91 @@ | ||
| 4443 | 4298 | } |
| 4444 | 4299 | |
| 4445 | 4300 | |
| 4446 | 4301 | |
| 4302 | + | |
| 4303 | + | |
| 4304 | +public function mxchat_close_button_color_callback() { | |
| 4305 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4306 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4307 | + | |
| 4308 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 4309 | + echo sprintf( | |
| 4310 | + '<input type="text" | |
| 4311 | + id="close_button_color" | |
| 4312 | + name="close_button_color" | |
| 4313 | + value="%s" | |
| 4314 | + class="my-color-field" | |
| 4315 | + data-default-color="#4a4a4a" | |
| 4316 | + %s />', | |
| 4317 | + isset($this->options['close_button_color']) ? esc_attr($this->options['close_button_color']) : '#4a4a4a', | |
| 4318 | + esc_attr($disabled) | |
| 4319 | + ); | |
| 4320 | + | |
| 4321 | + if (!$this->is_activated) { | |
| 4322 | + echo '<div class="pro-feature-overlay">'; | |
| 4323 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 4324 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 4325 | + echo '</a>'; | |
| 4326 | + echo '</div>'; | |
| 4327 | + } | |
| 4328 | + echo '</div>'; | |
| 4329 | +} | |
| 4330 | + | |
| 4331 | +public function mxchat_chatbot_bg_color_callback() { | |
| 4332 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4333 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4334 | + | |
| 4335 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 4336 | + echo sprintf( | |
| 4337 | + '<input type="text" | |
| 4338 | + id="chatbot_bg_color" | |
| 4339 | + name="chatbot_bg_color" | |
| 4340 | + value="%s" | |
| 4341 | + class="my-color-field" | |
| 4342 | + data-default-color="#f9f9f9" | |
| 4343 | + %s />', | |
| 4344 | + isset($this->options['chatbot_bg_color']) ? esc_attr($this->options['chatbot_bg_color']) : '#f9f9f9', | |
| 4345 | + esc_attr($disabled) | |
| 4346 | + ); | |
| 4347 | + | |
| 4348 | + if (!$this->is_activated) { | |
| 4349 | + echo '<div class="pro-feature-overlay">'; | |
| 4350 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 4351 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 4352 | + echo '</a>'; | |
| 4353 | + echo '</div>'; | |
| 4354 | + } | |
| 4355 | + echo '</div>'; | |
| 4356 | +} | |
| 4357 | + | |
| 4358 | +public function mxchat_user_message_bg_color_callback() { | |
| 4359 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4360 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4361 | + | |
| 4362 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 4363 | + echo sprintf( | |
| 4364 | + '<input type="text" | |
| 4365 | + id="user_message_bg_color" | |
| 4366 | + name="user_message_bg_color" | |
| 4367 | + value="%s" | |
| 4368 | + class="my-color-field" | |
| 4369 | + data-default-color="#0078d7" | |
| 4370 | + %s />', | |
| 4371 | + isset($this->options['user_message_bg_color']) ? esc_attr($this->options['user_message_bg_color']) : '#0078d7', | |
| 4372 | + esc_attr($disabled) | |
| 4373 | + ); | |
| 4374 | + | |
| 4375 | + if (!$this->is_activated) { | |
| 4376 | + echo '<div class="pro-feature-overlay">'; | |
| 4377 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 4378 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 4379 | + echo '</a>'; | |
| 4380 | + echo '</div>'; | |
| 4381 | + } | |
| 4382 | + echo '</div>'; | |
| 4383 | +} | |
| 4384 | + | |
| 4447 | 4385 | public function mxchat_user_message_font_color_callback() { |
| 4448 | 4386 | $disabled = $this->is_activated ? '' : 'disabled'; |
| 4449 | 4387 | $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4450 | 4388 | |
| @@ -4931,20 +4869,39 @@ | ||
| 4931 | 4869 | // Get complianz toggle value with fallback |
| 4932 | 4870 | $complianz_toggle = isset($options['complianz_toggle']) ? $options['complianz_toggle'] : 'off'; |
| 4933 | 4871 | $checked = ($complianz_toggle === 'on') ? 'checked' : ''; |
| 4934 | 4872 | |
| 4873 | + // Check if the plugin is activated (paid feature) | |
| 4874 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4875 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4876 | + | |
| 4877 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 4878 | + | |
| 4935 | 4879 | // Output the toggle switch |
| 4936 | 4880 | echo '<label class="toggle-switch">'; |
| 4937 | 4881 | echo sprintf( |
| 4938 | - '<input type="checkbox" id="complianz_toggle" name="complianz_toggle" value="on" %s />', | |
| 4939 | - esc_attr($checked) | |
| 4882 | + '<input type="checkbox" id="complianz_toggle" name="complianz_toggle" value="on" %s %s />', | |
| 4883 | + esc_attr($checked), | |
| 4884 | + esc_attr($disabled) | |
| 4940 | 4885 | ); |
| 4941 | 4886 | echo '<span class="slider"></span>'; |
| 4942 | 4887 | echo '</label>'; |
| 4943 | 4888 | |
| 4944 | 4889 | echo '<p class="description">' . esc_html__('Enable this option to apply Complianz consent logic to the chatbot (must have Complianz Plugin).', 'mxchat') . '</p>'; |
| 4890 | + | |
| 4891 | + // If the feature is not activated, show the Pro feature overlay | |
| 4892 | + if (!$this->is_activated) { | |
| 4893 | + echo '<div class="pro-feature-overlay">'; | |
| 4894 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 4895 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 4896 | + echo '</a>'; | |
| 4897 | + echo '</div>'; | |
| 4898 | + } | |
| 4899 | + | |
| 4900 | + echo '</div>'; | |
| 4945 | 4901 | } |
| 4946 | 4902 | |
| 4903 | + | |
| 4947 | 4904 | public function mxchat_link_target_toggle_callback() { |
| 4948 | 4905 | // Load from mxchat_options array |
| 4949 | 4906 | $options = get_option('mxchat_options', []); |
| 4950 | 4907 | |
| @@ -4970,20 +4927,39 @@ | ||
| 4970 | 4927 | // Get chat persistence toggle value with fallback |
| 4971 | 4928 | $chat_persistence_toggle = isset($options['chat_persistence_toggle']) ? $options['chat_persistence_toggle'] : 'off'; |
| 4972 | 4929 | $checked = ($chat_persistence_toggle === 'on') ? 'checked' : ''; |
| 4973 | 4930 | |
| 4931 | + // Check if the plugin is activated (paid feature) | |
| 4932 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4933 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4934 | + | |
| 4935 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 4936 | + | |
| 4974 | 4937 | // Output the toggle switch |
| 4975 | 4938 | echo '<label class="toggle-switch">'; |
| 4976 | 4939 | echo sprintf( |
| 4977 | - '<input type="checkbox" id="chat_persistence_toggle" name="chat_persistence_toggle" value="on" %s />', | |
| 4978 | - esc_attr($checked) | |
| 4940 | + '<input type="checkbox" id="chat_persistence_toggle" name="chat_persistence_toggle" value="on" %s %s />', | |
| 4941 | + esc_attr($checked), | |
| 4942 | + esc_attr($disabled) | |
| 4979 | 4943 | ); |
| 4980 | 4944 | echo '<span class="slider"></span>'; |
| 4981 | 4945 | echo '</label>'; |
| 4982 | 4946 | |
| 4983 | 4947 | echo '<p class="description">' . esc_html__('Enable to keep chat history when users navigate tabs or return to the site within 24 hours.', 'mxchat') . '</p>'; |
| 4948 | + | |
| 4949 | + // If not activated, show Pro feature overlay | |
| 4950 | + if (!$this->is_activated) { | |
| 4951 | + echo '<div class="pro-feature-overlay">'; | |
| 4952 | + echo '<a href="https://mxchat.ai/" target="_blank">'; | |
| 4953 | + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />'; | |
| 4954 | + echo '</a>'; | |
| 4955 | + echo '</div>'; | |
| 4956 | + } | |
| 4957 | + | |
| 4958 | + echo '</div>'; | |
| 4984 | 4959 | } |
| 4985 | 4960 | |
| 4961 | + | |
| 4986 | 4962 | public function mxchat_popular_question_1_callback() { |
| 4987 | 4963 | // Load the full plugin options array |
| 4988 | 4964 | $all_options = get_option('mxchat_options', []); |
| 4989 | 4965 | |
| @@ -4993,13 +4969,13 @@ | ||
| 4993 | 4969 | // Render the input field |
| 4994 | 4970 | printf( |
| 4995 | 4971 | '<input type="text" id="popular_question_1" name="popular_question_1" value="%s" placeholder="%s" class="regular-text" />', |
| 4996 | 4972 | esc_attr($popular_question_1), |
| 4997 | - esc_attr__('Enter Quick Question 1', 'mxchat') | |
| 4973 | + esc_attr__('Enter Popular Question 1', 'mxchat') | |
| 4998 | 4974 | ); |
| 4999 | 4975 | |
| 5000 | 4976 | // Add a description for the field |
| 5001 | - echo '<p class="description">' . esc_html__('This will be the first Quick Question in the chatbot, displayed above the input field.', 'mxchat') . '</p>'; | |
| 4977 | + echo '<p class="description">' . esc_html__('This will be the first popular question in the chatbot.', 'mxchat') . '</p>'; | |
| 5002 | 4978 | } |
| 5003 | 4979 | |
| 5004 | 4980 | |
| 5005 | 4981 | public function mxchat_popular_question_2_callback() { |
| @@ -5008,38 +4984,72 @@ | ||
| 5008 | 4984 | |
| 5009 | 4985 | // Retrieve the specific option for popular_question_2 |
| 5010 | 4986 | $popular_question_2 = isset($all_options['popular_question_2']) ? $all_options['popular_question_2'] : ''; |
| 5011 | 4987 | |
| 4988 | + // Check if the plugin is activated (paid feature) | |
| 4989 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 4990 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 4991 | + | |
| 4992 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 4993 | + | |
| 5012 | 4994 | // Render the input field |
| 5013 | 4995 | printf( |
| 5014 | - '<input type="text" id="popular_question_2" name="popular_question_2" value="%s" placeholder="%s" class="regular-text" />', | |
| 4996 | + '<input type="text" id="popular_question_2" name="popular_question_2" value="%s" placeholder="%s" class="regular-text" %s />', | |
| 5015 | 4997 | esc_attr($popular_question_2), |
| 5016 | - esc_attr__('Enter Quick Question 2', 'mxchat') | |
| 4998 | + esc_attr__('Enter Popular Question 2', 'mxchat'), | |
| 4999 | + esc_attr($disabled) | |
| 5017 | 5000 | ); |
| 5018 | 5001 | |
| 5019 | 5002 | // Add a description for the field |
| 5020 | - echo '<p class="description">' . esc_html__('This will be the second Quick Question in the chatbot.', 'mxchat') . '</p>'; | |
| 5003 | + echo '<p class="description">' . esc_html__('This will be the second popular question in the chatbot.', 'mxchat') . '</p>'; | |
| 5004 | + | |
| 5005 | + // If not activated, show Pro feature overlay | |
| 5006 | + if (!$this->is_activated) { | |
| 5007 | + echo '<div class="pro-feature-overlay">'; | |
| 5008 | + echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="' . esc_attr__('Pro Only', 'mxchat') . '" /></a>'; | |
| 5009 | + echo '</div>'; | |
| 5010 | + } | |
| 5011 | + | |
| 5012 | + echo '</div>'; | |
| 5021 | 5013 | } |
| 5022 | 5014 | |
| 5023 | 5015 | |
| 5016 | + | |
| 5024 | 5017 | public function mxchat_popular_question_3_callback() { |
| 5025 | - // Load the full plugin options array | |
| 5026 | - $all_options = get_option('mxchat_options', []); | |
| 5018 | + // Load the full plugin options array | |
| 5019 | + $all_options = get_option('mxchat_options', []); | |
| 5027 | 5020 | |
| 5028 | - // Retrieve the specific option for popular_question_3 | |
| 5029 | - $popular_question_3 = isset($all_options['popular_question_3']) ? $all_options['popular_question_3'] : ''; | |
| 5021 | + // Retrieve the specific option for popular_question_3 | |
| 5022 | + $popular_question_3 = isset($all_options['popular_question_3']) ? $all_options['popular_question_3'] : ''; | |
| 5030 | 5023 | |
| 5031 | - // Render the input field | |
| 5032 | - printf( | |
| 5033 | - '<input type="text" id="popular_question_3" name="popular_question_3" value="%s" placeholder="%s" class="regular-text" />', | |
| 5034 | - esc_attr($popular_question_3), | |
| 5035 | - esc_attr(__('Enter Quick Question 3', 'mxchat')) | |
| 5036 | - ); | |
| 5024 | + // Check if the plugin is activated (paid feature) | |
| 5025 | + $disabled = $this->is_activated ? '' : 'disabled'; | |
| 5026 | + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; | |
| 5037 | 5027 | |
| 5038 | - // Add a description for the field | |
| 5039 | - echo '<p class="description">' . esc_html__('This will be the third Quick Question in the chatbot.', 'mxchat') . '</p>'; | |
| 5028 | + echo '<div class="' . esc_attr($class) . '">'; | |
| 5029 | + | |
| 5030 | + // Render the input field | |
| 5031 | + printf( | |
| 5032 | + '<input type="text" id="popular_question_3" name="popular_question_3" value="%s" placeholder="%s" class="regular-text" %s />', | |
| 5033 | + esc_attr($popular_question_3), | |
| 5034 | + esc_attr(__('Enter Popular Question 3', 'mxchat')), | |
| 5035 | + esc_attr($disabled) | |
| 5036 | + ); | |
| 5037 | + | |
| 5038 | + // Add a description for the field | |
| 5039 | + echo '<p class="description">' . esc_html__('This will be the third popular question in the chatbot.', 'mxchat') . '</p>'; | |
| 5040 | + | |
| 5041 | + // If not activated, show Pro feature overlay | |
| 5042 | + if (!$this->is_activated) { | |
| 5043 | + echo '<div class="pro-feature-overlay">'; | |
| 5044 | + echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="' . esc_attr__('Pro Only', 'mxchat') . '" /></a>'; | |
| 5045 | + echo '</div>'; | |
| 5046 | + } | |
| 5047 | + | |
| 5048 | + echo '</div>'; | |
| 5040 | 5049 | } |
| 5041 | 5050 | |
| 5051 | + | |
| 5042 | 5052 | public function mxchat_additional_popular_questions_callback() { |
| 5043 | 5053 | $options = get_option('mxchat_options', []); |
| 5044 | 5054 | $additional_questions = isset($options['additional_popular_questions']) |
| 5045 | 5055 | ? $options['additional_popular_questions'] |
| @@ -5058,9 +5068,9 @@ | ||
| 5058 | 5068 | <button type="button" class="button mxchat-remove-question" |
| 5059 | 5069 | aria-label="%s">%s</button> |
| 5060 | 5070 | </div>', |
| 5061 | 5071 | esc_attr($question), |
| 5062 | - esc_attr(sprintf(__('Enter Additional Quick Question %d', 'mxchat'), $index + 4)), | |
| 5072 | + esc_attr(sprintf(__('Enter Additional Popular Question %d', 'mxchat'), $index + 4)), | |
| 5063 | 5073 | $index, |
| 5064 | 5074 | esc_attr(__('Remove question', 'mxchat')), |
| 5065 | 5075 | esc_html__('Remove', 'mxchat') |
| 5066 | 5076 | ); |
| @@ -5075,9 +5085,9 @@ | ||
| 5075 | 5085 | data-question-index="0" /> |
| 5076 | 5086 | <button type="button" class="button mxchat-remove-question" |
| 5077 | 5087 | aria-label="%s">%s</button> |
| 5078 | 5088 | </div>', |
| 5079 | - esc_attr(__('Enter Additional Quick Question 4', 'mxchat')), | |
| 5089 | + esc_attr(__('Enter Additional Popular Question 4', 'mxchat')), | |
| 5080 | 5090 | esc_attr(__('Remove question', 'mxchat')), |
| 5081 | 5091 | esc_html__('Remove', 'mxchat') |
| 5082 | 5092 | ); |
| 5083 | 5093 | } |
| @@ -5086,9 +5096,9 @@ | ||
| 5086 | 5096 | '<button type="button" class="button mxchat-add-question" aria-label="%s">%s</button>', |
| 5087 | 5097 | esc_attr(__('Add question', 'mxchat')), |
| 5088 | 5098 | esc_html__('Add Question', 'mxchat') |
| 5089 | 5099 | ); |
| 5090 | - echo '<p class="description">' . esc_html__('Add as many Quick Questions as you need.', 'mxchat') . '</p>'; | |
| 5100 | + echo '<p class="description">' . esc_html__('Add as many popular questions as you need.', 'mxchat') . '</p>'; | |
| 5091 | 5101 | echo '</div>'; |
| 5092 | 5102 | } |
| 5093 | 5103 | |
| 5094 | 5104 | public function mxchat_brave_api_key_callback() { |
| @@ -5524,9 +5534,9 @@ | ||
| 5524 | 5534 | public function mxchat_enqueue_admin_assets() { |
| 5525 | 5535 | wp_enqueue_style('wp-color-picker'); |
| 5526 | 5536 | |
| 5527 | 5537 | // Get the plugin version or file modification time for cache busting |
| 5528 | - $plugin_version = '2.0.6'; // Replace this with your plugin's version | |
| 5538 | + $plugin_version = '2.0.0'; // Replace this with your plugin's version | |
| 5529 | 5539 | |
| 5530 | 5540 | // File paths |
| 5531 | 5541 | $color_picker_js_path = plugin_dir_path(__FILE__) . '../js/my-color-picker.js'; |
| 5532 | 5542 | $embedding_check_js_path = plugin_dir_path(__FILE__) . '../js/embedding-check.js'; |
| @@ -5532,12 +5542,10 @@ | ||
| 5532 | 5542 | $embedding_check_js_path = plugin_dir_path(__FILE__) . '../js/embedding-check.js'; |
| 5533 | 5543 | $admin_css_path = plugin_dir_path(__FILE__) . '../css/admin-style.css'; |
| 5534 | 5544 | $knowledge_css_path = plugin_dir_path(__FILE__) . '../css/knowledge-style.css'; |
| 5535 | 5545 | $intent_css_path = plugin_dir_path(__FILE__) . '../css/intent-style.css'; |
| 5536 | - $transcripts_css_path = plugin_dir_path(__FILE__) . '../css/chat-transcripts.css'; | |
| 5537 | 5546 | $transcripts_js_path = plugin_dir_path(__FILE__) . '../js/mxchat_transcripts.js'; |
| 5538 | 5547 | |
| 5539 | - | |
| 5540 | 5548 | // Check if files exist and get modification times |
| 5541 | 5549 | $color_picker_version = file_exists($color_picker_js_path) ? filemtime($color_picker_js_path) : $plugin_version; |
| 5542 | 5550 | $embedding_check_version = file_exists($embedding_check_js_path) ? filemtime($embedding_check_js_path) : $plugin_version; |
| 5543 | 5551 | $admin_css_version = file_exists($admin_css_path) ? filemtime($admin_css_path) : $plugin_version; |
| @@ -5542,12 +5550,10 @@ | ||
| 5542 | 5550 | $embedding_check_version = file_exists($embedding_check_js_path) ? filemtime($embedding_check_js_path) : $plugin_version; |
| 5543 | 5551 | $admin_css_version = file_exists($admin_css_path) ? filemtime($admin_css_path) : $plugin_version; |
| 5544 | 5552 | $knowledge_css_version = file_exists($knowledge_css_path) ? filemtime($knowledge_css_path) : $plugin_version; |
| 5545 | 5553 | $intent_css_version = file_exists($intent_css_path) ? filemtime($intent_css_path) : $plugin_version; |
| 5546 | - $transcripts_css_version = file_exists($transcripts_css_path) ? filemtime($transcripts_css_path) : $plugin_version; | |
| 5547 | 5554 | $transcripts_js_version = file_exists($transcripts_js_path) ? filemtime($transcripts_js_path) : $plugin_version; |
| 5548 | 5555 | |
| 5549 | - | |
| 5550 | 5556 | // Enqueue scripts and styles with corrected paths |
| 5551 | 5557 | wp_enqueue_script( |
| 5552 | 5558 | 'mxchat-color-picker', |
| 5553 | 5559 | plugin_dir_url(__FILE__) . '../js/my-color-picker.js', |
| @@ -5564,8 +5570,16 @@ | ||
| 5564 | 5570 | true |
| 5565 | 5571 | ); |
| 5566 | 5572 | |
| 5567 | 5573 | wp_enqueue_script( |
| 5574 | + 'mxchat-transcripts-js', | |
| 5575 | + plugin_dir_url(__FILE__) . '../js/mxchat_transcripts.js', | |
| 5576 | + array('jquery'), | |
| 5577 | + $transcripts_js_version, | |
| 5578 | + true | |
| 5579 | + ); | |
| 5580 | + | |
| 5581 | + wp_enqueue_script( | |
| 5568 | 5582 | 'mxchat-admin-js', |
| 5569 | 5583 | plugin_dir_url(__FILE__) . '../js/mxchat-admin.js', |
| 5570 | 5584 | array('jquery'), |
| 5571 | 5585 | $plugin_version, |
| @@ -5576,11 +5590,10 @@ | ||
| 5576 | 5590 | 'ajax_url' => admin_url('admin-ajax.php'), |
| 5577 | 5591 | 'license_nonce' => wp_create_nonce('mxchat_activate_license_nonce'), |
| 5578 | 5592 | 'inline_edit_nonce' => wp_create_nonce('mxchat_save_inline_nonce'), |
| 5579 | 5593 | 'setting_nonce' => wp_create_nonce('mxchat_save_setting_nonce'), |
| 5580 | - 'export_nonce' => wp_create_nonce('mxchat_export_transcripts'), | |
| 5581 | 5594 | )); |
| 5582 | - | |
| 5595 | + | |
| 5583 | 5596 | // Enqueue the admin CSS |
| 5584 | 5597 | wp_enqueue_style( |
| 5585 | 5598 | 'mxchat-admin-css', |
| 5586 | 5599 | plugin_dir_url(__FILE__) . '../css/admin-style.css', |
| @@ -5586,26 +5599,9 @@ | ||
| 5586 | 5599 | plugin_dir_url(__FILE__) . '../css/admin-style.css', |
| 5587 | 5600 | array(), |
| 5588 | 5601 | $admin_css_version |
| 5589 | 5602 | ); |
| 5590 | - | |
| 5591 | - if (isset($_GET['page']) && $_GET['page'] === 'mxchat-transcripts') { | |
| 5592 | - wp_enqueue_style( | |
| 5593 | - 'mxchat-chat-transcripts-css', | |
| 5594 | - plugin_dir_url(__FILE__) . '../css/chat-transcripts.css', | |
| 5595 | - array(), | |
| 5596 | - $transcripts_css_version | |
| 5597 | - ); | |
| 5598 | - | |
| 5599 | - wp_enqueue_script( | |
| 5600 | - 'mxchat-transcripts-js', | |
| 5601 | - plugin_dir_url(__FILE__) . '../js/mxchat_transcripts.js', | |
| 5602 | - array('jquery'), | |
| 5603 | - $transcripts_js_version, | |
| 5604 | - true | |
| 5605 | - ); | |
| 5606 | - } | |
| 5607 | - | |
| 5603 | + | |
| 5608 | 5604 | wp_enqueue_style( |
| 5609 | 5605 | 'mxchat-knowledge-css', |
| 5610 | 5606 | plugin_dir_url(__FILE__) . '../css/knowledge-style.css', |
| 5611 | 5607 | array(), |
| @@ -5610,10 +5606,10 @@ | ||
| 5610 | 5606 | plugin_dir_url(__FILE__) . '../css/knowledge-style.css', |
| 5611 | 5607 | array(), |
| 5612 | 5608 | $knowledge_css_version |
| 5613 | 5609 | ); |
| 5614 | - | |
| 5615 | - | |
| 5610 | + | |
| 5611 | + | |
| 5616 | 5612 | wp_enqueue_style( |
| 5617 | 5613 | 'mxchat-intent-css', |
| 5618 | 5614 | plugin_dir_url(__FILE__) . '../css/intent-style.css', |
| 5619 | 5615 | array(), |
| @@ -5618,9 +5614,9 @@ | ||
| 5618 | 5614 | plugin_dir_url(__FILE__) . '../css/intent-style.css', |
| 5619 | 5615 | array(), |
| 5620 | 5616 | $intent_css_version |
| 5621 | 5617 | ); |
| 5622 | - | |
| 5618 | + | |
| 5623 | 5619 | // IMPORTANT: Use the same script handle as above for localizing mxchatPromptsAdmin |
| 5624 | 5620 | wp_localize_script( 'mxchat-admin-js', 'mxchatPromptsAdmin', array( |
| 5625 | 5621 | 'ajax_url' => admin_url( 'admin-ajax.php' ), |
| 5626 | 5622 | 'prompts_setting_nonce' => wp_create_nonce( 'mxchat_prompts_setting_nonce' ), |
| @@ -5778,25 +5774,8 @@ | ||
| 5778 | 5774 | if (isset($input['pre_chat_message'])) { |
| 5779 | 5775 | $new_input['pre_chat_message'] = sanitize_textarea_field($input['pre_chat_message']); |
| 5780 | 5776 | } |
| 5781 | 5777 | |
| 5782 | - if (isset($input['voyage_api_key'])) { | |
| 5783 | - $new_input['voyage_api_key'] = sanitize_text_field($input['voyage_api_key']); | |
| 5784 | - } | |
| 5785 | - | |
| 5786 | - // Add to your sanitize function | |
| 5787 | - if (isset($input['embedding_model'])) { | |
| 5788 | - $allowed_models = array( | |
| 5789 | - 'text-embedding-ada-002', | |
| 5790 | - 'text-embedding-3-small', | |
| 5791 | - 'text-embedding-3-large', | |
| 5792 | - 'voyage-3-large' | |
| 5793 | - ); | |
| 5794 | - if (in_array($input['embedding_model'], $allowed_models)) { | |
| 5795 | - $new_input['embedding_model'] = sanitize_text_field($input['embedding_model']); | |
| 5796 | - } | |
| 5797 | - } | |
| 5798 | - | |
| 5799 | 5778 | if (isset($input['model'])) { |
| 5800 | 5779 | $allowed_models = array( |
| 5801 | 5780 | 'grok-beta', |
| 5802 | 5781 | 'grok-2', |
| @@ -5815,8 +5794,9 @@ | ||
| 5815 | 5794 | $new_input['model'] = sanitize_text_field($input['model']); |
| 5816 | 5795 | } |
| 5817 | 5796 | } |
| 5818 | 5797 | |
| 5798 | + // Sanitize new pro features | |
| 5819 | 5799 | if (isset($input['close_button_color'])) { |
| 5820 | 5800 | $new_input['close_button_color'] = sanitize_hex_color($input['close_button_color']); |
| 5821 | 5801 | } |
| 5822 | 5802 | |
| @@ -6028,9 +6008,9 @@ | ||
| 6028 | 6008 | |
| 6029 | 6009 | |
| 6030 | 6010 | private static function mxchat_extract_main_content($html) { |
| 6031 | 6011 | if (empty($html)) { |
| 6032 | - //error_log('mxchat_extract_main_content: Empty HTML content received'); | |
| 6012 | + error_log('mxchat_extract_main_content: Empty HTML content received'); | |
| 6033 | 6013 | return ''; |
| 6034 | 6014 | } |
| 6035 | 6015 | |
| 6036 | 6016 | try { |
| @@ -6035,14 +6015,14 @@ | ||
| 6035 | 6015 | |
| 6036 | 6016 | try { |
| 6037 | 6017 | $dom = new DOMDocument; |
| 6038 | 6018 | libxml_use_internal_errors(true); // Suppress HTML parsing errors |
| 6039 | - | |
| 6019 | + | |
| 6040 | 6020 | // Simple load of HTML, with @ to suppress warnings |
| 6041 | 6021 | @$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); |
| 6042 | - | |
| 6022 | + | |
| 6043 | 6023 | $xpath = new DOMXPath($dom); |
| 6044 | - | |
| 6024 | + | |
| 6045 | 6025 | // Simplified selectors focusing on common content areas |
| 6046 | 6026 | $selectors = [ |
| 6047 | 6027 | '//article', |
| 6048 | 6028 | '//*[@id="content"]', |
| @@ -6048,9 +6028,9 @@ | ||
| 6048 | 6028 | '//*[@id="content"]', |
| 6049 | 6029 | '//*[@class="entry-content"]', |
| 6050 | 6030 | '//main' |
| 6051 | 6031 | ]; |
| 6052 | - | |
| 6032 | + | |
| 6053 | 6033 | foreach ($selectors as $selector) { |
| 6054 | 6034 | $nodes = $xpath->query($selector); |
| 6055 | 6035 | if ($nodes && $nodes->length > 0) { |
| 6056 | 6036 | $content = ''; |
| @@ -6061,20 +6041,20 @@ | ||
| 6061 | 6041 | return $content; |
| 6062 | 6042 | } |
| 6063 | 6043 | } |
| 6064 | 6044 | } |
| 6065 | - | |
| 6045 | + | |
| 6066 | 6046 | // Fallback: Return the entire body content if no specific selector matches |
| 6067 | 6047 | $body = $dom->getElementsByTagName('body'); |
| 6068 | 6048 | if ($body->length > 0) { |
| 6069 | 6049 | return $dom->saveHTML($body->item(0)); |
| 6070 | 6050 | } |
| 6071 | - | |
| 6051 | + | |
| 6072 | 6052 | // Last resort: return the original HTML |
| 6073 | 6053 | return $html; |
| 6074 | - | |
| 6054 | + | |
| 6075 | 6055 | } catch (Exception $e) { |
| 6076 | - //error_log('mxchat_extract_main_content error: ' . $e->getMessage()); | |
| 6056 | + error_log('mxchat_extract_main_content error: ' . $e->getMessage()); | |
| 6077 | 6057 | return $html; // Return original HTML if parsing fails |
| 6078 | 6058 | } finally { |
| 6079 | 6059 | libxml_clear_errors(); |
| 6080 | 6060 | } |