get_contents( $logo_path ); if ( $svg_content !== false ) { // Return the raw SVG content directly return 'data:image/svg+xml;base64,' . base64_encode( $svg_content ); } } // Fallback - simple OHM-inspired icon if logo files are not available if ( $is_dark_theme ) { // Light icon for dark themes $svg = ' '; } else { // Dark icon for light themes $svg = ' '; } return 'data:image/svg+xml;base64,' . base64_encode( $svg ); } /** * Optimize the full OHM logo for use as a 20x20 menu icon * * @param string $svg_content Original SVG content * @param bool $is_dark_theme Whether we're using dark theme * @return string Optimized SVG */ private function optimize_logo_for_menu( $svg_content, $is_dark_theme ) { // Create a simplified version of the actual OHM mandala logo for the menu $fill_color = $is_dark_theme ? 'rgba(255,255,255,0.85)' : '#000000'; $stroke_color = $is_dark_theme ? 'rgba(255,255,255,0.85)' : '#000000'; $optimized_svg = ' '; return $optimized_svg; } public function register_admin_pages() { // Main Menu Page - using dynamic OHM SVG icon add_menu_page( 'AIOHM Assistant', 'AIOHM', 'manage_options', 'aiohm-knowledge-assistant', array( $this, 'render_dashboard_page' ), $this->get_menu_icon(), 2 ); // Dashboard add_submenu_page( 'aiohm-knowledge-assistant', 'Dashboard', 'Dashboard', 'manage_options', 'aiohm-knowledge-assistant', array( $this, 'render_dashboard_page' ) ); // Settings with submenu add_submenu_page( 'aiohm-knowledge-assistant', 'Settings', 'Settings', 'manage_options', 'aiohm-settings', array( $this, 'render_form_settings_page' ) ); add_submenu_page( 'aiohm-knowledge-assistant', 'Scan Content', 'Scan Content', 'manage_options', 'aiohm-scan-content', array( $this, 'render_scan_page' ) ); add_submenu_page( 'aiohm-knowledge-assistant', 'Manage Knowledge Base', 'Manage KB', 'manage_options', 'aiohm-manage-kb', array( $this, 'render_manage_kb_page' ) ); // AI Brand Core add_submenu_page( 'aiohm-knowledge-assistant', 'AI Brand Core', 'AI Brand Core', 'manage_options', 'aiohm-brand-soul', array( $this, 'render_brand_soul_page' ) ); // Mirror Mode and Muse Mode (always available to admins) add_submenu_page( 'aiohm-knowledge-assistant', 'Mirror Mode', 'Mirror Mode', 'manage_options', 'aiohm-mirror-mode', array( $this, 'render_mirror_mode_page' ) ); add_submenu_page( 'aiohm-knowledge-assistant', 'Muse Mode', 'Muse Mode', 'manage_options', 'aiohm-muse-mode', array( $this, 'render_muse_mode_page' ) ); // Get Help page add_submenu_page( 'aiohm-knowledge-assistant', 'Get Help', 'Get Help', 'manage_options', 'aiohm-get-help', array( $this, 'render_help_page' ) ); } public function enqueue_admin_scripts( $hook ) { // Load global admin styles on all AIOHM pages if ( strpos( $hook, 'aiohm-' ) !== false ) { wp_enqueue_style( 'aiohm-admin-global-styles', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-chat.css', array(), AIOHM_KB_VERSION ); wp_enqueue_style( 'aiohm-admin-header-styles', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-header.css', array(), AIOHM_KB_VERSION ); } $mirror_mode_hook = 'aiohm_page_aiohm-mirror-mode'; $muse_mode_hook = 'aiohm_page_aiohm-muse-mode'; $settings_hook = 'aiohm_page_aiohm-settings'; $license_hook = 'aiohm_page_aiohm-license'; $dashboard_hook = 'aiohm_page_aiohm-knowledge-assistant'; $toplevel_dashboard_hook = 'toplevel_page_aiohm-knowledge-assistant'; $help_hook = 'aiohm_page_aiohm-get-help'; $scan_hook = 'aiohm_page_aiohm-scan-content'; $manage_kb_hook = 'aiohm_page_aiohm-manage-kb'; $brand_soul_hook = 'aiohm_page_aiohm-brand-soul'; // Mirror Mode page - separate CSS and JS files // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Safe $_GET check for admin page identification if ( $hook === $mirror_mode_hook || ( isset( $_GET['page'] ) && sanitize_text_field( wp_unslash( $_GET['page'] ) ) === 'aiohm-mirror-mode' ) ) { wp_enqueue_style( 'aiohm-admin-mirror-mode-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-mirror-mode.css', array(), AIOHM_KB_VERSION ); } // Settings page - separate CSS and JS files // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Safe $_GET check for admin page identification if ( $hook === $settings_hook || ( isset( $_GET['page'] ) && sanitize_text_field( wp_unslash( $_GET['page'] ) ) === 'aiohm-settings' ) ) { wp_enqueue_style( 'aiohm-admin-settings-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-settings.css', array(), AIOHM_KB_VERSION ); wp_enqueue_style( 'aiohm-provider-icons-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-provider-icons.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-provider-selection', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-provider-selection.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); } // Shared JavaScript for Mirror Mode and Settings pages if ( $hook === $mirror_mode_hook || $hook === $settings_hook ) { wp_enqueue_script( 'aiohm-admin-modes-script', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-modes.js', array( 'jquery' ), AIOHM_KB_VERSION, true // Load in footer ); // Prepare and localize data to pass from PHP to our JavaScript file $localized_data = array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'pluginUrl' => AIOHM_KB_PLUGIN_URL, ); if ( $hook === $mirror_mode_hook ) { wp_enqueue_media(); // Needed for the media uploader $localized_data['mode'] = 'mirror'; $localized_data['formId'] = 'mirror-mode-settings-form'; $localized_data['saveButtonId'] = 'save-mirror-mode-settings'; $localized_data['saveAction'] = 'aiohm_save_mirror_mode_settings'; $localized_data['testChatAction'] = 'aiohm_test_mirror_mode_chat'; $localized_data['nonceFieldId'] = 'aiohm_mirror_mode_nonce_field'; $localized_data['defaultPrompt'] = "You are the official AI Knowledge Assistant for \"%site_name%\".\n\nYour core mission is to embody our brand's tagline: \"%site_tagline%\".\n\nYou are to act as a thoughtful and emotionally intelligent guide for all website visitors, reflecting the unique voice of the brand. You should be aware that today is %day_of_week%, %current_date%.\n\nCore Instructions:\n\n1. Primary Directive:\n Your primary goal is to answer the user's question by grounding your response in the context provided below. This context is your main source of truth.\n\n2. Tone & Personality:\n • Speak with emotional clarity, not robotic formality\n • Sound like a thoughtful assistant, not a sales rep\n • Be concise, but not curt — useful, but never cold\n • Your purpose is to express with presence, not persuasion\n\n3. Formatting Rules:\n • Use only basic HTML tags for clarity (like or if needed). Do not use Markdown\n • Never end your response with a question like \"Do you need help with anything else?\"\n\n4. Fallback Response (Crucial):\n If the provided context does not contain enough information to answer the user's question, you MUST respond with this exact phrase: \"Hmm… I don't want to guess here. This might need a human's wisdom. You can connect with the person behind this site on the contact page. They'll know exactly how to help.\"\n\nPrimary Context for Answering the User's Question:\n{context}"; } if ( $hook === $settings_hook ) { $localized_data['mode'] = 'settings'; $localized_data['ajax_url'] = admin_url( 'admin-ajax.php' ); $localized_data['nonce'] = wp_create_nonce( 'aiohm_admin_nonce' ); } wp_localize_script( 'aiohm-admin-modes-script', 'aiohm_admin_modes_data', $localized_data ); } // Enqueue license page specific styles and scripts if ( $hook === $license_hook ) { wp_enqueue_style( 'aiohm-admin-license-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-license.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-license', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-license.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); wp_localize_script( 'aiohm-admin-license', 'aiohm_license_ajax', array( 'nonce' => wp_create_nonce( 'aiohm_license_verification' ), ) ); } // Enqueue dashboard page specific styles if ( $hook === $dashboard_hook || $hook === $toplevel_dashboard_hook ) { wp_enqueue_style( 'aiohm-admin-dashboard-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-dashboard.css', array(), AIOHM_KB_VERSION ); } // Enqueue help page specific styles and scripts if ( $hook === $help_hook ) { wp_enqueue_style( 'aiohm-admin-help-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-help.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-help-script', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-help.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); // Localize script for AJAX wp_localize_script( 'aiohm-admin-help-script', 'aiohm_admin_help_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'aiohm_admin_nonce' ), ) ); } // Enqueue muse mode specific styles and scripts (completely separate from admin-modes) if ( $hook === $muse_mode_hook ) { wp_enqueue_style( 'aiohm-admin-modes-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-modes.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-muse-mode', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-muse-mode.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); wp_localize_script( 'aiohm-admin-muse-mode', 'aiohm_muse_mode_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'plugin_url' => AIOHM_KB_PLUGIN_URL, 'nonce' => wp_create_nonce( 'aiohm_admin_nonce' ), ) ); } // Enqueue scan website page specific styles and scripts if ( $hook === $scan_hook ) { wp_enqueue_style( 'aiohm-admin-scan-website-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-scan-website.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-scan-website', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-scan-website.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); wp_localize_script( 'aiohm-admin-scan-website', 'aiohm_scan_website_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'aiohm_admin_nonce' ), 'plugin_url' => AIOHM_KB_PLUGIN_URL, ) ); } // Enqueue manage KB page specific styles and scripts if ( $hook === $manage_kb_hook ) { wp_enqueue_style( 'aiohm-admin-manage-kb-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-manage-kb.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-manage-kb', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-manage-kb.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); wp_localize_script( 'aiohm-admin-manage-kb', 'aiohm_manage_kb_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'aiohm_admin_nonce' ), ) ); wp_localize_script( 'aiohm-admin-manage-kb', 'aiohm_admin', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'aiohm_admin_nonce' ), ) ); } // Enqueue brand soul page specific styles and scripts if ( $hook === $brand_soul_hook ) { wp_enqueue_style( 'aiohm-admin-brand-soul-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-brand-soul.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-brand-soul', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-brand-soul.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); wp_localize_script( 'aiohm-admin-brand-soul', 'aiohm_brand_soul_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'aiohm_brand_soul_nonce' ), 'save_answers_text' => __( 'Save Answers', 'aiohm-knowledge-assistant' ), 'add_to_kb_text' => __( 'Add to Knowledge Base', 'aiohm-knowledge-assistant' ), 'download_pdf_text' => __( 'Download', 'aiohm-knowledge-assistant' ), 'saving_text' => __( 'Saving...', 'aiohm-knowledge-assistant' ), 'download_pdf_url' => wp_nonce_url( admin_url( 'admin.php?page=aiohm-brand-soul&action=download_brand_soul_pdf' ), 'download_brand_soul_pdf' ), ) ); } // Enqueue settings backup page specific styles and scripts if ( $hook === 'aiohm_page_aiohm-settings-backup' ) { wp_enqueue_style( 'aiohm-admin-settings-backup-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-settings-backup.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-settings-backup', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-settings-backup.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); } // Enqueue main settings page specific styles and scripts if ( $hook === $settings_hook ) { wp_enqueue_style( 'aiohm-admin-settings-style', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-settings.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-settings', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-settings.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); // Add licensing helper for premium features wp_localize_script( 'aiohm-admin-settings', 'aiohm_licensing', array( 'can_use_premium_code' => aiohm_kb_fs()->is__premium_only(), ) ); wp_localize_script( 'aiohm-admin-settings', 'aiohm_admin_settings_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'aiohm_admin_nonce' ), ) ); } // Brand Soul page scripts if ( $hook == 'aiohm_page_aiohm-brand-soul' ) { wp_enqueue_style( 'aiohm-admin-brand-soul', AIOHM_KB_PLUGIN_URL . 'assets/css/aiohm-admin-brand-soul.css', array(), AIOHM_KB_VERSION ); wp_enqueue_script( 'aiohm-admin-brand-soul', AIOHM_KB_PLUGIN_URL . 'assets/js/aiohm-admin-brand-soul.js', array( 'jquery' ), AIOHM_KB_VERSION, true ); wp_localize_script( 'aiohm-admin-brand-soul', 'aiohm_brand_soul_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'nonce' => wp_create_nonce( 'aiohm_brand_soul_nonce' ), 'download_pdf_url' => add_query_arg( array( 'action' => 'aiohm_download_brand_soul_pdf', 'nonce' => wp_create_nonce( 'aiohm_brand_soul_pdf' ), ), admin_url( 'admin.php' ) ), 'save_answers_text' => esc_html__( 'Save Answers', 'aiohm-knowledge-assistant' ), 'add_to_kb_text' => esc_html__( 'Add to Knowledge Base', 'aiohm-knowledge-assistant' ), 'download_pdf_text' => esc_html__( 'Download', 'aiohm-knowledge-assistant' ), 'saving_text' => esc_html__( 'Saving...', 'aiohm-knowledge-assistant' ), 'adding_text' => esc_html__( 'Adding to KB...', 'aiohm-knowledge-assistant' ), 'save_success_text' => esc_html__( 'Brand soul answers saved successfully!', 'aiohm-knowledge-assistant' ), 'progress_save_success_text' => esc_html__( 'Progress saved!', 'aiohm-knowledge-assistant' ), 'save_error_text' => esc_html__( 'Failed to save answers. Please try again.', 'aiohm-knowledge-assistant' ), 'add_to_kb_success_text' => esc_html__( 'Brand soul successfully added to your private knowledge base!', 'aiohm-knowledge-assistant' ), 'add_to_kb_error_text' => esc_html__( 'Failed to add to knowledge base. Please try again.', 'aiohm-knowledge-assistant' ), 'server_error_text' => esc_html__( 'Server error. Please try again later.', 'aiohm-knowledge-assistant' ), ) ); } } public function render_dashboard_page() { $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-dashboard.php'; $this->include_footer(); } public function render_form_settings_page() { $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-settings.php'; $this->include_footer(); } public function render_scan_page() { $site_crawler = new AIOHM_KB_Site_Crawler(); $uploads_crawler = new AIOHM_KB_Uploads_Crawler(); $site_stats = $site_crawler->get_scan_stats(); $uploads_stats = $uploads_crawler->get_stats(); $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-scan-website.php'; $this->include_footer(); } public function render_manage_kb_page() { $this->include_header(); $manager = new AIOHM_KB_Manager(); $manager->display_page(); $this->include_footer(); } public function render_brand_soul_page() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'aiohm-knowledge-assistant' ) ); } $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-brand-soul.php'; $this->include_footer(); } public function render_mirror_mode_page() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'aiohm-knowledge-assistant' ) ); } $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-mirror-mode.php'; $this->include_footer(); } public function render_muse_mode_page() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'aiohm-knowledge-assistant' ) ); } $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-muse-mode.php'; $this->include_footer(); } public function render_help_page() { $this->include_header(); include AIOHM_KB_PLUGIN_DIR . 'templates/admin-help.php'; $this->include_footer(); } public function register_settings() { register_setting( 'aiohm_kb_settings', 'aiohm_kb_settings', array( $this, 'sanitize_settings' ) ); } /** * Handle AJAX request to save brand soul answers */ public function ajax_save_brand_soul() { // Verify nonce if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'aiohm_brand_soul_nonce' ) ) { wp_send_json_error( array( 'message' => 'Security check failed' ) ); return; } // Check user permissions if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Insufficient permissions' ) ); return; } // Get answers directly from POST and sanitize them $answers = isset( $_POST['answers'] ) ? map_deep( wp_unslash( $_POST['answers'] ), 'sanitize_textarea_field' ) : array(); if ( empty( $answers ) ) { wp_send_json_error( array( 'message' => 'No answers provided.' ) ); return; } // Save to user meta $user_id = get_current_user_id(); $saved = update_user_meta( $user_id, 'aiohm_brand_soul_answers', $answers ); if ( $saved !== false ) { wp_send_json_success( array( 'message' => __( 'Brand soul answers saved successfully!', 'aiohm-knowledge-assistant' ) ) ); } else { wp_send_json_error( array( 'message' => __( 'Failed to save answers. Please try again.', 'aiohm-knowledge-assistant' ) ) ); } } /** * Handle AJAX request to add brand soul to knowledge base */ public function ajax_add_brand_soul_to_kb() { // Verify nonce if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'aiohm_brand_soul_nonce' ) ) { wp_send_json_error( array( 'message' => 'Security check failed' ) ); return; } // Check user permissions if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => 'Insufficient permissions' ) ); return; } try { // Get answers directly from POST and sanitize them $answers = isset( $_POST['answers'] ) ? map_deep( wp_unslash( $_POST['answers'] ), 'sanitize_textarea_field' ) : array(); if ( empty( $answers ) ) { wp_send_json_error( array( 'message' => 'No answers to add to knowledge base.' ) ); return; } // Format answers for knowledge base $content = "# Brand Soul Questionnaire Answers\n\n"; $content .= 'Generated on: ' . gmdate( 'Y-m-d H:i:s' ) . " UTC\n\n"; // Define question categories $questions = array( '✨ Foundation' => array( 'foundation_1' => "What's the deeper purpose behind your brand — beyond profit?", 'foundation_2' => 'What life experiences shaped this work you now do?', 'foundation_3' => 'Who were you before this calling emerged?', 'foundation_4' => 'If your brand had a soul story, how would you tell it?', 'foundation_5' => "What's one transformation you've witnessed that reminds you why you do this?", ), '🌀 Energy' => array( 'energy_1' => 'What 3 words describe the emotional tone of your brand voice?', 'energy_2' => 'How do you want your audience to feel after encountering your message?', 'energy_3' => 'What do you not want to sound like?', 'energy_4' => 'Do you prefer poetic, punchy, playful, or professional language?', 'energy_5' => 'Share a quote, phrase, or piece of content that feels like you.', ), '🎨 Expression' => array( 'expression_1' => "What are your brand's primary colors (and any specific hex codes)?", 'expression_2' => 'What font(s) do you use — or wish to use — for headers and body text?', 'expression_3' => 'Is there a visual theme (earthy, cosmic, minimalist, ornate) that matches your brand essence?', 'expression_4' => 'Are there any logos, patterns, or symbols that hold meaning for your brand?', 'expression_5' => 'What offerings are you currently sharing with the world — and how are they priced or exchanged?', ), '🚀 Direction' => array( 'direction_1' => "What's your current main offer or project you want support with?", 'direction_2' => 'Who is your dream client? Describe them with emotion and detail.', 'direction_3' => 'What are 3 key goals you have for the next 6 months?', 'direction_4' => 'Where do you feel stuck, overwhelmed, or unsure — and where would you love AI support?', 'direction_5' => 'If this AI assistant could speak your soul fluently, what would you want it to never forget?', ), ); foreach ( $questions as $section_title => $section_questions ) { $content .= '## ' . $section_title . "\n\n"; foreach ( $section_questions as $key => $question ) { if ( ! empty( $answers[ $key ] ) ) { $content .= '### ' . $question . "\n\n"; $content .= $answers[ $key ] . "\n\n"; } } } // Add to knowledge base using RAG engine $rag_engine = new AIOHM_KB_RAG_Engine(); $user_id = get_current_user_id(); $result = $rag_engine->add_entry( $content, 'brand_soul', 'Brand Soul Questionnaire', array( 'source_type' => 'brand_soul', 'user_id' => $user_id, 'created_date' => gmdate( 'Y-m-d H:i:s' ), ), $user_id, 0 ); if ( is_wp_error( $result ) ) { wp_send_json_error( array( 'message' => 'Failed to add to knowledge base: ' . $result->get_error_message() ) ); } else { wp_send_json_success( array( 'message' => __( 'Brand soul successfully added to your private knowledge base!', 'aiohm-knowledge-assistant' ) ) ); } } catch ( Exception $e ) { wp_send_json_error( array( 'message' => 'Error: ' . $e->getMessage() ) ); } } /** * Generate and download brand soul PDF */ public function download_brand_soul_pdf() { // Check user permissions if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'Insufficient permissions' ); } // Verify nonce if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['nonce'] ) ), 'aiohm_brand_soul_pdf' ) ) { wp_die( 'Security check failed' ); } try { $user_id = get_current_user_id(); $answers = get_user_meta( $user_id, 'aiohm_brand_soul_answers', true ); if ( empty( $answers ) ) { wp_die( 'No brand soul answers found. Please complete the questionnaire first.' ); } // Initialize PDF loader $pdf_loader = AIOHM_PDF_Library_Loader::get_instance(); if ( ! $pdf_loader->load_mpdf() ) { wp_die( esc_html__( 'PDF generation is not available.', 'aiohm-knowledge-assistant' ) ); } // Create PDF instance $pdf = $pdf_loader->get_pdf(); // Add title $pdf->ChapterTitle( 'Brand Soul Questionnaire' ); // Define questions for PDF $questions = array( '✨ Foundation' => array( 'foundation_1' => "What's the deeper purpose behind your brand — beyond profit?", 'foundation_2' => 'What life experiences shaped this work you now do?', 'foundation_3' => 'Who were you before this calling emerged?', 'foundation_4' => 'If your brand had a soul story, how would you tell it?', 'foundation_5' => "What's one transformation you've witnessed that reminds you why you do this?", ), '🌀 Energy' => array( 'energy_1' => 'What 3 words describe the emotional tone of your brand voice?', 'energy_2' => 'How do you want your audience to feel after encountering your message?', 'energy_3' => 'What do you not want to sound like?', 'energy_4' => 'Do you prefer poetic, punchy, playful, or professional language?', 'energy_5' => 'Share a quote, phrase, or piece of content that feels like you.', ), '🎨 Expression' => array( 'expression_1' => "What are your brand's primary colors (and any specific hex codes)?", 'expression_2' => 'What font(s) do you use — or wish to use — for headers and body text?', 'expression_3' => 'Is there a visual theme (earthy, cosmic, minimalist, ornate) that matches your brand essence?', 'expression_4' => 'Are there any logos, patterns, or symbols that hold meaning for your brand?', 'expression_5' => 'What offerings are you currently sharing with the world — and how are they priced or exchanged?', ), '🚀 Direction' => array( 'direction_1' => "What's your current main offer or project you want support with?", 'direction_2' => 'Who is your dream client? Describe them with emotion and detail.', 'direction_3' => 'What are 3 key goals you have for the next 6 months?', 'direction_4' => 'Where do you feel stuck, overwhelmed, or unsure — and where would you love AI support?', 'direction_5' => 'If this AI assistant could speak your soul fluently, what would you want it to never forget?', ), ); // Add content to PDF foreach ( $questions as $section_title => $section_questions ) { $pdf->ChapterTitle( $section_title ); foreach ( $section_questions as $key => $question ) { if ( ! empty( $answers[ $key ] ) ) { $pdf->MessageBlock( 'question', $question, gmdate( 'Y-m-d H:i:s' ) ); $pdf->MessageBlock( 'answer', $answers[ $key ], gmdate( 'Y-m-d H:i:s' ) ); } } } // Output PDF $filename = 'brand-soul-questionnaire-' . gmdate( 'Y-m-d' ) . '.pdf'; $pdf->Output( $filename, 'D' ); } catch ( Exception $e ) { wp_die( 'Error generating PDF: ' . esc_html( $e->getMessage() ) ); } } /** * AJAX handler for saving individual settings */ public function ajax_save_setting() { // Verify nonce if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'aiohm_admin_nonce' ) ) { wp_send_json_error( 'Security check failed' ); return; } // Check user permissions if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'Insufficient permissions' ); return; } $setting_key = sanitize_text_field( wp_unslash( $_POST['setting_key'] ?? '' ) ); $setting_value = sanitize_text_field( wp_unslash( $_POST['setting_value'] ?? '' ) ); if ( empty( $setting_key ) ) { wp_send_json_error( 'Setting key is required' ); return; } // Get current settings $current_settings = AIOHM_KB_Assistant::get_settings(); // Update the specific setting $current_settings[ $setting_key ] = $setting_value; // Save the updated settings $result = update_option( 'aiohm_kb_settings', $current_settings ); if ( $result !== false ) { wp_send_json_success( 'Setting saved successfully' ); } else { wp_send_json_error( 'Failed to save setting' ); } } /** * AJAX handler for saving multiple settings (like Muse mode form) */ public function ajax_save_settings() { // Verify nonce if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['aiohm_muse_mode_nonce_field'] ?? '' ) ), 'aiohm_muse_mode_nonce' ) ) { wp_send_json_error( 'Security check failed' ); return; } // Check user permissions if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'Insufficient permissions' ); return; } // Get current settings $current_settings = AIOHM_KB_Assistant::get_settings(); // Handle form data - check if we have aiohm_kb_settings in the POST data if ( isset( $_POST['aiohm_kb_settings'] ) && is_array( $_POST['aiohm_kb_settings'] ) ) { $form_settings = map_deep( wp_unslash( $_POST['aiohm_kb_settings'] ), 'sanitize_text_field' ); // Recursively sanitize and merge the settings $sanitized_settings = $this->sanitize_settings_array( $form_settings ); $current_settings = array_merge( $current_settings, $sanitized_settings ); // Save the updated settings $result = update_option( 'aiohm_kb_settings', $current_settings ); if ( $result !== false ) { wp_send_json_success( 'Settings saved successfully' ); } else { wp_send_json_error( 'Failed to save settings' ); } } else { wp_send_json_error( 'No settings data received' ); } } /** * Recursively sanitize settings array */ private function sanitize_settings_array( $settings ) { $sanitized = array(); foreach ( $settings as $key => $value ) { $sanitized_key = sanitize_key( $key ); if ( is_array( $value ) ) { $sanitized[ $sanitized_key ] = $this->sanitize_settings_array( $value ); } else { // Handle different types of values if ( is_bool( $value ) || $value === '1' || $value === '0' ) { $sanitized[ $sanitized_key ] = (bool) $value; } elseif ( is_numeric( $value ) ) { $sanitized[ $sanitized_key ] = floatval( $value ); } else { // For text fields, use textarea sanitization to preserve line breaks $sanitized[ $sanitized_key ] = sanitize_textarea_field( $value ); } } } return $sanitized; } public function sanitize_settings( $input ) { $old_settings = get_option( 'aiohm_kb_settings', array() ); $sanitized = is_array( $old_settings ) ? $old_settings : array(); // Sanitize API keys and encrypt them for storage $api_keys = array( 'openai_api_key', 'gemini_api_key', 'claude_api_key' ); foreach ( $api_keys as $field ) { if ( isset( $input[ $field ] ) ) { $sanitized_key = sanitize_text_field( trim( $input[ $field ] ) ); // Only encrypt if not empty and not already encrypted if ( ! empty( $sanitized_key ) ) { if ( base64_decode( $sanitized_key, true ) === false || strlen( base64_decode( $sanitized_key ) ) < 17 ) { $sanitized[ $field ] = AIOHM_KB_Assistant::encrypt_api_key( $sanitized_key ); } else { $sanitized[ $field ] = $sanitized_key; // Assume it's already encrypted from AJAX save } } else { $sanitized[ $field ] = ''; } } } // ShareAI API key and model are handled via AJAX, but sanitize if submitted with main form if ( isset( $input['shareai_api_key'] ) ) { $sanitized['shareai_api_key'] = sanitize_text_field( trim( $input['shareai_api_key'] ) ); } // Sanitize other text fields $text_fields = array( 'aiohm_app_email', 'private_llm_server_url', 'private_llm_model' ); foreach ( $text_fields as $field ) { if ( isset( $input[ $field ] ) ) { $sanitized[ $field ] = sanitize_text_field( trim( $input[ $field ] ) ); } } // Sanitize select fields if ( isset( $input['default_ai_provider'] ) ) { $sanitized['default_ai_provider'] = sanitize_text_field( $input['default_ai_provider'] ); } // Sanitize checkboxes $checkboxes = array( 'chat_enabled', 'show_floating_chat', 'enable_private_assistant', 'enable_search_shortcode', 'enable_qa_shortcode', 'delete_data_on_uninstall', 'external_api_consent' ); foreach ( $checkboxes as $checkbox ) { $sanitized[ $checkbox ] = ! empty( $input[ $checkbox ] ); } // Handle nested Mirror Mode settings if ( isset( $input['mirror_mode'] ) && is_array( $input['mirror_mode'] ) ) { $mirror_mode = $input['mirror_mode']; $sanitized['mirror_mode'] = $sanitized['mirror_mode'] ?? array(); $mirror_text_fields = array( 'business_name', 'ai_model' ); foreach ( $mirror_text_fields as $field ) { if ( isset( $mirror_mode[ $field ] ) ) { $sanitized['mirror_mode'][ $field ] = sanitize_text_field( trim( $mirror_mode[ $field ] ) ); } } if ( isset( $mirror_mode['qa_system_message'] ) ) { $sanitized['mirror_mode']['qa_system_message'] = sanitize_textarea_field( $mirror_mode['qa_system_message'] ); } if ( isset( $mirror_mode['welcome_message'] ) ) { $sanitized['mirror_mode']['welcome_message'] = sanitize_textarea_field( $mirror_mode['welcome_message'] ); } if ( isset( $mirror_mode['qa_temperature'] ) ) { $sanitized['mirror_mode']['qa_temperature'] = floatval( $mirror_mode['qa_temperature'] ); } if ( isset( $mirror_mode['primary_color'] ) ) { $sanitized['mirror_mode']['primary_color'] = sanitize_hex_color( $mirror_mode['primary_color'] ); } if ( isset( $mirror_mode['background_color'] ) ) { $sanitized['mirror_mode']['background_color'] = sanitize_hex_color( $mirror_mode['background_color'] ); } if ( isset( $mirror_mode['text_color'] ) ) { $sanitized['mirror_mode']['text_color'] = sanitize_hex_color( $mirror_mode['text_color'] ); } if ( isset( $mirror_mode['ai_avatar'] ) ) { $sanitized['mirror_mode']['ai_avatar'] = esc_url_raw( trim( $mirror_mode['ai_avatar'] ) ); } if ( isset( $mirror_mode['meeting_button_url'] ) ) { $sanitized['mirror_mode']['meeting_button_url'] = esc_url_raw( trim( $mirror_mode['meeting_button_url'] ) ); } } return $sanitized; } /** * Handle muse mode preview chat AJAX request */ public function ajax_muse_preview_chat() { if ( ! check_ajax_referer( 'aiohm_admin_nonce', 'nonce', false ) || ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Security check failed.', 'aiohm-knowledge-assistant' ) ) ); } try { $user_message = isset( $_POST['message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['message'] ) ) : ''; if ( empty( $user_message ) ) { wp_send_json_error( array( 'message' => __( 'Message cannot be empty.', 'aiohm-knowledge-assistant' ) ) ); } // Get muse mode settings $all_settings = AIOHM_KB_Assistant::get_settings(); $muse_settings = $all_settings['muse_mode'] ?? array(); $system_prompt = isset( $muse_settings['system_prompt'] ) ? wp_kses_post( $muse_settings['system_prompt'] ) : 'You are a helpful creative assistant.'; $temperature = floatval( $muse_settings['temperature'] ?? 0.7 ); $assistant_name = $muse_settings['assistant_name'] ?? 'Muse'; $ai_model = $muse_settings['ai_model'] ?? 'gpt-3.5-turbo'; // Initialize AI client $ai_client = new AIOHM_KB_AI_GPT_Client( $all_settings ); // Check if any AI provider is configured $providers = array( 'openai', 'gemini', 'claude', 'groq', 'shareai' ); $has_api_key = false; foreach ( $providers as $provider ) { if ( $ai_client->is_api_key_configured( $provider ) ) { $has_api_key = true; break; } } if ( ! $has_api_key ) { wp_send_json_error( array( 'message' => __( 'No AI API keys are configured. Please configure at least one AI provider in the settings.', 'aiohm-knowledge-assistant' ) ) ); } $rag_engine = new AIOHM_KB_RAG_Engine(); // Get relevant context from knowledge base $context_data = array(); try { $context_data = $rag_engine->find_relevant_context( $user_message, 5 ); } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch // If context retrieval fails (e.g., no API keys for embeddings), continue with empty context. $context_data = array(); } $context_string = ''; foreach ( $context_data as $data ) { $context_string .= 'Source: ' . $data['entry']['title'] . "\nContent: " . $data['entry']['content'] . "\n\n"; } if ( empty( $context_string ) ) { $context_string = 'No relevant context found.'; } // Replace placeholders in system prompt $replacements = array( '{context}' => $context_string, '%site_name%' => get_bloginfo( 'name' ), '%assistant_name%' => $assistant_name, '%day_of_week%' => wp_date( 'l' ), '%current_date%' => wp_date( get_option( 'date_format' ) ), '%current_time%' => wp_date( get_option( 'time_format' ) ), ); $final_system_prompt = str_replace( array_keys( $replacements ), array_values( $replacements ), $system_prompt ); // Send request to AI $ai_response = $ai_client->get_chat_completion( $final_system_prompt, $user_message, $temperature, $ai_model ); if ( $ai_response ) { wp_send_json_success( $ai_response ); } else { wp_send_json_error( array( 'message' => __( 'Failed to get AI response.', 'aiohm-knowledge-assistant' ) ) ); } } catch ( Exception $e ) { wp_send_json_error( array( 'message' => __( 'An error occurred while processing your request.', 'aiohm-knowledge-assistant' ) ) ); } } /** * Handle brand soul PDF download request */ public function handle_brand_soul_pdf_download() { $this->download_brand_soul_pdf(); } }