| 1 |
<?php |
| 2 |
if (!defined('ABSPATH')) { |
| 3 |
exit; // Exit if accessed directly |
| 4 |
} |
| 5 |
|
| 6 |
class MxChat_Admin { |
| 7 |
private $options; |
| 8 |
private $chat_count; |
| 9 |
private $is_activated; |
| 10 |
|
| 11 |
public function __construct() { |
| 12 |
$this->options = get_option('mxchat_options'); |
| 13 |
$this->chat_count = get_option('mxchat_chat_count', 0); |
| 14 |
$this->is_activated = $this->is_license_active(); |
| 15 |
|
| 16 |
// Initialize default options if they are not set |
| 17 |
if (!$this->options) { |
| 18 |
$this->initialize_default_options(); |
| 19 |
} |
| 20 |
|
| 21 |
// Add admin menu and initialize settings |
| 22 |
add_action('admin_menu', array($this, 'mxchat_add_plugin_page')); |
| 23 |
add_action('admin_init', array($this, 'mxchat_page_init')); |
| 24 |
add_action('admin_init', array($this, 'mxchat_prompts_page_init')); // Add this line |
| 25 |
add_action('admin_enqueue_scripts', array($this, 'mxchat_enqueue_admin_assets')); |
| 26 |
add_action('wp_ajax_mxchat_delete_chat_history', array($this, 'mxchat_delete_chat_history')); |
| 27 |
add_action('admin_post_mxchat_submit_content', array($this, 'mxchat_handle_content_submission')); |
| 28 |
add_action('admin_post_mxchat_delete_prompt', array($this, 'mxchat_handle_delete_prompt')); |
| 29 |
add_action('wp_ajax_mxchat_fetch_chat_history', array($this, 'mxchat_fetch_chat_history')); |
| 30 |
add_action('wp_ajax_nopriv_mxchat_fetch_chat_history', array($this, 'mxchat_fetch_chat_history')); |
| 31 |
add_action('admin_post_mxchat_submit_sitemap', array($this, 'mxchat_handle_sitemap_submission')); |
| 32 |
add_action('wp_footer', array($this, 'mxchat_append_chatbot_to_body')); |
| 33 |
add_action('admin_head-mxchat-prompts', array($this, 'mxchat_enqueue_admin_assets')); |
| 34 |
add_action('admin_head-toplevel_page_mxchat-max', array($this, 'mxchat_enqueue_admin_assets')); |
| 35 |
add_action('wp_ajax_mxchat_activate_license', array($this, 'mxchat_handle_activate_license')); |
| 36 |
add_action('admin_notices', array($this, 'mxchat_display_admin_notice')); |
| 37 |
// Add the AJAX handler for logged-in users |
| 38 |
add_action('wp_ajax_mxchat_save_inline_prompt', array($this, 'mxchat_save_inline_prompt')); |
| 39 |
add_action('admin_post_mxchat_delete_all_prompts', array($this, 'mxchat_handle_delete_all_prompts')); |
| 40 |
|
| 41 |
// Define admin_post actions for form submission handling |
| 42 |
add_action('admin_post_mxchat_add_intent', array($this, 'mxchat_handle_add_intent')); |
| 43 |
add_action('admin_post_mxchat_delete_intent', array($this, 'mxchat_handle_delete_intent')); |
| 44 |
add_action('admin_post_mxchat_update_intent_threshold', array($this, 'mxchat_handle_update_intent_threshold')); |
| 45 |
add_action('admin_post_mxchat_stop_processing', array($this, 'mxchat_stop_processing')); |
| 46 |
add_action('admin_post_mxchat_edit_intent', array($this, 'handle_edit_intent')); |
| 47 |
|
| 48 |
add_action('save_post', array($this, 'handle_post_update'), 10, 3); |
| 49 |
add_action('post_updated', array($this, 'handle_post_update'), 10, 3); |
| 50 |
add_action('wp_ajax_mxchat_save_setting', array($this, 'mxchat_save_setting_callback')); |
| 51 |
|
| 52 |
|
| 53 |
} |
| 54 |
|
| 55 |
// Method to check if the license is active |
| 56 |
private function is_license_active() { |
| 57 |
$license_status = get_option('mxchat_license_status', 'inactive'); |
| 58 |
return $license_status === 'active'; |
| 59 |
} |
| 60 |
|
| 61 |
// Initialize default options |
| 62 |
private function initialize_default_options() { |
| 63 |
$default_options = array( |
| 64 |
'api_key' => '', |
| 65 |
'xai_api_key' => '', |
| 66 |
'claude_api_key' => '', |
| 67 |
'system_prompt_instructions' => '[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: |
| 68 |
- Your name is [Chatbot Name]. |
| 69 |
- 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. |
| 70 |
- Do not make up links to pages. Only use specific links you see in your knowledgebase. |
| 71 |
- Keep your responses short, concise, and to the point. Provide clear and direct answers suitable for a chatbot interaction. |
| 72 |
- 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.', |
| 73 |
'model' => 'gpt-4o', |
| 74 |
'rate_limit_logged_in' => '100', |
| 75 |
'rate_limit_logged_out' => '100', |
| 76 |
'rate_limit_message' => 'Rate limit exceeded. Please try again later.', |
| 77 |
'enable_email_block' => '', |
| 78 |
'email_blocker_header_content' => "<h2>Welcome to Our Chat!</h2>\n<p>Let's get started. Enter your email to begin chatting with us.</p>", |
| 79 |
'email_blocker_button_text' => 'Start Chat', |
| 80 |
'top_bar_title' => 'MxChat', |
| 81 |
'intro_message' => 'Hello! How can I assist you today?', |
| 82 |
'input_copy' => 'How can I assist?', |
| 83 |
'append_to_body' => 'off', |
| 84 |
'close_button_color' => '#fff', |
| 85 |
'chatbot_bg_color' => '#fff', |
| 86 |
'user_message_bg_color' => '#fff', |
| 87 |
'user_message_font_color' => '#212121', |
| 88 |
'bot_message_bg_color' => '#212121', |
| 89 |
'bot_message_font_color' => '#fff', |
| 90 |
'top_bar_bg_color' => '#212121', |
| 91 |
'send_button_font_color' => '#212121', |
| 92 |
'chat_input_font_color' => '#212121', |
| 93 |
'chatbot_background_color' => '#212121', |
| 94 |
'icon_color' => '#fff', |
| 95 |
'enable_woocommerce_integration' => '0', |
| 96 |
'link_target_toggle' => 'off', |
| 97 |
'pre_chat_message' => 'Hey there! Ask me anything!', |
| 98 |
|
| 99 |
// New fields for Loops Integration |
| 100 |
'loops_api_key' => '', |
| 101 |
'loops_mailing_list' => '', |
| 102 |
'triggered_phrase_response' => 'Would you like to join our mailing list? Please provide your email below.', |
| 103 |
'email_capture_response' => 'Thank you for providing your email! You\'ve been added to our list.', |
| 104 |
'popular_question_1' => '', |
| 105 |
'popular_question_2' => '', |
| 106 |
'popular_question_3' => '', |
| 107 |
'pdf_intent_trigger_text' => "Please provide the URL to the PDF you'd like to discuss.", |
| 108 |
'pdf_intent_success_text' => "I've processed the PDF. What questions do you have about it?", |
| 109 |
'pdf_intent_error_text' => "Sorry, I couldn't process the PDF. Please ensure it's a valid file.", |
| 110 |
'pdf_max_pages' => 69, |
| 111 |
|
| 112 |
// Live Agent Integration |
| 113 |
'live_agent_webhook_url' => '', |
| 114 |
'live_agent_secret_key' => '', |
| 115 |
'live_agent_bot_token' => '', |
| 116 |
'live_agent_message_bg_color' => '#ffffff', |
| 117 |
'live_agent_message_font_color' => '#333333', |
| 118 |
'chat_toolbar_toggle' => 'off', |
| 119 |
'mode_indicator_bg_color' => '#767676', |
| 120 |
'mode_indicator_font_color' => '#ffffff', |
| 121 |
'toolbar_icon_color' => '#212121', |
| 122 |
); |
| 123 |
|
| 124 |
|
| 125 |
// Merge existing options with defaults |
| 126 |
$existing_options = get_option('mxchat_options', array()); |
| 127 |
$merged_options = wp_parse_args($existing_options, $default_options); |
| 128 |
|
| 129 |
// Update the options if they have changed |
| 130 |
if ($existing_options !== $merged_options) { |
| 131 |
update_option('mxchat_options', $merged_options); |
| 132 |
} |
| 133 |
|
| 134 |
// Update the $this->options property |
| 135 |
$this->options = $merged_options; |
| 136 |
} |
| 137 |
|
| 138 |
|
| 139 |
|
| 140 |
public function mxchat_add_plugin_page() { |
| 141 |
// Main menu page |
| 142 |
add_menu_page( |
| 143 |
'MxChat Settings', |
| 144 |
'MxChat', |
| 145 |
'manage_options', |
| 146 |
'mxchat-max', |
| 147 |
array($this, 'mxchat_create_admin_page'), |
| 148 |
'dashicons-testimonial', |
| 149 |
6 |
| 150 |
); |
| 151 |
|
| 152 |
// Submenu page for Knowledge |
| 153 |
add_submenu_page( |
| 154 |
'mxchat-max', |
| 155 |
'Prompts', |
| 156 |
'Knowledge', |
| 157 |
'manage_options', |
| 158 |
'mxchat-prompts', |
| 159 |
array($this, 'mxchat_create_prompts_page') |
| 160 |
); |
| 161 |
|
| 162 |
// Submenu page for Chat Transcripts |
| 163 |
add_submenu_page( |
| 164 |
'mxchat-max', // Corrected parent slug to match the main menu |
| 165 |
'Chat Transcripts', |
| 166 |
'Transcripts', |
| 167 |
'manage_options', |
| 168 |
'mxchat-transcripts', |
| 169 |
array($this, 'mxchat_create_transcripts_page') // Prefixed function name with mxchat_ |
| 170 |
); |
| 171 |
|
| 172 |
// Submenu page for Intents |
| 173 |
add_submenu_page( |
| 174 |
'mxchat-max', // Parent slug |
| 175 |
'MxChat Intents', // Page title |
| 176 |
'Intents', // Menu title |
| 177 |
'manage_options', // Capability |
| 178 |
'mxchat-intents', // Menu slug |
| 179 |
array($this, 'mxchat_intents_page_html') // Callback function |
| 180 |
); |
| 181 |
|
| 182 |
// Submenu page for Activation Key |
| 183 |
add_submenu_page( |
| 184 |
'mxchat-max', |
| 185 |
'Pro Upgrade', |
| 186 |
'Pro Upgrade', |
| 187 |
'manage_options', |
| 188 |
'mxchat-activation', |
| 189 |
array($this, 'mxchat_create_activation_page') |
| 190 |
); |
| 191 |
|
| 192 |
|
| 193 |
} |
| 194 |
|
| 195 |
public function mxchat_save_setting_callback() { |
| 196 |
check_ajax_referer('mxchat_save_setting_nonce'); |
| 197 |
|
| 198 |
if (!current_user_can('manage_options')) { |
| 199 |
wp_send_json_error(['message' => 'Unauthorized']); |
| 200 |
} |
| 201 |
|
| 202 |
$name = isset($_POST['name']) ? $_POST['name'] : ''; |
| 203 |
// Strip slashes from the value before saving |
| 204 |
$value = isset($_POST['value']) ? stripslashes($_POST['value']) : ''; |
| 205 |
|
| 206 |
if (empty($name)) { |
| 207 |
wp_send_json_error(['message' => 'Invalid field name']); |
| 208 |
} |
| 209 |
|
| 210 |
// Load the full options array |
| 211 |
$options = get_option('mxchat_options', []); |
| 212 |
|
| 213 |
// Handle special cases |
| 214 |
switch ($name) { |
| 215 |
case 'additional_popular_questions': |
| 216 |
$questions = json_decode($value, true); // No need for stripslashes here |
| 217 |
if (is_array($questions)) { |
| 218 |
$options[$name] = $questions; |
| 219 |
// Also update old option for backwards compatibility |
| 220 |
update_option('additional_popular_questions', $questions); |
| 221 |
} |
| 222 |
break; |
| 223 |
|
| 224 |
case 'close_button_color': |
| 225 |
case 'user_message_bg_color': |
| 226 |
case 'user_message_font_color': |
| 227 |
case 'bot_message_bg_color': |
| 228 |
case 'bot_message_font_color': |
| 229 |
case 'top_bar_bg_color': |
| 230 |
case 'send_button_font_color': |
| 231 |
case 'chatbot_background_color': |
| 232 |
case 'icon_color': |
| 233 |
case 'chat_input_font_color': |
| 234 |
case 'live_agent_message_bg_color': |
| 235 |
case 'live_agent_message_font_color': |
| 236 |
case 'mode_indicator_bg_color': |
| 237 |
|
| 238 |
case 'mode_indicator_font_color': |
| 239 |
case 'toolbar_icon_color': |
| 240 |
// Store color values directly |
| 241 |
$options[$name] = $value; |
| 242 |
break; |
| 243 |
case 'live_agent_status': |
| 244 |
// Set the new value |
| 245 |
$options[$name] = ($value === 'on') ? 'on' : 'off'; |
| 246 |
break; |
| 247 |
|
| 248 |
case 'enable_woocommerce_integration': |
| 249 |
// Handle values that used to be 1/0 |
| 250 |
$options[$name] = ($value === 'on' || $value === '1') ? 'on' : 'off'; |
| 251 |
break; |
| 252 |
|
| 253 |
default: |
| 254 |
// Handle toggles |
| 255 |
if (strpos($name, 'toggle') !== false || in_array($name, [ |
| 256 |
'chat_persistence_toggle', |
| 257 |
'privacy_toggle', |
| 258 |
'complianz_toggle', |
| 259 |
'chat_toolbar_toggle' // Removed live_agent_status from here |
| 260 |
])) { |
| 261 |
$options[$name] = ($value === 'on') ? 'on' : 'off'; |
| 262 |
} else { |
| 263 |
// Store all other values directly |
| 264 |
$options[$name] = $value; |
| 265 |
} |
| 266 |
break; |
| 267 |
} |
| 268 |
|
| 269 |
// Save all updates |
| 270 |
$updated = update_option('mxchat_options', $options); |
| 271 |
|
| 272 |
// Handle backwards compatibility for certain fields |
| 273 |
$legacy_fields = ['brave_api_key', 'brave_image_count', 'brave_safe_search', 'brave_news_count', |
| 274 |
'brave_country', 'brave_language', 'similarity_threshold']; |
| 275 |
|
| 276 |
if (in_array($name, $legacy_fields)) { |
| 277 |
// Also update the individual option for backwards compatibility |
| 278 |
update_option($name, $value); |
| 279 |
} |
| 280 |
|
| 281 |
if ($updated) { |
| 282 |
wp_send_json_success(['message' => 'Setting saved']); |
| 283 |
} else { |
| 284 |
wp_send_json_error(['message' => 'Update failed or no changes']); |
| 285 |
} |
| 286 |
} |
| 287 |
|
| 288 |
public function mxchat_display_admin_notice() { |
| 289 |
// Success notice |
| 290 |
if ($message = get_transient('mxchat_admin_notice_success')) { |
| 291 |
?> |
| 292 |
<div class="notice notice-success is-dismissible"> |
| 293 |
<p><?php echo esc_html($message); ?></p> |
| 294 |
<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span></button> |
| 295 |
</div> |
| 296 |
<?php |
| 297 |
delete_transient('mxchat_admin_notice_success'); // Clear the transient after displaying |
| 298 |
} |
| 299 |
|
| 300 |
// Error notice |
| 301 |
if ($message = get_transient('mxchat_admin_notice_error')) { |
| 302 |
?> |
| 303 |
<div class="notice notice-error is-dismissible"> |
| 304 |
<p><?php echo esc_html($message); ?></p> |
| 305 |
<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span></button> |
| 306 |
</div> |
| 307 |
<?php |
| 308 |
delete_transient('mxchat_admin_notice_error'); // Clear the transient after displaying |
| 309 |
} |
| 310 |
} |
| 311 |
|
| 312 |
|
| 313 |
|
| 314 |
|
| 315 |
|
| 316 |
public function mxchat_create_admin_page() { |
| 317 |
?> |
| 318 |
<div class="wrap mxchat-admin"> |
| 319 |
<?php if (!$this->is_activated): ?> |
| 320 |
<div class="mxchat-pro-banner"> |
| 321 |
<p> |
| 322 |
For a limited time, get lifetime access and save $20 on MxChat Pro! |
| 323 |
<a href="https://mxchat.ai/" target="_blank">Upgrade to Pro today</a> |
| 324 |
</p> |
| 325 |
</div> |
| 326 |
<?php endif; ?> |
| 327 |
|
| 328 |
<div class="mxchat-agents-banner"> |
| 329 |
<p> |
| 330 |
Pro users get exclusive access to <a href="https://mxchat.ai/agents/" target="_blank">MxChat AI Agents</a> – our groundbreaking platform to test, refine, and deploy your chatbot with confidence. Take your AI assistant to the next level! |
| 331 |
</p> |
| 332 |
</div> |
| 333 |
|
| 334 |
<h2 class="mxchat-nav-tab-wrapper"> |
| 335 |
<a href="#chatbot" class="mxchat-nav-tab mxchat-nav-tab-active" data-tab="chatbot">Chatbot</a> |
| 336 |
<a href="#embed" class="mxchat-nav-tab" data-tab="embed">Integrations</a> |
| 337 |
<a href="#theme" class="mxchat-nav-tab" data-tab="theme">Theme</a> |
| 338 |
<a href="#general" class="mxchat-nav-tab" data-tab="general">FAQ</a> |
| 339 |
</h2> |
| 340 |
|
| 341 |
<div id="chatbot" class="mxchat-tab-content active"> |
| 342 |
<div class="mxchat-autosave-section"> |
| 343 |
<?php do_settings_sections('mxchat-chatbot'); ?> |
| 344 |
</div> |
| 345 |
</div> |
| 346 |
|
| 347 |
<div id="embed" class="mxchat-tab-content"> |
| 348 |
<div class="mxchat-autosave-section"> |
| 349 |
<div class="mxchat-settings-section"> |
| 350 |
<h2>WooCommerce Settings</h2> |
| 351 |
<table class="form-table"> |
| 352 |
<?php do_settings_fields('mxchat-embed', 'mxchat_woocommerce_section'); ?> |
| 353 |
</table> |
| 354 |
</div> |
| 355 |
<div class="section-divider"></div> |
| 356 |
|
| 357 |
<div class="mxchat-settings-section"> |
| 358 |
<h2>Loops Settings</h2> |
| 359 |
<table class="form-table"> |
| 360 |
<?php do_settings_fields('mxchat-embed', 'mxchat_loops_section'); ?> |
| 361 |
</table> |
| 362 |
</div> |
| 363 |
|
| 364 |
<div class="section-divider"></div> |
| 365 |
|
| 366 |
<div class="mxchat-settings-section"> |
| 367 |
<h2>Brave Search Settings</h2> |
| 368 |
<table class="form-table"> |
| 369 |
<?php do_settings_fields('mxchat-embed', 'mxchat_brave_section'); ?> |
| 370 |
</table> |
| 371 |
</div> |
| 372 |
|
| 373 |
<div class="section-divider"></div> |
| 374 |
|
| 375 |
<div class="mxchat-settings-section"> |
| 376 |
<h2>Toolbar Settings & Intents</h2> |
| 377 |
<table class="form-table"> |
| 378 |
<?php do_settings_fields('mxchat-embed', 'mxchat_pdf_intent_section'); ?> |
| 379 |
</table> |
| 380 |
</div> |
| 381 |
|
| 382 |
<div class="section-divider"></div> |
| 383 |
|
| 384 |
|
| 385 |
<!-- Live Agent Settings Section --> |
| 386 |
<div class="mxchat-settings-section"> |
| 387 |
<h2>Live Agent Settings</h2> |
| 388 |
<p>Visit our <a href="https://mxchat.ai/documentation/#slack_integration" target="_blank">documentation page</a> to set up live agent transfer via Slack.</p> |
| 389 |
<table class="form-table"> |
| 390 |
<?php do_settings_fields('mxchat-embed', 'mxchat_live_agent_section'); ?> |
| 391 |
</table> |
| 392 |
</div> |
| 393 |
</div> |
| 394 |
</div> |
| 395 |
|
| 396 |
<div id="theme" class="mxchat-tab-content"> |
| 397 |
<div class="mxchat-autosave-section"> |
| 398 |
<?php do_settings_sections('mxchat-theme'); ?> |
| 399 |
</div> |
| 400 |
</div> |
| 401 |
|
| 402 |
<div id="general" class="mxchat-tab-content"> |
| 403 |
<?php do_settings_sections('mxchat-general'); ?> |
| 404 |
<p> |
| 405 |
If you’re having trouble with setup or getting the responses you need, we encourage you to review our |
| 406 |
<a href="https://mxchat.ai/documentation/" target="_blank" rel="noopener noreferrer">documentation</a> or |
| 407 |
<a href="https://wordpress.org/support/plugin/mxchat-basic/" target="_blank" rel="noopener noreferrer">create a support ticket</a>. |
| 408 |
</p> |
| 409 |
<p> |
| 410 |
If you like our plugin, please consider <a href="https://wordpress.org/plugins/mxchat-basic/#reviews" target="_blank" rel="noopener noreferrer">leaving us a review</a>. |
| 411 |
</p> |
| 412 |
|
| 413 |
<div class="faq-item"> |
| 414 |
<h3>How does the Claude API integration work?</h3> |
| 415 |
<p> |
| 416 |
The Claude API, provided by Anthropic, allows for intelligent, context-aware chatbot responses in MxChat. To use it, you will need both an OpenAI API key and a Claude API key. This is necessary because the system utilizes OpenAI for vector embedding in the Retrieval-Augmented Generation (RAG) process, as Claude does not currently offer an embedding API. |
| 417 |
</p> |
| 418 |
<p> |
| 419 |
When using the Claude API, your custom content is sent to Claude for generating responses, while the embeddings are processed through OpenAI. This ensures your chatbot provides accurate and engaging responses while maintaining knowledge relevant to your website. |
| 420 |
</p> |
| 421 |
<p> |
| 422 |
You can obtain your Claude API key by signing up on the <a href="https://www.anthropic.com/api" target="_blank" rel="noopener">Anthropic API page</a>. |
| 423 |
</p> |
| 424 |
</div> |
| 425 |
|
| 426 |
<div class="faq-item"> |
| 427 |
<h3>How does the X.AI API integration work?</h3> |
| 428 |
<p> |
| 429 |
The X.AI API, released on 10.21.24, is currently in beta. To use it, you will need both an OpenAI API key and an X.AI API key. This is because OpenAI handles vector embeddings in the Retrieval-Augmented Generation (RAG) process, as X.AI does not yet provide an embedding API. |
| 430 |
</p> |
| 431 |
<p> |
| 432 |
Custom content is sent to the X.AI API for generating responses, while OpenAI processes the embeddings. This allows the chatbot to provide advanced responses while maintaining context from your website. You can get your X.AI API key from the <a href="https://docs.x.ai/docs" target="_blank" rel="noopener">X.AI API documentation</a>. |
| 433 |
</p> |
| 434 |
</div> |
| 435 |
|
| 436 |
<div class="faq-item"> |
| 437 |
<h3>Do I need an OpenAI API key to use the chatbot?</h3> |
| 438 |
<p> |
| 439 |
Yes, you will need an OpenAI API key to power the chatbot. You can obtain an API key by signing up on the <a href="https://platform.openai.com/signup" target="_blank" rel="noopener">OpenAI platform</a>. After signing up, you must add credits to your account—typically, $5 in credits is sufficient to get started. |
| 440 |
</p> |
| 441 |
<p> |
| 442 |
Once you have your API key, simply enter it in the chatbot's settings to enable functionality. The chatbot relies on OpenAI’s models for generating responses, so having sufficient credits in your OpenAI account is essential for smooth operation. |
| 443 |
</p> |
| 444 |
</div> |
| 445 |
|
| 446 |
<div class="faq-item"> |
| 447 |
<h3>How do I add the chatbot to my site?</h3> |
| 448 |
<p> |
| 449 |
You can add the chatbot using the shortcode <code>[mxchat_chatbot floating="yes"]</code> or <code>[mxchat_chatbot floating="no"]</code>. For initial testing and styling, it's best to use the shortcode on a draft or non-public page. Once you’re ready to go live, enable the “Append Chat Widget to Body” option in the settings for site-wide integration (recommended) or add shortcode to the footer. |
| 450 |
</p> |
| 451 |
</div> |
| 452 |
|
| 453 |
<div class="faq-item"> |
| 454 |
<h3>How does the chatbot use my content to generate responses?</h3> |
| 455 |
<p> |
| 456 |
The chatbot uses AI and vector embeddings to connect users with relevant information. When you submit content, it converts it into a mathematical format. When a user asks a question, the bot matches it to your stored content and generates a response based on relevance. For example, submitting "Our phone number is 910-123-4567" allows the bot to retrieve this information when asked about contact details. To ensure related information is provided together, submit it in one entry. |
| 457 |
</p> |
| 458 |
</div> |
| 459 |
|
| 460 |
<div class="faq-item"> |
| 461 |
<h3>Why does the chatbot sometimes make up links or information?</h3> |
| 462 |
<p> |
| 463 |
Occasionally, the chatbot may generate inaccurate links or information, known as "hallucinations." To minimize this, you can add system instructions to guide its behavior. For example, include an instruction like: "Only provide links you directly have access to or retrieve from the knowledge base. Do not make up links or information that you do not have direct access to." This helps the bot stay aligned with your content. |
| 464 |
</p> |
| 465 |
</div> |
| 466 |
|
| 467 |
<div class="faq-item"> |
| 468 |
<h3>How do intents work in MxChat?</h3> |
| 469 |
<p> |
| 470 |
Intents allow MxChat to recognize user requests and trigger specific actions, such as capturing emails or displaying product information. This helps provide a more interactive and responsive experience. For a detailed explanation of each intent, please refer to our <a href="https://mxchat.ai/documentation/#intents" target="_blank" rel="noopener noreferrer">Intents Documentation</a>. |
| 471 |
</p> |
| 472 |
</div> |
| 473 |
|
| 474 |
|
| 475 |
<div class="faq-item"> |
| 476 |
<h3>How does the Complianz integration work?</h3> |
| 477 |
<p> |
| 478 |
The Pro version offers direct integration with the Complianz GDPR plugin, making it easy to stay compliant with GDPR. If Complianz is enabled on your website, users must accept consent before the chatbot widget appears. The chatbot will only display once the user has accepted, ensuring compliance with data privacy regulations. |
| 479 |
</p> |
| 480 |
</div> |
| 481 |
|
| 482 |
<div class="faq-item"> |
| 483 |
<h3>How does the WooCommerce integration work?</h3> |
| 484 |
<p> |
| 485 |
With WooCommerce integration, the chatbot automatically embeds new products and updates existing ones. For already-published products, you can click update or submit the product sitemap. The “Order History Access” setting allows the bot to access users' order history (requires login) and assist with order inquiries. To enable the “Add to Cart” feature, add this system instruction: “After discussing a product, ask if the user wants to add it to their cart. The user must say 'Add to cart' exactly.” Currently, this feature supports English only, with more languages coming soon. |
| 486 |
</p> |
| 487 |
</div> |
| 488 |
|
| 489 |
<div class="faq-item"> |
| 490 |
<h3>Why isn't my chatbot responding as expected?</h3> |
| 491 |
<p> |
| 492 |
AI chatbots can sometimes behave in unexpected ways, especially if you're new to configuring AI for specific tasks. We're committed to helping you get the most out of your chatbot experience. While we’re working on comprehensive guides and video tutorials, our team is here to assist you directly. If your chatbot isn't delivering the responses you need, please don’t hesitate to <a href="https://mxchat.ai/contact/" target="_blank" rel="noopener noreferrer">contact us</a> for personalized support. |
| 493 |
</p> |
| 494 |
<p> |
| 495 |
We’re dedicated to your success and ready to guide you in aligning the AI's behavior to meet your goals. |
| 496 |
</p> |
| 497 |
</div> |
| 498 |
|
| 499 |
<div class="faq-item"> |
| 500 |
<h3>What is Loops, and how do I get an API key?</h3> |
| 501 |
<p> |
| 502 |
Loops is a powerful SaaS email service that helps you automate and enhance your email marketing campaigns, making it easy to reach and engage with your audience. To integrate Loops with MxChat, you’ll need an API key from Loops. You can obtain this key by logging into your Loops account and navigating to the API settings. Visit the <a href="https://loops.so" target="_blank" rel="noopener noreferrer">Loops website</a> to get started or to sign up for an account. |
| 503 |
</p> |
| 504 |
</div> |
| 505 |
|
| 506 |
|
| 507 |
</div> |
| 508 |
</div> |
| 509 |
<?php |
| 510 |
} |
| 511 |
|
| 512 |
|
| 513 |
|
| 514 |
public function mxchat_create_transcripts_page() { |
| 515 |
global $wpdb; |
| 516 |
$table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; |
| 517 |
|
| 518 |
// Get basic stats |
| 519 |
$total_chats = $wpdb->get_var("SELECT COUNT(DISTINCT session_id) FROM $table_name"); |
| 520 |
$total_messages = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); |
| 521 |
$total_users = $wpdb->get_var("SELECT COUNT(DISTINCT user_email) FROM $table_name WHERE user_email != ''"); |
| 522 |
?> |
| 523 |
<div class="wrap mxchat-admin"> |
| 524 |
<!-- Stats Cards --> |
| 525 |
<div class="mxchat-stats-grid"> |
| 526 |
<div class="mxchat-stat-card"> |
| 527 |
<div class="stat-icon">💬</div> |
| 528 |
<div class="stat-content"> |
| 529 |
<span class="stat-value"><?php echo esc_html($total_chats); ?></span> |
| 530 |
<span class="stat-label"><?php esc_html_e('Total Chats', 'mxchat'); ?></span> |
| 531 |
</div> |
| 532 |
</div> |
| 533 |
<div class="mxchat-stat-card"> |
| 534 |
<div class="stat-icon">📝</div> |
| 535 |
<div class="stat-content"> |
| 536 |
<span class="stat-value"><?php echo esc_html($total_messages); ?></span> |
| 537 |
<span class="stat-label"><?php esc_html_e('Total Messages', 'mxchat'); ?></span> |
| 538 |
</div> |
| 539 |
</div> |
| 540 |
<div class="mxchat-stat-card"> |
| 541 |
<div class="stat-icon">👥</div> |
| 542 |
<div class="stat-content"> |
| 543 |
<span class="stat-value"><?php echo esc_html($total_users); ?></span> |
| 544 |
<span class="stat-label"><?php esc_html_e('Unique Users', 'mxchat'); ?></span> |
| 545 |
</div> |
| 546 |
</div> |
| 547 |
</div> |
| 548 |
|
| 549 |
<!-- Search and Filter Controls --> |
| 550 |
<div class="mxchat-controls-wrapper"> |
| 551 |
<div class="mxchat-search-box"> |
| 552 |
<input type="text" id="mxchat-search-transcripts" |
| 553 |
placeholder="<?php esc_attr_e('Search transcripts...', 'mxchat'); ?>" |
| 554 |
class="regular-text"> |
| 555 |
</div> |
| 556 |
|
| 557 |
<form id="mxchat-delete-form" method="post"> |
| 558 |
<?php wp_nonce_field('mxchat_delete_chat_history', 'mxchat_delete_chat_nonce'); ?> |
| 559 |
<div class="mxchat-controls"> |
| 560 |
<button type="button" id="mxchat-select-all-transcripts" class="mxchat-select-button"> |
| 561 |
<span class="dashicons dashicons-yes-alt"></span> |
| 562 |
<span class="button-text"><?php esc_html_e('Select All', 'mxchat'); ?></span> |
| 563 |
</button> |
| 564 |
<button type="submit" class="button delete-chats-button"> |
| 565 |
<span class="dashicons dashicons-trash"></span> |
| 566 |
<?php esc_html_e('Delete Selected', 'mxchat'); ?> |
| 567 |
</button> |
| 568 |
</div> |
| 569 |
</form> |
| 570 |
</div> |
| 571 |
|
| 572 |
<!-- Transcripts Container --> |
| 573 |
<div id="mxchat-transcripts"></div> |
| 574 |
</div> |
| 575 |
<?php |
| 576 |
} |
| 577 |
|
| 578 |
|
| 579 |
|
| 580 |
|
| 581 |
public function mxchat_create_prompts_page() { |
| 582 |
global $wpdb; |
| 583 |
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 584 |
|
| 585 |
// Display success message if all prompts were deleted |
| 586 |
if (isset($_GET['all_deleted']) && $_GET['all_deleted'] === 'true') { |
| 587 |
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__('All knowledge has been deleted successfully.', 'mxchat') . '</p></div>'; |
| 588 |
} |
| 589 |
|
| 590 |
// Set up pagination and search query |
| 591 |
$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field($_GET['_wpnonce']) : ''; |
| 592 |
$search_query = (!empty($nonce) && wp_verify_nonce($nonce, 'mxchat_prompts_search_nonce') && isset($_GET['search'])) ? sanitize_text_field($_GET['search']) : ''; |
| 593 |
$current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; |
| 594 |
$per_page = 10; |
| 595 |
$offset = ($current_page - 1) * $per_page; |
| 596 |
|
| 597 |
// Modify query to handle search input |
| 598 |
$sql_search = ""; |
| 599 |
if ($search_query) { |
| 600 |
$sql_search = $wpdb->prepare("WHERE article_content LIKE %s", '%' . $wpdb->esc_like($search_query) . '%'); |
| 601 |
} |
| 602 |
|
| 603 |
// Retrieve total number of prompts, considering search filter |
| 604 |
$total_prompts = $wpdb->get_var("SELECT COUNT(*) FROM {$table_name} {$sql_search}"); |
| 605 |
$total_pages = ceil($total_prompts / $per_page); |
| 606 |
|
| 607 |
// Retrieve prompts from the database |
| 608 |
$prompts = $wpdb->get_results( |
| 609 |
$wpdb->prepare( |
| 610 |
"SELECT * FROM {$table_name} {$sql_search} ORDER BY timestamp DESC LIMIT %d OFFSET %d", |
| 611 |
$per_page, |
| 612 |
$offset |
| 613 |
) |
| 614 |
); |
| 615 |
|
| 616 |
?> |
| 617 |
|
| 618 |
<div class="wrap mxchat-admin"> |
| 619 |
<div class="mxchat-grid-container"> |
| 620 |
<!-- Submit Content Form --> |
| 621 |
<div class="mxchat-grid-item"> |
| 622 |
<h2>Submit Content</h2> |
| 623 |
<form id="mxchat-content-form" method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_submit_content')); ?>"> |
| 624 |
<?php wp_nonce_field('mxchat_submit_content_action', 'mxchat_submit_content_nonce'); ?> |
| 625 |
<div class="mxchat-form-group"> |
| 626 |
<label for="article_content">Article Content:</label> |
| 627 |
<textarea name="article_content" id="article_content" required></textarea> |
| 628 |
</div> |
| 629 |
<div class="mxchat-form-group"> |
| 630 |
<label for="article_url">Article URL (Optional):</label> |
| 631 |
<input type="url" name="article_url" id="article_url" placeholder="Enter related URL for the content"> |
| 632 |
</div> |
| 633 |
<input type="submit" name="submit_content" value="Submit Content" class="button button-primary submit-content-button" /> |
| 634 |
</form> |
| 635 |
<div id="mxchat-content-loading" class="mxchat-content-spinner" style="display: none;"></div> |
| 636 |
<div id="mxchat-content-loading-text" class="mxchat-loading-text">Submitting content, please wait...</div> |
| 637 |
</div> |
| 638 |
|
| 639 |
|
| 640 |
<!-- Combined Knowledge Import Settings --> |
| 641 |
<div class="mxchat-grid-item"> |
| 642 |
<div class="mxchat-flex-section"> |
| 643 |
<h2><?php esc_html_e('Content Import Settings', 'mxchat'); ?></h2> |
| 644 |
|
| 645 |
<div class="mxchat-settings-row"> |
| 646 |
<!-- Auto-Sync Toggle Section --> |
| 647 |
<div class="mxchat-sync-settings"> |
| 648 |
<form method="post" action="options.php" class="mxchat-sync-settings-form"> |
| 649 |
<?php |
| 650 |
settings_fields('mxchat_prompts_options'); |
| 651 |
$posts_sync = get_option('mxchat_auto_sync_posts'); |
| 652 |
$pages_sync = get_option('mxchat_auto_sync_pages'); |
| 653 |
?> |
| 654 |
<div class="mxchat-toggle-group"> |
| 655 |
<div class="mxchat-toggle-container"> |
| 656 |
<label class="mxchat-toggle-switch"> |
| 657 |
<input type="checkbox" |
| 658 |
name="mxchat_auto_sync_posts" |
| 659 |
value="1" |
| 660 |
<?php checked($posts_sync, '1'); ?>> |
| 661 |
<span class="mxchat-toggle-slider"></span> |
| 662 |
</label> |
| 663 |
<span class="mxchat-toggle-label"> |
| 664 |
<?php esc_html_e('Auto-sync Posts', 'mxchat'); ?> |
| 665 |
</span> |
| 666 |
</div> |
| 667 |
|
| 668 |
<div class="mxchat-toggle-container"> |
| 669 |
<label class="mxchat-toggle-switch"> |
| 670 |
<input type="checkbox" |
| 671 |
name="mxchat_auto_sync_pages" |
| 672 |
value="1" |
| 673 |
<?php checked($pages_sync, '1'); ?>> |
| 674 |
<span class="mxchat-toggle-slider"></span> |
| 675 |
</label> |
| 676 |
<span class="mxchat-toggle-label"> |
| 677 |
<?php esc_html_e('Auto-sync Pages', 'mxchat'); ?> |
| 678 |
</span> |
| 679 |
</div> |
| 680 |
<div class="mxchat-submit-wrapper"> |
| 681 |
<?php submit_button('Save Settings', 'save-button-settings', 'submit', false); ?> |
| 682 |
</div> |
| 683 |
</div> |
| 684 |
</form> |
| 685 |
</div> |
| 686 |
|
| 687 |
<!-- URL Import Section with Processing Status --> |
| 688 |
<div class="mxchat-import-section"> |
| 689 |
<?php |
| 690 |
// Check for any active processing |
| 691 |
$pdf_url = get_transient('mxchat_last_pdf_url'); |
| 692 |
$sitemap_url = get_transient('mxchat_last_sitemap_url'); |
| 693 |
$pdf_status = $pdf_url ? $this->get_pdf_processing_status($pdf_url) : false; |
| 694 |
$sitemap_status = $sitemap_url ? $this->get_sitemap_processing_status($sitemap_url) : false; |
| 695 |
|
| 696 |
// Clear old completed statuses |
| 697 |
if ($pdf_status && $pdf_status['status'] === 'complete') { |
| 698 |
delete_transient('mxchat_last_pdf_url'); |
| 699 |
$pdf_status = false; |
| 700 |
} |
| 701 |
if ($sitemap_status && $sitemap_status['status'] === 'complete') { |
| 702 |
delete_transient('mxchat_last_sitemap_url'); |
| 703 |
$sitemap_status = false; |
| 704 |
} |
| 705 |
|
| 706 |
$is_processing = ($pdf_status && $pdf_status['status'] === 'processing') || |
| 707 |
($sitemap_status && $sitemap_status['status'] === 'processing'); |
| 708 |
?> |
| 709 |
|
| 710 |
<!-- Import Description --> |
| 711 |
<div class="mxchat-import-description"> |
| 712 |
<p class="description-text"> |
| 713 |
Import content from various sources: |
| 714 |
</p> |
| 715 |
<ul class="import-options"> |
| 716 |
<li><strong>Sitemap URL:</strong> Add all pages from your sitemap</li> |
| 717 |
<li><strong>PDF URL:</strong> Import content from an online PDF</li> |
| 718 |
<li><strong>Single URL:</strong> Import from any webpage</li> |
| 719 |
</ul> |
| 720 |
</div> |
| 721 |
|
| 722 |
<!-- URL Import Form --> |
| 723 |
<?php if (!$is_processing) : ?> |
| 724 |
<form id="mxchat-sitemap-form" method="post" class="mxchat-sitemap-form" |
| 725 |
action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_submit_sitemap')); ?>"> |
| 726 |
<?php wp_nonce_field('mxchat_submit_sitemap_action', 'mxchat_submit_sitemap_nonce'); ?> |
| 727 |
<div class="mxchat-url-input-group"> |
| 728 |
<input type="url" |
| 729 |
name="sitemap_url" |
| 730 |
id="sitemap_url" |
| 731 |
placeholder="<?php esc_attr_e('Enter URL (Sitemap, PDF, or webpage)', 'mxchat'); ?>" |
| 732 |
required |
| 733 |
aria-label="<?php esc_attr_e('URL Input', 'mxchat'); ?>" |
| 734 |
/> |
| 735 |
<input type="submit" |
| 736 |
name="submit_sitemap" |
| 737 |
value="<?php esc_attr_e('Import', 'mxchat'); ?>" |
| 738 |
class="button button-primary" |
| 739 |
/> |
| 740 |
</div> |
| 741 |
</form> |
| 742 |
<?php endif; ?> |
| 743 |
|
| 744 |
<!-- Loading Indicators --> |
| 745 |
<div id="mxchat-sitemap-loading" class="mxchat-spinner" style="display: none;" |
| 746 |
aria-hidden="true"></div> |
| 747 |
<div id="mxchat-loading-text" class="screen-reader-text" style="display: none;"> |
| 748 |
<?php esc_html_e('Loading information into database, please wait...', 'mxchat'); ?> |
| 749 |
</div> |
| 750 |
|
| 751 |
<!-- PDF Processing Status --> |
| 752 |
<?php if ($pdf_status && $pdf_status['status'] !== 'complete') : ?> |
| 753 |
<div class="mxchat-process-status pdf" role="alert" aria-live="polite"> |
| 754 |
<h3><?php esc_html_e('PDF Processing Status (Refresh page for update)', 'mxchat'); ?></h3> |
| 755 |
<p><?php printf(esc_html__('Progress: %1$d of %2$d pages (%3$d%%)', 'mxchat'), |
| 756 |
absint($pdf_status['processed_pages']), |
| 757 |
absint($pdf_status['total_pages']), |
| 758 |
absint($pdf_status['percentage'])); |
| 759 |
?></p> |
| 760 |
<p><?php printf(esc_html__('Status: %s', 'mxchat'), |
| 761 |
esc_html(ucfirst($pdf_status['status']))); |
| 762 |
?></p> |
| 763 |
<p><?php printf(esc_html__('Last update: %s', 'mxchat'), |
| 764 |
esc_html($pdf_status['last_update'])); |
| 765 |
?></p> |
| 766 |
</div> |
| 767 |
<?php endif; ?> |
| 768 |
|
| 769 |
<!-- Sitemap Processing Status --> |
| 770 |
<?php if ($sitemap_status && $sitemap_status['status'] !== 'complete') : ?> |
| 771 |
<div class="mxchat-process-status sitemap" role="alert" aria-live="polite"> |
| 772 |
<h3><?php esc_html_e('Sitemap Processing Status (Refresh page for update)', 'mxchat'); ?></h3> |
| 773 |
<p><?php printf(esc_html__('Progress: %1$d of %2$d URLs (%3$d%%)', 'mxchat'), |
| 774 |
absint($sitemap_status['processed_urls']), |
| 775 |
absint($sitemap_status['total_urls']), |
| 776 |
absint($sitemap_status['percentage'])); |
| 777 |
?></p> |
| 778 |
<p><?php printf(esc_html__('Status: %s', 'mxchat'), |
| 779 |
esc_html(ucfirst($sitemap_status['status']))); |
| 780 |
?></p> |
| 781 |
<p><?php printf(esc_html__('Last update: %s', 'mxchat'), |
| 782 |
esc_html($sitemap_status['last_update'])); |
| 783 |
?></p> |
| 784 |
</div> |
| 785 |
<?php endif; ?> |
| 786 |
|
| 787 |
<!-- Stop Processing Button --> |
| 788 |
<?php if ($is_processing) : ?> |
| 789 |
<form id="mxchat-stop-form" method="post" class="mxchat-stop-form" |
| 790 |
action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_stop_processing')); ?>"> |
| 791 |
<?php wp_nonce_field('mxchat_stop_processing_action', 'mxchat_stop_processing_nonce'); ?> |
| 792 |
<input type="submit" |
| 793 |
name="stop_processing" |
| 794 |
value="<?php esc_attr_e('Stop Processing', 'mxchat'); ?>" |
| 795 |
class="button button-secondary" |
| 796 |
/> |
| 797 |
</form> |
| 798 |
<?php endif; ?> |
| 799 |
</div> |
| 800 |
</div> |
| 801 |
</div> |
| 802 |
</div> |
| 803 |
|
| 804 |
</div> |
| 805 |
|
| 806 |
<!-- Knowledge Base Management Section --> |
| 807 |
<div class="mxchat-knowledge-container"> |
| 808 |
<!-- Left Column: Management Controls --> |
| 809 |
<div class="mxchat-knowledge-controls"> |
| 810 |
<div class="mxchat-controls-header"> |
| 811 |
<span class="displaying-num"><?php echo esc_html($total_prompts); ?> items</span> |
| 812 |
</div> |
| 813 |
|
| 814 |
<?php |
| 815 |
// Generate pagination links |
| 816 |
$page_links = paginate_links(array( |
| 817 |
'base' => add_query_arg(array( |
| 818 |
'paged' => '%#%', |
| 819 |
'search' => urlencode($search_query), |
| 820 |
'_wpnonce' => wp_create_nonce('mxchat_prompts_search_nonce') |
| 821 |
), admin_url('admin.php?page=mxchat-prompts')), |
| 822 |
'format' => '', |
| 823 |
'prev_text' => __('« Previous'), |
| 824 |
'next_text' => __('Next »'), |
| 825 |
'total' => $total_pages, |
| 826 |
'current' => $current_page, |
| 827 |
)); |
| 828 |
|
| 829 |
if ($page_links) : ?> |
| 830 |
<div class="mxchat-pagination"> |
| 831 |
<?php echo wp_kses_post($page_links); ?> |
| 832 |
</div> |
| 833 |
<?php endif; ?> |
| 834 |
|
| 835 |
|
| 836 |
<form method="post" |
| 837 |
action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_delete_all_prompts')); ?>" |
| 838 |
class="delete-form" |
| 839 |
onsubmit="return confirm('<?php esc_attr_e('Are you sure you want to delete all prompts? This action cannot be undone.', 'mxchat'); ?>');"> |
| 840 |
<?php wp_nonce_field('mxchat_delete_all_prompts_action', 'mxchat_delete_all_prompts_nonce'); ?> |
| 841 |
<input type="submit" |
| 842 |
name="delete_all_prompts" |
| 843 |
value="<?php esc_attr_e('Delete All Knowledge', 'mxchat'); ?>" |
| 844 |
class="button button-link-delete mxchat-delete-all" /> |
| 845 |
</form> |
| 846 |
|
| 847 |
</div> |
| 848 |
|
| 849 |
<!-- Right Column: Search --> |
| 850 |
<div class="mxchat-knowledge-search"> |
| 851 |
<form method="get" id="knowledge-search" class="search-form"> |
| 852 |
<?php wp_nonce_field('mxchat_prompts_search_nonce'); ?> |
| 853 |
<input type="hidden" name="page" value="mxchat-prompts" /> |
| 854 |
<div class="mxchat-search-group"> |
| 855 |
<input type="text" |
| 856 |
name="search" |
| 857 |
placeholder="Search Knowledge" |
| 858 |
value="<?php echo esc_attr($search_query); ?>" |
| 859 |
class="search-input" /> |
| 860 |
<button type="submit" class="button button-primary search-button"> |
| 861 |
<span class="dashicons dashicons-search"></span> |
| 862 |
Search |
| 863 |
</button> |
| 864 |
</div> |
| 865 |
</form> |
| 866 |
</div> |
| 867 |
</div> |
| 868 |
|
| 869 |
|
| 870 |
<!-- Prompts Table --> |
| 871 |
<table class="mxchat-table"> |
| 872 |
<thead> |
| 873 |
<tr> |
| 874 |
<th>ID</th> |
| 875 |
<th>Article Content</th> |
| 876 |
<th>URL</th> |
| 877 |
<th>Actions</th> |
| 878 |
</tr> |
| 879 |
</thead> |
| 880 |
<tbody> |
| 881 |
<?php if ($prompts) : ?> |
| 882 |
<?php foreach ($prompts as $prompt) : ?> |
| 883 |
<tr id="prompt-<?php echo esc_attr($prompt->id); ?>"> |
| 884 |
<td><?php echo esc_html($prompt->id); ?></td> |
| 885 |
<td class="mxchat_article_content_dashboard"> |
| 886 |
<span class="content-view"><?php echo wp_kses_post(wpautop(esc_textarea($prompt->article_content))); ?></span> |
| 887 |
<textarea class="content-edit" style="display:none;"><?php echo esc_textarea($prompt->article_content); ?></textarea> |
| 888 |
</td> |
| 889 |
<td class="mxchat_article_url_dashboard"> |
| 890 |
<span class="url-view"> |
| 891 |
<?php if (!empty($prompt->source_url)) : ?> |
| 892 |
<a href="<?php echo esc_url($prompt->source_url); ?>" target="_blank"><?php echo esc_html($prompt->source_url); ?></a> |
| 893 |
<?php else : ?> |
| 894 |
N/A |
| 895 |
<?php endif; ?> |
| 896 |
</span> |
| 897 |
<input type="url" class="url-edit" value="<?php echo esc_attr($prompt->source_url); ?>" style="display:none;" /> |
| 898 |
</td> |
| 899 |
<td> |
| 900 |
<button class="button edit-button" data-id="<?php echo esc_attr($prompt->id); ?>">Edit</button> |
| 901 |
<button class="button save-button mxchat-save-prompt" data-id="<?php echo esc_attr($prompt->id); ?>" style="display:none;" data-nonce="<?php echo wp_create_nonce('mxchat_save_inline_nonce'); ?>">Save</button> <a href="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_delete_prompt&id=' . esc_attr($prompt->id) . '&_wpnonce=' . wp_create_nonce('mxchat_delete_prompt_nonce'))); ?>" class="button delete-button">Delete</a> |
| 902 |
</td> |
| 903 |
</tr> |
| 904 |
<?php endforeach; ?> |
| 905 |
<?php else : ?> |
| 906 |
<tr> |
| 907 |
<td colspan="4"><?php esc_html_e('No prompts found.', 'mxchat'); ?></td> |
| 908 |
</tr> |
| 909 |
<?php endif; ?> |
| 910 |
</tbody> |
| 911 |
</table> |
| 912 |
</div> |
| 913 |
<?php |
| 914 |
} |
| 915 |
public function mxchat_handle_delete_all_prompts() { |
| 916 |
// Verify nonce |
| 917 |
if (!isset($_POST['mxchat_delete_all_prompts_nonce']) || !wp_verify_nonce($_POST['mxchat_delete_all_prompts_nonce'], 'mxchat_delete_all_prompts_action')) { |
| 918 |
wp_die(__('Nonce verification failed.', 'mxchat')); |
| 919 |
} |
| 920 |
|
| 921 |
// Check permissions |
| 922 |
if (!current_user_can('manage_options')) { |
| 923 |
wp_die(__('You do not have sufficient permissions to delete all prompts.', 'mxchat')); |
| 924 |
} |
| 925 |
|
| 926 |
global $wpdb; |
| 927 |
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 928 |
|
| 929 |
// Delete all prompts from the table |
| 930 |
$wpdb->query("DELETE FROM {$table_name}"); |
| 931 |
|
| 932 |
// Clear relevant cache |
| 933 |
wp_cache_delete('all_prompts', 'mxchat_prompts'); |
| 934 |
|
| 935 |
// Redirect back with a success message |
| 936 |
$redirect_url = add_query_arg(array( |
| 937 |
'page' => 'mxchat-prompts', |
| 938 |
'all_deleted' => 'true' |
| 939 |
), admin_url('admin.php')); |
| 940 |
|
| 941 |
wp_safe_redirect($redirect_url); |
| 942 |
exit; |
| 943 |
} |
| 944 |
public function mxchat_handle_delete_prompt() { |
| 945 |
// Sanitize and validate nonce |
| 946 |
$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : ''; |
| 947 |
if (empty($nonce) || !wp_verify_nonce($nonce, 'mxchat_delete_prompt_nonce')) { |
| 948 |
wp_die('Nonce verification failed.'); |
| 949 |
} |
| 950 |
|
| 951 |
// Check permissions |
| 952 |
if (!current_user_can('manage_options')) { |
| 953 |
wp_die('You do not have sufficient permissions to delete prompts.'); |
| 954 |
} |
| 955 |
|
| 956 |
// Validate and sanitize ID parameter |
| 957 |
$id = isset($_GET['id']) ? intval($_GET['id']) : 0; |
| 958 |
if ($id <= 0) { |
| 959 |
wp_die('Invalid prompt ID.'); |
| 960 |
} |
| 961 |
|
| 962 |
global $wpdb; |
| 963 |
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 964 |
|
| 965 |
// Clear cache and delete prompt |
| 966 |
wp_cache_delete('prompt_' . $id, 'mxchat_prompts'); |
| 967 |
$wpdb->delete($table_name, array('id' => $id), array('%d')); |
| 968 |
|
| 969 |
wp_safe_redirect(add_query_arg(array('page' => 'mxchat-prompts', 'deleted' => 'true'), admin_url('admin.php'))); |
| 970 |
exit; |
| 971 |
} |
| 972 |
public function mxchat_generate_embedding($text) { |
| 973 |
$options = get_option('mxchat_options'); |
| 974 |
$api_key = $options['api_key'] ?? 'default_api_key'; |
| 975 |
|
| 976 |
$response = wp_remote_post('https://api.openai.com/v1/embeddings', array( |
| 977 |
'body' => wp_json_encode(array( |
| 978 |
'model' => 'text-embedding-ada-002', |
| 979 |
'input' => $text |
| 980 |
)), |
| 981 |
'headers' => array( |
| 982 |
'Authorization' => 'Bearer ' . $api_key, |
| 983 |
'Content-Type' => 'application/json' |
| 984 |
), |
| 985 |
)); |
| 986 |
|
| 987 |
if (is_wp_error($response)) { |
| 988 |
return null; |
| 989 |
} |
| 990 |
|
| 991 |
$response_data = json_decode(wp_remote_retrieve_body($response), true); |
| 992 |
return $response_data['data'][0]['embedding'] ?? null; |
| 993 |
} |
| 994 |
public function mxchat_delete_chat_history() { |
| 995 |
if (!current_user_can('manage_options')) { |
| 996 |
echo wp_json_encode(['error' => 'You do not have sufficient permissions.']); |
| 997 |
wp_die(); |
| 998 |
} |
| 999 |
|
| 1000 |
check_ajax_referer('mxchat_delete_chat_history', 'security'); |
| 1001 |
|
| 1002 |
global $wpdb; |
| 1003 |
$table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; |
| 1004 |
|
| 1005 |
if (isset($_POST['delete_session_ids']) && is_array($_POST['delete_session_ids'])) { |
| 1006 |
foreach ($_POST['delete_session_ids'] as $session_id) { |
| 1007 |
$session_id_sanitized = sanitize_text_field($session_id); |
| 1008 |
|
| 1009 |
// Clear relevant cache before deletion |
| 1010 |
$cache_key = 'chat_session_' . $session_id_sanitized; |
| 1011 |
wp_cache_delete($cache_key, 'mxchat_chat_sessions'); |
| 1012 |
|
| 1013 |
// Perform the deletion |
| 1014 |
$wpdb->delete($table_name, ['session_id' => $session_id_sanitized]); |
| 1015 |
} |
| 1016 |
|
| 1017 |
// Optionally, clear a general cache if you have one |
| 1018 |
wp_cache_delete('all_chat_sessions', 'mxchat_chat_sessions'); |
| 1019 |
|
| 1020 |
echo wp_json_encode(['success' => 'Selected chat sessions have been deleted.']); |
| 1021 |
} else { |
| 1022 |
echo wp_json_encode(['error' => 'No chat sessions selected for deletion.']); |
| 1023 |
} |
| 1024 |
|
| 1025 |
wp_die(); |
| 1026 |
} |
| 1027 |
|
| 1028 |
|
| 1029 |
public function mxchat_save_inline_prompt() { |
| 1030 |
// Check for nonce security |
| 1031 |
check_ajax_referer('mxchat_save_inline_nonce'); |
| 1032 |
|
| 1033 |
// Verify permissions |
| 1034 |
if (!current_user_can('manage_options')) { |
| 1035 |
wp_send_json_error('Permission denied.'); |
| 1036 |
return; |
| 1037 |
} |
| 1038 |
|
| 1039 |
global $wpdb; |
| 1040 |
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 1041 |
|
| 1042 |
// Validate and sanitize input data |
| 1043 |
$prompt_id = isset($_POST['id']) ? absint($_POST['id']) : 0; |
| 1044 |
$article_content = isset($_POST['article_content']) ? sanitize_textarea_field($_POST['article_content']) : ''; |
| 1045 |
$article_url = isset($_POST['article_url']) ? esc_url_raw($_POST['article_url']) : ''; |
| 1046 |
|
| 1047 |
if ($prompt_id > 0 && !empty($article_content)) { |
| 1048 |
// Re-generate the embedding vector for the updated content |
| 1049 |
$embedding_vector = $this->mxchat_generate_embedding($article_content); |
| 1050 |
|
| 1051 |
if (is_array($embedding_vector)) { |
| 1052 |
// Serialize the embedding vector before storing it |
| 1053 |
$embedding_vector_serialized = serialize($embedding_vector); |
| 1054 |
|
| 1055 |
// Update the prompt in the database |
| 1056 |
$updated = $wpdb->update( |
| 1057 |
$table_name, |
| 1058 |
array( |
| 1059 |
'article_content' => $article_content, |
| 1060 |
'embedding_vector' => $embedding_vector_serialized, |
| 1061 |
'source_url' => $article_url, |
| 1062 |
), |
| 1063 |
array('id' => $prompt_id), |
| 1064 |
array('%s', '%s', '%s'), |
| 1065 |
array('%d') |
| 1066 |
); |
| 1067 |
|
| 1068 |
if ($updated !== false) { |
| 1069 |
wp_send_json_success(); |
| 1070 |
} else { |
| 1071 |
wp_send_json_error('Database update failed.'); |
| 1072 |
} |
| 1073 |
} else { |
| 1074 |
wp_send_json_error('Embedding generation failed.'); |
| 1075 |
} |
| 1076 |
} else { |
| 1077 |
wp_send_json_error('Invalid data.'); |
| 1078 |
} |
| 1079 |
} |
| 1080 |
|
| 1081 |
|
| 1082 |
|
| 1083 |
// Add this method to handle post updates |
| 1084 |
public function handle_post_update($post_id, $post, $update) { |
| 1085 |
// Don't process auto-saves or revisions |
| 1086 |
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { |
| 1087 |
//error_log('MXChat: Skipping - autosave'); |
| 1088 |
return; |
| 1089 |
} |
| 1090 |
if (wp_is_post_revision($post_id)) { |
| 1091 |
//error_log('MXChat: Skipping - revision'); |
| 1092 |
return; |
| 1093 |
} |
| 1094 |
|
| 1095 |
// Only process published content |
| 1096 |
if (!in_array($post->post_status, array('publish'))) { |
| 1097 |
//error_log('MXChat: Skipping - not published'); |
| 1098 |
return; |
| 1099 |
} |
| 1100 |
|
| 1101 |
// Check if sync is enabled for this post type |
| 1102 |
$post_type = $post->post_type; |
| 1103 |
$sync_option = ($post_type === 'post') ? 'mxchat_auto_sync_posts' : 'mxchat_auto_sync_pages'; |
| 1104 |
|
| 1105 |
if (get_option($sync_option) !== '1') { |
| 1106 |
//error_log('MXChat: Skipping - sync not enabled for this type'); |
| 1107 |
return; |
| 1108 |
} |
| 1109 |
|
| 1110 |
// Only process posts and pages |
| 1111 |
if (!in_array($post_type, array('post', 'page'))) return; |
| 1112 |
|
| 1113 |
global $wpdb; |
| 1114 |
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 1115 |
|
| 1116 |
// Get the post content and URL |
| 1117 |
$content = wp_strip_all_tags($post->post_content); |
| 1118 |
$url = get_permalink($post_id); |
| 1119 |
|
| 1120 |
// Check if this URL already exists in the database |
| 1121 |
$existing_entry = $wpdb->get_row( |
| 1122 |
$wpdb->prepare( |
| 1123 |
"SELECT id FROM $table_name WHERE source_url = %s", |
| 1124 |
$url |
| 1125 |
) |
| 1126 |
); |
| 1127 |
|
| 1128 |
// Generate embedding for the content |
| 1129 |
$embedding_vector = $this->mxchat_generate_embedding($content); |
| 1130 |
if (!$embedding_vector) return; |
| 1131 |
|
| 1132 |
if ($existing_entry) { |
| 1133 |
// Update existing entry |
| 1134 |
$wpdb->update( |
| 1135 |
$table_name, |
| 1136 |
array( |
| 1137 |
'article_content' => $content, |
| 1138 |
'embedding_vector' => serialize($embedding_vector), |
| 1139 |
'timestamp' => current_time('mysql') |
| 1140 |
), |
| 1141 |
array('id' => $existing_entry->id), |
| 1142 |
array('%s', '%s', '%s'), |
| 1143 |
array('%d') |
| 1144 |
); |
| 1145 |
} else { |
| 1146 |
// Insert new entry |
| 1147 |
$wpdb->insert( |
| 1148 |
$table_name, |
| 1149 |
array( |
| 1150 |
'article_content' => $content, |
| 1151 |
'source_url' => $url, |
| 1152 |
'embedding_vector' => serialize($embedding_vector), |
| 1153 |
'timestamp' => current_time('mysql') |
| 1154 |
), |
| 1155 |
array('%s', '%s', '%s', '%s') |
| 1156 |
); |
| 1157 |
} |
| 1158 |
} |
| 1159 |
public function mxchat_handle_content_submission() { |
| 1160 |
// Check if the form was submitted and the user has sufficient permissions |
| 1161 |
if (!isset($_POST['submit_content']) || !current_user_can('manage_options')) { |
| 1162 |
return; |
| 1163 |
} |
| 1164 |
|
| 1165 |
// Verify the nonce field for security |
| 1166 |
$nonce = isset($_POST['mxchat_submit_content_nonce']) ? sanitize_text_field(wp_unslash($_POST['mxchat_submit_content_nonce'])) : ''; |
| 1167 |
if (!wp_verify_nonce($nonce, 'mxchat_submit_content_action')) { |
| 1168 |
wp_die('Nonce verification failed.'); |
| 1169 |
} |
| 1170 |
|
| 1171 |
// Sanitize the content input |
| 1172 |
$article_content = sanitize_textarea_field($_POST['article_content']); |
| 1173 |
|
| 1174 |
// Sanitize the URL input (optional URL) |
| 1175 |
$article_url = isset($_POST['article_url']) ? esc_url_raw($_POST['article_url']) : ''; // Default to empty if not provided |
| 1176 |
|
| 1177 |
// Generate the embedding vector for the content |
| 1178 |
$embedding_vector = $this->mxchat_generate_embedding($article_content); |
| 1179 |
|
| 1180 |
global $wpdb; |
| 1181 |
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 1182 |
|
| 1183 |
// Check if the 'source_url' column exists in the table and add it if it doesn't |
| 1184 |
if ($wpdb->get_var($wpdb->prepare("SHOW COLUMNS FROM {$table_name} LIKE %s", 'source_url')) != 'source_url') { |
| 1185 |
// Use wpdb::query and a prepared statement to avoid SQL injection |
| 1186 |
$wpdb->query($wpdb->prepare("ALTER TABLE {$table_name} ADD source_url VARCHAR(255) DEFAULT ''")); |
| 1187 |
} |
| 1188 |
|
| 1189 |
if (is_array($embedding_vector)) { |
| 1190 |
// Serialize the embedding vector before storing it |
| 1191 |
$embedding_vector_serialized = serialize($embedding_vector); |
| 1192 |
|
| 1193 |
// Insert the content, embedding vector, and source URL into the database, using a prepared statement |
| 1194 |
$inserted = $wpdb->insert( |
| 1195 |
$table_name, |
| 1196 |
array( |
| 1197 |
'article_content' => $article_content, |
| 1198 |
'embedding_vector' => $embedding_vector_serialized, |
| 1199 |
'source_url' => $article_url, // Insert the URL, empty string if not provided |
| 1200 |
), |
| 1201 |
array( |
| 1202 |
'%s', // Format for article_content (string) |
| 1203 |
'%s', // Format for embedding_vector (serialized string) |
| 1204 |
'%s', // Format for source_url (string) |
| 1205 |
) |
| 1206 |
); |
| 1207 |
|
| 1208 |
if ($inserted === false) { |
| 1209 |
//error_log('Error inserting content: ' . $wpdb->last_error); |
| 1210 |
set_transient('mxchat_admin_notice_error', 'Error inserting content into the database. Please try again.', 30); |
| 1211 |
} else { |
| 1212 |
set_transient('mxchat_admin_notice_success', 'Content successfully submitted!', 30); |
| 1213 |
} |
| 1214 |
|
| 1215 |
} else { |
| 1216 |
//error_log('Embedding generation failed for article content: ' . $article_content); |
| 1217 |
set_transient('mxchat_admin_notice_error', 'Embedding generation failed. Please ensure your API key is correct and try again.', 30); |
| 1218 |
} |
| 1219 |
|
| 1220 |
// Redirect after setting the transient |
| 1221 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1222 |
exit; |
| 1223 |
} |
| 1224 |
private function is_pdf_url($url, $response) { |
| 1225 |
$content_type = wp_remote_retrieve_header($response, 'content-type'); |
| 1226 |
$file_extension = strtolower(pathinfo($url, PATHINFO_EXTENSION)); |
| 1227 |
|
| 1228 |
return strpos($content_type, 'pdf') !== false || $file_extension === 'pdf'; |
| 1229 |
} |
| 1230 |
private function handle_pdf_for_knowledge_base($pdf_url, $response) { |
| 1231 |
if (!current_user_can('manage_options')) { |
| 1232 |
//error_log('Unauthorized PDF processing attempt'); |
| 1233 |
return false; |
| 1234 |
} |
| 1235 |
|
| 1236 |
$pdf_url = esc_url_raw($pdf_url); |
| 1237 |
$upload_dir = wp_upload_dir(); |
| 1238 |
|
| 1239 |
if (isset($upload_dir['error']) && $upload_dir['error'] !== false) { |
| 1240 |
//error_log(sprintf('Upload directory error: %s', esc_html($upload_dir['error']))); |
| 1241 |
return false; |
| 1242 |
} |
| 1243 |
|
| 1244 |
$pdf_filename = sanitize_file_name('mxchat_kb_' . time() . '.pdf'); |
| 1245 |
$pdf_path = trailingslashit($upload_dir['path']) . $pdf_filename; |
| 1246 |
|
| 1247 |
$response_body = wp_remote_retrieve_body($response); |
| 1248 |
if (empty($response_body)) { |
| 1249 |
//error_log('Empty PDF response body'); |
| 1250 |
return false; |
| 1251 |
} |
| 1252 |
|
| 1253 |
if (!wp_mkdir_p(dirname($pdf_path))) { |
| 1254 |
//error_log(sprintf('Failed to create directory for PDF: %s', esc_html($pdf_path))); |
| 1255 |
return false; |
| 1256 |
} |
| 1257 |
|
| 1258 |
try { |
| 1259 |
file_put_contents($pdf_path, $response_body); |
| 1260 |
|
| 1261 |
if (!file_exists($pdf_path)) { |
| 1262 |
throw new Exception('Failed to save PDF file'); |
| 1263 |
} |
| 1264 |
|
| 1265 |
$parser = new \Smalot\PdfParser\Parser(); |
| 1266 |
$pdf = $parser->parseFile($pdf_path); |
| 1267 |
$total_pages = absint(count($pdf->getPages())); |
| 1268 |
|
| 1269 |
if ($total_pages < 1) { |
| 1270 |
throw new Exception('Invalid PDF: no pages found'); |
| 1271 |
} |
| 1272 |
|
| 1273 |
wp_schedule_single_event(time(), 'mxchat_process_pdf_pages', array( |
| 1274 |
'pdf_path' => $pdf_path, |
| 1275 |
'pdf_url' => $pdf_url, |
| 1276 |
'total_pages' => $total_pages, |
| 1277 |
'batch_size' => absint(15), |
| 1278 |
'batch_pause' => absint(10) |
| 1279 |
)); |
| 1280 |
|
| 1281 |
$status_data = array( |
| 1282 |
'total_pages' => $total_pages, |
| 1283 |
'processed_pages' => 0, |
| 1284 |
'status' => 'processing', |
| 1285 |
'last_update' => time() |
| 1286 |
); |
| 1287 |
|
| 1288 |
set_transient( |
| 1289 |
sanitize_key('mxchat_pdf_status_' . md5($pdf_url)), |
| 1290 |
array_map('sanitize_text_field', $status_data), |
| 1291 |
DAY_IN_SECONDS |
| 1292 |
); |
| 1293 |
|
| 1294 |
return 'scheduled'; |
| 1295 |
|
| 1296 |
} catch (Exception $e) { |
| 1297 |
//error_log(sprintf('Error preparing PDF for processing: %s', esc_html($e->getMessage()))); |
| 1298 |
if (file_exists($pdf_path)) { |
| 1299 |
wp_delete_file($pdf_path); |
| 1300 |
} |
| 1301 |
return false; |
| 1302 |
} |
| 1303 |
} |
| 1304 |
public static function process_pdf_pages_cron($pdf_path, $pdf_url, $total_pages, $batch_size, $batch_pause) { |
| 1305 |
// Validate inputs |
| 1306 |
$pdf_path = sanitize_text_field($pdf_path); |
| 1307 |
$pdf_url = esc_url_raw($pdf_url); |
| 1308 |
$total_pages = absint($total_pages); |
| 1309 |
$batch_size = absint($batch_size); |
| 1310 |
$batch_pause = absint($batch_pause); |
| 1311 |
|
| 1312 |
try { |
| 1313 |
if (!file_exists($pdf_path)) { |
| 1314 |
throw new Exception(sprintf('PDF file not found at path: %s', esc_html($pdf_path))); |
| 1315 |
} |
| 1316 |
|
| 1317 |
$parser = new \Smalot\PdfParser\Parser(); |
| 1318 |
$pdf = $parser->parseFile($pdf_path); |
| 1319 |
$pages = $pdf->getPages(); |
| 1320 |
|
| 1321 |
// Get current progress |
| 1322 |
$status_key = sanitize_key('mxchat_pdf_status_' . md5($pdf_url)); |
| 1323 |
$status = get_transient($status_key); |
| 1324 |
|
| 1325 |
if (!$status || !is_array($status)) { |
| 1326 |
throw new Exception('Invalid status data retrieved from transient'); |
| 1327 |
} |
| 1328 |
|
| 1329 |
$start_page = absint($status['processed_pages']); |
| 1330 |
$end_page = min($start_page + $batch_size, $total_pages); |
| 1331 |
|
| 1332 |
$instance = new self(); // Create an instance of the class |
| 1333 |
|
| 1334 |
for ($i = $start_page; $i < $end_page; $i++) { |
| 1335 |
$text = $pages[$i]->getText(); |
| 1336 |
$sanitized_content = $instance->mxchat_sanitize_content_for_api($text); // Call via instance |
| 1337 |
|
| 1338 |
if (!empty($sanitized_content)) { |
| 1339 |
$embedding_vector = $instance->mxchat_generate_embedding($sanitized_content); // Call via instance |
| 1340 |
if (is_array($embedding_vector)) { |
| 1341 |
$metadata = array( |
| 1342 |
'document_type' => 'pdf', |
| 1343 |
'total_pages' => $total_pages, |
| 1344 |
'current_page' => $i + 1, |
| 1345 |
'prev_page' => $i > 0 ? $i : null, |
| 1346 |
'next_page' => $i < ($total_pages - 1) ? $i + 2 : null, |
| 1347 |
'source_url' => $pdf_url |
| 1348 |
); |
| 1349 |
|
| 1350 |
$content_with_metadata = wp_json_encode($metadata) . "\n---\n" . $sanitized_content; |
| 1351 |
$page_url = esc_url($pdf_url . "#page=" . ($i + 1)); |
| 1352 |
|
| 1353 |
$options = get_option('mxchat_options'); |
| 1354 |
MxChat_Utils::submit_content_to_db($content_with_metadata, $page_url, $options['api_key']); |
| 1355 |
} |
| 1356 |
} |
| 1357 |
|
| 1358 |
// Update progress with sanitized data |
| 1359 |
$status['processed_pages'] = absint($i + 1); |
| 1360 |
$status['last_update'] = time(); |
| 1361 |
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 1362 |
} |
| 1363 |
|
| 1364 |
// Schedule next batch if needed |
| 1365 |
if ($end_page < $total_pages) { |
| 1366 |
wp_schedule_single_event(time() + $batch_pause, 'mxchat_process_pdf_pages', array( |
| 1367 |
'pdf_path' => $pdf_path, |
| 1368 |
'pdf_url' => $pdf_url, |
| 1369 |
'total_pages' => $total_pages, |
| 1370 |
'batch_size' => $batch_size, |
| 1371 |
'batch_pause' => $batch_pause |
| 1372 |
)); |
| 1373 |
} else { |
| 1374 |
// Processing complete |
| 1375 |
$status['status'] = 'complete'; |
| 1376 |
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 1377 |
if (file_exists($pdf_path)) { |
| 1378 |
wp_delete_file($pdf_path); |
| 1379 |
} |
| 1380 |
} |
| 1381 |
|
| 1382 |
} catch (\Exception $e) { |
| 1383 |
$status['status'] = 'error'; |
| 1384 |
$status['error'] = sanitize_text_field($e->getMessage()); |
| 1385 |
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 1386 |
if (file_exists($pdf_path)) { |
| 1387 |
wp_delete_file($pdf_path); |
| 1388 |
} |
| 1389 |
} |
| 1390 |
} |
| 1391 |
public function get_pdf_processing_status($pdf_url) { |
| 1392 |
$pdf_url = esc_url_raw($pdf_url); |
| 1393 |
$status = get_transient(sanitize_key('mxchat_pdf_status_' . md5($pdf_url))); |
| 1394 |
|
| 1395 |
if (!$status || !is_array($status)) { |
| 1396 |
return false; |
| 1397 |
} |
| 1398 |
|
| 1399 |
return array( |
| 1400 |
'total_pages' => absint($status['total_pages']), |
| 1401 |
'processed_pages' => absint($status['processed_pages']), |
| 1402 |
'percentage' => round((absint($status['processed_pages']) / absint($status['total_pages'])) * 100), |
| 1403 |
'status' => sanitize_text_field($status['status']), |
| 1404 |
'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ago' |
| 1405 |
); |
| 1406 |
} |
| 1407 |
public function mxchat_handle_sitemap_submission() { |
| 1408 |
// Check if the form was submitted and verify permissions |
| 1409 |
if (!isset($_POST['submit_sitemap']) || !current_user_can('manage_options')) { |
| 1410 |
wp_die(esc_html__('Unauthorized access', 'mxchat')); |
| 1411 |
} |
| 1412 |
|
| 1413 |
// Verify nonce |
| 1414 |
check_admin_referer('mxchat_submit_sitemap_action', 'mxchat_submit_sitemap_nonce'); |
| 1415 |
|
| 1416 |
// Validate URL |
| 1417 |
if (!isset($_POST['sitemap_url']) || empty($_POST['sitemap_url'])) { |
| 1418 |
set_transient('mxchat_admin_notice_error', |
| 1419 |
esc_html__('Please provide a valid URL.', 'mxchat'), |
| 1420 |
30 |
| 1421 |
); |
| 1422 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1423 |
exit; |
| 1424 |
} |
| 1425 |
|
| 1426 |
$submitted_url = esc_url_raw($_POST['sitemap_url']); |
| 1427 |
$response = wp_remote_get($submitted_url, array('timeout' => 30)); |
| 1428 |
|
| 1429 |
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) { |
| 1430 |
$error_message = is_wp_error($response) ? $response->get_error_message() : 'Failed to fetch URL'; |
| 1431 |
set_transient('mxchat_admin_notice_error', |
| 1432 |
sprintf( |
| 1433 |
esc_html__('Failed to fetch the URL: %s', 'mxchat'), |
| 1434 |
esc_html($error_message) |
| 1435 |
), |
| 1436 |
30 |
| 1437 |
); |
| 1438 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1439 |
exit; |
| 1440 |
} |
| 1441 |
|
| 1442 |
$content_type = wp_remote_retrieve_header($response, 'content-type'); |
| 1443 |
$body_content = wp_remote_retrieve_body($response); |
| 1444 |
|
| 1445 |
if (empty($body_content)) { |
| 1446 |
set_transient('mxchat_admin_notice_error', |
| 1447 |
esc_html__('Empty response received from URL.', 'mxchat'), |
| 1448 |
30 |
| 1449 |
); |
| 1450 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1451 |
exit; |
| 1452 |
} |
| 1453 |
|
| 1454 |
// Handle PDF URL |
| 1455 |
if ($this->is_pdf_url($submitted_url, $response)) { |
| 1456 |
$result = $this->handle_pdf_for_knowledge_base($submitted_url, $response); |
| 1457 |
|
| 1458 |
if ($result === 'scheduled') { |
| 1459 |
set_transient( |
| 1460 |
'mxchat_last_pdf_url', |
| 1461 |
sanitize_text_field($submitted_url), |
| 1462 |
DAY_IN_SECONDS |
| 1463 |
); |
| 1464 |
set_transient('mxchat_admin_notice_info', |
| 1465 |
esc_html__('PDF processing has started in the background. You can check the progress in the Knowledge Base section.', 'mxchat'), |
| 1466 |
30 |
| 1467 |
); |
| 1468 |
} else { |
| 1469 |
set_transient('mxchat_admin_notice_error', |
| 1470 |
esc_html__('Failed to start PDF processing. Please try again.', 'mxchat'), |
| 1471 |
30 |
| 1472 |
); |
| 1473 |
} |
| 1474 |
|
| 1475 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1476 |
exit; |
| 1477 |
} |
| 1478 |
|
| 1479 |
// Handle Sitemap XML |
| 1480 |
if (strpos($content_type, 'xml') !== false || strpos($body_content, '<urlset') !== false) { |
| 1481 |
libxml_use_internal_errors(true); |
| 1482 |
$xml = simplexml_load_string($body_content); |
| 1483 |
$xml_errors = libxml_get_errors(); |
| 1484 |
libxml_clear_errors(); |
| 1485 |
|
| 1486 |
if ($xml === false || !empty($xml_errors)) { |
| 1487 |
set_transient('mxchat_admin_notice_error', |
| 1488 |
esc_html__('Invalid sitemap XML. Please provide a valid sitemap.', 'mxchat'), |
| 1489 |
30 |
| 1490 |
); |
| 1491 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1492 |
exit; |
| 1493 |
} |
| 1494 |
|
| 1495 |
$result = $this->handle_sitemap_for_knowledge_base($xml, $submitted_url); |
| 1496 |
|
| 1497 |
if ($result === 'scheduled') { |
| 1498 |
set_transient( |
| 1499 |
'mxchat_last_sitemap_url', |
| 1500 |
sanitize_text_field($submitted_url), |
| 1501 |
DAY_IN_SECONDS |
| 1502 |
); |
| 1503 |
set_transient('mxchat_admin_notice_info', |
| 1504 |
esc_html__('Sitemap processing has started in the background. You can check the progress in the Knowledge Base section.', 'mxchat'), |
| 1505 |
30 |
| 1506 |
); |
| 1507 |
} else { |
| 1508 |
set_transient('mxchat_admin_notice_error', |
| 1509 |
esc_html__('Failed to start sitemap processing. Please try again.', 'mxchat'), |
| 1510 |
30 |
| 1511 |
); |
| 1512 |
} |
| 1513 |
|
| 1514 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1515 |
exit; |
| 1516 |
} |
| 1517 |
|
| 1518 |
// Handle Regular URL |
| 1519 |
$page_content = $this->mxchat_extract_main_content($body_content); |
| 1520 |
$sanitized_content = $this->mxchat_sanitize_content_for_api($page_content); |
| 1521 |
|
| 1522 |
if (empty($sanitized_content)) { |
| 1523 |
set_transient('mxchat_admin_notice_error', |
| 1524 |
esc_html__('No valid content found on the provided URL.', 'mxchat'), |
| 1525 |
30 |
| 1526 |
); |
| 1527 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1528 |
exit; |
| 1529 |
} |
| 1530 |
|
| 1531 |
$embedding_vector = $this->mxchat_generate_embedding($sanitized_content); |
| 1532 |
if (is_array($embedding_vector)) { |
| 1533 |
MxChat_Utils::submit_content_to_db( |
| 1534 |
$sanitized_content, |
| 1535 |
$submitted_url, |
| 1536 |
$this->options['api_key'] |
| 1537 |
); |
| 1538 |
set_transient('mxchat_admin_notice_success', |
| 1539 |
esc_html__('URL content successfully submitted!', 'mxchat'), |
| 1540 |
30 |
| 1541 |
); |
| 1542 |
} else { |
| 1543 |
set_transient('mxchat_admin_notice_error', |
| 1544 |
esc_html__('Failed to generate embedding for the URL content. Please check your API key and try again.', 'mxchat'), |
| 1545 |
30 |
| 1546 |
); |
| 1547 |
} |
| 1548 |
|
| 1549 |
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 1550 |
exit; |
| 1551 |
} |
| 1552 |
private function handle_sitemap_for_knowledge_base($xml, $sitemap_url) { |
| 1553 |
if (!current_user_can('manage_options')) { |
| 1554 |
//error_log('Unauthorized sitemap processing attempt'); |
| 1555 |
return false; |
| 1556 |
} |
| 1557 |
|
| 1558 |
try { |
| 1559 |
$sitemap_url = esc_url_raw($sitemap_url); |
| 1560 |
|
| 1561 |
if (!$xml || !is_object($xml)) { |
| 1562 |
throw new Exception('Invalid XML object provided'); |
| 1563 |
} |
| 1564 |
|
| 1565 |
$urls = []; |
| 1566 |
foreach ($xml->url as $url_element) { |
| 1567 |
$url = esc_url_raw((string)$url_element->loc); |
| 1568 |
if ($url) { |
| 1569 |
$urls[] = $url; |
| 1570 |
} |
| 1571 |
} |
| 1572 |
|
| 1573 |
$total_urls = absint(count($urls)); |
| 1574 |
|
| 1575 |
if ($total_urls < 1) { |
| 1576 |
throw new Exception('No valid URLs found in sitemap'); |
| 1577 |
} |
| 1578 |
|
| 1579 |
wp_schedule_single_event(time(), 'mxchat_process_sitemap_urls', array( |
| 1580 |
'urls' => $urls, |
| 1581 |
'sitemap_url' => $sitemap_url, |
| 1582 |
'total_urls' => $total_urls, |
| 1583 |
'batch_size' => absint(10), |
| 1584 |
'batch_pause' => absint(5) |
| 1585 |
)); |
| 1586 |
|
| 1587 |
$status_data = array( |
| 1588 |
'total_urls' => $total_urls, |
| 1589 |
'processed_urls' => 0, |
| 1590 |
'status' => 'processing', |
| 1591 |
'last_update' => time() |
| 1592 |
); |
| 1593 |
|
| 1594 |
set_transient( |
| 1595 |
sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url)), |
| 1596 |
array_map('sanitize_text_field', $status_data), |
| 1597 |
DAY_IN_SECONDS |
| 1598 |
); |
| 1599 |
|
| 1600 |
return 'scheduled'; |
| 1601 |
|
| 1602 |
} catch (\Exception $e) { |
| 1603 |
//error_log(sprintf('Error preparing sitemap for processing: %s', esc_html($e->getMessage()))); |
| 1604 |
return false; |
| 1605 |
} |
| 1606 |
} |
| 1607 |
public static function process_sitemap_urls_cron($urls, $sitemap_url, $total_urls, $batch_size, $batch_pause) { |
| 1608 |
// Validate inputs |
| 1609 |
$sitemap_url = esc_url_raw($sitemap_url); |
| 1610 |
$total_urls = absint($total_urls); |
| 1611 |
$batch_size = absint($batch_size); |
| 1612 |
$batch_pause = absint($batch_pause); |
| 1613 |
|
| 1614 |
if (!is_array($urls) || empty($urls)) { |
| 1615 |
return; |
| 1616 |
} |
| 1617 |
|
| 1618 |
try { |
| 1619 |
$status_key = sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url)); |
| 1620 |
$status = get_transient($status_key); |
| 1621 |
|
| 1622 |
if (!$status || !is_array($status)) { |
| 1623 |
throw new Exception('Invalid status data retrieved from transient'); |
| 1624 |
} |
| 1625 |
|
| 1626 |
$start_url = absint($status['processed_urls']); |
| 1627 |
$end_url = min($start_url + $batch_size, $total_urls); |
| 1628 |
|
| 1629 |
$instance = new self(); // Create an instance of the class |
| 1630 |
$embedding_success = true; |
| 1631 |
|
| 1632 |
for ($i = $start_url; $i < $end_url; $i++) { |
| 1633 |
$page_url = esc_url_raw($urls[$i]); |
| 1634 |
$page_response = wp_remote_get($page_url); |
| 1635 |
|
| 1636 |
if (is_wp_error($page_response) || wp_remote_retrieve_response_code($page_response) !== 200) { |
| 1637 |
continue; |
| 1638 |
} |
| 1639 |
|
| 1640 |
$page_html = wp_remote_retrieve_body($page_response); |
| 1641 |
$page_content = $instance->mxchat_extract_main_content($page_html); // Call via instance |
| 1642 |
$sanitized_content = $instance->mxchat_sanitize_content_for_api($page_content); // Call via instance |
| 1643 |
|
| 1644 |
if (!empty($sanitized_content)) { |
| 1645 |
$embedding_vector = $instance->mxchat_generate_embedding($sanitized_content); // Call via instance |
| 1646 |
if (is_array($embedding_vector)) { |
| 1647 |
$options = get_option('mxchat_options'); |
| 1648 |
MxChat_Utils::submit_content_to_db($sanitized_content, $page_url, $options['api_key']); |
| 1649 |
} else { |
| 1650 |
$embedding_success = false; |
| 1651 |
} |
| 1652 |
} |
| 1653 |
|
| 1654 |
$status['processed_urls'] = absint($i + 1); |
| 1655 |
$status['last_update'] = time(); |
| 1656 |
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 1657 |
} |
| 1658 |
|
| 1659 |
if ($end_url < $total_urls) { |
| 1660 |
wp_schedule_single_event(time() + $batch_pause, 'mxchat_process_sitemap_urls', array( |
| 1661 |
'urls' => array_map('esc_url_raw', $urls), |
| 1662 |
'sitemap_url' => $sitemap_url, |
| 1663 |
'total_urls' => $total_urls, |
| 1664 |
'batch_size' => $batch_size, |
| 1665 |
'batch_pause' => $batch_pause, |
| 1666 |
)); |
| 1667 |
} else { |
| 1668 |
$status['status'] = 'complete'; |
| 1669 |
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 1670 |
} |
| 1671 |
} catch (\Exception $e) { |
| 1672 |
$status['status'] = 'error'; |
| 1673 |
$status['error'] = sanitize_text_field($e->getMessage()); |
| 1674 |
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS); |
| 1675 |
} |
| 1676 |
} |
| 1677 |
public function get_sitemap_processing_status($sitemap_url) { |
| 1678 |
$sitemap_url = esc_url_raw($sitemap_url); |
| 1679 |
$status = get_transient(sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url))); |
| 1680 |
|
| 1681 |
if (!$status || !is_array($status)) { |
| 1682 |
return false; |
| 1683 |
} |
| 1684 |
|
| 1685 |
return array( |
| 1686 |
'total_urls' => absint($status['total_urls']), |
| 1687 |
'processed_urls' => absint($status['processed_urls']), |
| 1688 |
'percentage' => round((absint($status['processed_urls']) / absint($status['total_urls'])) * 100), |
| 1689 |
'status' => sanitize_text_field($status['status']), |
| 1690 |
'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ago' |
| 1691 |
); |
| 1692 |
} |
| 1693 |
public function mxchat_stop_processing() { |
| 1694 |
// Verify permissions |
| 1695 |
if (!current_user_can('manage_options')) { |
| 1696 |
wp_die(esc_html__('Unauthorized access', 'mxchat')); |
| 1697 |
} |
| 1698 |
|
| 1699 |
// Verify nonce |
| 1700 |
check_admin_referer('mxchat_stop_processing_action', 'mxchat_stop_processing_nonce'); |
| 1701 |
|
| 1702 |
// Get the last sitemap URL and clear its transient |
| 1703 |
$sitemap_url = get_transient('mxchat_last_sitemap_url'); |
| 1704 |
if ($sitemap_url) { |
| 1705 |
delete_transient('mxchat_sitemap_status_' . md5($sitemap_url)); |
| 1706 |
delete_transient('mxchat_last_sitemap_url'); |
| 1707 |
} |
| 1708 |
|
| 1709 |
// Get the last PDF URL and clear its transient |
| 1710 |
$pdf_url = get_transient('mxchat_last_pdf_url'); |
| 1711 |
if ($pdf_url) { |
| 1712 |
delete_transient('mxchat_pdf_status_' . md5($pdf_url)); |
| 1713 |
delete_transient('mxchat_last_pdf_url'); |
| 1714 |
} |
| 1715 |
|
| 1716 |
// Unschedule any pending sitemap events |
| 1717 |
$timestamp = wp_next_scheduled('mxchat_process_sitemap_urls'); |
| 1718 |
if ($timestamp) { |
| 1719 |
wp_unschedule_event($timestamp, 'mxchat_process_sitemap_urls'); |
| 1720 |
} |
| 1721 |
|
| 1722 |
// Redirect back with a success message |
| 1723 |
set_transient('mxchat_admin_notice_success', |
| 1724 |
esc_html__('Processing has been stopped successfully.', 'mxchat'), |
| 1725 |
30 |
| 1726 |
); |
| 1727 |
wp_safe_redirect(admin_url('admin.php?page=mxchat-prompts')); |
| 1728 |
exit; |
| 1729 |
} |
| 1730 |
private function mxchat_sanitize_content_for_api($content) { |
| 1731 |
// Remove script, style tags, and HTML comments |
| 1732 |
$content = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $content); |
| 1733 |
$content = preg_replace('/<style\b[^>]*>(.*?)<\/style>/is', '', $content); |
| 1734 |
$content = preg_replace('/<!--(.|\s)*?-->/', '', $content); |
| 1735 |
|
| 1736 |
// Remove all HTML tags and decode HTML entities |
| 1737 |
$content = wp_strip_all_tags($content); |
| 1738 |
$content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5); |
| 1739 |
|
| 1740 |
// Trim and normalize whitespace |
| 1741 |
$content = trim(preg_replace('/\s+/', ' ', $content)); |
| 1742 |
|
| 1743 |
return $content; |
| 1744 |
} |
| 1745 |
|
| 1746 |
|
| 1747 |
|
| 1748 |
|
| 1749 |
|
| 1750 |
|
| 1751 |
public function mxchat_fetch_chat_history() { |
| 1752 |
global $wpdb; |
| 1753 |
$table_name = $wpdb->prefix . 'mxchat_chat_transcripts'; |
| 1754 |
|
| 1755 |
if (!current_user_can('manage_options')) { |
| 1756 |
wp_die(esc_html__('You do not have sufficient permissions to view this page.', 'mxchat')); |
| 1757 |
} |
| 1758 |
|
| 1759 |
// First get unique session IDs ordered by most recent message in each session |
| 1760 |
$session_ids = $wpdb->get_col( |
| 1761 |
$wpdb->prepare( |
| 1762 |
"SELECT DISTINCT session_id |
| 1763 |
FROM {$table_name} |
| 1764 |
GROUP BY session_id |
| 1765 |
ORDER BY MAX(timestamp) DESC" |
| 1766 |
) |
| 1767 |
); |
| 1768 |
|
| 1769 |
if (empty($session_ids)) { |
| 1770 |
wp_die(esc_html__('No chat history available.', 'mxchat')); |
| 1771 |
} |
| 1772 |
|
| 1773 |
ob_start(); |
| 1774 |
echo '<div class="mxchat-transcript">'; |
| 1775 |
|
| 1776 |
// Iterate through sessions from newest to oldest |
| 1777 |
foreach ($session_ids as $session_id) { |
| 1778 |
// Get the email associated with this session (if available) |
| 1779 |
$email = $wpdb->get_var( |
| 1780 |
$wpdb->prepare( |
| 1781 |
"SELECT user_email |
| 1782 |
FROM {$table_name} |
| 1783 |
WHERE session_id = %s AND user_email != '' |
| 1784 |
ORDER BY timestamp ASC |
| 1785 |
LIMIT 1", |
| 1786 |
$session_id |
| 1787 |
) |
| 1788 |
); |
| 1789 |
|
| 1790 |
// Debug: Check email retrieval |
| 1791 |
if (empty($email)) { |
| 1792 |
//error_log("No email found for session {$session_id}"); |
| 1793 |
} else { |
| 1794 |
//error_log("Email for session {$session_id}: " . $email); |
| 1795 |
} |
| 1796 |
|
| 1797 |
// Get messages for this session ordered by timestamp |
| 1798 |
$messages = $wpdb->get_results( |
| 1799 |
$wpdb->prepare( |
| 1800 |
"SELECT * FROM {$table_name} |
| 1801 |
WHERE session_id = %s |
| 1802 |
ORDER BY timestamp ASC", |
| 1803 |
$session_id |
| 1804 |
) |
| 1805 |
); |
| 1806 |
|
| 1807 |
// Start session block |
| 1808 |
echo '<div class="mxchat-session">'; |
| 1809 |
echo '<div class="mxchat-session-header">'; |
| 1810 |
// Wrap checkbox and session ID in one block |
| 1811 |
echo '<div class="mxchat-session-id">'; |
| 1812 |
echo '<input type="checkbox" name="delete_session_ids[]" value="' . esc_attr($session_id) . '"> '; |
| 1813 |
echo '<strong>Session ID:</strong> ' . esc_html($session_id); |
| 1814 |
echo '</div>'; |
| 1815 |
|
| 1816 |
// Place email directly below the session ID block |
| 1817 |
if (!empty($email)) { |
| 1818 |
echo '<div class="mxchat-session-email">'; |
| 1819 |
echo '<strong>Email:</strong> ' . esc_html($email); |
| 1820 |
echo '</div>'; |
| 1821 |
} |
| 1822 |
echo '</div>'; |
| 1823 |
|
| 1824 |
echo '<div class="mxchat-messages">'; |
| 1825 |
|
| 1826 |
// Display messages for this session |
| 1827 |
foreach ($messages as $transcript) { |
| 1828 |
$formatted_timestamp = date_i18n('F j, Y g:i a', strtotime($transcript->timestamp)); |
| 1829 |
|
| 1830 |
// Determine message styling |
| 1831 |
switch ($transcript->role) { |
| 1832 |
case 'assistant': |
| 1833 |
case 'bot': |
| 1834 |
$message_class = 'bot-message'; |
| 1835 |
$display_role = esc_html__('Chatbot', 'mxchat'); |
| 1836 |
break; |
| 1837 |
case 'user': |
| 1838 |
$message_class = 'user-message'; |
| 1839 |
$display_role = !empty($transcript->user_identifier) |
| 1840 |
? sanitize_text_field($transcript->user_identifier) |
| 1841 |
: esc_html__('User', 'mxchat'); |
| 1842 |
break; |
| 1843 |
case 'agent': |
| 1844 |
$message_class = 'agent-message'; |
| 1845 |
$display_role = esc_html__('Agent', 'mxchat'); |
| 1846 |
break; |
| 1847 |
default: |
| 1848 |
$message_class = 'unknown-message'; |
| 1849 |
$display_role = esc_html__('Unknown', 'mxchat'); |
| 1850 |
} |
| 1851 |
|
| 1852 |
// Process message content |
| 1853 |
$message_content = wp_kses( |
| 1854 |
stripslashes($transcript->message), |
| 1855 |
[ |
| 1856 |
'b' => [], 'strong' => [], 'i' => [], 'em' => [], 'u' => [], |
| 1857 |
'br' => [], 'p' => [], 'ul' => [], 'ol' => [], 'li' => [], |
| 1858 |
'a' => ['href' => [], 'title' => []] |
| 1859 |
] |
| 1860 |
); |
| 1861 |
$message_content = nl2br($message_content); |
| 1862 |
|
| 1863 |
// Render message |
| 1864 |
echo '<div class="mxchat-message ' . esc_attr($message_class) . '">'; |
| 1865 |
echo '<div class="mxchat-message-header">' . esc_html($display_role) . '</div>'; |
| 1866 |
echo '<div class="mxchat-message-content">' . $message_content . '</div>'; |
| 1867 |
echo '<div class="mxchat-timestamp">' . esc_html($formatted_timestamp) . '</div>'; |
| 1868 |
echo '</div>'; |
| 1869 |
} |
| 1870 |
|
| 1871 |
// Close session block |
| 1872 |
echo '</div></div>'; |
| 1873 |
} |
| 1874 |
|
| 1875 |
echo '</div>'; |
| 1876 |
$output = ob_get_clean(); |
| 1877 |
echo $output; |
| 1878 |
wp_die(); |
| 1879 |
} |
| 1880 |
|
| 1881 |
public function mxchat_create_activation_page() { |
| 1882 |
$license_status = get_option('mxchat_license_status', 'inactive'); |
| 1883 |
$license_error = get_option('mxchat_license_error', ''); |
| 1884 |
?> |
| 1885 |
<div class="wrap mxchat-admin"> |
| 1886 |
<h2>MxChat Pro: Activation</h2> |
| 1887 |
<?php if ($license_status === 'inactive' && !empty($license_error)): ?> |
| 1888 |
<div class="error notice"> |
| 1889 |
<p><?php echo esc_html($license_error); ?></p> |
| 1890 |
</div> |
| 1891 |
<?php endif; ?> |
| 1892 |
|
| 1893 |
<form id="mxchat-activation-form" style="<?php echo $license_status === 'active' ? 'display: none;' : ''; ?>"> |
| 1894 |
<table class="form-table"> |
| 1895 |
<tr valign="top"> |
| 1896 |
<th scope="row">Email Address</th> |
| 1897 |
<td> |
| 1898 |
<input type="email" id="mxchat_pro_email" name="mxchat_pro_email" value="<?php echo esc_attr(get_option('mxchat_pro_email')); ?>" class="regular-text" required /> |
| 1899 |
</td> |
| 1900 |
</tr> |
| 1901 |
<tr valign="top"> |
| 1902 |
<th scope="row">Activation Key</th> |
| 1903 |
<td> |
| 1904 |
<input type="text" id="mxchat_activation_key" name="mxchat_activation_key" value="<?php echo esc_attr(get_option('mxchat_activation_key')); ?>" class="regular-text" required /> |
| 1905 |
</td> |
| 1906 |
</tr> |
| 1907 |
</table> |
| 1908 |
<?php if ($license_status !== 'active'): ?> |
| 1909 |
<button type="submit" id="activate_license_button" class="button button-primary"><?php esc_html_e('Activate License', 'mxchat'); ?></button> |
| 1910 |
<div id="mxchat-activation-spinner" class="mxchat-activation-spinner" style="display: none;"></div> |
| 1911 |
<?php endif; ?> |
| 1912 |
</form> |
| 1913 |
|
| 1914 |
<!-- License Status Display --> |
| 1915 |
<h3>License Status: <span id="mxchat-license-status"><?php echo $license_status === 'active' ? 'Active' : 'Inactive'; ?></span></h3> |
| 1916 |
</div> |
| 1917 |
<?php |
| 1918 |
} |
| 1919 |
|
| 1920 |
public function mxchat_intents_page_html() { |
| 1921 |
if ( ! current_user_can( 'manage_options' ) ) { |
| 1922 |
return; |
| 1923 |
} |
| 1924 |
|
| 1925 |
// Fetch existing intents with pagination and filtering |
| 1926 |
global $wpdb; |
| 1927 |
$table_name = $wpdb->prefix . 'mxchat_intents'; |
| 1928 |
$page = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1; |
| 1929 |
$per_page = 20; |
| 1930 |
$offset = ( $page - 1 ) * $per_page; |
| 1931 |
|
| 1932 |
|
| 1933 |
// Add at the start of mxchat_intents_page_html() |
| 1934 |
if (isset($_GET['updated']) && $_GET['updated'] === 'true') { |
| 1935 |
echo '<div class="notice notice-success is-dismissible"><p>' . |
| 1936 |
esc_html__('Intent updated successfully.', 'mxchat') . |
| 1937 |
'</p></div>'; |
| 1938 |
} |
| 1939 |
|
| 1940 |
// Build the WHERE clause based on filters |
| 1941 |
$where = '1=1'; |
| 1942 |
$search_term = isset( $_GET['s'] ) ? trim( $_GET['s'] ) : ''; |
| 1943 |
$callback_filter = isset( $_GET['callback_filter'] ) ? sanitize_text_field( $_GET['callback_filter'] ) : ''; |
| 1944 |
|
| 1945 |
if ( $search_term ) { |
| 1946 |
$search_term_like = '%' . $wpdb->esc_like( $search_term ) . '%'; |
| 1947 |
$where .= $wpdb->prepare( ' AND (intent_label LIKE %s OR phrases LIKE %s)', $search_term_like, $search_term_like ); |
| 1948 |
} |
| 1949 |
|
| 1950 |
if ( $callback_filter ) { |
| 1951 |
$where .= $wpdb->prepare( ' AND callback_function = %s', $callback_filter ); |
| 1952 |
} |
| 1953 |
|
| 1954 |
// Get total count for pagination |
| 1955 |
$total_intents = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE $where" ); |
| 1956 |
$total_pages = ceil( $total_intents / $per_page ); |
| 1957 |
|
| 1958 |
// Fetch intents with pagination and filters |
| 1959 |
$intents = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE $where LIMIT %d OFFSET %d", $per_page, $offset ) ); |
| 1960 |
|
| 1961 |
// Get available callback functions with 'pro_only' flag |
| 1962 |
$available_callbacks = $this->mxchat_get_available_callbacks(); |
| 1963 |
?> |
| 1964 |
|
| 1965 |
<div class="wrap mxchat-admin"> |
| 1966 |
<!-- Add Intent Form --> |
| 1967 |
<form id="mxchat-add-intent-form" method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>"> |
| 1968 |
<input type="hidden" name="action" value="mxchat_add_intent"> |
| 1969 |
<?php wp_nonce_field( 'mxchat_add_intent_nonce' ); ?> |
| 1970 |
<h2><?php esc_html_e( 'Add New Intent', 'mxchat' ); ?></h2> |
| 1971 |
<p class="description"> |
| 1972 |
<?php esc_html_e( 'We highly encourage users to quickly read our ', 'mxchat' ); ?> |
| 1973 |
<a href="https://mxchat.ai/documentation/#intents" target="_blank" rel="noopener noreferrer"> |
| 1974 |
<?php esc_html_e( 'documentation', 'mxchat' ); ?> |
| 1975 |
</a> |
| 1976 |
<?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' ); ?> |
| 1977 |
</p> |
| 1978 |
|
| 1979 |
<div class="mxchat-form-group"> |
| 1980 |
<label for="intent_label"><?php esc_html_e( 'Intent Label (For your reference only)', 'mxchat' ); ?></label> |
| 1981 |
<input name="intent_label" type="text" id="intent_label" class="regular-text" required |
| 1982 |
placeholder="Example Email Capture: Newsletter Signup"> |
| 1983 |
</div> |
| 1984 |
<div class="mxchat-form-group"> |
| 1985 |
<label for="phrases"><?php esc_html_e( 'Phrases (comma-separated)', 'mxchat' ); ?></label> |
| 1986 |
<textarea name="phrases" id="phrases" rows="5" class="large-text" required |
| 1987 |
placeholder="Example Email Capture: sign me up, subscribe me, I want to join, add me to the newsletter, send me updates, keep me informed"></textarea> |
| 1988 |
</div> |
| 1989 |
<div class="mxchat-form-group"> |
| 1990 |
<label for="callback_function"><?php esc_html_e( 'Callback Function', 'mxchat' ); ?></label> |
| 1991 |
<select name="callback_function" id="callback_function" required> |
| 1992 |
<option value=""><?php esc_html_e('Select a Callback', 'mxchat'); ?></option> |
| 1993 |
<?php |
| 1994 |
$groups = $this->mxchat_get_available_callbacks(true); // Fetch grouped data |
| 1995 |
|
| 1996 |
foreach ($groups as $group_label => $group_callbacks) : |
| 1997 |
echo '<optgroup label="' . esc_attr($group_label) . '">'; |
| 1998 |
foreach ($group_callbacks as $function => $data) : |
| 1999 |
$label = $data['label']; |
| 2000 |
$pro_only = $data['pro_only']; |
| 2001 |
$disabled = (!$this->is_activated && $pro_only) ? 'disabled' : ''; |
| 2002 |
$label_suffix = (!$this->is_activated && $pro_only) ? ' (Pro Only)' : ''; |
| 2003 |
?> |
| 2004 |
<option value="<?php echo esc_attr($function); ?>" <?php echo $disabled; ?>> |
| 2005 |
<?php echo esc_html($label . $label_suffix); ?> |
| 2006 |
</option> |
| 2007 |
<?php endforeach; |
| 2008 |
echo '</optgroup>'; |
| 2009 |
endforeach; |
| 2010 |
?> |
| 2011 |
</select> |
| 2012 |
|
| 2013 |
|
| 2014 |
|
| 2015 |
</div> |
| 2016 |
<button type="submit" class="button button-primary submit-content-button"> |
| 2017 |
<?php esc_html_e( 'Add Intent', 'mxchat' ); ?> |
| 2018 |
</button> |
| 2019 |
<div id="mxchat-intent-loading" style="display: none;"></div> |
| 2020 |
<div id="mxchat-intent-loading-text" style="display: none;"> |
| 2021 |
<?php esc_html_e( 'Saving intent, please wait...', 'mxchat' ); ?> |
| 2022 |
</div> |
| 2023 |
|
| 2024 |
</form> |
| 2025 |
|
| 2026 |
<!-- Filter Form --> |
| 2027 |
<form method="get" action=""> |
| 2028 |
<input type="hidden" name="page" value="mxchat-intents"> |
| 2029 |
<div class="mxchat-search-group"> |
| 2030 |
<input type="text" name="s" id="mxchat-intent-search" placeholder="<?php esc_attr_e( 'Search Intents', 'mxchat' ); ?>" value="<?php echo esc_attr( $search_term ); ?>"> |
| 2031 |
<select name="callback_filter" id="mxchat-callback-filter"> |
| 2032 |
<option value=""><?php esc_html_e( 'All Callbacks', 'mxchat' ); ?></option> |
| 2033 |
<?php foreach ( $available_callbacks as $function => $callback_data ) : ?> |
| 2034 |
<?php $label = $callback_data['label']; ?> |
| 2035 |
<option value="<?php echo esc_attr( $function ); ?>" <?php selected( $callback_filter, $function ); ?>><?php echo esc_html( $label ); ?></option> |
| 2036 |
<?php endforeach; ?> |
| 2037 |
</select> |
| 2038 |
<button type="submit" class="button"><?php esc_html_e( 'Filter', 'mxchat' ); ?></button> |
| 2039 |
</div> |
| 2040 |
</form> |
| 2041 |
|
| 2042 |
<!-- Intents Table --> |
| 2043 |
<table class="wp-list-table mxchat-intents-table widefat fixed striped"> |
| 2044 |
<thead> |
| 2045 |
<tr> |
| 2046 |
<th><?php esc_html_e( 'Intent Label', 'mxchat' ); ?></th> |
| 2047 |
<th><?php esc_html_e( 'Phrases', 'mxchat' ); ?></th> |
| 2048 |
<th><?php esc_html_e( 'Callback Function', 'mxchat' ); ?></th> |
| 2049 |
<th><?php esc_html_e( 'Similarity Threshold', 'mxchat' ); ?></th> |
| 2050 |
<th><?php esc_html_e( 'Actions', 'mxchat' ); ?></th> |
| 2051 |
</tr> |
| 2052 |
</thead> |
| 2053 |
<tbody> |
| 2054 |
<?php if ( $intents ) : ?> |
| 2055 |
<?php foreach ( $intents as $intent ) : ?> |
| 2056 |
<?php |
| 2057 |
$callback_function = $intent->callback_function; |
| 2058 |
$callback_label = isset( $available_callbacks[ $callback_function ]['label'] ) ? $available_callbacks[ $callback_function ]['label'] : $callback_function; |
| 2059 |
$threshold_value = isset( $intent->similarity_threshold ) ? round( $intent->similarity_threshold * 100 ) : 85; |
| 2060 |
?> |
| 2061 |
<tr> |
| 2062 |
<td><?php echo esc_html( $intent->intent_label ); ?></td> |
| 2063 |
<td><?php echo esc_html( $intent->phrases ); ?></td> |
| 2064 |
<td><?php echo esc_html( $callback_label ); ?></td> |
| 2065 |
<!-- Similarity Threshold Column --> |
| 2066 |
<td> |
| 2067 |
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"> |
| 2068 |
<?php wp_nonce_field( 'mxchat_update_intent_threshold_nonce' ); ?> |
| 2069 |
<input type="hidden" name="action" value="mxchat_update_intent_threshold"> |
| 2070 |
<input type="hidden" name="intent_id" value="<?php echo esc_attr( $intent->id ); ?>"> |
| 2071 |
<input type="range" name="intent_threshold" id="intent_threshold_<?php echo esc_attr( $intent->id ); ?>" min="70" max="95" value="<?php echo esc_attr( $threshold_value ); ?>" oninput="document.getElementById('threshold_output_<?php echo esc_attr( $intent->id ); ?>').value = this.value + '%'"> |
| 2072 |
<output id="threshold_output_<?php echo esc_attr( $intent->id ); ?>"><?php echo esc_html( $threshold_value ); ?>%</output> |
| 2073 |
</td> |
| 2074 |
<!-- Actions Column --> |
| 2075 |
<td> |
| 2076 |
<button type="submit" class="button button-primary mxchat-save-button"> |
| 2077 |
<?php esc_html_e( 'Save', 'mxchat' ); ?> |
| 2078 |
</button> |
| 2079 |
</form> |
| 2080 |
|
| 2081 |
|
| 2082 |
|
| 2083 |
|
| 2084 |
<button type="button" |
| 2085 |
class="button button-secondary mxchat-edit-button" |
| 2086 |
data-intent-id="<?php echo esc_attr($intent->id); ?>" |
| 2087 |
data-phrases="<?php echo esc_attr($intent->phrases); ?>"> |
| 2088 |
<?php esc_html_e('Edit', 'mxchat'); ?> |
| 2089 |
</button> |
| 2090 |
|
| 2091 |
|
| 2092 |
|
| 2093 |
|
| 2094 |
<!-- Delete Form --> |
| 2095 |
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" onsubmit="return confirm('<?php esc_attr_e( 'Are you sure you want to delete this intent?', 'mxchat' ); ?>');"> |
| 2096 |
<?php wp_nonce_field( 'mxchat_delete_intent_nonce' ); ?> |
| 2097 |
<input type="hidden" name="action" value="mxchat_delete_intent"> |
| 2098 |
<input type="hidden" name="intent_id" value="<?php echo esc_attr( $intent->id ); ?>"> |
| 2099 |
<button type="submit" class="button mxchat-delete-all"> |
| 2100 |
<?php esc_html_e( 'Delete', 'mxchat' ); ?> |
| 2101 |
</button> |
| 2102 |
</form> |
| 2103 |
</td> |
| 2104 |
</tr> |
| 2105 |
<?php endforeach; ?> |
| 2106 |
<?php else : ?> |
| 2107 |
<tr> |
| 2108 |
<td colspan="5"><?php esc_html_e( 'No intents found.', 'mxchat' ); ?></td> |
| 2109 |
</tr> |
| 2110 |
<?php endif; ?> |
| 2111 |
</tbody> |
| 2112 |
</table> |
| 2113 |
|
| 2114 |
|
| 2115 |
<div id="mxchat-edit-modal" class="mxchat-modal" style="display: none;"> |
| 2116 |
<div class="mxchat-modal-content"> |
| 2117 |
<span class="mxchat-modal-close">×</span> |
| 2118 |
<h2><?php esc_html_e('Edit Intent Phrases', 'mxchat'); ?></h2> |
| 2119 |
<form id="mxchat-edit-intent-form" method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> |
| 2120 |
<?php wp_nonce_field('mxchat_edit_intent_nonce'); ?> |
| 2121 |
<input type="hidden" name="action" value="mxchat_edit_intent"> |
| 2122 |
<input type="hidden" name="intent_id" id="edit_intent_id"> |
| 2123 |
<div class="mxchat-form-group"> |
| 2124 |
<label for="edit_phrases"><?php esc_html_e('Phrases (comma-separated)', 'mxchat'); ?></label> |
| 2125 |
<textarea name="phrases" id="edit_phrases" rows="5" class="large-text" required></textarea> |
| 2126 |
</div> |
| 2127 |
<button type="submit" class="button button-primary"> |
| 2128 |
<?php esc_html_e('Update Phrases', 'mxchat'); ?> |
| 2129 |
</button> |
| 2130 |
</form> |
| 2131 |
</div> |
| 2132 |
</div> |
| 2133 |
|
| 2134 |
|
| 2135 |
|
| 2136 |
|
| 2137 |
</div> |
| 2138 |
<?php |
| 2139 |
} |
| 2140 |
|
| 2141 |
|
| 2142 |
|
| 2143 |
/** |
| 2144 |
* Handle editing of intent phrases |
| 2145 |
* |
| 2146 |
* @since 1.0.0 |
| 2147 |
* @return void |
| 2148 |
*/ |
| 2149 |
public function handle_edit_intent() { |
| 2150 |
// Verify nonce and user capabilities |
| 2151 |
if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'mxchat_edit_intent_nonce')) { |
| 2152 |
wp_die(esc_html__('Security check failed.', 'mxchat')); |
| 2153 |
} |
| 2154 |
|
| 2155 |
if (!current_user_can('manage_options')) { |
| 2156 |
wp_die(esc_html__('You do not have permission to perform this action.', 'mxchat')); |
| 2157 |
} |
| 2158 |
|
| 2159 |
// Validate and sanitize input |
| 2160 |
$intent_id = isset($_POST['intent_id']) ? absint($_POST['intent_id']) : 0; |
| 2161 |
if (!$intent_id) { |
| 2162 |
wp_die(esc_html__('Invalid intent ID.', 'mxchat')); |
| 2163 |
} |
| 2164 |
|
| 2165 |
$phrases_input = isset($_POST['phrases']) ? sanitize_textarea_field($_POST['phrases']) : ''; |
| 2166 |
if (empty($phrases_input)) { |
| 2167 |
wp_die(esc_html__('Phrases cannot be empty.', 'mxchat')); |
| 2168 |
} |
| 2169 |
|
| 2170 |
// Process phrases the same way as in intent creation |
| 2171 |
$phrases_array = array_map('sanitize_text_field', array_filter(array_map('trim', explode(',', $phrases_input)))); |
| 2172 |
|
| 2173 |
if (empty($phrases_array)) { |
| 2174 |
wp_die(esc_html__('Please enter at least one valid phrase.', 'mxchat')); |
| 2175 |
} |
| 2176 |
|
| 2177 |
// Generate embeddings and combine them |
| 2178 |
$vectors = []; |
| 2179 |
foreach ($phrases_array as $phrase) { |
| 2180 |
$embedding_vector = $this->mxchat_generate_embedding($phrase, $this->options['api_key']); |
| 2181 |
if (is_array($embedding_vector)) { |
| 2182 |
$vectors[] = $embedding_vector; |
| 2183 |
} else { |
| 2184 |
wp_die(esc_html__('Error generating embedding for phrase: ', 'mxchat') . esc_html($phrase)); |
| 2185 |
} |
| 2186 |
} |
| 2187 |
|
| 2188 |
if (empty($vectors)) { |
| 2189 |
wp_die(esc_html__('No valid embeddings generated. Please check your phrases.', 'mxchat')); |
| 2190 |
} |
| 2191 |
|
| 2192 |
// Create combined vector just like in intent creation |
| 2193 |
$combined_vector = $this->mxchat_average_vectors($vectors); |
| 2194 |
$serialized_vector = maybe_serialize($combined_vector); |
| 2195 |
|
| 2196 |
global $wpdb; |
| 2197 |
$table_name = $wpdb->prefix . 'mxchat_intents'; |
| 2198 |
|
| 2199 |
// Update the intent with both new phrases and the combined vector |
| 2200 |
$result = $wpdb->update( |
| 2201 |
$table_name, |
| 2202 |
array( |
| 2203 |
'phrases' => implode(', ', $phrases_array), |
| 2204 |
'embedding_vector' => $serialized_vector |
| 2205 |
), |
| 2206 |
array('id' => $intent_id), |
| 2207 |
array('%s', '%s'), |
| 2208 |
array('%d') |
| 2209 |
); |
| 2210 |
|
| 2211 |
if (false === $result) { |
| 2212 |
wp_die(esc_html__('Failed to update intent.', 'mxchat')); |
| 2213 |
} |
| 2214 |
|
| 2215 |
// Redirect back to the intents page with a success message |
| 2216 |
$redirect_url = add_query_arg( |
| 2217 |
array( |
| 2218 |
'page' => 'mxchat-intents', |
| 2219 |
'updated' => 'true' |
| 2220 |
), |
| 2221 |
admin_url('admin.php') |
| 2222 |
); |
| 2223 |
|
| 2224 |
wp_safe_redirect($redirect_url); |
| 2225 |
exit; |
| 2226 |
} |
| 2227 |
public function mxchat_handle_update_intent_threshold() { |
| 2228 |
if ( ! current_user_can( 'manage_options' ) ) { |
| 2229 |
wp_die( esc_html__('Unauthorized user', 'mxchat') ); |
| 2230 |
} |
| 2231 |
|
| 2232 |
check_admin_referer('mxchat_update_intent_threshold_nonce'); |
| 2233 |
|
| 2234 |
if (isset($_POST['intent_id'], $_POST['intent_threshold'])) { |
| 2235 |
global $wpdb; |
| 2236 |
$table_name = $wpdb->prefix . 'mxchat_intents'; |
| 2237 |
$intent_id = intval($_POST['intent_id']); |
| 2238 |
$threshold_percentage = max(70, min(95, intval($_POST['intent_threshold']))); |
| 2239 |
$similarity_threshold = $threshold_percentage / 100; |
| 2240 |
|
| 2241 |
$wpdb->update( |
| 2242 |
$table_name, |
| 2243 |
['similarity_threshold' => $similarity_threshold], |
| 2244 |
['id' => $intent_id], |
| 2245 |
['%f'], |
| 2246 |
['%d'] |
| 2247 |
); |
| 2248 |
} |
| 2249 |
|
| 2250 |
wp_safe_redirect(admin_url('admin.php?page=mxchat-intents')); |
| 2251 |
exit; |
| 2252 |
} |
| 2253 |
|
| 2254 |
public function mxchat_handle_add_intent() { |
| 2255 |
if ( ! current_user_can( 'manage_options' ) ) { |
| 2256 |
wp_die( esc_html__('Unauthorized user', 'mxchat') ); |
| 2257 |
} |
| 2258 |
|
| 2259 |
check_admin_referer('mxchat_add_intent_nonce'); |
| 2260 |
|
| 2261 |
global $wpdb; |
| 2262 |
$table_name = $wpdb->prefix . 'mxchat_intents'; |
| 2263 |
|
| 2264 |
$intent_label = isset($_POST['intent_label']) ? sanitize_text_field($_POST['intent_label']) : ''; |
| 2265 |
$phrases_input = isset($_POST['phrases']) ? sanitize_textarea_field($_POST['phrases']) : ''; |
| 2266 |
$callback_function = isset($_POST['callback_function']) ? sanitize_text_field($_POST['callback_function']) : ''; |
| 2267 |
$default_threshold = 0.85; |
| 2268 |
|
| 2269 |
if (empty($intent_label) || empty($callback_function) || empty($phrases_input)) { |
| 2270 |
wp_die( esc_html__('Invalid input. Please ensure all fields are filled out.', 'mxchat') ); |
| 2271 |
} |
| 2272 |
|
| 2273 |
$available_callbacks = $this->mxchat_get_available_callbacks(); |
| 2274 |
|
| 2275 |
if (!array_key_exists($callback_function, $available_callbacks)) { |
| 2276 |
wp_die( esc_html__('Invalid callback function selected.', 'mxchat') ); |
| 2277 |
} |
| 2278 |
|
| 2279 |
$is_pro_only = $available_callbacks[$callback_function]['pro_only']; |
| 2280 |
if ($is_pro_only && !$this->is_activated) { |
| 2281 |
wp_die( esc_html__('This callback function is available in the Pro version only.', 'mxchat') ); |
| 2282 |
} |
| 2283 |
|
| 2284 |
$phrases_array = array_map('sanitize_text_field', array_filter(array_map('trim', explode(',', $phrases_input)))); |
| 2285 |
|
| 2286 |
if (empty($phrases_array)) { |
| 2287 |
wp_die( esc_html__('Please enter at least one valid phrase.', 'mxchat') ); |
| 2288 |
} |
| 2289 |
|
| 2290 |
$vectors = []; |
| 2291 |
foreach ($phrases_array as $phrase) { |
| 2292 |
$embedding_vector = $this->mxchat_generate_embedding($phrase, $this->options['api_key']); |
| 2293 |
if (is_array($embedding_vector)) { |
| 2294 |
$vectors[] = $embedding_vector; |
| 2295 |
} else { |
| 2296 |
wp_die( esc_html__('Error generating embedding for phrase: ', 'mxchat') . esc_html($phrase) ); |
| 2297 |
} |
| 2298 |
} |
| 2299 |
|
| 2300 |
if (!empty($vectors)) { |
| 2301 |
$combined_vector = $this->mxchat_average_vectors($vectors); |
| 2302 |
$serialized_vector = maybe_serialize($combined_vector); |
| 2303 |
|
| 2304 |
$result = $wpdb->insert($table_name, [ |
| 2305 |
'intent_label' => $intent_label, |
| 2306 |
'phrases' => implode(', ', $phrases_array), |
| 2307 |
'embedding_vector' => $serialized_vector, |
| 2308 |
'callback_function' => $callback_function, |
| 2309 |
'similarity_threshold' => $default_threshold, |
| 2310 |
]); |
| 2311 |
|
| 2312 |
if ($result === false) { |
| 2313 |
wp_die( esc_html__('Database error: ', 'mxchat') . esc_html($wpdb->last_error) ); |
| 2314 |
} |
| 2315 |
} else { |
| 2316 |
wp_die( esc_html__('No valid embeddings generated. Please check your phrases.', 'mxchat') ); |
| 2317 |
} |
| 2318 |
|
| 2319 |
wp_safe_redirect(admin_url('admin.php?page=mxchat-intents')); |
| 2320 |
exit; |
| 2321 |
} |
| 2322 |
|
| 2323 |
|
| 2324 |
|
| 2325 |
|
| 2326 |
|
| 2327 |
|
| 2328 |
private function mxchat_get_available_callbacks($grouped = false) { |
| 2329 |
$callbacks = [ |
| 2330 |
'mxchat_handle_email_capture' => [ |
| 2331 |
'label' => 'Email Capture', |
| 2332 |
'pro_only' => false, |
| 2333 |
'group' => 'Customer Engagement', |
| 2334 |
], |
| 2335 |
'mxchat_handle_product_inquiry' => [ |
| 2336 |
'label' => 'Show Product Card', |
| 2337 |
'pro_only' => true, |
| 2338 |
'group' => 'WooCommerce Features', |
| 2339 |
], |
| 2340 |
'mxchat_handle_order_history' => [ |
| 2341 |
'label' => 'Order History', |
| 2342 |
'pro_only' => true, |
| 2343 |
'group' => 'WooCommerce Features', |
| 2344 |
], |
| 2345 |
'mxchat_generate_image' => [ |
| 2346 |
'label' => 'Generate Image', |
| 2347 |
'pro_only' => true, |
| 2348 |
'group' => 'Other Features', |
| 2349 |
], |
| 2350 |
'mxchat_handle_search_request' => [ |
| 2351 |
'label' => 'Brave Web Search', |
| 2352 |
'pro_only' => false, |
| 2353 |
'group' => 'Search Features', |
| 2354 |
], |
| 2355 |
'mxchat_handle_image_search_request' => [ |
| 2356 |
'label' => 'Brave Image Search', |
| 2357 |
'pro_only' => false, |
| 2358 |
'group' => 'Search Features', |
| 2359 |
], |
| 2360 |
'mxchat_handle_add_to_cart_intent' => [ |
| 2361 |
'label' => 'Add to Cart', |
| 2362 |
'pro_only' => true, |
| 2363 |
'group' => 'WooCommerce Features', |
| 2364 |
], |
| 2365 |
'mxchat_handle_checkout_intent' => [ |
| 2366 |
'label' => 'Proceed to Checkout', |
| 2367 |
'pro_only' => true, |
| 2368 |
'group' => 'WooCommerce Features', |
| 2369 |
], |
| 2370 |
'mxchat_handle_pdf_discussion' => [ |
| 2371 |
'label' => 'Chat with PDF', |
| 2372 |
'pro_only' => true, |
| 2373 |
'group' => 'Other Features', |
| 2374 |
], |
| 2375 |
'mxchat_handle_product_recommendations' => [ |
| 2376 |
'label' => 'Product Recommendations', |
| 2377 |
'pro_only' => true, |
| 2378 |
'group' => 'WooCommerce Features', |
| 2379 |
], |
| 2380 |
'mxchat_live_agent_handover' => [ |
| 2381 |
'label' => 'Live Agent', |
| 2382 |
'pro_only' => true, |
| 2383 |
'group' => 'Customer Engagement', |
| 2384 |
], |
| 2385 |
'mxchat_handle_switch_to_chatbot_intent' => [ |
| 2386 |
'label' => 'Back to Chatbot', |
| 2387 |
'pro_only' => true, |
| 2388 |
'group' => 'Customer Engagement', |
| 2389 |
], |
| 2390 |
]; |
| 2391 |
|
| 2392 |
// Return grouped structure if requested |
| 2393 |
if ($grouped) { |
| 2394 |
$grouped_callbacks = []; |
| 2395 |
foreach ($callbacks as $key => $data) { |
| 2396 |
$group_label = $data['group'] ?? 'Other Features'; |
| 2397 |
$grouped_callbacks[$group_label][$key] = [ |
| 2398 |
'label' => $data['label'], |
| 2399 |
'pro_only' => $data['pro_only'], |
| 2400 |
]; |
| 2401 |
} |
| 2402 |
return $grouped_callbacks; |
| 2403 |
} |
| 2404 |
|
| 2405 |
return $callbacks; |
| 2406 |
} |
| 2407 |
|
| 2408 |
|
| 2409 |
|
| 2410 |
private function mxchat_average_vectors($vectors) { |
| 2411 |
$vector_length = count($vectors[0]); |
| 2412 |
$sum_vector = array_fill(0, $vector_length, 0); |
| 2413 |
|
| 2414 |
foreach ($vectors as $vector) { |
| 2415 |
for ($i = 0; $i < $vector_length; $i++) { |
| 2416 |
$sum_vector[$i] += $vector[$i]; |
| 2417 |
} |
| 2418 |
} |
| 2419 |
|
| 2420 |
// Divide each component by the number of vectors to get the average |
| 2421 |
$num_vectors = count($vectors); |
| 2422 |
for ($i = 0; $i < $vector_length; $i++) { |
| 2423 |
$sum_vector[$i] /= $num_vectors; |
| 2424 |
} |
| 2425 |
|
| 2426 |
return $sum_vector; |
| 2427 |
} |
| 2428 |
|
| 2429 |
public function mxchat_handle_delete_intent() { |
| 2430 |
if ( ! current_user_can( 'manage_options' ) ) { |
| 2431 |
wp_die( esc_html__('Unauthorized user', 'mxchat') ); |
| 2432 |
} |
| 2433 |
|
| 2434 |
check_admin_referer('mxchat_delete_intent_nonce'); |
| 2435 |
|
| 2436 |
if (isset($_POST['intent_id'])) { |
| 2437 |
global $wpdb; |
| 2438 |
$table_name = $wpdb->prefix . 'mxchat_intents'; |
| 2439 |
$intent_id = intval($_POST['intent_id']); |
| 2440 |
|
| 2441 |
$wpdb->delete($table_name, ['id' => $intent_id], ['%d']); |
| 2442 |
} |
| 2443 |
|
| 2444 |
wp_safe_redirect(admin_url('admin.php?page=mxchat-intents')); |
| 2445 |
exit; |
| 2446 |
} |
| 2447 |
|
| 2448 |
|
| 2449 |
public function mxchat_page_init() { |
| 2450 |
// Register settings |
| 2451 |
register_setting( |
| 2452 |
'mxchat_option_group', |
| 2453 |
'mxchat_options', |
| 2454 |
array($this, 'mxchat_sanitize') |
| 2455 |
); |
| 2456 |
|
| 2457 |
register_setting( |
| 2458 |
'mxchat_option_group', |
| 2459 |
'mxchat_similarity_threshold', |
| 2460 |
array( |
| 2461 |
'type' => 'number', |
| 2462 |
'sanitize_callback' => function($value) { |
| 2463 |
$value = absint($value); // Ensure it's an integer |
| 2464 |
return min(max($value, 70), 85); // Enforce range |
| 2465 |
}, |
| 2466 |
'default' => 80, |
| 2467 |
) |
| 2468 |
); |
| 2469 |
|
| 2470 |
|
| 2471 |
// Chatbot Settings Section |
| 2472 |
add_settings_section( |
| 2473 |
'mxchat_chatbot_section', |
| 2474 |
'Chatbot Settings', |
| 2475 |
null, |
| 2476 |
'mxchat-chatbot' |
| 2477 |
); |
| 2478 |
|
| 2479 |
// Similarity Threshold Slider |
| 2480 |
add_settings_field( |
| 2481 |
'similarity_threshold', // Field ID |
| 2482 |
'Similarity Threshold', // Field title |
| 2483 |
array($this, 'mxchat_similarity_threshold_callback'), // Callback function |
| 2484 |
'mxchat-chatbot', // Page |
| 2485 |
'mxchat_chatbot_section' // Section |
| 2486 |
); |
| 2487 |
|
| 2488 |
// Existing fields... |
| 2489 |
add_settings_field( |
| 2490 |
'api_key', |
| 2491 |
'OpenAI API Key', |
| 2492 |
array($this, 'api_key_callback'), |
| 2493 |
'mxchat-chatbot', |
| 2494 |
'mxchat_chatbot_section' |
| 2495 |
); |
| 2496 |
|
| 2497 |
add_settings_field( |
| 2498 |
'xai_api_key', |
| 2499 |
'X.AI API Key', |
| 2500 |
array($this, 'xai_api_key_callback'), |
| 2501 |
'mxchat-chatbot', |
| 2502 |
'mxchat_chatbot_section' |
| 2503 |
); |
| 2504 |
|
| 2505 |
add_settings_field( |
| 2506 |
'claude_api_key', |
| 2507 |
'Claude API Key', |
| 2508 |
array($this, 'claude_api_key_callback'), |
| 2509 |
'mxchat-chatbot', |
| 2510 |
'mxchat_chatbot_section' |
| 2511 |
); |
| 2512 |
|
| 2513 |
|
| 2514 |
add_settings_field( |
| 2515 |
'system_prompt_instructions', |
| 2516 |
'AI Instructions (Behavior)', |
| 2517 |
array($this, 'system_prompt_instructions_callback'), |
| 2518 |
'mxchat-chatbot', |
| 2519 |
'mxchat_chatbot_section' |
| 2520 |
); |
| 2521 |
|
| 2522 |
add_settings_field( |
| 2523 |
'model', |
| 2524 |
'Model', |
| 2525 |
array($this, 'mxchat_model_callback'), |
| 2526 |
'mxchat-chatbot', |
| 2527 |
'mxchat_chatbot_section' |
| 2528 |
); |
| 2529 |
|
| 2530 |
add_settings_field( |
| 2531 |
'top_bar_title', |
| 2532 |
'Top Bar Title', |
| 2533 |
array($this, 'mxchat_top_bar_title_callback'), |
| 2534 |
'mxchat-chatbot', |
| 2535 |
'mxchat_chatbot_section' |
| 2536 |
); |
| 2537 |
|
| 2538 |
add_settings_field( |
| 2539 |
'enable_email_block', |
| 2540 |
'Require Email Before Chat', |
| 2541 |
array($this, 'enable_email_block_callback'), |
| 2542 |
'mxchat-chatbot', |
| 2543 |
'mxchat_chatbot_section' |
| 2544 |
); |
| 2545 |
|
| 2546 |
add_settings_field( |
| 2547 |
'email_blocker_header_content', |
| 2548 |
'Require Email Chat Content', |
| 2549 |
array($this, 'email_blocker_header_content_callback'), |
| 2550 |
'mxchat-chatbot', |
| 2551 |
'mxchat_chatbot_section' |
| 2552 |
); |
| 2553 |
|
| 2554 |
add_settings_field( |
| 2555 |
'email_blocker_button_text', |
| 2556 |
'Require Email Chat Button Text', |
| 2557 |
[$this, 'email_blocker_button_text_callback'], |
| 2558 |
'mxchat-chatbot', |
| 2559 |
'mxchat_chatbot_section' |
| 2560 |
); |
| 2561 |
|
| 2562 |
add_settings_field( |
| 2563 |
'intro_message', |
| 2564 |
'Introductory Message', |
| 2565 |
array($this, 'mxchat_intro_message_callback'), |
| 2566 |
'mxchat-chatbot', |
| 2567 |
'mxchat_chatbot_section' |
| 2568 |
); |
| 2569 |
|
| 2570 |
add_settings_field( |
| 2571 |
'input_copy', |
| 2572 |
'Input Copy', |
| 2573 |
array($this, 'mxchat_input_copy_callback'), |
| 2574 |
'mxchat-chatbot', |
| 2575 |
'mxchat_chatbot_section' |
| 2576 |
); |
| 2577 |
|
| 2578 |
add_settings_field( |
| 2579 |
'rate_limit_logged_in', |
| 2580 |
__('Rate Limit for Logged-in Users', 'mxchat'), |
| 2581 |
array($this, 'mxchat_rate_limit_logged_in_callback'), |
| 2582 |
'mxchat-chatbot', |
| 2583 |
'mxchat_chatbot_section' |
| 2584 |
); |
| 2585 |
|
| 2586 |
add_settings_field( |
| 2587 |
'rate_limit_logged_out', |
| 2588 |
__('Rate Limit for Logged-out Users', 'mxchat'), |
| 2589 |
array($this, 'mxchat_rate_limit_logged_out_callback'), |
| 2590 |
'mxchat-chatbot', |
| 2591 |
'mxchat_chatbot_section' |
| 2592 |
); |
| 2593 |
|
| 2594 |
add_settings_field( |
| 2595 |
'rate_limit_message', |
| 2596 |
'Rate Limit Message', |
| 2597 |
array($this, 'mxchat_rate_limit_message_callback'), |
| 2598 |
'mxchat-chatbot', |
| 2599 |
'mxchat_chatbot_section' |
| 2600 |
); |
| 2601 |
|
| 2602 |
add_settings_field( |
| 2603 |
'pre_chat_message', |
| 2604 |
'Chat Teaser Pop-up', |
| 2605 |
array($this, 'mxchat_pre_chat_message_callback'), |
| 2606 |
'mxchat-chatbot', |
| 2607 |
'mxchat_chatbot_section' |
| 2608 |
); |
| 2609 |
|
| 2610 |
add_settings_field( |
| 2611 |
'append_to_body', |
| 2612 |
'Append Chat Widget to Body', |
| 2613 |
array($this, 'mxchat_append_to_body_callback'), |
| 2614 |
'mxchat-chatbot', |
| 2615 |
'mxchat_chatbot_section' |
| 2616 |
); |
| 2617 |
|
| 2618 |
add_settings_field( |
| 2619 |
'privacy_toggle', |
| 2620 |
'Toggle Privacy Notice', |
| 2621 |
array($this, 'mxchat_privacy_toggle_callback'), |
| 2622 |
'mxchat-chatbot', |
| 2623 |
'mxchat_chatbot_section' |
| 2624 |
); |
| 2625 |
|
| 2626 |
add_settings_field( |
| 2627 |
'complianz_toggle', |
| 2628 |
'Enable Complianz', |
| 2629 |
array($this, 'mxchat_complianz_toggle_callback'), |
| 2630 |
'mxchat-chatbot', |
| 2631 |
'mxchat_chatbot_section' |
| 2632 |
); |
| 2633 |
|
| 2634 |
add_settings_field( |
| 2635 |
'link_target_toggle', |
| 2636 |
'Open Links in a New Tab', |
| 2637 |
array($this, 'mxchat_link_target_toggle_callback'), |
| 2638 |
'mxchat-chatbot', |
| 2639 |
'mxchat_chatbot_section' |
| 2640 |
); |
| 2641 |
|
| 2642 |
add_settings_field( |
| 2643 |
'chat_persistence_toggle', |
| 2644 |
'Enable Chat Persistence', |
| 2645 |
array($this, 'mxchat_chat_persistence_toggle_callback'), |
| 2646 |
'mxchat-chatbot', |
| 2647 |
'mxchat_chatbot_section' |
| 2648 |
); |
| 2649 |
|
| 2650 |
add_settings_field( |
| 2651 |
'popular_question_1', |
| 2652 |
'Popular Question 1', |
| 2653 |
array($this, 'mxchat_popular_question_1_callback'), |
| 2654 |
'mxchat-chatbot', |
| 2655 |
'mxchat_chatbot_section' |
| 2656 |
); |
| 2657 |
|
| 2658 |
add_settings_field( |
| 2659 |
'popular_question_2', |
| 2660 |
'Popular Question 2', |
| 2661 |
array($this, 'mxchat_popular_question_2_callback'), |
| 2662 |
'mxchat-chatbot', |
| 2663 |
'mxchat_chatbot_section' |
| 2664 |
); |
| 2665 |
|
| 2666 |
add_settings_field( |
| 2667 |
'popular_question_3', |
| 2668 |
'Popular Question 3', |
| 2669 |
array($this, 'mxchat_popular_question_3_callback'), |
| 2670 |
'mxchat-chatbot', |
| 2671 |
'mxchat_chatbot_section' |
| 2672 |
); |
| 2673 |
|
| 2674 |
add_settings_field( |
| 2675 |
'additional_popular_questions', |
| 2676 |
'Additional Popular Questions', |
| 2677 |
array($this, 'mxchat_additional_popular_questions_callback'), |
| 2678 |
'mxchat-chatbot', |
| 2679 |
'mxchat_chatbot_section' |
| 2680 |
); |
| 2681 |
|
| 2682 |
|
| 2683 |
// WooCommerce Settings Section |
| 2684 |
add_settings_section( |
| 2685 |
'mxchat_woocommerce_section', |
| 2686 |
'WooCommerce Settings', |
| 2687 |
null, |
| 2688 |
'mxchat-embed' |
| 2689 |
); |
| 2690 |
|
| 2691 |
// Loops Settings Section |
| 2692 |
add_settings_section( |
| 2693 |
'mxchat_loops_section', |
| 2694 |
'Loops Settings', |
| 2695 |
null, |
| 2696 |
'mxchat-embed' |
| 2697 |
); |
| 2698 |
|
| 2699 |
// WooCommerce Settings Fields |
| 2700 |
add_settings_field( |
| 2701 |
'enable_woocommerce_integration', |
| 2702 |
'Automatically Embed Products', |
| 2703 |
array($this, 'mxchat_enable_woocommerce_integration_callback'), |
| 2704 |
'mxchat-embed', |
| 2705 |
'mxchat_woocommerce_section' |
| 2706 |
); |
| 2707 |
|
| 2708 |
|
| 2709 |
add_settings_field( |
| 2710 |
'woocommerce_consumer_key', |
| 2711 |
'WooCommerce Consumer Key', |
| 2712 |
array($this, 'mxchat_woocommerce_consumer_key_callback'), |
| 2713 |
'mxchat-embed', |
| 2714 |
'mxchat_woocommerce_section' |
| 2715 |
); |
| 2716 |
|
| 2717 |
add_settings_field( |
| 2718 |
'woocommerce_consumer_secret', |
| 2719 |
'WooCommerce Consumer Secret', |
| 2720 |
array($this, 'mxchat_woocommerce_consumer_secret_callback'), |
| 2721 |
'mxchat-embed', |
| 2722 |
'mxchat_woocommerce_section' |
| 2723 |
); |
| 2724 |
|
| 2725 |
// Loops Settings Fields |
| 2726 |
add_settings_field( |
| 2727 |
'loops_api_key', |
| 2728 |
'Loops API Key', |
| 2729 |
array($this, 'mxchat_loops_api_key_callback'), |
| 2730 |
'mxchat-embed', |
| 2731 |
'mxchat_loops_section' |
| 2732 |
); |
| 2733 |
|
| 2734 |
add_settings_field( |
| 2735 |
'loops_mailing_list', |
| 2736 |
'Loops Mailing List', |
| 2737 |
array($this, 'mxchat_loops_mailing_list_callback'), |
| 2738 |
'mxchat-embed', |
| 2739 |
'mxchat_loops_section' |
| 2740 |
); |
| 2741 |
|
| 2742 |
add_settings_field( |
| 2743 |
'triggered_phrase_response', |
| 2744 |
'Triggered Phrase Response', |
| 2745 |
array($this, 'mxchat_triggered_phrase_response_callback'), |
| 2746 |
'mxchat-embed', |
| 2747 |
'mxchat_loops_section' |
| 2748 |
); |
| 2749 |
|
| 2750 |
add_settings_field( |
| 2751 |
'email_capture_response', |
| 2752 |
'Email Capture Response', |
| 2753 |
array($this, 'mxchat_email_capture_response_callback'), |
| 2754 |
'mxchat-embed', |
| 2755 |
'mxchat_loops_section' |
| 2756 |
); |
| 2757 |
|
| 2758 |
|
| 2759 |
// Brave Search Settings Fields |
| 2760 |
add_settings_section( |
| 2761 |
'mxchat_brave_section', |
| 2762 |
__('Brave Search Settings', 'mxchat'), |
| 2763 |
array($this, 'mxchat_brave_section_callback'), |
| 2764 |
'mxchat-embed' |
| 2765 |
); |
| 2766 |
|
| 2767 |
add_settings_field( |
| 2768 |
'brave_api_key', |
| 2769 |
__('Brave API Key', 'mxchat'), |
| 2770 |
array($this, 'mxchat_brave_api_key_callback'), |
| 2771 |
'mxchat-embed', |
| 2772 |
'mxchat_brave_section' |
| 2773 |
); |
| 2774 |
|
| 2775 |
add_settings_field( |
| 2776 |
'brave_image_count', |
| 2777 |
__('Number of Images to Return', 'mxchat'), |
| 2778 |
array($this, 'mxchat_brave_image_count_callback'), |
| 2779 |
'mxchat-embed', |
| 2780 |
'mxchat_brave_section' |
| 2781 |
); |
| 2782 |
|
| 2783 |
add_settings_field( |
| 2784 |
'brave_safe_search', |
| 2785 |
__('Safe Search', 'mxchat'), |
| 2786 |
array($this, 'mxchat_brave_safe_search_callback'), |
| 2787 |
'mxchat-embed', |
| 2788 |
'mxchat_brave_section' |
| 2789 |
); |
| 2790 |
|
| 2791 |
add_settings_field( |
| 2792 |
'brave_news_count', |
| 2793 |
__('Number of News Articles', 'mxchat'), |
| 2794 |
array($this, 'mxchat_brave_news_count_callback'), |
| 2795 |
'mxchat-embed', |
| 2796 |
'mxchat_brave_section' |
| 2797 |
); |
| 2798 |
|
| 2799 |
add_settings_field( |
| 2800 |
'brave_country', |
| 2801 |
__('Country', 'mxchat'), |
| 2802 |
array($this, 'mxchat_brave_country_callback'), |
| 2803 |
'mxchat-embed', |
| 2804 |
'mxchat_brave_section' |
| 2805 |
); |
| 2806 |
|
| 2807 |
add_settings_field( |
| 2808 |
'brave_language', |
| 2809 |
__('Language', 'mxchat'), |
| 2810 |
array($this, 'mxchat_brave_language_callback'), |
| 2811 |
'mxchat-embed', |
| 2812 |
'mxchat_brave_section' |
| 2813 |
); |
| 2814 |
|
| 2815 |
|
| 2816 |
// Chat with PDF Intent Settings Fields |
| 2817 |
add_settings_section( |
| 2818 |
'mxchat_pdf_intent_section', |
| 2819 |
__('Toolbar Settings & Intents', 'mxchat'), |
| 2820 |
array($this, 'mxchat_pdf_intent_section_callback'), |
| 2821 |
'mxchat-embed' |
| 2822 |
); |
| 2823 |
|
| 2824 |
add_settings_field( |
| 2825 |
'chat_toolbar_toggle', |
| 2826 |
__('Show Chat Toolbar', 'mxchat'), |
| 2827 |
array($this, 'mxchat_chat_toolbar_toggle_callback'), |
| 2828 |
'mxchat-embed', |
| 2829 |
'mxchat_pdf_intent_section' |
| 2830 |
); |
| 2831 |
|
| 2832 |
|
| 2833 |
add_settings_field( |
| 2834 |
'pdf_intent_trigger_text', |
| 2835 |
__('Intent Trigger Text', 'mxchat'), |
| 2836 |
array($this, 'mxchat_pdf_intent_trigger_text_callback'), |
| 2837 |
'mxchat-embed', |
| 2838 |
'mxchat_pdf_intent_section' |
| 2839 |
); |
| 2840 |
|
| 2841 |
add_settings_field( |
| 2842 |
'pdf_intent_success_text', |
| 2843 |
__('Success Text', 'mxchat'), |
| 2844 |
array($this, 'mxchat_pdf_intent_success_text_callback'), |
| 2845 |
'mxchat-embed', |
| 2846 |
'mxchat_pdf_intent_section' |
| 2847 |
); |
| 2848 |
|
| 2849 |
add_settings_field( |
| 2850 |
'pdf_intent_error_text', |
| 2851 |
__('Error Text', 'mxchat'), |
| 2852 |
array($this, 'mxchat_pdf_intent_error_text_callback'), |
| 2853 |
'mxchat-embed', |
| 2854 |
'mxchat_pdf_intent_section' |
| 2855 |
); |
| 2856 |
|
| 2857 |
// Add PDF Maximum Pages Field |
| 2858 |
add_settings_field( |
| 2859 |
'pdf_max_pages', |
| 2860 |
__('Maximum Document Pages', 'mxchat'), |
| 2861 |
array($this, 'mxchat_pdf_max_pages_callback'), |
| 2862 |
'mxchat-embed', |
| 2863 |
'mxchat_pdf_intent_section' |
| 2864 |
); |
| 2865 |
|
| 2866 |
|
| 2867 |
|
| 2868 |
|
| 2869 |
// Live Agent Settings Fields |
| 2870 |
add_settings_section( |
| 2871 |
'mxchat_live_agent_section', |
| 2872 |
__('Live Agent Settings', 'mxchat'), |
| 2873 |
array($this, 'mxchat_live_agent_section_callback'), |
| 2874 |
'mxchat-embed' |
| 2875 |
); |
| 2876 |
|
| 2877 |
// Live Agent Status Fields (add at top of live agent settings) |
| 2878 |
add_settings_field( |
| 2879 |
'live_agent_status', |
| 2880 |
__('Live Agent Status', 'mxchat'), |
| 2881 |
array($this, 'mxchat_live_agent_status_callback'), |
| 2882 |
'mxchat-embed', |
| 2883 |
'mxchat_live_agent_section' |
| 2884 |
); |
| 2885 |
|
| 2886 |
add_settings_field( |
| 2887 |
'live_agent_notification_message', |
| 2888 |
__('Notification Message', 'mxchat'), |
| 2889 |
array($this, 'mxchat_live_agent_notification_message_callback'), |
| 2890 |
'mxchat-embed', |
| 2891 |
'mxchat_live_agent_section' |
| 2892 |
); |
| 2893 |
|
| 2894 |
add_settings_field( |
| 2895 |
'live_agent_away_message', |
| 2896 |
__('Away Message', 'mxchat'), |
| 2897 |
array($this, 'mxchat_live_agent_away_message_callback'), |
| 2898 |
'mxchat-embed', |
| 2899 |
'mxchat_live_agent_section' |
| 2900 |
); |
| 2901 |
|
| 2902 |
add_settings_field( |
| 2903 |
'live_agent_webhook_url', |
| 2904 |
__('Slack Webhook URL', 'mxchat'), |
| 2905 |
array($this, 'mxchat_live_agent_webhook_url_callback'), |
| 2906 |
'mxchat-embed', |
| 2907 |
'mxchat_live_agent_section' |
| 2908 |
); |
| 2909 |
|
| 2910 |
add_settings_field( |
| 2911 |
'live_agent_secret_key', |
| 2912 |
__('Slack Secret Key', 'mxchat'), |
| 2913 |
array($this, 'mxchat_live_agent_secret_key_callback'), |
| 2914 |
'mxchat-embed', |
| 2915 |
'mxchat_live_agent_section' |
| 2916 |
); |
| 2917 |
|
| 2918 |
// Live Agent Integration Fields |
| 2919 |
add_settings_field( |
| 2920 |
'live_agent_bot_token', |
| 2921 |
__('Slack Bot OAuth Token', 'mxchat'), |
| 2922 |
array($this, 'mxchat_live_agent_bot_token_callback'), |
| 2923 |
'mxchat-embed', |
| 2924 |
'mxchat_live_agent_section' |
| 2925 |
); |
| 2926 |
|
| 2927 |
|
| 2928 |
// Theme Settings Section |
| 2929 |
add_settings_section( |
| 2930 |
'mxchat_theme_section', |
| 2931 |
'Theme Settings', |
| 2932 |
null, |
| 2933 |
'mxchat-theme' |
| 2934 |
); |
| 2935 |
|
| 2936 |
add_settings_field( |
| 2937 |
'close_button_color', |
| 2938 |
'Close Button & Title Color', |
| 2939 |
array($this, 'mxchat_close_button_color_callback'), |
| 2940 |
'mxchat-theme', |
| 2941 |
'mxchat_theme_section' |
| 2942 |
); |
| 2943 |
|
| 2944 |
add_settings_field( |
| 2945 |
'chatbot_bg_color', |
| 2946 |
'Chatbot Background Color', |
| 2947 |
array($this, 'mxchat_chatbot_bg_color_callback'), |
| 2948 |
'mxchat-theme', |
| 2949 |
'mxchat_theme_section' |
| 2950 |
); |
| 2951 |
|
| 2952 |
add_settings_field( |
| 2953 |
'user_message_bg_color', |
| 2954 |
'User Message Background Color', |
| 2955 |
array($this, 'mxchat_user_message_bg_color_callback'), |
| 2956 |
'mxchat-theme', |
| 2957 |
'mxchat_theme_section' |
| 2958 |
); |
| 2959 |
|
| 2960 |
add_settings_field( |
| 2961 |
'user_message_font_color', |
| 2962 |
'User Message Font Color', |
| 2963 |
array($this, 'mxchat_user_message_font_color_callback'), |
| 2964 |
'mxchat-theme', |
| 2965 |
'mxchat_theme_section' |
| 2966 |
); |
| 2967 |
|
| 2968 |
add_settings_field( |
| 2969 |
'bot_message_bg_color', |
| 2970 |
'Bot Message Background Color', |
| 2971 |
array($this, 'mxchat_bot_message_bg_color_callback'), |
| 2972 |
'mxchat-theme', |
| 2973 |
'mxchat_theme_section' |
| 2974 |
); |
| 2975 |
|
| 2976 |
add_settings_field( |
| 2977 |
'bot_message_font_color', |
| 2978 |
'Bot Message Font Color', |
| 2979 |
array($this, 'mxchat_bot_message_font_color_callback'), |
| 2980 |
'mxchat-theme', |
| 2981 |
'mxchat_theme_section' |
| 2982 |
); |
| 2983 |
|
| 2984 |
add_settings_field( |
| 2985 |
'top_bar_bg_color', |
| 2986 |
'Top Bar Background Color', |
| 2987 |
array($this, 'mxchat_top_bar_bg_color_callback'), |
| 2988 |
'mxchat-theme', |
| 2989 |
'mxchat_theme_section' |
| 2990 |
); |
| 2991 |
|
| 2992 |
add_settings_field( |
| 2993 |
'send_button_font_color', |
| 2994 |
'Send Button Color', |
| 2995 |
array($this, 'mxchat_send_button_font_color_callback'), |
| 2996 |
'mxchat-theme', |
| 2997 |
'mxchat_theme_section' |
| 2998 |
); |
| 2999 |
|
| 3000 |
add_settings_field( |
| 3001 |
'chat_input_font_color', |
| 3002 |
'Chat Input Font Color', |
| 3003 |
array($this, 'mxchat_chat_input_font_color_callback'), |
| 3004 |
'mxchat-theme', |
| 3005 |
'mxchat_theme_section' |
| 3006 |
); |
| 3007 |
|
| 3008 |
add_settings_field( |
| 3009 |
'chatbot_background_color', |
| 3010 |
'Floating Widget Background Color', |
| 3011 |
array($this, 'mxchat_chatbot_background_color_callback'), |
| 3012 |
'mxchat-theme', |
| 3013 |
'mxchat_theme_section' |
| 3014 |
); |
| 3015 |
|
| 3016 |
add_settings_field( |
| 3017 |
'icon_color', |
| 3018 |
'Chatbot Icon Color', |
| 3019 |
array($this, 'mxchat_icon_color_callback'), |
| 3020 |
'mxchat-theme', |
| 3021 |
'mxchat_theme_section' |
| 3022 |
); |
| 3023 |
|
| 3024 |
add_settings_field( |
| 3025 |
'custom_icon', |
| 3026 |
'Custom Chatbot Icon (PNG)', |
| 3027 |
array($this, 'mxchat_custom_icon_callback'), |
| 3028 |
'mxchat-theme', |
| 3029 |
'mxchat_theme_section' |
| 3030 |
); |
| 3031 |
|
| 3032 |
add_settings_field( |
| 3033 |
'title_icon', |
| 3034 |
'Title Bar Icon (PNG)', |
| 3035 |
array($this, 'mxchat_title_icon_callback'), |
| 3036 |
'mxchat-theme', |
| 3037 |
'mxchat_theme_section' |
| 3038 |
); |
| 3039 |
|
| 3040 |
|
| 3041 |
add_settings_field( |
| 3042 |
'live_agent_message_bg_color', |
| 3043 |
'Live Agent Background Color', |
| 3044 |
array($this, 'mxchat_live_agent_message_bg_color_callback'), |
| 3045 |
'mxchat-theme', |
| 3046 |
'mxchat_theme_section' |
| 3047 |
); |
| 3048 |
|
| 3049 |
add_settings_field( |
| 3050 |
'live_agent_message_font_color', |
| 3051 |
'Live Agent Font Color', |
| 3052 |
array($this, 'mxchat_live_agent_message_font_color_callback'), |
| 3053 |
'mxchat-theme', |
| 3054 |
'mxchat_theme_section' |
| 3055 |
); |
| 3056 |
|
| 3057 |
// Mode Indicator Background Color |
| 3058 |
add_settings_field( |
| 3059 |
'mode_indicator_bg_color', |
| 3060 |
'Mode Indicator Background Color', |
| 3061 |
array($this, 'mxchat_mode_indicator_bg_color_callback'), |
| 3062 |
'mxchat-theme', |
| 3063 |
'mxchat_theme_section' |
| 3064 |
); |
| 3065 |
|
| 3066 |
// Mode Indicator Font Color |
| 3067 |
add_settings_field( |
| 3068 |
'mode_indicator_font_color', |
| 3069 |
'Mode Indicator Font Color', |
| 3070 |
array($this, 'mxchat_mode_indicator_font_color_callback'), |
| 3071 |
'mxchat-theme', |
| 3072 |
'mxchat_theme_section' |
| 3073 |
); |
| 3074 |
|
| 3075 |
add_settings_field( |
| 3076 |
'toolbar_icon_color', |
| 3077 |
'Toolbar Icon Color', |
| 3078 |
array($this, 'mxchat_toolbar_icon_color_callback'), |
| 3079 |
'mxchat-theme', |
| 3080 |
'mxchat_theme_section' |
| 3081 |
); |
| 3082 |
|
| 3083 |
// General Settings Section |
| 3084 |
add_settings_section( |
| 3085 |
'mxchat_general_section', |
| 3086 |
'Frequently Asked Questions (FAQ)', |
| 3087 |
null, |
| 3088 |
'mxchat-general' |
| 3089 |
); |
| 3090 |
|
| 3091 |
|
| 3092 |
|
| 3093 |
|
| 3094 |
|
| 3095 |
|
| 3096 |
} |
| 3097 |
|
| 3098 |
public function mxchat_prompts_page_init() { |
| 3099 |
// Register settings for the prompts/knowledge base page |
| 3100 |
register_setting( |
| 3101 |
'mxchat_prompts_options', |
| 3102 |
'mxchat_auto_sync_posts', |
| 3103 |
array( |
| 3104 |
'type' => 'boolean', |
| 3105 |
'description' => 'Automatically sync posts to knowledge base', |
| 3106 |
'sanitize_callback' => array($this, 'sanitize_sync_setting'), |
| 3107 |
'default' => 0, |
| 3108 |
'show_in_rest' => false, |
| 3109 |
) |
| 3110 |
); |
| 3111 |
register_setting( |
| 3112 |
'mxchat_prompts_options', |
| 3113 |
'mxchat_auto_sync_pages', |
| 3114 |
array( |
| 3115 |
'type' => 'boolean', |
| 3116 |
'description' => 'Automatically sync pages to knowledge base', |
| 3117 |
'sanitize_callback' => array($this, 'sanitize_sync_setting'), |
| 3118 |
'default' => 0, |
| 3119 |
'show_in_rest' => false, |
| 3120 |
) |
| 3121 |
); |
| 3122 |
|
| 3123 |
// Add settings saved message |
| 3124 |
add_action('admin_notices', array($this, 'sync_settings_notice')); |
| 3125 |
} |
| 3126 |
|
| 3127 |
public function sync_settings_notice() { |
| 3128 |
// Only show notice on our plugin page |
| 3129 |
if (!isset($_GET['page']) || $_GET['page'] !== 'mxchat-prompts') { |
| 3130 |
return; |
| 3131 |
} |
| 3132 |
|
| 3133 |
// Check if settings were updated |
| 3134 |
if (isset($_GET['settings-updated'])) { |
| 3135 |
?> |
| 3136 |
<div class="notice notice-success is-dismissible"> |
| 3137 |
<p><?php esc_html_e('Sync settings updated successfully.', 'mxchat'); ?></p> |
| 3138 |
</div> |
| 3139 |
<?php |
| 3140 |
} |
| 3141 |
} |
| 3142 |
// Add this sanitization function to your class |
| 3143 |
public function sanitize_sync_setting($input) { |
| 3144 |
return (bool)$input ? '1' : ''; |
| 3145 |
} |
| 3146 |
|
| 3147 |
|
| 3148 |
|
| 3149 |
public function mxchat_handle_activate_license() { |
| 3150 |
// Check nonce |
| 3151 |
if (!check_ajax_referer('mxchat_activate_license_nonce', 'security', false)) { |
| 3152 |
wp_send_json_error('Invalid security token'); |
| 3153 |
return; |
| 3154 |
} |
| 3155 |
|
| 3156 |
// Verify user capabilities |
| 3157 |
if (!current_user_can('manage_options')) { |
| 3158 |
wp_send_json_error('Unauthorized access'); |
| 3159 |
return; |
| 3160 |
} |
| 3161 |
|
| 3162 |
$license_key = isset($_POST['mxchat_activation_key']) ? sanitize_text_field($_POST['mxchat_activation_key']) : ''; |
| 3163 |
$customer_email = isset($_POST['mxchat_pro_email']) ? sanitize_email($_POST['mxchat_pro_email']) : ''; |
| 3164 |
|
| 3165 |
if (empty($license_key) || empty($customer_email)) { |
| 3166 |
wp_send_json_error('Email or License Key is missing'); |
| 3167 |
return; |
| 3168 |
} |
| 3169 |
|
| 3170 |
$product_id = 'MxChatPRO'; |
| 3171 |
$response = wp_remote_get( |
| 3172 |
add_query_arg( |
| 3173 |
array( |
| 3174 |
'wc-api' => 'software-api', |
| 3175 |
'request' => 'activation', |
| 3176 |
'email' => $customer_email, |
| 3177 |
'license_key' => $license_key, |
| 3178 |
'product_id' => $product_id |
| 3179 |
), |
| 3180 |
'http://mxchat.ai/' |
| 3181 |
) |
| 3182 |
); |
| 3183 |
|
| 3184 |
if (is_wp_error($response)) { |
| 3185 |
wp_send_json_error('Activation failed due to a server error: ' . $response->get_error_message()); |
| 3186 |
return; |
| 3187 |
} |
| 3188 |
|
| 3189 |
$body = wp_remote_retrieve_body($response); |
| 3190 |
$data = json_decode($body); |
| 3191 |
|
| 3192 |
if ($data && isset($data->activated) && $data->activated) { |
| 3193 |
update_option('mxchat_license_status', 'active'); |
| 3194 |
update_option('mxchat_pro_email', $customer_email); |
| 3195 |
update_option('mxchat_activation_key', $license_key); |
| 3196 |
wp_send_json_success(array('message' => 'License activated successfully')); |
| 3197 |
} else { |
| 3198 |
$error_message = isset($data->error) ? $data->error : 'Activation failed'; |
| 3199 |
update_option('mxchat_license_status', 'inactive'); |
| 3200 |
update_option('mxchat_license_error', $error_message); |
| 3201 |
wp_send_json_error($error_message); |
| 3202 |
} |
| 3203 |
} |
| 3204 |
|
| 3205 |
public function mxchat_rate_limit_logged_in_callback() { |
| 3206 |
// Load the entire 'mxchat_options' array |
| 3207 |
$all_options = get_option('mxchat_options', []); |
| 3208 |
|
| 3209 |
// Retrieve the saved rate limit or use the default value |
| 3210 |
$default_rate_limit = '100'; |
| 3211 |
$selected_rate_limit = isset($all_options['rate_limit_logged_in']) ? $all_options['rate_limit_logged_in'] : $default_rate_limit; |
| 3212 |
|
| 3213 |
// Define available rate limits |
| 3214 |
$rate_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); |
| 3215 |
|
| 3216 |
// Output the dropdown |
| 3217 |
echo '<div class="pro-feature-wrapper active">'; |
| 3218 |
echo '<select id="rate_limit_logged_in" name="rate_limit_logged_in">'; |
| 3219 |
foreach ($rate_limits as $limit) { |
| 3220 |
echo '<option value="' . esc_attr($limit) . '" ' . selected($selected_rate_limit, $limit, false) . '>' . esc_html($limit) . '</option>'; |
| 3221 |
} |
| 3222 |
echo '</select>'; |
| 3223 |
echo '<p class="description">Set the maximum number of messages a logged-in user can send within a 24-hour period.</p>'; |
| 3224 |
echo '</div>'; |
| 3225 |
} |
| 3226 |
|
| 3227 |
|
| 3228 |
|
| 3229 |
public function mxchat_rate_limit_logged_out_callback() { |
| 3230 |
// Load the entire 'mxchat_options' array |
| 3231 |
$all_options = get_option('mxchat_options', []); |
| 3232 |
|
| 3233 |
// Retrieve the saved rate limit or use the default value |
| 3234 |
$default_rate_limit = '10'; |
| 3235 |
$selected_rate_limit = isset($all_options['rate_limit_logged_out']) ? $all_options['rate_limit_logged_out'] : $default_rate_limit; |
| 3236 |
|
| 3237 |
// Define available rate limits |
| 3238 |
$rate_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); |
| 3239 |
|
| 3240 |
// Output the dropdown |
| 3241 |
echo '<div class="pro-feature-wrapper active">'; |
| 3242 |
echo '<select id="rate_limit_logged_out" name="rate_limit_logged_out">'; |
| 3243 |
foreach ($rate_limits as $limit) { |
| 3244 |
echo '<option value="' . esc_attr($limit) . '" ' . selected($selected_rate_limit, $limit, false) . '>' . esc_html($limit) . '</option>'; |
| 3245 |
} |
| 3246 |
echo '</select>'; |
| 3247 |
echo '<p class="description">Set the maximum number of messages a logged-out user can send within a 24-hour period.</p>'; |
| 3248 |
echo '</div>'; |
| 3249 |
} |
| 3250 |
|
| 3251 |
public function mxchat_rate_limit_message_callback() { |
| 3252 |
// Load the entire 'mxchat_options' array |
| 3253 |
$all_options = get_option('mxchat_options', []); |
| 3254 |
|
| 3255 |
// Retrieve the saved message or use the default value |
| 3256 |
$default_message = 'Rate limit exceeded. Please try again later.'; |
| 3257 |
$rate_limit_message = isset($all_options['rate_limit_message']) ? $all_options['rate_limit_message'] : $default_message; |
| 3258 |
|
| 3259 |
// Output the textarea |
| 3260 |
echo '<div class="pro-feature-wrapper active">'; |
| 3261 |
printf( |
| 3262 |
'<textarea id="rate_limit_message" name="rate_limit_message" rows="3" cols="50">%s</textarea>', |
| 3263 |
esc_textarea($rate_limit_message) |
| 3264 |
); |
| 3265 |
echo '<p class="description">This message will be displayed when a user exceeds the rate limit.</p>'; |
| 3266 |
echo '</div>'; |
| 3267 |
} |
| 3268 |
|
| 3269 |
|
| 3270 |
public function mxchat_enable_woocommerce_integration_callback() { |
| 3271 |
// Load from mxchat_options array |
| 3272 |
$options = get_option('mxchat_options', []); |
| 3273 |
|
| 3274 |
// Get WooCommerce integration status with backwards compatibility |
| 3275 |
$woo_integration = isset($options['enable_woocommerce_integration']) |
| 3276 |
? $options['enable_woocommerce_integration'] |
| 3277 |
: ''; |
| 3278 |
|
| 3279 |
// Support both old ('1') and new ('on') values |
| 3280 |
$checked = ($woo_integration === 'on' || $woo_integration === '1') ? 'checked' : ''; |
| 3281 |
|
| 3282 |
// Check if the feature is activated (paid feature) |
| 3283 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3284 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3285 |
|
| 3286 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3287 |
|
| 3288 |
echo '<label class="toggle-switch">'; |
| 3289 |
echo sprintf( |
| 3290 |
'<input type="checkbox" id="enable_woocommerce_integration" name="enable_woocommerce_integration" value="on" %s %s />', |
| 3291 |
esc_attr($checked), |
| 3292 |
esc_attr($disabled) |
| 3293 |
); |
| 3294 |
echo '<span class="slider"></span>'; |
| 3295 |
echo '</label>'; |
| 3296 |
|
| 3297 |
echo '<p class="description">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.</p>'; |
| 3298 |
|
| 3299 |
// Pro feature overlay for non-activated users |
| 3300 |
if (!$this->is_activated) { |
| 3301 |
echo '<div class="pro-feature-overlay">'; |
| 3302 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3303 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3304 |
echo '</a>'; |
| 3305 |
echo '</div>'; |
| 3306 |
} |
| 3307 |
|
| 3308 |
echo '</div>'; |
| 3309 |
} |
| 3310 |
|
| 3311 |
|
| 3312 |
|
| 3313 |
|
| 3314 |
private function mxchat_add_option_field($id, $title, $callback = '') { |
| 3315 |
add_settings_field( |
| 3316 |
$id, |
| 3317 |
$title, |
| 3318 |
$callback ? array($this, $callback) : array($this, $id . '_callback'), |
| 3319 |
'mxchat-max', |
| 3320 |
'mxchat_setting_section_id', |
| 3321 |
$id === 'model' ? ['label_for' => 'model'] : [] |
| 3322 |
); |
| 3323 |
} |
| 3324 |
|
| 3325 |
public function api_key_callback() { |
| 3326 |
// Retrieve from your stored 'api_key' in the mxchat_options array |
| 3327 |
$apiKey = isset($this->options['api_key']) ? esc_attr($this->options['api_key']) : ''; |
| 3328 |
|
| 3329 |
// Notice we changed the name to "api_key" (no array notation). |
| 3330 |
echo '<input type="password" id="api_key" name="api_key" value="' . $apiKey . '" class="regular-text" />'; |
| 3331 |
echo '<button type="button" id="toggleApiKeyVisibility">Show</button>'; |
| 3332 |
echo '<p class="description">The OpenAI API key is required even when using other models as it is used for vector embedding functionality.</p>'; |
| 3333 |
} |
| 3334 |
|
| 3335 |
|
| 3336 |
|
| 3337 |
|
| 3338 |
public function xai_api_key_callback() { |
| 3339 |
// Check if the feature is activated (paid feature) |
| 3340 |
$disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated |
| 3341 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; // CSS class to style the wrapper based on activation status |
| 3342 |
|
| 3343 |
// Retrieve the X.AI API key value |
| 3344 |
$xaiApiKey = isset($this->options['xai_api_key']) ? esc_attr($this->options['xai_api_key']) : ''; |
| 3345 |
|
| 3346 |
// Render the input field for the X.AI API key |
| 3347 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3348 |
printf( |
| 3349 |
'<input type="password" id="xai_api_key" name="xai_api_key" value="%s" class="regular-text" %s />', |
| 3350 |
$xaiApiKey, |
| 3351 |
$disabled |
| 3352 |
); |
| 3353 |
echo '<button type="button" id="toggleXaiApiKeyVisibility">Show</button>'; |
| 3354 |
|
| 3355 |
// If the feature is not activated, show the overlay with a "Pro Only" message |
| 3356 |
if (!$this->is_activated) { |
| 3357 |
echo '<div class="pro-feature-overlay">'; |
| 3358 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 3359 |
echo '</div>'; |
| 3360 |
} |
| 3361 |
|
| 3362 |
echo '</div>'; |
| 3363 |
} |
| 3364 |
|
| 3365 |
|
| 3366 |
public function claude_api_key_callback() { |
| 3367 |
// Check if the feature is activated (paid feature) |
| 3368 |
$disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated |
| 3369 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; // CSS class to style the wrapper based on activation status |
| 3370 |
|
| 3371 |
// Retrieve the Claude API key value |
| 3372 |
$claudeApiKey = isset($this->options['claude_api_key']) ? esc_attr($this->options['claude_api_key']) : ''; |
| 3373 |
|
| 3374 |
// Render the input field for the Claude API key |
| 3375 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3376 |
printf( |
| 3377 |
'<input type="password" id="claude_api_key" name="claude_api_key" value="%s" class="regular-text" %s />', |
| 3378 |
$claudeApiKey, |
| 3379 |
$disabled |
| 3380 |
); |
| 3381 |
echo '<button type="button" id="toggleClaudeApiKeyVisibility">Show</button>'; |
| 3382 |
|
| 3383 |
// If the feature is not activated, show the overlay with a "Pro Only" message |
| 3384 |
if (!$this->is_activated) { |
| 3385 |
echo '<div class="pro-feature-overlay">'; |
| 3386 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 3387 |
echo '</div>'; |
| 3388 |
} |
| 3389 |
|
| 3390 |
echo '</div>'; |
| 3391 |
} |
| 3392 |
|
| 3393 |
public function mxchat_woocommerce_consumer_key_callback() { |
| 3394 |
// Load the entire 'mxchat_options' array |
| 3395 |
$all_options = get_option('mxchat_options', []); |
| 3396 |
|
| 3397 |
// Retrieve the WooCommerce consumer key or set a default |
| 3398 |
$consumer_key = isset($all_options['woocommerce_consumer_key']) ? $all_options['woocommerce_consumer_key'] : ''; |
| 3399 |
|
| 3400 |
// Check if the feature is activated (paid feature) |
| 3401 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3402 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3403 |
|
| 3404 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3405 |
|
| 3406 |
// Render the input field |
| 3407 |
printf( |
| 3408 |
'<input type="text" id="woocommerce_consumer_key" name="woocommerce_consumer_key" value="%s" class="regular-text" %s />', |
| 3409 |
esc_attr($consumer_key), |
| 3410 |
esc_attr($disabled) |
| 3411 |
); |
| 3412 |
|
| 3413 |
// Description for the input field |
| 3414 |
echo '<p class="description">Enter your WooCommerce consumer key for integration.</p>'; |
| 3415 |
|
| 3416 |
// Pro feature overlay for non-activated users |
| 3417 |
if (!$this->is_activated) { |
| 3418 |
echo '<div class="pro-feature-overlay">'; |
| 3419 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 3420 |
echo '</div>'; |
| 3421 |
} |
| 3422 |
|
| 3423 |
echo '</div>'; |
| 3424 |
} |
| 3425 |
|
| 3426 |
|
| 3427 |
public function mxchat_woocommerce_consumer_secret_callback() { |
| 3428 |
// Get value with fallback |
| 3429 |
$consumer_secret = isset($this->options['woocommerce_consumer_secret']) |
| 3430 |
? esc_attr($this->options['woocommerce_consumer_secret']) |
| 3431 |
: ''; |
| 3432 |
|
| 3433 |
// Check if the feature is activated (paid feature) |
| 3434 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3435 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3436 |
|
| 3437 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3438 |
|
| 3439 |
// Output the password input |
| 3440 |
echo sprintf( |
| 3441 |
'<input type="password" |
| 3442 |
id="woocommerce_consumer_secret" |
| 3443 |
name="woocommerce_consumer_secret" |
| 3444 |
value="%s" |
| 3445 |
class="regular-text" |
| 3446 |
%s />', |
| 3447 |
$consumer_secret, |
| 3448 |
esc_attr($disabled) |
| 3449 |
); |
| 3450 |
|
| 3451 |
// Add show/hide button |
| 3452 |
echo '<button type="button" id="toggleWooCommerceSecretVisibility">Show</button>'; |
| 3453 |
|
| 3454 |
// Pro feature overlay |
| 3455 |
if (!$this->is_activated) { |
| 3456 |
echo '<div class="pro-feature-overlay">'; |
| 3457 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3458 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3459 |
echo '</a>'; |
| 3460 |
echo '</div>'; |
| 3461 |
} |
| 3462 |
|
| 3463 |
echo '</div>'; |
| 3464 |
} |
| 3465 |
public function mxchat_loops_api_key_callback() { |
| 3466 |
// Support both old and new format |
| 3467 |
$loops_api_key = isset($this->options['loops_api_key']) ? esc_attr($this->options['loops_api_key']) : ''; |
| 3468 |
|
| 3469 |
echo '<div class="api-key-wrapper">'; |
| 3470 |
echo sprintf( |
| 3471 |
'<input type="password" id="loops_api_key" name="loops_api_key" value="%s" class="regular-text" />', |
| 3472 |
$loops_api_key |
| 3473 |
); |
| 3474 |
echo '<button type="button" id="toggleLoopsApiKeyVisibility">Show</button>'; |
| 3475 |
echo '</div>'; |
| 3476 |
echo '<p class="description">Enter your Loops API Key here. (See FAQ for details)</p>'; |
| 3477 |
} |
| 3478 |
|
| 3479 |
public function mxchat_loops_mailing_list_callback() { |
| 3480 |
// Add error handling and type checking |
| 3481 |
$loops_api_key = ''; |
| 3482 |
$selected_list = ''; |
| 3483 |
|
| 3484 |
// Safely get the API key |
| 3485 |
if (isset($this->options['loops_api_key']) && is_string($this->options['loops_api_key'])) { |
| 3486 |
$loops_api_key = $this->options['loops_api_key']; |
| 3487 |
} |
| 3488 |
|
| 3489 |
// Safely get the selected list |
| 3490 |
if (isset($this->options['loops_mailing_list']) && is_string($this->options['loops_mailing_list'])) { |
| 3491 |
$selected_list = $this->options['loops_mailing_list']; |
| 3492 |
} |
| 3493 |
|
| 3494 |
if (!empty($loops_api_key)) { |
| 3495 |
$lists = $this->mxchat_fetch_loops_mailing_lists($loops_api_key); |
| 3496 |
if (is_array($lists) && !empty($lists)) { |
| 3497 |
echo '<select id="loops_mailing_list" name="loops_mailing_list">'; |
| 3498 |
foreach ($lists as $list) { |
| 3499 |
if (is_array($list) && isset($list['id']) && isset($list['name'])) { |
| 3500 |
echo sprintf( |
| 3501 |
'<option value="%s" %s>%s</option>', |
| 3502 |
esc_attr($list['id']), |
| 3503 |
selected($selected_list, $list['id'], false), |
| 3504 |
esc_html($list['name']) |
| 3505 |
); |
| 3506 |
} |
| 3507 |
} |
| 3508 |
echo '</select>'; |
| 3509 |
} else { |
| 3510 |
echo '<p class="description">No lists found. Please verify your API Key.</p>'; |
| 3511 |
} |
| 3512 |
} else { |
| 3513 |
echo '<p class="description">Enter a valid Loops API Key to load mailing lists.</p>'; |
| 3514 |
} |
| 3515 |
} |
| 3516 |
public function mxchat_triggered_phrase_response_callback() { |
| 3517 |
$default_response = 'Would you like to join our mailing list? Please provide your email below.'; |
| 3518 |
$triggered_response = isset($this->options['triggered_phrase_response']) |
| 3519 |
? $this->options['triggered_phrase_response'] |
| 3520 |
: $default_response; |
| 3521 |
|
| 3522 |
echo sprintf( |
| 3523 |
'<textarea id="triggered_phrase_response" name="triggered_phrase_response" rows="3" cols="50">%s</textarea>', |
| 3524 |
esc_textarea($triggered_response) |
| 3525 |
); |
| 3526 |
echo '<p class="description">Enter the chatbot response when a trigger keyword is detected, prompting the user to share their email.</p>'; |
| 3527 |
} |
| 3528 |
|
| 3529 |
public function mxchat_email_capture_response_callback() { |
| 3530 |
$default_response = 'Thank you for providing your email! You\'ve been added to our list.'; |
| 3531 |
$email_capture_response = isset($this->options['email_capture_response']) |
| 3532 |
? $this->options['email_capture_response'] |
| 3533 |
: $default_response; |
| 3534 |
|
| 3535 |
echo sprintf( |
| 3536 |
'<textarea id="email_capture_response" name="email_capture_response" rows="3" cols="50">%s</textarea>', |
| 3537 |
esc_textarea($email_capture_response) |
| 3538 |
); |
| 3539 |
echo '<p class="description">Enter the message to send when a user provides their email.</p>'; |
| 3540 |
} |
| 3541 |
|
| 3542 |
public function mxchat_pre_chat_message_callback() { |
| 3543 |
// Load the entire 'mxchat_options' array |
| 3544 |
$all_options = get_option('mxchat_options', []); |
| 3545 |
|
| 3546 |
// Retrieve the saved message or use the default value |
| 3547 |
$default_message = 'Hey there! Ask me anything!'; |
| 3548 |
$pre_chat_message = isset($all_options['pre_chat_message']) ? $all_options['pre_chat_message'] : $default_message; |
| 3549 |
|
| 3550 |
// Output the textarea |
| 3551 |
printf( |
| 3552 |
'<textarea id="pre_chat_message" name="pre_chat_message" rows="5" cols="50">%s</textarea>', |
| 3553 |
esc_textarea($pre_chat_message) |
| 3554 |
); |
| 3555 |
echo '<p class="description">Set the message displayed to users before they start a chat. Use this to provide a friendly greeting or instructions.</p>'; |
| 3556 |
} |
| 3557 |
|
| 3558 |
|
| 3559 |
|
| 3560 |
// Callback for AI Instructions textarea |
| 3561 |
public function system_prompt_instructions_callback() { |
| 3562 |
// Retrieve the current value of the system prompt instructions |
| 3563 |
$instructions = isset($this->options['system_prompt_instructions']) ? esc_textarea($this->options['system_prompt_instructions']) : ''; |
| 3564 |
|
| 3565 |
// Render the textarea field |
| 3566 |
printf( |
| 3567 |
'<textarea id="system_prompt_instructions" name="system_prompt_instructions" rows="5" cols="50">%s</textarea>', |
| 3568 |
$instructions |
| 3569 |
); |
| 3570 |
|
| 3571 |
// Provide a helpful description |
| 3572 |
echo '<p class="description">Provide system-level instructions for the AI to guide its behavior. Be clear and concise for better results.</p>'; |
| 3573 |
} |
| 3574 |
|
| 3575 |
|
| 3576 |
public function mxchat_model_callback() { |
| 3577 |
// Define available models grouped by provider |
| 3578 |
$models = array( |
| 3579 |
'X.AI Models' => array( |
| 3580 |
'grok-beta' => 'grok-beta (Early Beta)', |
| 3581 |
'grok-2' => 'Grok 2' |
| 3582 |
), |
| 3583 |
'Claude Models' => array( |
| 3584 |
'claude-3-5-sonnet-20241022' => 'Claude 3.5 Sonnet (Most Intelligent)', |
| 3585 |
'claude-3-opus-20240229' => 'Claude 3 Opus (Highly Complex Tasks)', |
| 3586 |
'claude-3-sonnet-20240229' => 'Claude 3 Sonnet (Balanced)', |
| 3587 |
'claude-3-haiku-20240307' => 'Claude 3 Haiku (Fastest)' |
| 3588 |
), |
| 3589 |
'OpenAI Models' => array( |
| 3590 |
'gpt-4o' => 'GPT-4o (Recommended)', |
| 3591 |
'gpt-4o-mini' => 'GPT-4o Mini (Fast and Lightweight)', |
| 3592 |
'gpt-4-turbo' => 'GPT-4 Turbo (High-Performance)', |
| 3593 |
'gpt-4' => 'GPT-4 (High Intelligence)', |
| 3594 |
'gpt-3.5-turbo' => 'GPT-3.5 Turbo (Affordable and Fast)' |
| 3595 |
) |
| 3596 |
); |
| 3597 |
|
| 3598 |
// Retrieve the currently selected model from saved options |
| 3599 |
$selected_model = isset($this->options['model']) ? esc_attr($this->options['model']) : 'gpt-3.5-turbo'; |
| 3600 |
|
| 3601 |
// Begin the select dropdown |
| 3602 |
echo '<select id="model" name="model">'; // No array notation in name attribute |
| 3603 |
|
| 3604 |
// Iterate over groups of models |
| 3605 |
foreach ($models as $group_label => $group_models) { |
| 3606 |
echo '<optgroup label="' . esc_attr($group_label) . '">'; |
| 3607 |
|
| 3608 |
foreach ($group_models as $model_value => $model_label) { |
| 3609 |
// Disable Pro-only models for non-activated users |
| 3610 |
$disabled = (!$this->is_activated && ($group_label === 'X.AI Models' || $group_label === 'Claude Models')) ? 'disabled' : ''; |
| 3611 |
$label_suffix = (!$this->is_activated && ($group_label === 'X.AI Models' || $group_label === 'Claude Models')) ? ' (Pro Only)' : ''; |
| 3612 |
|
| 3613 |
// Output the option element |
| 3614 |
echo '<option value="' . esc_attr($model_value) . '" ' . selected($selected_model, $model_value, false) . ' ' . $disabled . '>' . esc_html($model_label . $label_suffix) . '</option>'; |
| 3615 |
} |
| 3616 |
|
| 3617 |
echo '</optgroup>'; |
| 3618 |
} |
| 3619 |
|
| 3620 |
// Close the select dropdown |
| 3621 |
echo '</select>'; |
| 3622 |
|
| 3623 |
// Add a description below the dropdown |
| 3624 |
echo '<p class="description">Select the AI model to use for your chatbot. Pro-only models are marked accordingly.</p>'; |
| 3625 |
} |
| 3626 |
|
| 3627 |
|
| 3628 |
|
| 3629 |
public function mxchat_top_bar_title_callback() { |
| 3630 |
// Retrieve the current value of the top bar title from saved options |
| 3631 |
$top_bar_title = isset($this->options['top_bar_title']) ? esc_attr($this->options['top_bar_title']) : ''; |
| 3632 |
|
| 3633 |
// Render the input field |
| 3634 |
echo '<input type="text" id="top_bar_title" name="top_bar_title" value="' . $top_bar_title . '" />'; |
| 3635 |
|
| 3636 |
// Add a description |
| 3637 |
echo '<p class="description">Enter the title text that will appear on the top bar of the chatbot.</p>'; |
| 3638 |
} |
| 3639 |
|
| 3640 |
public function enable_email_block_callback() { |
| 3641 |
// Load full plugin options array |
| 3642 |
$all_options = get_option('mxchat_options', []); |
| 3643 |
|
| 3644 |
// Get the value, default to 'off' |
| 3645 |
$enable_email_block = isset($all_options['enable_email_block']) ? $all_options['enable_email_block'] : 'off'; |
| 3646 |
|
| 3647 |
// Check if it's 'on' |
| 3648 |
$checked = ($enable_email_block === 'on') ? 'checked' : ''; |
| 3649 |
|
| 3650 |
echo '<label class="toggle-switch">'; |
| 3651 |
echo sprintf( |
| 3652 |
'<input type="checkbox" id="enable_email_block" name="enable_email_block" value="on" %s />', |
| 3653 |
esc_attr($checked) |
| 3654 |
); |
| 3655 |
echo '<span class="slider"></span>'; |
| 3656 |
echo '</label>'; |
| 3657 |
echo '<p class="description">Enable to require email before a user chats. Their email will appear at the top of the transcript.</p>'; |
| 3658 |
} |
| 3659 |
|
| 3660 |
|
| 3661 |
|
| 3662 |
public function email_blocker_header_content_callback() { |
| 3663 |
// Load the entire 'mxchat_options' array |
| 3664 |
$all_options = get_option('mxchat_options', []); |
| 3665 |
|
| 3666 |
// Retrieve the saved content or default to empty |
| 3667 |
$content = isset($all_options['email_blocker_header_content']) |
| 3668 |
? $all_options['email_blocker_header_content'] |
| 3669 |
: ''; |
| 3670 |
|
| 3671 |
// Render the textarea |
| 3672 |
echo '<textarea |
| 3673 |
id="email_blocker_header_content" |
| 3674 |
name="email_blocker_header_content" |
| 3675 |
rows="5" |
| 3676 |
cols="70" |
| 3677 |
>' . esc_textarea($content) . '</textarea>'; |
| 3678 |
|
| 3679 |
echo '<p class="description">'; |
| 3680 |
echo 'You may enter HTML here, such as <h2>Welcome</h2> or <p>Let\'s get started</p>.'; |
| 3681 |
echo ' Email form will show for users who are not logged in or have not provided an email within 24h.'; |
| 3682 |
echo '</p>'; |
| 3683 |
} |
| 3684 |
|
| 3685 |
|
| 3686 |
public function email_blocker_button_text_callback() { |
| 3687 |
// Load the entire 'mxchat_options' array |
| 3688 |
$all_options = get_option('mxchat_options', []); |
| 3689 |
|
| 3690 |
// Retrieve the saved button text or default to empty |
| 3691 |
$button_text = isset($all_options['email_blocker_button_text']) |
| 3692 |
? $all_options['email_blocker_button_text'] |
| 3693 |
: ''; |
| 3694 |
|
| 3695 |
// Use esc_attr to safely render the existing text |
| 3696 |
echo '<input type="text" id="email_blocker_button_text" name="email_blocker_button_text" value="' . esc_attr($button_text) . '" style="width: 300px;" />'; |
| 3697 |
|
| 3698 |
echo '<p class="description">'; |
| 3699 |
echo 'Enter the text you want on the submit button, e.g. "Start Chat".'; |
| 3700 |
echo '</p>'; |
| 3701 |
} |
| 3702 |
|
| 3703 |
|
| 3704 |
|
| 3705 |
public function mxchat_intro_message_callback() { |
| 3706 |
// Load the entire 'mxchat_options' array |
| 3707 |
$all_options = get_option('mxchat_options', []); |
| 3708 |
|
| 3709 |
// Retrieve the saved intro message or use the default |
| 3710 |
$default_message = 'Hello! How can I assist you today?'; |
| 3711 |
$saved_message = isset($all_options['intro_message']) ? $all_options['intro_message'] : $default_message; |
| 3712 |
|
| 3713 |
// Output the textarea with the saved value |
| 3714 |
?> |
| 3715 |
<textarea id="intro_message" name="intro_message" rows="5" cols="50"><?php echo esc_textarea($saved_message); ?></textarea> |
| 3716 |
<p class="description"> |
| 3717 |
<?php esc_html_e('Enter your message. Line breaks will be preserved.', 'mxchat'); ?> |
| 3718 |
</p> |
| 3719 |
<?php |
| 3720 |
} |
| 3721 |
|
| 3722 |
|
| 3723 |
public function mxchat_input_copy_callback() { |
| 3724 |
// Load the entire 'mxchat_options' array |
| 3725 |
$all_options = get_option('mxchat_options', []); |
| 3726 |
|
| 3727 |
// Retrieve the saved input copy or use the default value |
| 3728 |
$default_copy = 'How can I assist?'; |
| 3729 |
$input_copy = isset($all_options['input_copy']) ? $all_options['input_copy'] : $default_copy; |
| 3730 |
|
| 3731 |
// Output the input field with the saved value |
| 3732 |
printf( |
| 3733 |
'<input type="text" id="input_copy" name="input_copy" value="%s" placeholder="How can I assist?" />', |
| 3734 |
esc_attr($input_copy) |
| 3735 |
); |
| 3736 |
|
| 3737 |
// Output the description |
| 3738 |
echo '<p class="description">This is the placeholder text for the chat input field.</p>'; |
| 3739 |
} |
| 3740 |
|
| 3741 |
|
| 3742 |
|
| 3743 |
|
| 3744 |
|
| 3745 |
public function mxchat_close_button_color_callback() { |
| 3746 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3747 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3748 |
|
| 3749 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3750 |
echo sprintf( |
| 3751 |
'<input type="text" |
| 3752 |
id="close_button_color" |
| 3753 |
name="close_button_color" |
| 3754 |
value="%s" |
| 3755 |
class="my-color-field" |
| 3756 |
data-default-color="#4a4a4a" |
| 3757 |
%s />', |
| 3758 |
isset($this->options['close_button_color']) ? esc_attr($this->options['close_button_color']) : '#4a4a4a', |
| 3759 |
esc_attr($disabled) |
| 3760 |
); |
| 3761 |
|
| 3762 |
if (!$this->is_activated) { |
| 3763 |
echo '<div class="pro-feature-overlay">'; |
| 3764 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3765 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3766 |
echo '</a>'; |
| 3767 |
echo '</div>'; |
| 3768 |
} |
| 3769 |
echo '</div>'; |
| 3770 |
} |
| 3771 |
|
| 3772 |
public function mxchat_chatbot_bg_color_callback() { |
| 3773 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3774 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3775 |
|
| 3776 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3777 |
echo sprintf( |
| 3778 |
'<input type="text" |
| 3779 |
id="chatbot_bg_color" |
| 3780 |
name="chatbot_bg_color" |
| 3781 |
value="%s" |
| 3782 |
class="my-color-field" |
| 3783 |
data-default-color="#f9f9f9" |
| 3784 |
%s />', |
| 3785 |
isset($this->options['chatbot_bg_color']) ? esc_attr($this->options['chatbot_bg_color']) : '#f9f9f9', |
| 3786 |
esc_attr($disabled) |
| 3787 |
); |
| 3788 |
|
| 3789 |
if (!$this->is_activated) { |
| 3790 |
echo '<div class="pro-feature-overlay">'; |
| 3791 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3792 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3793 |
echo '</a>'; |
| 3794 |
echo '</div>'; |
| 3795 |
} |
| 3796 |
echo '</div>'; |
| 3797 |
} |
| 3798 |
|
| 3799 |
public function mxchat_user_message_bg_color_callback() { |
| 3800 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3801 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3802 |
|
| 3803 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3804 |
echo sprintf( |
| 3805 |
'<input type="text" |
| 3806 |
id="user_message_bg_color" |
| 3807 |
name="user_message_bg_color" |
| 3808 |
value="%s" |
| 3809 |
class="my-color-field" |
| 3810 |
data-default-color="#0078d7" |
| 3811 |
%s />', |
| 3812 |
isset($this->options['user_message_bg_color']) ? esc_attr($this->options['user_message_bg_color']) : '#0078d7', |
| 3813 |
esc_attr($disabled) |
| 3814 |
); |
| 3815 |
|
| 3816 |
if (!$this->is_activated) { |
| 3817 |
echo '<div class="pro-feature-overlay">'; |
| 3818 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3819 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3820 |
echo '</a>'; |
| 3821 |
echo '</div>'; |
| 3822 |
} |
| 3823 |
echo '</div>'; |
| 3824 |
} |
| 3825 |
|
| 3826 |
public function mxchat_user_message_font_color_callback() { |
| 3827 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3828 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3829 |
|
| 3830 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3831 |
echo sprintf( |
| 3832 |
'<input type="text" |
| 3833 |
id="user_message_font_color" |
| 3834 |
name="user_message_font_color" |
| 3835 |
value="%s" |
| 3836 |
class="my-color-field" |
| 3837 |
data-default-color="#ffffff" |
| 3838 |
%s />', |
| 3839 |
isset($this->options['user_message_font_color']) ? esc_attr($this->options['user_message_font_color']) : '#ffffff', |
| 3840 |
esc_attr($disabled) |
| 3841 |
); |
| 3842 |
|
| 3843 |
if (!$this->is_activated) { |
| 3844 |
echo '<div class="pro-feature-overlay">'; |
| 3845 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3846 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3847 |
echo '</a>'; |
| 3848 |
echo '</div>'; |
| 3849 |
} |
| 3850 |
echo '</div>'; |
| 3851 |
} |
| 3852 |
|
| 3853 |
public function mxchat_bot_message_bg_color_callback() { |
| 3854 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3855 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3856 |
|
| 3857 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3858 |
echo sprintf( |
| 3859 |
'<input type="text" |
| 3860 |
id="bot_message_bg_color" |
| 3861 |
name="bot_message_bg_color" |
| 3862 |
value="%s" |
| 3863 |
class="my-color-field" |
| 3864 |
data-default-color="#e1e1e1" |
| 3865 |
%s />', |
| 3866 |
isset($this->options['bot_message_bg_color']) ? esc_attr($this->options['bot_message_bg_color']) : '#e1e1e1', |
| 3867 |
esc_attr($disabled) |
| 3868 |
); |
| 3869 |
|
| 3870 |
if (!$this->is_activated) { |
| 3871 |
echo '<div class="pro-feature-overlay">'; |
| 3872 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3873 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3874 |
echo '</a>'; |
| 3875 |
echo '</div>'; |
| 3876 |
} |
| 3877 |
echo '</div>'; |
| 3878 |
} |
| 3879 |
|
| 3880 |
public function mxchat_bot_message_font_color_callback() { |
| 3881 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3882 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3883 |
|
| 3884 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3885 |
echo sprintf( |
| 3886 |
'<input type="text" |
| 3887 |
id="bot_message_font_color" |
| 3888 |
name="bot_message_font_color" |
| 3889 |
value="%s" |
| 3890 |
class="my-color-field" |
| 3891 |
data-default-color="#333333" |
| 3892 |
%s />', |
| 3893 |
isset($this->options['bot_message_font_color']) ? esc_attr($this->options['bot_message_font_color']) : '#333333', |
| 3894 |
esc_attr($disabled) |
| 3895 |
); |
| 3896 |
|
| 3897 |
if (!$this->is_activated) { |
| 3898 |
echo '<div class="pro-feature-overlay">'; |
| 3899 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3900 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3901 |
echo '</a>'; |
| 3902 |
echo '</div>'; |
| 3903 |
} |
| 3904 |
echo '</div>'; |
| 3905 |
} |
| 3906 |
|
| 3907 |
public function mxchat_live_agent_message_bg_color_callback() { |
| 3908 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3909 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3910 |
|
| 3911 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3912 |
echo sprintf( |
| 3913 |
'<input type="text" |
| 3914 |
id="live_agent_message_bg_color" |
| 3915 |
name="live_agent_message_bg_color" |
| 3916 |
value="%s" |
| 3917 |
class="my-color-field" |
| 3918 |
data-default-color="#ffffff" |
| 3919 |
%s />', |
| 3920 |
isset($this->options['live_agent_message_bg_color']) ? esc_attr($this->options['live_agent_message_bg_color']) : '#ffffff', |
| 3921 |
esc_attr($disabled) |
| 3922 |
); |
| 3923 |
|
| 3924 |
if (!$this->is_activated) { |
| 3925 |
echo '<div class="pro-feature-overlay">'; |
| 3926 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3927 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3928 |
echo '</a>'; |
| 3929 |
echo '</div>'; |
| 3930 |
} |
| 3931 |
echo '</div>'; |
| 3932 |
} |
| 3933 |
|
| 3934 |
public function mxchat_live_agent_message_font_color_callback() { |
| 3935 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3936 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3937 |
|
| 3938 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3939 |
echo sprintf( |
| 3940 |
'<input type="text" |
| 3941 |
id="live_agent_message_font_color" |
| 3942 |
name="live_agent_message_font_color" |
| 3943 |
value="%s" |
| 3944 |
class="my-color-field" |
| 3945 |
data-default-color="#333333" |
| 3946 |
%s />', |
| 3947 |
isset($this->options['live_agent_message_font_color']) ? esc_attr($this->options['live_agent_message_font_color']) : '#333333', |
| 3948 |
esc_attr($disabled) |
| 3949 |
); |
| 3950 |
|
| 3951 |
if (!$this->is_activated) { |
| 3952 |
echo '<div class="pro-feature-overlay">'; |
| 3953 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3954 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3955 |
echo '</a>'; |
| 3956 |
echo '</div>'; |
| 3957 |
} |
| 3958 |
echo '</div>'; |
| 3959 |
} |
| 3960 |
|
| 3961 |
public function mxchat_mode_indicator_bg_color_callback() { |
| 3962 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3963 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3964 |
|
| 3965 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3966 |
echo sprintf( |
| 3967 |
'<input type="text" |
| 3968 |
id="mode_indicator_bg_color" |
| 3969 |
name="mode_indicator_bg_color" |
| 3970 |
value="%s" |
| 3971 |
class="my-color-field" |
| 3972 |
data-default-color="#767676" |
| 3973 |
%s />', |
| 3974 |
isset($this->options['mode_indicator_bg_color']) ? esc_attr($this->options['mode_indicator_bg_color']) : '#767676', |
| 3975 |
esc_attr($disabled) |
| 3976 |
); |
| 3977 |
|
| 3978 |
if (!$this->is_activated) { |
| 3979 |
echo '<div class="pro-feature-overlay">'; |
| 3980 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 3981 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 3982 |
echo '</a>'; |
| 3983 |
echo '</div>'; |
| 3984 |
} |
| 3985 |
echo '</div>'; |
| 3986 |
} |
| 3987 |
|
| 3988 |
public function mxchat_mode_indicator_font_color_callback() { |
| 3989 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 3990 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 3991 |
|
| 3992 |
echo '<div class="' . esc_attr($class) . '">'; |
| 3993 |
echo sprintf( |
| 3994 |
'<input type="text" |
| 3995 |
id="mode_indicator_font_color" |
| 3996 |
name="mode_indicator_font_color" |
| 3997 |
value="%s" |
| 3998 |
class="my-color-field" |
| 3999 |
data-default-color="#ffffff" |
| 4000 |
%s />', |
| 4001 |
isset($this->options['mode_indicator_font_color']) ? esc_attr($this->options['mode_indicator_font_color']) : '#ffffff', |
| 4002 |
esc_attr($disabled) |
| 4003 |
); |
| 4004 |
|
| 4005 |
if (!$this->is_activated) { |
| 4006 |
echo '<div class="pro-feature-overlay">'; |
| 4007 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4008 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4009 |
echo '</a>'; |
| 4010 |
echo '</div>'; |
| 4011 |
} |
| 4012 |
echo '</div>'; |
| 4013 |
} |
| 4014 |
|
| 4015 |
public function mxchat_toolbar_icon_color_callback() { |
| 4016 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4017 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4018 |
|
| 4019 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4020 |
echo sprintf( |
| 4021 |
'<input type="text" |
| 4022 |
id="toolbar_icon_color" |
| 4023 |
name="toolbar_icon_color" |
| 4024 |
value="%s" |
| 4025 |
class="my-color-field" |
| 4026 |
data-default-color="#212121" |
| 4027 |
%s />', |
| 4028 |
isset($this->options['toolbar_icon_color']) ? esc_attr($this->options['toolbar_icon_color']) : '#212121', |
| 4029 |
esc_attr($disabled) |
| 4030 |
); |
| 4031 |
|
| 4032 |
if (!$this->is_activated) { |
| 4033 |
echo '<div class="pro-feature-overlay">'; |
| 4034 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4035 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4036 |
echo '</a>'; |
| 4037 |
echo '</div>'; |
| 4038 |
} |
| 4039 |
echo '</div>'; |
| 4040 |
} |
| 4041 |
|
| 4042 |
public function mxchat_top_bar_bg_color_callback() { |
| 4043 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4044 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4045 |
|
| 4046 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4047 |
echo sprintf( |
| 4048 |
'<input type="text" |
| 4049 |
id="top_bar_bg_color" |
| 4050 |
name="top_bar_bg_color" |
| 4051 |
value="%s" |
| 4052 |
class="my-color-field" |
| 4053 |
data-default-color="#00b294" |
| 4054 |
%s />', |
| 4055 |
isset($this->options['top_bar_bg_color']) ? esc_attr($this->options['top_bar_bg_color']) : '#00b294', |
| 4056 |
esc_attr($disabled) |
| 4057 |
); |
| 4058 |
|
| 4059 |
if (!$this->is_activated) { |
| 4060 |
echo '<div class="pro-feature-overlay">'; |
| 4061 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4062 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4063 |
echo '</a>'; |
| 4064 |
echo '</div>'; |
| 4065 |
} |
| 4066 |
echo '</div>'; |
| 4067 |
} |
| 4068 |
|
| 4069 |
public function mxchat_send_button_font_color_callback() { |
| 4070 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4071 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4072 |
|
| 4073 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4074 |
echo sprintf( |
| 4075 |
'<input type="text" |
| 4076 |
id="send_button_font_color" |
| 4077 |
name="send_button_font_color" |
| 4078 |
value="%s" |
| 4079 |
class="my-color-field" |
| 4080 |
data-default-color="#ffffff" |
| 4081 |
%s />', |
| 4082 |
isset($this->options['send_button_font_color']) ? esc_attr($this->options['send_button_font_color']) : '#ffffff', |
| 4083 |
esc_attr($disabled) |
| 4084 |
); |
| 4085 |
|
| 4086 |
if (!$this->is_activated) { |
| 4087 |
echo '<div class="pro-feature-overlay">'; |
| 4088 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4089 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4090 |
echo '</a>'; |
| 4091 |
echo '</div>'; |
| 4092 |
} |
| 4093 |
echo '</div>'; |
| 4094 |
} |
| 4095 |
|
| 4096 |
public function mxchat_chatbot_background_color_callback() { |
| 4097 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4098 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4099 |
|
| 4100 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4101 |
echo sprintf( |
| 4102 |
'<input type="text" |
| 4103 |
id="chatbot_background_color" |
| 4104 |
name="chatbot_background_color" |
| 4105 |
value="%s" |
| 4106 |
class="my-color-field" |
| 4107 |
data-default-color="#000000" |
| 4108 |
%s />', |
| 4109 |
isset($this->options['chatbot_background_color']) ? esc_attr($this->options['chatbot_background_color']) : '#000000', |
| 4110 |
esc_attr($disabled) |
| 4111 |
); |
| 4112 |
|
| 4113 |
if (!$this->is_activated) { |
| 4114 |
echo '<div class="pro-feature-overlay">'; |
| 4115 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4116 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4117 |
echo '</a>'; |
| 4118 |
echo '</div>'; |
| 4119 |
} |
| 4120 |
echo '</div>'; |
| 4121 |
} |
| 4122 |
|
| 4123 |
public function mxchat_icon_color_callback() { |
| 4124 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4125 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4126 |
|
| 4127 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4128 |
echo sprintf( |
| 4129 |
'<input type="text" |
| 4130 |
id="icon_color" |
| 4131 |
name="icon_color" |
| 4132 |
value="%s" |
| 4133 |
class="my-color-field" |
| 4134 |
data-default-color="#ffffff" |
| 4135 |
%s />', |
| 4136 |
isset($this->options['icon_color']) ? esc_attr($this->options['icon_color']) : '#ffffff', |
| 4137 |
esc_attr($disabled) |
| 4138 |
); |
| 4139 |
|
| 4140 |
if (!$this->is_activated) { |
| 4141 |
echo '<div class="pro-feature-overlay">'; |
| 4142 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4143 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4144 |
echo '</a>'; |
| 4145 |
echo '</div>'; |
| 4146 |
} |
| 4147 |
echo '</div>'; |
| 4148 |
} |
| 4149 |
|
| 4150 |
public function mxchat_custom_icon_callback() { |
| 4151 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4152 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4153 |
$custom_icon_url = isset($this->options['custom_icon']) ? esc_url($this->options['custom_icon']) : ''; |
| 4154 |
|
| 4155 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4156 |
echo sprintf( |
| 4157 |
'<input type="url" |
| 4158 |
id="custom_icon" |
| 4159 |
name="custom_icon" |
| 4160 |
value="%s" |
| 4161 |
placeholder="Enter PNG URL" |
| 4162 |
class="regular-text" |
| 4163 |
%s />', |
| 4164 |
$custom_icon_url, |
| 4165 |
esc_attr($disabled) |
| 4166 |
); |
| 4167 |
|
| 4168 |
// Preview container for the icon |
| 4169 |
if (!empty($custom_icon_url)) { |
| 4170 |
echo '<div class="icon-preview" style="margin-top: 10px;">'; |
| 4171 |
echo '<img src="' . esc_url($custom_icon_url) . '" alt="Custom Icon Preview" style="max-width: 48px; height: auto;" />'; |
| 4172 |
echo '</div>'; |
| 4173 |
} |
| 4174 |
|
| 4175 |
echo '<p class="description">Upload your PNG icon and paste the URL here. Recommended size: 48x48 pixels.</p>'; |
| 4176 |
|
| 4177 |
if (!$this->is_activated) { |
| 4178 |
echo '<div class="pro-feature-overlay">'; |
| 4179 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4180 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4181 |
echo '</a>'; |
| 4182 |
echo '</div>'; |
| 4183 |
} |
| 4184 |
echo '</div>'; |
| 4185 |
} |
| 4186 |
|
| 4187 |
public function mxchat_title_icon_callback() { |
| 4188 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4189 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4190 |
// Fixed the variable reference - it was using custom_icon instead of title_icon |
| 4191 |
$title_icon_url = isset($this->options['title_icon']) ? esc_url($this->options['title_icon']) : ''; |
| 4192 |
|
| 4193 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4194 |
echo sprintf( |
| 4195 |
'<input type="url" |
| 4196 |
id="title_icon" |
| 4197 |
name="title_icon" |
| 4198 |
value="%s" |
| 4199 |
placeholder="Enter PNG URL" |
| 4200 |
class="regular-text" |
| 4201 |
%s />', |
| 4202 |
$title_icon_url, |
| 4203 |
esc_attr($disabled) |
| 4204 |
); |
| 4205 |
|
| 4206 |
// Preview container for the icon |
| 4207 |
if (!empty($title_icon_url)) { |
| 4208 |
echo '<div class="icon-preview" style="margin-top: 10px;">'; |
| 4209 |
echo '<img src="' . esc_url($title_icon_url) . '" alt="Title Icon Preview" style="max-width: 48px; height: auto;" />'; |
| 4210 |
echo '</div>'; |
| 4211 |
} |
| 4212 |
|
| 4213 |
echo '<p class="description">Upload your PNG icon and paste the URL here. Recommended size: 48x48 pixels.</p>'; |
| 4214 |
|
| 4215 |
if (!$this->is_activated) { |
| 4216 |
echo '<div class="pro-feature-overlay">'; |
| 4217 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4218 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4219 |
echo '</a>'; |
| 4220 |
echo '</div>'; |
| 4221 |
} |
| 4222 |
echo '</div>'; |
| 4223 |
} |
| 4224 |
|
| 4225 |
public function mxchat_chat_input_font_color_callback() { |
| 4226 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4227 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4228 |
|
| 4229 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4230 |
echo sprintf( |
| 4231 |
'<input type="text" |
| 4232 |
id="chat_input_font_color" |
| 4233 |
name="chat_input_font_color" |
| 4234 |
value="%s" |
| 4235 |
class="my-color-field" |
| 4236 |
data-default-color="#555555" |
| 4237 |
%s />', |
| 4238 |
isset($this->options['chat_input_font_color']) ? esc_attr($this->options['chat_input_font_color']) : '#555555', |
| 4239 |
esc_attr($disabled) |
| 4240 |
); |
| 4241 |
|
| 4242 |
if (!$this->is_activated) { |
| 4243 |
echo '<div class="pro-feature-overlay">'; |
| 4244 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4245 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4246 |
echo '</a>'; |
| 4247 |
echo '</div>'; |
| 4248 |
} |
| 4249 |
echo '</div>'; |
| 4250 |
} |
| 4251 |
|
| 4252 |
public function mxchat_append_to_body_callback() { |
| 4253 |
// Get value from options array, default to 'off' |
| 4254 |
$append_to_body = isset($this->options['append_to_body']) ? $this->options['append_to_body'] : 'off'; |
| 4255 |
$checked = ($append_to_body === 'on') ? 'checked' : ''; |
| 4256 |
|
| 4257 |
echo '<label class="toggle-switch">'; |
| 4258 |
echo sprintf( |
| 4259 |
'<input type="checkbox" id="append_to_body" name="append_to_body" value="on" %s />', |
| 4260 |
esc_attr($checked) |
| 4261 |
); |
| 4262 |
echo '<span class="slider"></span>'; |
| 4263 |
echo '</label>'; |
| 4264 |
echo '<p class="description">Enable this option to automatically append the chat widget to the body of every page (recommended). No need to manually use the shortcode [mxchat_chatbot floating="yes"].</p>'; |
| 4265 |
} |
| 4266 |
|
| 4267 |
|
| 4268 |
|
| 4269 |
public function mxchat_privacy_toggle_callback() { |
| 4270 |
// Load from mxchat_options array |
| 4271 |
$options = get_option('mxchat_options', []); |
| 4272 |
|
| 4273 |
// Get privacy toggle value with fallback |
| 4274 |
$privacy_toggle = isset($options['privacy_toggle']) ? $options['privacy_toggle'] : 'off'; |
| 4275 |
$checked = ($privacy_toggle === 'on') ? 'checked' : ''; |
| 4276 |
|
| 4277 |
// Get privacy text with fallback |
| 4278 |
$privacy_text = isset($options['privacy_text']) |
| 4279 |
? $options['privacy_text'] |
| 4280 |
: 'By chatting, you agree to our <a href="https://example.com/privacy-policy" target="_blank">privacy policy</a>.'; |
| 4281 |
|
| 4282 |
// Output the toggle switch |
| 4283 |
echo '<label class="toggle-switch">'; |
| 4284 |
echo sprintf( |
| 4285 |
'<input type="checkbox" id="privacy_toggle" name="privacy_toggle" value="on" %s />', |
| 4286 |
esc_attr($checked) |
| 4287 |
); |
| 4288 |
echo '<span class="slider"></span>'; |
| 4289 |
echo '</label>'; |
| 4290 |
echo '<p class="description">Enable this option to display a privacy notice below the chat widget.</p>'; |
| 4291 |
|
| 4292 |
// Output the custom text input field |
| 4293 |
echo sprintf( |
| 4294 |
'<textarea id="privacy_text" name="privacy_text" rows="5" cols="50" class="regular-text">%s</textarea>', |
| 4295 |
esc_textarea($privacy_text) |
| 4296 |
); |
| 4297 |
echo '<p class="description">Enter the privacy policy text. You can include HTML links.</p>'; |
| 4298 |
} |
| 4299 |
|
| 4300 |
|
| 4301 |
public function mxchat_complianz_toggle_callback() { |
| 4302 |
// Load from mxchat_options array |
| 4303 |
$options = get_option('mxchat_options', []); |
| 4304 |
|
| 4305 |
// Get complianz toggle value with fallback |
| 4306 |
$complianz_toggle = isset($options['complianz_toggle']) ? $options['complianz_toggle'] : 'off'; |
| 4307 |
$checked = ($complianz_toggle === 'on') ? 'checked' : ''; |
| 4308 |
|
| 4309 |
// Check if the plugin is activated (paid feature) |
| 4310 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4311 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4312 |
|
| 4313 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4314 |
|
| 4315 |
// Output the toggle switch |
| 4316 |
echo '<label class="toggle-switch">'; |
| 4317 |
echo sprintf( |
| 4318 |
'<input type="checkbox" id="complianz_toggle" name="complianz_toggle" value="on" %s %s />', |
| 4319 |
esc_attr($checked), |
| 4320 |
esc_attr($disabled) |
| 4321 |
); |
| 4322 |
echo '<span class="slider"></span>'; |
| 4323 |
echo '</label>'; |
| 4324 |
|
| 4325 |
echo '<p class="description">Enable this option to apply Complianz consent logic to the chatbot (must have Complianz Plugin).</p>'; |
| 4326 |
|
| 4327 |
// If the feature is not activated, show the Pro feature overlay |
| 4328 |
if (!$this->is_activated) { |
| 4329 |
echo '<div class="pro-feature-overlay">'; |
| 4330 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4331 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4332 |
echo '</a>'; |
| 4333 |
echo '</div>'; |
| 4334 |
} |
| 4335 |
|
| 4336 |
echo '</div>'; |
| 4337 |
} |
| 4338 |
|
| 4339 |
|
| 4340 |
public function mxchat_link_target_toggle_callback() { |
| 4341 |
// Load from mxchat_options array |
| 4342 |
$options = get_option('mxchat_options', []); |
| 4343 |
|
| 4344 |
// Get link target toggle value with fallback |
| 4345 |
$link_target_toggle = isset($options['link_target_toggle']) ? $options['link_target_toggle'] : 'off'; |
| 4346 |
$checked = ($link_target_toggle === 'on') ? 'checked' : ''; |
| 4347 |
|
| 4348 |
// Output the toggle switch |
| 4349 |
echo '<label class="toggle-switch">'; |
| 4350 |
echo sprintf( |
| 4351 |
'<input type="checkbox" id="link_target_toggle" name="link_target_toggle" value="on" %s />', |
| 4352 |
esc_attr($checked) |
| 4353 |
); |
| 4354 |
echo '<span class="slider"></span>'; |
| 4355 |
echo '</label>'; |
| 4356 |
echo '<p class="description">Enable to open links in a new tab (default is to open in the same tab).</p>'; |
| 4357 |
} |
| 4358 |
|
| 4359 |
public function mxchat_chat_persistence_toggle_callback() { |
| 4360 |
// Load from mxchat_options array |
| 4361 |
$options = get_option('mxchat_options', []); |
| 4362 |
|
| 4363 |
// Get chat persistence toggle value with fallback |
| 4364 |
$chat_persistence_toggle = isset($options['chat_persistence_toggle']) ? $options['chat_persistence_toggle'] : 'off'; |
| 4365 |
$checked = ($chat_persistence_toggle === 'on') ? 'checked' : ''; |
| 4366 |
|
| 4367 |
// Check if the plugin is activated (paid feature) |
| 4368 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4369 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4370 |
|
| 4371 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4372 |
|
| 4373 |
// Output the toggle switch |
| 4374 |
echo '<label class="toggle-switch">'; |
| 4375 |
echo sprintf( |
| 4376 |
'<input type="checkbox" id="chat_persistence_toggle" name="chat_persistence_toggle" value="on" %s %s />', |
| 4377 |
esc_attr($checked), |
| 4378 |
esc_attr($disabled) |
| 4379 |
); |
| 4380 |
echo '<span class="slider"></span>'; |
| 4381 |
echo '</label>'; |
| 4382 |
|
| 4383 |
echo '<p class="description">Enable to keep chat history when users navigate tabs or return to the site within 24 hours.</p>'; |
| 4384 |
|
| 4385 |
// If not activated, show Pro feature overlay |
| 4386 |
if (!$this->is_activated) { |
| 4387 |
echo '<div class="pro-feature-overlay">'; |
| 4388 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4389 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4390 |
echo '</a>'; |
| 4391 |
echo '</div>'; |
| 4392 |
} |
| 4393 |
|
| 4394 |
echo '</div>'; |
| 4395 |
} |
| 4396 |
|
| 4397 |
|
| 4398 |
public function mxchat_popular_question_1_callback() { |
| 4399 |
// Load the full plugin options array |
| 4400 |
$all_options = get_option('mxchat_options', []); |
| 4401 |
|
| 4402 |
// Retrieve the specific option for popular_question_1 |
| 4403 |
$popular_question_1 = isset($all_options['popular_question_1']) ? $all_options['popular_question_1'] : ''; |
| 4404 |
|
| 4405 |
// Render the input field |
| 4406 |
printf( |
| 4407 |
'<input type="text" id="popular_question_1" name="popular_question_1" value="%s" placeholder="Enter Popular Question 1" class="regular-text" />', |
| 4408 |
esc_attr($popular_question_1) |
| 4409 |
); |
| 4410 |
|
| 4411 |
// Add a description for the field |
| 4412 |
echo '<p class="description">This will be the first popular question in the chatbot.</p>'; |
| 4413 |
} |
| 4414 |
|
| 4415 |
|
| 4416 |
public function mxchat_popular_question_2_callback() { |
| 4417 |
// Load the full plugin options array |
| 4418 |
$all_options = get_option('mxchat_options', []); |
| 4419 |
|
| 4420 |
// Retrieve the specific option for popular_question_2 |
| 4421 |
$popular_question_2 = isset($all_options['popular_question_2']) ? $all_options['popular_question_2'] : ''; |
| 4422 |
|
| 4423 |
// Check if the plugin is activated (paid feature) |
| 4424 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4425 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4426 |
|
| 4427 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4428 |
|
| 4429 |
// Render the input field |
| 4430 |
printf( |
| 4431 |
'<input type="text" id="popular_question_2" name="popular_question_2" value="%s" placeholder="Enter Popular Question 2" class="regular-text" %s />', |
| 4432 |
esc_attr($popular_question_2), |
| 4433 |
esc_attr($disabled) |
| 4434 |
); |
| 4435 |
|
| 4436 |
// Add a description for the field |
| 4437 |
echo '<p class="description">This will be the second popular question in the chatbot.</p>'; |
| 4438 |
|
| 4439 |
// If not activated, show Pro feature overlay |
| 4440 |
if (!$this->is_activated) { |
| 4441 |
echo '<div class="pro-feature-overlay">'; |
| 4442 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4443 |
echo '</div>'; |
| 4444 |
} |
| 4445 |
|
| 4446 |
echo '</div>'; |
| 4447 |
} |
| 4448 |
|
| 4449 |
|
| 4450 |
|
| 4451 |
public function mxchat_popular_question_3_callback() { |
| 4452 |
// Load the full plugin options array |
| 4453 |
$all_options = get_option('mxchat_options', []); |
| 4454 |
|
| 4455 |
// Retrieve the specific option for popular_question_3 |
| 4456 |
$popular_question_3 = isset($all_options['popular_question_3']) ? $all_options['popular_question_3'] : ''; |
| 4457 |
|
| 4458 |
// Check if the plugin is activated (paid feature) |
| 4459 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4460 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4461 |
|
| 4462 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4463 |
|
| 4464 |
// Render the input field |
| 4465 |
printf( |
| 4466 |
'<input type="text" id="popular_question_3" name="popular_question_3" value="%s" placeholder="Enter Popular Question 3" class="regular-text" %s />', |
| 4467 |
esc_attr($popular_question_3), |
| 4468 |
esc_attr($disabled) |
| 4469 |
); |
| 4470 |
|
| 4471 |
// Add a description for the field |
| 4472 |
echo '<p class="description">This will be the third popular question in the chatbot.</p>'; |
| 4473 |
|
| 4474 |
// If not activated, show Pro feature overlay |
| 4475 |
if (!$this->is_activated) { |
| 4476 |
echo '<div class="pro-feature-overlay">'; |
| 4477 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4478 |
echo '</div>'; |
| 4479 |
} |
| 4480 |
|
| 4481 |
echo '</div>'; |
| 4482 |
} |
| 4483 |
|
| 4484 |
|
| 4485 |
public function mxchat_additional_popular_questions_callback() { |
| 4486 |
// Load from both possible sources for backwards compatibility |
| 4487 |
$options = get_option('mxchat_options', []); |
| 4488 |
$additional_questions = isset($options['additional_popular_questions']) |
| 4489 |
? $options['additional_popular_questions'] |
| 4490 |
: get_option('additional_popular_questions', array()); |
| 4491 |
|
| 4492 |
// Check if the feature is activated (paid feature) |
| 4493 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4494 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4495 |
|
| 4496 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4497 |
echo '<div id="mxchat-additional-questions-container">'; |
| 4498 |
|
| 4499 |
if (!empty($additional_questions)) { |
| 4500 |
foreach ($additional_questions as $index => $question) { |
| 4501 |
printf( |
| 4502 |
'<div class="mxchat-question-row"> |
| 4503 |
<input type="text" name="additional_popular_questions[]" |
| 4504 |
value="%s" |
| 4505 |
placeholder="Enter Additional Popular Question %d" |
| 4506 |
class="regular-text mxchat-question-input" |
| 4507 |
data-question-index="%d" |
| 4508 |
%s /> |
| 4509 |
<button type="button" class="button mxchat-remove-question" |
| 4510 |
aria-label="Remove question" %s>Remove</button> |
| 4511 |
</div>', |
| 4512 |
esc_attr($question), |
| 4513 |
$index + 4, |
| 4514 |
$index, |
| 4515 |
esc_attr($disabled), |
| 4516 |
esc_attr($disabled) |
| 4517 |
); |
| 4518 |
} |
| 4519 |
} else { |
| 4520 |
printf( |
| 4521 |
'<div class="mxchat-question-row"> |
| 4522 |
<input type="text" name="additional_popular_questions[]" |
| 4523 |
value="" |
| 4524 |
placeholder="Enter Additional Popular Question 4" |
| 4525 |
class="regular-text mxchat-question-input" |
| 4526 |
data-question-index="0" |
| 4527 |
%s /> |
| 4528 |
<button type="button" class="button mxchat-remove-question" |
| 4529 |
aria-label="Remove question" %s>Remove</button> |
| 4530 |
</div>', |
| 4531 |
esc_attr($disabled), |
| 4532 |
esc_attr($disabled) |
| 4533 |
); |
| 4534 |
} |
| 4535 |
|
| 4536 |
echo '</div>'; |
| 4537 |
|
| 4538 |
printf( |
| 4539 |
'<button type="button" class="button mxchat-add-question" aria-label="Add question" %s>Add Question</button>', |
| 4540 |
esc_attr($disabled) |
| 4541 |
); |
| 4542 |
|
| 4543 |
echo '<p class="description">You can add more popular questions beyond the default three here.</p>'; |
| 4544 |
|
| 4545 |
if (!$this->is_activated) { |
| 4546 |
echo '<div class="pro-feature-overlay">'; |
| 4547 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4548 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4549 |
echo '</a>'; |
| 4550 |
echo '</div>'; |
| 4551 |
} |
| 4552 |
|
| 4553 |
echo '</div>'; |
| 4554 |
} |
| 4555 |
|
| 4556 |
|
| 4557 |
public function mxchat_brave_api_key_callback() { |
| 4558 |
$brave_api_key = isset($this->options['brave_api_key']) ? esc_attr($this->options['brave_api_key']) : ''; |
| 4559 |
|
| 4560 |
echo '<div class="api-key-wrapper">'; |
| 4561 |
echo sprintf( |
| 4562 |
'<input type="password" id="brave_api_key" name="brave_api_key" value="%s" class="regular-text" />', |
| 4563 |
$brave_api_key |
| 4564 |
); |
| 4565 |
echo '<button type="button" id="toggleBraveApiKeyVisibility">Show</button>'; |
| 4566 |
echo '</div>'; |
| 4567 |
echo '<p class="description">' . __('Enter your Brave Search API Key here. (See FAQ for details)', 'mxchat') . '</p>'; |
| 4568 |
} |
| 4569 |
|
| 4570 |
public function mxchat_brave_image_count_callback() { |
| 4571 |
$brave_image_count = isset($this->options['brave_image_count']) |
| 4572 |
? intval($this->options['brave_image_count']) |
| 4573 |
: 4; |
| 4574 |
|
| 4575 |
echo sprintf( |
| 4576 |
'<input type="number" id="brave_image_count" name="brave_image_count" |
| 4577 |
value="%d" min="1" max="6" class="small-text" />', |
| 4578 |
$brave_image_count |
| 4579 |
); |
| 4580 |
echo '<p class="description">' . __('Select the number of images to return (1-6).', 'mxchat') . '</p>'; |
| 4581 |
} |
| 4582 |
|
| 4583 |
public function mxchat_brave_safe_search_callback() { |
| 4584 |
$brave_safe_search = isset($this->options['brave_safe_search']) |
| 4585 |
? esc_attr($this->options['brave_safe_search']) |
| 4586 |
: 'strict'; |
| 4587 |
|
| 4588 |
echo '<select id="brave_safe_search" name="brave_safe_search">'; |
| 4589 |
echo sprintf( |
| 4590 |
'<option value="strict" %s>%s</option>', |
| 4591 |
selected($brave_safe_search, 'strict', false), |
| 4592 |
__('Strict', 'mxchat') |
| 4593 |
); |
| 4594 |
echo sprintf( |
| 4595 |
'<option value="off" %s>%s</option>', |
| 4596 |
selected($brave_safe_search, 'off', false), |
| 4597 |
__('Off', 'mxchat') |
| 4598 |
); |
| 4599 |
echo '</select>'; |
| 4600 |
echo '<p class="description">' . |
| 4601 |
__('Set the Safe Search level for image searches. Brave Search only supports "Strict" and "Off" options.', 'mxchat') . |
| 4602 |
'</p>'; |
| 4603 |
} |
| 4604 |
|
| 4605 |
public function mxchat_brave_news_count_callback() { |
| 4606 |
$brave_news_count = isset($this->options['brave_news_count']) |
| 4607 |
? intval($this->options['brave_news_count']) |
| 4608 |
: 3; |
| 4609 |
|
| 4610 |
echo sprintf( |
| 4611 |
'<input type="number" id="brave_news_count" name="brave_news_count" |
| 4612 |
value="%d" min="1" max="10" class="small-text" />', |
| 4613 |
$brave_news_count |
| 4614 |
); |
| 4615 |
echo '<p class="description">' . __('Select the number of news articles to retrieve (1-10).', 'mxchat') . '</p>'; |
| 4616 |
} |
| 4617 |
|
| 4618 |
public function mxchat_brave_country_callback() { |
| 4619 |
$brave_country = isset($this->options['brave_country']) |
| 4620 |
? esc_attr($this->options['brave_country']) |
| 4621 |
: 'us'; |
| 4622 |
|
| 4623 |
echo sprintf( |
| 4624 |
'<input type="text" id="brave_country" name="brave_country" |
| 4625 |
value="%s" maxlength="2" class="small-text" />', |
| 4626 |
$brave_country |
| 4627 |
); |
| 4628 |
echo '<p class="description">' . __('Enter the country code (e.g., "us" for United States).', 'mxchat') . '</p>'; |
| 4629 |
} |
| 4630 |
|
| 4631 |
public function mxchat_brave_language_callback() { |
| 4632 |
$brave_language = isset($this->options['brave_language']) |
| 4633 |
? esc_attr($this->options['brave_language']) |
| 4634 |
: 'en'; |
| 4635 |
|
| 4636 |
echo sprintf( |
| 4637 |
'<input type="text" id="brave_language" name="brave_language" |
| 4638 |
value="%s" maxlength="2" class="small-text" />', |
| 4639 |
$brave_language |
| 4640 |
); |
| 4641 |
echo '<p class="description">' . __('Enter the language code (e.g., "en" for English).', 'mxchat') . '</p>'; |
| 4642 |
} |
| 4643 |
|
| 4644 |
|
| 4645 |
|
| 4646 |
|
| 4647 |
|
| 4648 |
// Section Callback |
| 4649 |
public function mxchat_pdf_intent_section_callback() { |
| 4650 |
echo '<p>' . esc_html__('Configure the intent settings for the Chat with PDF feature.', 'mxchat') . '</p>'; |
| 4651 |
} |
| 4652 |
|
| 4653 |
public function mxchat_chat_toolbar_toggle_callback() { |
| 4654 |
// Get chat toolbar toggle value with fallback |
| 4655 |
$chat_toolbar_toggle = isset($this->options['chat_toolbar_toggle']) ? $this->options['chat_toolbar_toggle'] : 'off'; |
| 4656 |
$checked = ($chat_toolbar_toggle === 'on') ? 'checked' : ''; |
| 4657 |
|
| 4658 |
// Check if the plugin is activated (paid feature) |
| 4659 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4660 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4661 |
|
| 4662 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4663 |
|
| 4664 |
// Output the toggle switch |
| 4665 |
echo '<label class="toggle-switch">'; |
| 4666 |
echo sprintf( |
| 4667 |
'<input type="checkbox" id="chat_toolbar_toggle" name="chat_toolbar_toggle" value="on" %s %s />', |
| 4668 |
esc_attr($checked), |
| 4669 |
esc_attr($disabled) |
| 4670 |
); |
| 4671 |
echo '<span class="slider"></span>'; |
| 4672 |
echo '</label>'; |
| 4673 |
|
| 4674 |
// Pro feature overlay |
| 4675 |
if (!$this->is_activated) { |
| 4676 |
echo '<div class="pro-feature-overlay">'; |
| 4677 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4678 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4679 |
echo '</a>'; |
| 4680 |
echo '</div>'; |
| 4681 |
} |
| 4682 |
|
| 4683 |
echo '</div>'; |
| 4684 |
echo '<p class="description">Enable to display the chat toolbar, adding two icons below the chatbot input field for uploading PDF and Word documents (default is hidden).</p>'; |
| 4685 |
} |
| 4686 |
|
| 4687 |
|
| 4688 |
public function mxchat_pdf_intent_trigger_text_callback() { |
| 4689 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4690 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4691 |
$default_text = "Please provide the URL to the PDF you'd like to discuss."; |
| 4692 |
|
| 4693 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4694 |
echo sprintf( |
| 4695 |
'<textarea id="pdf_intent_trigger_text" |
| 4696 |
name="pdf_intent_trigger_text" |
| 4697 |
rows="3" |
| 4698 |
cols="50" |
| 4699 |
placeholder="Enter trigger text" |
| 4700 |
%s>%s</textarea>', |
| 4701 |
esc_attr($disabled), |
| 4702 |
isset($this->options['pdf_intent_trigger_text']) |
| 4703 |
? esc_textarea($this->options['pdf_intent_trigger_text']) |
| 4704 |
: esc_textarea($default_text) |
| 4705 |
); |
| 4706 |
echo '<p class="description">Text displayed when the intent is triggered.</p>'; |
| 4707 |
|
| 4708 |
if (!$this->is_activated) { |
| 4709 |
echo '<div class="pro-feature-overlay">'; |
| 4710 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4711 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4712 |
echo '</a>'; |
| 4713 |
echo '</div>'; |
| 4714 |
} |
| 4715 |
echo '</div>'; |
| 4716 |
} |
| 4717 |
|
| 4718 |
public function mxchat_pdf_intent_success_text_callback() { |
| 4719 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4720 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4721 |
$default_text = "I've processed the PDF. What questions do you have about it?"; |
| 4722 |
|
| 4723 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4724 |
echo sprintf( |
| 4725 |
'<textarea id="pdf_intent_success_text" |
| 4726 |
name="pdf_intent_success_text" |
| 4727 |
rows="3" |
| 4728 |
cols="50" |
| 4729 |
placeholder="Enter success text" |
| 4730 |
%s>%s</textarea>', |
| 4731 |
esc_attr($disabled), |
| 4732 |
isset($this->options['pdf_intent_success_text']) |
| 4733 |
? esc_textarea($this->options['pdf_intent_success_text']) |
| 4734 |
: esc_textarea($default_text) |
| 4735 |
); |
| 4736 |
echo '<p class="description">Text displayed when the intent is successful.</p>'; |
| 4737 |
|
| 4738 |
if (!$this->is_activated) { |
| 4739 |
echo '<div class="pro-feature-overlay">'; |
| 4740 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4741 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4742 |
echo '</a>'; |
| 4743 |
echo '</div>'; |
| 4744 |
} |
| 4745 |
echo '</div>'; |
| 4746 |
} |
| 4747 |
|
| 4748 |
public function mxchat_pdf_intent_error_text_callback() { |
| 4749 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4750 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4751 |
$default_text = "Sorry, I couldn't process the PDF. Please ensure it's a valid file."; |
| 4752 |
|
| 4753 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4754 |
echo sprintf( |
| 4755 |
'<textarea id="pdf_intent_error_text" |
| 4756 |
name="pdf_intent_error_text" |
| 4757 |
rows="3" |
| 4758 |
cols="50" |
| 4759 |
placeholder="Enter error text" |
| 4760 |
%s>%s</textarea>', |
| 4761 |
esc_attr($disabled), |
| 4762 |
isset($this->options['pdf_intent_error_text']) |
| 4763 |
? esc_textarea($this->options['pdf_intent_error_text']) |
| 4764 |
: esc_textarea($default_text) |
| 4765 |
); |
| 4766 |
echo '<p class="description">Text displayed when an error occurs during the intent.</p>'; |
| 4767 |
|
| 4768 |
if (!$this->is_activated) { |
| 4769 |
echo '<div class="pro-feature-overlay">'; |
| 4770 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4771 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4772 |
echo '</a>'; |
| 4773 |
echo '</div>'; |
| 4774 |
} |
| 4775 |
echo '</div>'; |
| 4776 |
} |
| 4777 |
|
| 4778 |
public function mxchat_pdf_max_pages_callback() { |
| 4779 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4780 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4781 |
$max_pages = isset($this->options['pdf_max_pages']) ? intval($this->options['pdf_max_pages']) : 69; |
| 4782 |
|
| 4783 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4784 |
echo sprintf( |
| 4785 |
'<input type="range" |
| 4786 |
id="pdf_max_pages" |
| 4787 |
name="pdf_max_pages" |
| 4788 |
min="1" |
| 4789 |
max="69" |
| 4790 |
value="%d" |
| 4791 |
%s |
| 4792 |
class="range-slider" />', |
| 4793 |
esc_attr($max_pages), |
| 4794 |
esc_attr($disabled) |
| 4795 |
); |
| 4796 |
echo '<span id="pdf_max_pages_output">' . esc_html($max_pages) . '</span>'; |
| 4797 |
echo '<p class="description">Set the maximum number of document pages users can upload for processing. (1-69 pages)</p>'; |
| 4798 |
|
| 4799 |
if (!$this->is_activated) { |
| 4800 |
echo '<div class="pro-feature-overlay">'; |
| 4801 |
echo '<a href="https://mxchat.ai/" target="_blank">'; |
| 4802 |
echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="Pro Only" />'; |
| 4803 |
echo '</a>'; |
| 4804 |
echo '</div>'; |
| 4805 |
} |
| 4806 |
echo '</div>'; |
| 4807 |
} |
| 4808 |
|
| 4809 |
public function mxchat_live_agent_status_callback() { |
| 4810 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4811 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4812 |
$status = isset($this->options['live_agent_status']) ? $this->options['live_agent_status'] : 'off'; |
| 4813 |
|
| 4814 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4815 |
echo '<label class="toggle-switch">'; |
| 4816 |
echo sprintf( |
| 4817 |
'<input type="checkbox" id="live_agent_status" name="live_agent_status" value="on" %s %s />', |
| 4818 |
checked($status, 'on', false), |
| 4819 |
esc_attr($disabled) |
| 4820 |
); |
| 4821 |
echo '<span class="slider"></span>'; |
| 4822 |
echo '</label>'; |
| 4823 |
echo '<label for="live_agent_status" class="mxchat-status-label">'; |
| 4824 |
echo '<span class="status-text">' . ($status === 'on' ? esc_html__('Online', 'mxchat') : esc_html__('Offline', 'mxchat')) . '</span>'; |
| 4825 |
echo '</label>'; |
| 4826 |
|
| 4827 |
if (!$this->is_activated) { |
| 4828 |
echo '<div class="pro-feature-overlay">'; |
| 4829 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4830 |
echo '</div>'; |
| 4831 |
} |
| 4832 |
echo '</div>'; |
| 4833 |
} |
| 4834 |
|
| 4835 |
|
| 4836 |
// Away Message Callback |
| 4837 |
public function mxchat_live_agent_away_message_callback() { |
| 4838 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4839 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4840 |
$message = isset($this->options['live_agent_away_message']) |
| 4841 |
? $this->options['live_agent_away_message'] |
| 4842 |
: __('Sorry, live agents are currently unavailable. I can continue helping you as an AI assistant.', 'mxchat'); |
| 4843 |
|
| 4844 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4845 |
printf( |
| 4846 |
'<textarea id="live_agent_away_message" name="live_agent_away_message" rows="3" cols="50" %s>%s</textarea>', |
| 4847 |
esc_attr($disabled), |
| 4848 |
esc_textarea($message) |
| 4849 |
); |
| 4850 |
echo '<p class="description">' . esc_html__('Message shown when live agents are offline.', 'mxchat') . '</p>'; |
| 4851 |
|
| 4852 |
if (!$this->is_activated) { |
| 4853 |
echo '<div class="pro-feature-overlay">'; |
| 4854 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4855 |
echo '</div>'; |
| 4856 |
} |
| 4857 |
echo '</div>'; |
| 4858 |
} |
| 4859 |
|
| 4860 |
public function mxchat_live_agent_notification_message_callback() { |
| 4861 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4862 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4863 |
$message = isset($this->options['live_agent_notification_message']) |
| 4864 |
? $this->options['live_agent_notification_message'] |
| 4865 |
: __('Live agent has been notified.', 'mxchat'); |
| 4866 |
|
| 4867 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4868 |
printf( |
| 4869 |
'<textarea id="live_agent_notification_message" name="live_agent_notification_message" rows="3" cols="50" %s>%s</textarea>', |
| 4870 |
esc_attr($disabled), |
| 4871 |
esc_textarea($message) |
| 4872 |
); |
| 4873 |
echo '<p class="description">' . esc_html__('Message shown when live transfer activated.', 'mxchat') . '</p>'; |
| 4874 |
|
| 4875 |
if (!$this->is_activated) { |
| 4876 |
echo '<div class="pro-feature-overlay">'; |
| 4877 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4878 |
echo '</div>'; |
| 4879 |
} |
| 4880 |
echo '</div>'; |
| 4881 |
} |
| 4882 |
|
| 4883 |
public function mxchat_live_agent_webhook_url_callback() { |
| 4884 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4885 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4886 |
$webhook_url = isset($this->options['live_agent_webhook_url']) |
| 4887 |
? esc_url($this->options['live_agent_webhook_url']) |
| 4888 |
: esc_url(get_option('live_agent_webhook_url', '')); |
| 4889 |
|
| 4890 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4891 |
printf( |
| 4892 |
'<input type="password" id="live_agent_webhook_url" name="live_agent_webhook_url" value="%s" class="regular-text" %s />', |
| 4893 |
$webhook_url, |
| 4894 |
esc_attr($disabled) |
| 4895 |
); |
| 4896 |
echo '<button type="button" id="toggleWebhookUrlVisibility">Show</button>'; |
| 4897 |
echo '<p class="description">Enter your Slack webhook URL for live agent notifications.</p>'; |
| 4898 |
|
| 4899 |
if (!$this->is_activated) { |
| 4900 |
echo '<div class="pro-feature-overlay">'; |
| 4901 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4902 |
echo '</div>'; |
| 4903 |
} |
| 4904 |
echo '</div>'; |
| 4905 |
} |
| 4906 |
|
| 4907 |
|
| 4908 |
public function mxchat_similarity_threshold_callback() { |
| 4909 |
// Load from mxchat_options array |
| 4910 |
$options = get_option('mxchat_options', []); |
| 4911 |
|
| 4912 |
// Get value with backwards compatibility |
| 4913 |
$threshold = isset($options['similarity_threshold']) |
| 4914 |
? $options['similarity_threshold'] |
| 4915 |
: get_option('mxchat_similarity_threshold', 80); |
| 4916 |
|
| 4917 |
echo '<div class="slider-container">'; |
| 4918 |
echo sprintf( |
| 4919 |
'<input type="range" |
| 4920 |
id="similarity_threshold" |
| 4921 |
name="similarity_threshold" |
| 4922 |
min="70" |
| 4923 |
max="85" |
| 4924 |
step="1" |
| 4925 |
value="%s" |
| 4926 |
class="range-slider" />', |
| 4927 |
esc_attr($threshold) |
| 4928 |
); |
| 4929 |
echo sprintf( |
| 4930 |
'<span id="threshold_value" class="range-value">%s</span>', |
| 4931 |
esc_html($threshold) |
| 4932 |
); |
| 4933 |
echo '</div>'; |
| 4934 |
|
| 4935 |
echo '<p class="description">'; |
| 4936 |
echo 'Set the similarity threshold (recommended: 75) to balance accuracy; too high might limit your bot\'s ability to find relevant knowledge.'; |
| 4937 |
echo '</p>'; |
| 4938 |
} |
| 4939 |
|
| 4940 |
|
| 4941 |
|
| 4942 |
public function mxchat_live_agent_secret_key_callback() { |
| 4943 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4944 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4945 |
|
| 4946 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4947 |
printf( |
| 4948 |
'<input type="password" id="live_agent_secret_key" name="live_agent_secret_key" value="%s" class="regular-text" %s />', |
| 4949 |
isset($this->options['live_agent_secret_key']) ? esc_attr($this->options['live_agent_secret_key']) : '', |
| 4950 |
esc_attr($disabled) |
| 4951 |
); |
| 4952 |
echo '<button type="button" id="toggleSecretKeyVisibility">Show</button>'; |
| 4953 |
echo '<p class="description">Secret key for validating Slack requests. Keep this secure.</p>'; |
| 4954 |
|
| 4955 |
if (!$this->is_activated) { |
| 4956 |
echo '<div class="pro-feature-overlay">'; |
| 4957 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4958 |
echo '</div>'; |
| 4959 |
} |
| 4960 |
echo '</div>'; |
| 4961 |
} |
| 4962 |
|
| 4963 |
public function mxchat_live_agent_bot_token_callback() { |
| 4964 |
$disabled = $this->is_activated ? '' : 'disabled'; |
| 4965 |
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; |
| 4966 |
|
| 4967 |
echo '<div class="' . esc_attr($class) . '">'; |
| 4968 |
printf( |
| 4969 |
'<input type="password" id="live_agent_bot_token" name="live_agent_bot_token" value="%s" class="regular-text" %s />', |
| 4970 |
isset($this->options['live_agent_bot_token']) ? esc_attr($this->options['live_agent_bot_token']) : '', |
| 4971 |
esc_attr($disabled) |
| 4972 |
); |
| 4973 |
echo '<button type="button" id="toggleBotTokenVisibility">Show</button>'; |
| 4974 |
echo '<p class="description">Your Slack Bot OAuth Token (starts with xoxb-). Keep this secure.</p>'; |
| 4975 |
|
| 4976 |
if (!$this->is_activated) { |
| 4977 |
echo '<div class="pro-feature-overlay">'; |
| 4978 |
echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="Pro Only" /></a>'; |
| 4979 |
echo '</div>'; |
| 4980 |
} |
| 4981 |
echo '</div>'; |
| 4982 |
} |
| 4983 |
|
| 4984 |
public function mxchat_enqueue_admin_assets() { |
| 4985 |
wp_enqueue_style('wp-color-picker'); |
| 4986 |
|
| 4987 |
// Get the plugin version or file modification time for cache busting |
| 4988 |
$plugin_version = '1.6.2'; // Replace this with your plugin's version |
| 4989 |
|
| 4990 |
// File paths |
| 4991 |
$color_picker_js_path = plugin_dir_path(__FILE__) . '../js/my-color-picker.js'; |
| 4992 |
$embedding_check_js_path = plugin_dir_path(__FILE__) . '../js/embedding-check.js'; |
| 4993 |
$admin_css_path = plugin_dir_path(__FILE__) . '../css/admin-style.css'; |
| 4994 |
$transcripts_js_path = plugin_dir_path(__FILE__) . '../js/mxchat_transcripts.js'; |
| 4995 |
|
| 4996 |
// Check if files exist and get modification times |
| 4997 |
$color_picker_version = file_exists($color_picker_js_path) ? filemtime($color_picker_js_path) : $plugin_version; |
| 4998 |
$embedding_check_version = file_exists($embedding_check_js_path) ? filemtime($embedding_check_js_path) : $plugin_version; |
| 4999 |
$admin_css_version = file_exists($admin_css_path) ? filemtime($admin_css_path) : $plugin_version; |
| 5000 |
$transcripts_js_version = file_exists($transcripts_js_path) ? filemtime($transcripts_js_path) : $plugin_version; |
| 5001 |
|
| 5002 |
// Enqueue scripts and styles with corrected paths |
| 5003 |
wp_enqueue_script( |
| 5004 |
'mxchat-color-picker', |
| 5005 |
plugin_dir_url(__FILE__) . '../js/my-color-picker.js', |
| 5006 |
array('wp-color-picker'), |
| 5007 |
$color_picker_version, |
| 5008 |
true |
| 5009 |
); |
| 5010 |
|
| 5011 |
wp_enqueue_script( |
| 5012 |
'mxchat-embedding-check', |
| 5013 |
plugin_dir_url(__FILE__) . '../js/embedding-check.js', |
| 5014 |
array(), |
| 5015 |
$embedding_check_version, |
| 5016 |
true |
| 5017 |
); |
| 5018 |
|
| 5019 |
wp_enqueue_script( |
| 5020 |
'mxchat-transcripts-js', |
| 5021 |
plugin_dir_url(__FILE__) . '../js/mxchat_transcripts.js', |
| 5022 |
array('jquery'), |
| 5023 |
$transcripts_js_version, |
| 5024 |
true |
| 5025 |
); |
| 5026 |
|
| 5027 |
wp_enqueue_script( |
| 5028 |
'mxchat-admin-js', |
| 5029 |
plugin_dir_url(__FILE__) . '../js/mxchat-admin.js', |
| 5030 |
array('jquery'), |
| 5031 |
$plugin_version, |
| 5032 |
true |
| 5033 |
); |
| 5034 |
|
| 5035 |
|
| 5036 |
wp_localize_script('mxchat-admin-js', 'mxchatAdmin', array( |
| 5037 |
'ajax_url' => admin_url('admin-ajax.php'), |
| 5038 |
'license_nonce' => wp_create_nonce('mxchat_activate_license_nonce'), |
| 5039 |
'inline_edit_nonce' => wp_create_nonce('mxchat_save_inline_nonce'), |
| 5040 |
'setting_nonce' => wp_create_nonce('mxchat_save_setting_nonce'), |
| 5041 |
)); |
| 5042 |
|
| 5043 |
|
| 5044 |
|
| 5045 |
// Enqueue the admin CSS |
| 5046 |
wp_enqueue_style( |
| 5047 |
'mxchat-admin-css', |
| 5048 |
plugin_dir_url(__FILE__) . '../css/admin-style.css', |
| 5049 |
array(), |
| 5050 |
$admin_css_version |
| 5051 |
); |
| 5052 |
|
| 5053 |
// Localize the script for color picker and settings |
| 5054 |
wp_localize_script('mxchat-color-picker', 'mxchatStyleSettings', array( |
| 5055 |
'ajax_url' => admin_url('admin-ajax.php'), |
| 5056 |
'link_target_toggle' => $this->options['link_target_toggle'] ?? 'off', |
| 5057 |
'user_message_bg_color' => $this->options['user_message_bg_color'] ?? '#fff', |
| 5058 |
'user_message_font_color' => $this->options['user_message_font_color'] ?? '#212121', |
| 5059 |
'bot_message_bg_color' => $this->options['bot_message_bg_color'] ?? '#212121', |
| 5060 |
'bot_message_font_color' => $this->options['bot_message_font_color'] ?? '#fff', |
| 5061 |
'top_bar_bg_color' => $this->options['top_bar_bg_color'] ?? '#212121', |
| 5062 |
'send_button_font_color' => $this->options['send_button_font_color'] ?? '#212121', |
| 5063 |
'close_button_color' => $this->options['close_button_color'] ?? '#fff', |
| 5064 |
'chatbot_background_color' => $this->options['chatbot_background_color'] ?? '#212121', |
| 5065 |
'icon_color' => $this->options['icon_color'] ?? '#fff', |
| 5066 |
'chat_input_font_color' => $this->options['chat_input_font_color'] ?? '#212121', |
| 5067 |
'pre_chat_message' => $this->options['pre_chat_message'] ?? 'Hey there! Ask me anything!', |
| 5068 |
'rate_limit_message' => $this->options['rate_limit_message'] ?? 'Rate limit exceeded. Please try again later.', |
| 5069 |
'loops_api_key' => $this->options['loops_api_key'] ?? '', |
| 5070 |
'loops_mailing_list' => $this->options['loops_mailing_list'] ?? '', |
| 5071 |
'triggered_phrase_response' => $this->options['triggered_phrase_response'] ?? 'Would you like to join our mailing list? Please provide your email below.', |
| 5072 |
'email_capture_response' => $this->options['email_capture_response'] ?? 'Thank you for providing your email! You\'ve been added to our list.', |
| 5073 |
'pdf_intent_trigger_text' => $this->options['pdf_intent_trigger_text'] ?? "Please provide the URL to the PDF you'd like to discuss.", |
| 5074 |
'pdf_intent_success_text' => $this->options['pdf_intent_success_text'] ?? "I've processed the PDF. What questions do you have about it?", |
| 5075 |
'pdf_intent_error_text' => $this->options['pdf_intent_error_text'] ?? "Sorry, I couldn't process the PDF. Please ensure it's a valid file.", |
| 5076 |
'pdf_max_pages' => $this->options['pdf_max_pages'] ?? 69, |
| 5077 |
'live_agent_webhook_url' => $this->options['live_agent_webhook_url'] ?? '', |
| 5078 |
'live_agent_secret_key' => $this->options['live_agent_secret_key'] ?? '', |
| 5079 |
'live_agent_bot_token' => $this->options['live_agent_bot_token'] ?? '', |
| 5080 |
'live_agent_message_bg_color' => $this->options['live_agent_message_bg_color'] ?? '#ffffff', |
| 5081 |
'live_agent_message_font_color' => $this->options['live_agent_message_font_color'] ?? '#333333', |
| 5082 |
'chat_toolbar_toggle' => $this->options['chat_toolbar_toggle'] ?? 'off', |
| 5083 |
'mode_indicator_bg_color' => $this->options['mode_indicator_bg_color'] ?? '#767676', |
| 5084 |
'mode_indicator_font_color' => $this->options['mode_indicator_font_color'] ?? '#ffffff', |
| 5085 |
'toolbar_icon_color' => $this->options['toolbar_icon_color'] ?? '#212121', |
| 5086 |
)); |
| 5087 |
} |
| 5088 |
|
| 5089 |
public function mxchat_sanitize($input) { |
| 5090 |
$new_input = array(); |
| 5091 |
|
| 5092 |
if (isset($input['api_key'])) { |
| 5093 |
$new_input['api_key'] = sanitize_text_field($input['api_key']); |
| 5094 |
} |
| 5095 |
|
| 5096 |
if (isset($input['similarity_threshold'])) { |
| 5097 |
$new_input['similarity_threshold'] = absint($input['similarity_threshold']); // Ensure it's an integer |
| 5098 |
$new_input['similarity_threshold'] = min(max($new_input['similarity_threshold'], 70), 85); // Enforce range |
| 5099 |
} |
| 5100 |
|
| 5101 |
if (isset($input['xai_api_key'])) { |
| 5102 |
$new_input['xai_api_key'] = sanitize_text_field($input['xai_api_key']); |
| 5103 |
} |
| 5104 |
|
| 5105 |
if (isset($input['claude_api_key'])) { |
| 5106 |
$new_input['claude_api_key'] = sanitize_text_field($input['claude_api_key']); |
| 5107 |
} |
| 5108 |
|
| 5109 |
if (isset($input['enable_woocommerce_integration'])) { |
| 5110 |
$new_input['enable_woocommerce_integration'] = $input['enable_woocommerce_integration'] === 'on' ? 'on' : 'off'; |
| 5111 |
} |
| 5112 |
|
| 5113 |
if (isset($input['privacy_toggle'])) { |
| 5114 |
$new_input['privacy_toggle'] = $input['privacy_toggle']; |
| 5115 |
} |
| 5116 |
|
| 5117 |
if (isset($input['complianz_toggle'])) { |
| 5118 |
$new_input['complianz_toggle'] = $input['complianz_toggle']; |
| 5119 |
} |
| 5120 |
|
| 5121 |
// Handle custom privacy text input |
| 5122 |
if (isset($input['privacy_text'])) { |
| 5123 |
// Allow basic HTML for links |
| 5124 |
$new_input['privacy_text'] = wp_kses_post($input['privacy_text']); |
| 5125 |
} |
| 5126 |
|
| 5127 |
if (isset($input['system_prompt_instructions'])) { |
| 5128 |
$new_input['system_prompt_instructions'] = sanitize_textarea_field($input['system_prompt_instructions']); |
| 5129 |
} |
| 5130 |
|
| 5131 |
if (isset($input['mxchat_pro_email'])) { |
| 5132 |
$new_input['mxchat_pro_email'] = sanitize_email($input['mxchat_pro_email']); |
| 5133 |
} |
| 5134 |
|
| 5135 |
if (isset($input['mxchat_activation_key'])) { |
| 5136 |
$new_input['mxchat_activation_key'] = sanitize_text_field($input['mxchat_activation_key']); |
| 5137 |
} |
| 5138 |
|
| 5139 |
if (isset($input['append_to_body'])) { |
| 5140 |
$new_input['append_to_body'] = $input['append_to_body'] === 'on' ? 'on' : 'off'; |
| 5141 |
} |
| 5142 |
|
| 5143 |
if (isset($input['top_bar_title'])) { |
| 5144 |
$new_input['top_bar_title'] = sanitize_text_field($input['top_bar_title']); |
| 5145 |
} |
| 5146 |
|
| 5147 |
if (isset($input['enable_email_block'])) { |
| 5148 |
$new_input['enable_email_block'] = sanitize_text_field($input['enable_email_block']); |
| 5149 |
} |
| 5150 |
|
| 5151 |
if (isset($input['email_blocker_header_content'])) { |
| 5152 |
// wp_kses_post() allows standard HTML tags permitted by WordPress |
| 5153 |
$new_input['email_blocker_header_content'] = wp_kses_post($input['email_blocker_header_content']); |
| 5154 |
} |
| 5155 |
if (isset($input['email_blocker_button_text'])) { |
| 5156 |
$new_input['email_blocker_button_text'] = sanitize_text_field($input['email_blocker_button_text']); |
| 5157 |
} |
| 5158 |
|
| 5159 |
if (isset($input['intro_message'])) { |
| 5160 |
$new_input['intro_message'] = sanitize_textarea_field($input['intro_message']); // Changed from sanitize_text_field |
| 5161 |
} |
| 5162 |
|
| 5163 |
if (isset($input['input_copy'])) { |
| 5164 |
$new_input['input_copy'] = sanitize_text_field($input['input_copy']); |
| 5165 |
} |
| 5166 |
|
| 5167 |
|
| 5168 |
if (isset($input['rate_limit_message'])) { |
| 5169 |
$new_input['rate_limit_message'] = sanitize_text_field($input['rate_limit_message']); |
| 5170 |
} |
| 5171 |
|
| 5172 |
if (isset($input['rate_limit_logged_in'])) { |
| 5173 |
$allowed_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); // Add 'unlimited' to allowed values |
| 5174 |
$rate_limit = sanitize_text_field($input['rate_limit_logged_in']); |
| 5175 |
|
| 5176 |
if (in_array($rate_limit, $allowed_limits, true)) { |
| 5177 |
$new_input['rate_limit_logged_in'] = $rate_limit; |
| 5178 |
} else { |
| 5179 |
$new_input['rate_limit_logged_in'] = '100'; // Default for logged-in users |
| 5180 |
} |
| 5181 |
} |
| 5182 |
|
| 5183 |
if (isset($input['rate_limit_logged_out'])) { |
| 5184 |
$allowed_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); // Add 'unlimited' to allowed values |
| 5185 |
$rate_limit = sanitize_text_field($input['rate_limit_logged_out']); |
| 5186 |
|
| 5187 |
if (in_array($rate_limit, $allowed_limits, true)) { |
| 5188 |
$new_input['rate_limit_logged_out'] = $rate_limit; |
| 5189 |
} else { |
| 5190 |
$new_input['rate_limit_logged_out'] = '10'; // Default for logged-out users |
| 5191 |
} |
| 5192 |
} |
| 5193 |
|
| 5194 |
if (isset($input['pre_chat_message'])) { |
| 5195 |
$new_input['pre_chat_message'] = sanitize_textarea_field($input['pre_chat_message']); |
| 5196 |
} |
| 5197 |
|
| 5198 |
if (isset($input['model'])) { |
| 5199 |
$allowed_models = array( |
| 5200 |
'grok-beta', |
| 5201 |
'grok-2', |
| 5202 |
'claude-3-5-sonnet-20241022', |
| 5203 |
'claude-3-opus-20240229', |
| 5204 |
'claude-3-sonnet-20240229', |
| 5205 |
'claude-3-haiku-20240307', |
| 5206 |
'gpt-4o', |
| 5207 |
'gpt-4o-mini', |
| 5208 |
'gpt-4-turbo', |
| 5209 |
'gpt-4', |
| 5210 |
'gpt-3.5-turbo', |
| 5211 |
); |
| 5212 |
if (in_array($input['model'], $allowed_models)) { |
| 5213 |
$new_input['model'] = sanitize_text_field($input['model']); |
| 5214 |
} |
| 5215 |
} |
| 5216 |
|
| 5217 |
// Sanitize new pro features |
| 5218 |
if (isset($input['close_button_color'])) { |
| 5219 |
$new_input['close_button_color'] = sanitize_hex_color($input['close_button_color']); |
| 5220 |
} |
| 5221 |
|
| 5222 |
if (isset($input['chatbot_bg_color'])) { |
| 5223 |
$new_input['chatbot_bg_color'] = sanitize_hex_color($input['chatbot_bg_color']); |
| 5224 |
} |
| 5225 |
|
| 5226 |
if (isset($input['woocommerce_consumer_key'])) { |
| 5227 |
$new_input['woocommerce_consumer_key'] = sanitize_text_field($input['woocommerce_consumer_key']); |
| 5228 |
} |
| 5229 |
|
| 5230 |
if (isset($input['woocommerce_consumer_secret'])) { |
| 5231 |
$new_input['woocommerce_consumer_secret'] = sanitize_text_field($input['woocommerce_consumer_secret']); |
| 5232 |
} |
| 5233 |
|
| 5234 |
if (isset($input['user_message_bg_color'])) { |
| 5235 |
$new_input['user_message_bg_color'] = sanitize_hex_color($input['user_message_bg_color']); |
| 5236 |
} |
| 5237 |
|
| 5238 |
if (isset($input['user_message_font_color'])) { |
| 5239 |
$new_input['user_message_font_color'] = sanitize_hex_color($input['user_message_font_color']); |
| 5240 |
} |
| 5241 |
|
| 5242 |
if (isset($input['bot_message_bg_color'])) { |
| 5243 |
$new_input['bot_message_bg_color'] = sanitize_hex_color($input['bot_message_bg_color']); |
| 5244 |
} |
| 5245 |
|
| 5246 |
if (isset($input['bot_message_font_color'])) { |
| 5247 |
$new_input['bot_message_font_color'] = sanitize_hex_color($input['bot_message_font_color']); |
| 5248 |
} |
| 5249 |
|
| 5250 |
if (isset($input['live_agent_message_bg_color'])) { |
| 5251 |
$new_input['live_agent_message_bg_color'] = sanitize_hex_color($input['live_agent_message_bg_color']); |
| 5252 |
} |
| 5253 |
|
| 5254 |
if (isset($input['live_agent_message_font_color'])) { |
| 5255 |
$new_input['live_agent_message_font_color'] = sanitize_hex_color($input['live_agent_message_font_color']); |
| 5256 |
} |
| 5257 |
|
| 5258 |
if (isset($input['mode_indicator_bg_color'])) { |
| 5259 |
$new_input['mode_indicator_bg_color'] = sanitize_hex_color($input['mode_indicator_bg_color']); |
| 5260 |
} |
| 5261 |
|
| 5262 |
if (isset($input['mode_indicator_font_color'])) { |
| 5263 |
$new_input['mode_indicator_font_color'] = sanitize_hex_color($input['mode_indicator_font_color']); |
| 5264 |
} |
| 5265 |
|
| 5266 |
if (isset($input['toolbar_icon_color'])) { |
| 5267 |
$new_input['toolbar_icon_color'] = sanitize_hex_color($input['toolbar_icon_color']); |
| 5268 |
} |
| 5269 |
|
| 5270 |
if (isset($input['top_bar_bg_color'])) { |
| 5271 |
$new_input['top_bar_bg_color'] = sanitize_hex_color($input['top_bar_bg_color']); |
| 5272 |
} |
| 5273 |
|
| 5274 |
if (isset($input['send_button_font_color'])) { |
| 5275 |
$new_input['send_button_font_color'] = sanitize_hex_color($input['send_button_font_color']); |
| 5276 |
} |
| 5277 |
|
| 5278 |
if (isset($input['chatbot_background_color'])) { |
| 5279 |
$new_input['chatbot_background_color'] = sanitize_hex_color($input['chatbot_background_color']); |
| 5280 |
} |
| 5281 |
|
| 5282 |
if (isset($input['icon_color'])) { |
| 5283 |
$new_input['icon_color'] = sanitize_hex_color($input['icon_color']); |
| 5284 |
} |
| 5285 |
|
| 5286 |
if (isset($input['custom_icon'])) { |
| 5287 |
$new_input['custom_icon'] = esc_url_raw($input['custom_icon']); |
| 5288 |
} |
| 5289 |
|
| 5290 |
|
| 5291 |
if (isset($input['title_icon'])) { |
| 5292 |
$new_input['title_icon'] = esc_url_raw($input['title_icon']); |
| 5293 |
} |
| 5294 |
|
| 5295 |
if (isset($input['chat_input_font_color'])) { |
| 5296 |
$new_input['chat_input_font_color'] = sanitize_hex_color($input['chat_input_font_color']); |
| 5297 |
} |
| 5298 |
|
| 5299 |
// Sanitize link_target_toggle |
| 5300 |
if (isset($input['link_target_toggle'])) { |
| 5301 |
$new_input['link_target_toggle'] = $input['link_target_toggle'] === 'on' ? 'on' : 'off'; |
| 5302 |
} |
| 5303 |
|
| 5304 |
// Sanitize Loops API Key |
| 5305 |
if (isset($input['loops_api_key'])) { |
| 5306 |
$new_input['loops_api_key'] = sanitize_text_field($input['loops_api_key']); |
| 5307 |
} |
| 5308 |
|
| 5309 |
if (isset($input['chat_persistence_toggle'])) { |
| 5310 |
$new_input['chat_persistence_toggle'] = $input['chat_persistence_toggle'] === 'on' ? 'on' : 'off'; |
| 5311 |
} |
| 5312 |
|
| 5313 |
|
| 5314 |
|
| 5315 |
if (isset($input['popular_question_1'])) { |
| 5316 |
$new_input['popular_question_1'] = sanitize_text_field($input['popular_question_1']); |
| 5317 |
} |
| 5318 |
|
| 5319 |
if (isset($input['popular_question_2'])) { |
| 5320 |
$new_input['popular_question_2'] = sanitize_text_field($input['popular_question_2']); |
| 5321 |
} |
| 5322 |
|
| 5323 |
if (isset($input['popular_question_3'])) { |
| 5324 |
$new_input['popular_question_3'] = sanitize_text_field($input['popular_question_3']); |
| 5325 |
} |
| 5326 |
|
| 5327 |
if (isset($input['additional_popular_questions']) && is_array($input['additional_popular_questions'])) { |
| 5328 |
$new_input['additional_popular_questions'] = array_map('sanitize_text_field', $input['additional_popular_questions']); |
| 5329 |
} |
| 5330 |
|
| 5331 |
// Sanitize Loops Mailing List |
| 5332 |
if (isset($input['loops_mailing_list'])) { |
| 5333 |
$new_input['loops_mailing_list'] = sanitize_text_field($input['loops_mailing_list']); |
| 5334 |
} |
| 5335 |
|
| 5336 |
// Sanitize Triggered Phrase Response |
| 5337 |
if (isset($input['triggered_phrase_response'])) { |
| 5338 |
$new_input['triggered_phrase_response'] = wp_kses_post($input['triggered_phrase_response']); |
| 5339 |
} |
| 5340 |
|
| 5341 |
if (isset($input['email_capture_response'])) { |
| 5342 |
$new_input['email_capture_response'] = sanitize_textarea_field($input['email_capture_response']); |
| 5343 |
} |
| 5344 |
|
| 5345 |
|
| 5346 |
// Sanitize Brave Search Settings |
| 5347 |
if (isset($input['brave_api_key'])) { |
| 5348 |
$new_input['brave_api_key'] = sanitize_text_field($input['brave_api_key']); |
| 5349 |
} |
| 5350 |
|
| 5351 |
if (isset($input['brave_image_count'])) { |
| 5352 |
$image_count = intval($input['brave_image_count']); |
| 5353 |
$new_input['brave_image_count'] = ($image_count >=1 && $image_count <=6) ? $image_count : 4; |
| 5354 |
} |
| 5355 |
|
| 5356 |
if (isset($input['brave_safe_search'])) { |
| 5357 |
$allowed = array('strict', 'off'); |
| 5358 |
$new_input['brave_safe_search'] = in_array($input['brave_safe_search'], $allowed, true) ? $input['brave_safe_search'] : 'strict'; |
| 5359 |
} |
| 5360 |
|
| 5361 |
if (isset($input['brave_news_count'])) { |
| 5362 |
$news_count = intval($input['brave_news_count']); |
| 5363 |
$new_input['brave_news_count'] = ($news_count >=1 && $news_count <=10) ? $news_count : 3; |
| 5364 |
} |
| 5365 |
|
| 5366 |
if (isset($input['brave_country'])) { |
| 5367 |
$new_input['brave_country'] = sanitize_text_field($input['brave_country']); |
| 5368 |
} |
| 5369 |
|
| 5370 |
if (isset($input['brave_language'])) { |
| 5371 |
$new_input['brave_language'] = sanitize_text_field($input['brave_language']); |
| 5372 |
} |
| 5373 |
|
| 5374 |
|
| 5375 |
if (isset($input['chat_toolbar_toggle'])) { |
| 5376 |
$new_input['chat_toolbar_toggle'] = $input['chat_toolbar_toggle'] === 'on' ? 'on' : 'off'; |
| 5377 |
} |
| 5378 |
|
| 5379 |
|
| 5380 |
if (isset($input['pdf_intent_trigger_text'])) { |
| 5381 |
$new_input['pdf_intent_trigger_text'] = sanitize_text_field($input['pdf_intent_trigger_text']); |
| 5382 |
} |
| 5383 |
|
| 5384 |
if (isset($input['pdf_intent_success_text'])) { |
| 5385 |
$new_input['pdf_intent_success_text'] = sanitize_text_field($input['pdf_intent_success_text']); |
| 5386 |
} |
| 5387 |
|
| 5388 |
if (isset($input['pdf_intent_error_text'])) { |
| 5389 |
$new_input['pdf_intent_error_text'] = sanitize_text_field($input['pdf_intent_error_text']); |
| 5390 |
} |
| 5391 |
|
| 5392 |
if (isset($input['pdf_max_pages'])) { |
| 5393 |
$new_input['pdf_max_pages'] = intval($input['pdf_max_pages']); |
| 5394 |
if ($new_input['pdf_max_pages'] < 1 || $new_input['pdf_max_pages'] > 69) { |
| 5395 |
$new_input['pdf_max_pages'] = 69; // Default to 69 if out of range |
| 5396 |
} |
| 5397 |
} |
| 5398 |
|
| 5399 |
|
| 5400 |
if (isset($input['live_agent_webhook_url'])) { |
| 5401 |
$new_input['live_agent_webhook_url'] = esc_url_raw($input['live_agent_webhook_url']); |
| 5402 |
} |
| 5403 |
if (isset($input['live_agent_secret_key'])) { |
| 5404 |
$new_input['live_agent_secret_key'] = sanitize_text_field($input['live_agent_secret_key']); |
| 5405 |
} |
| 5406 |
|
| 5407 |
// Live Agent Integration |
| 5408 |
if (isset($input['live_agent_bot_token'])) { |
| 5409 |
$new_input['live_agent_bot_token'] = sanitize_text_field($input['live_agent_bot_token']); |
| 5410 |
} |
| 5411 |
|
| 5412 |
if (isset($input['live_agent_status'])) { |
| 5413 |
$new_input['live_agent_status'] = ($input['live_agent_status'] === 'on') ? 'on' : 'off'; |
| 5414 |
} |
| 5415 |
if (isset($input['live_agent_away_message'])) { |
| 5416 |
$new_input['live_agent_away_message'] = sanitize_textarea_field($input['live_agent_away_message']); |
| 5417 |
} |
| 5418 |
if (isset($input['live_agent_notification_message'])) { |
| 5419 |
$new_input['live_agent_notification_message'] = sanitize_textarea_field($input['live_agent_notification_message']); |
| 5420 |
} |
| 5421 |
|
| 5422 |
|
| 5423 |
return $new_input; |
| 5424 |
} |
| 5425 |
|
| 5426 |
|
| 5427 |
// Method to append the chatbot to the body |
| 5428 |
public function mxchat_append_chatbot_to_body() { |
| 5429 |
$options = get_option('mxchat_options'); |
| 5430 |
if (isset($options['append_to_body']) && $options['append_to_body'] === 'on') { |
| 5431 |
echo do_shortcode('[mxchat_chatbot floating="yes"]'); |
| 5432 |
} |
| 5433 |
} |
| 5434 |
|
| 5435 |
|
| 5436 |
|
| 5437 |
private static function mxchat_extract_main_content($html) { |
| 5438 |
$dom = new DOMDocument; |
| 5439 |
libxml_use_internal_errors(true); // Suppress HTML parsing errors |
| 5440 |
@$dom->loadHTML($html); |
| 5441 |
libxml_clear_errors(); |
| 5442 |
|
| 5443 |
$xpath = new DOMXPath($dom); |
| 5444 |
|
| 5445 |
// Simplified selectors focusing on common content areas |
| 5446 |
$selectors = [ |
| 5447 |
'//article', |
| 5448 |
'//*[@id="content"]', |
| 5449 |
'//*[@class="entry-content"]', |
| 5450 |
'//main', |
| 5451 |
]; |
| 5452 |
|
| 5453 |
foreach ($selectors as $selector) { |
| 5454 |
$nodes = $xpath->query($selector); |
| 5455 |
if ($nodes->length > 0) { |
| 5456 |
$content = ''; |
| 5457 |
foreach ($nodes as $node) { |
| 5458 |
$content .= $dom->saveHTML($node); |
| 5459 |
} |
| 5460 |
return $content; |
| 5461 |
} |
| 5462 |
} |
| 5463 |
|
| 5464 |
// Fallback: Return the entire body content if no specific selector matches |
| 5465 |
$body = $dom->getElementsByTagName('body'); |
| 5466 |
return $body->length > 0 ? $dom->saveHTML($body->item(0)) : $html; |
| 5467 |
} |
| 5468 |
private function mxchat_fetch_loops_mailing_lists($api_key) { |
| 5469 |
$url = 'https://app.loops.so/api/v1/lists'; |
| 5470 |
$response = wp_remote_get($url, array( |
| 5471 |
'headers' => array( |
| 5472 |
'Authorization' => 'Bearer ' . $api_key, |
| 5473 |
'Content-Type' => 'application/json' |
| 5474 |
) |
| 5475 |
)); |
| 5476 |
|
| 5477 |
if (is_wp_error($response)) { |
| 5478 |
return array(); |
| 5479 |
} |
| 5480 |
|
| 5481 |
$body = wp_remote_retrieve_body($response); |
| 5482 |
$lists = json_decode($body, true); |
| 5483 |
|
| 5484 |
return isset($lists) && is_array($lists) ? $lists : array(); |
| 5485 |
} |
| 5486 |
|
| 5487 |
|
| 5488 |
|
| 5489 |
|
| 5490 |
|
| 5491 |
function mxchat_calculate_cosine_similarity($vec1, $vec2) { |
| 5492 |
if (empty($vec1) || empty($vec2)) { |
| 5493 |
return 0.0; |
| 5494 |
} |
| 5495 |
|
| 5496 |
$dot_product = 0.0; |
| 5497 |
$norm_a = 0.0; |
| 5498 |
$norm_b = 0.0; |
| 5499 |
|
| 5500 |
for ($i = 0; $i < count($vec1); $i++) { |
| 5501 |
$dot_product += $vec1[$i] * $vec2[$i]; |
| 5502 |
$norm_a += pow($vec1[$i], 2); |
| 5503 |
$norm_b += pow($vec2[$i], 2); |
| 5504 |
} |
| 5505 |
|
| 5506 |
if ($norm_a == 0.0 || $norm_b == 0.0) { |
| 5507 |
return 0.0; |
| 5508 |
} else { |
| 5509 |
return $dot_product / (sqrt($norm_a) * sqrt($norm_b)); |
| 5510 |
} |
| 5511 |
} |
| 5512 |
|
| 5513 |
|
| 5514 |
|
| 5515 |
|
| 5516 |
} |
| 5517 |
?> |
| 5518 |
|