isset($options['button_icon']) ? $options['button_icon'] : 'AI Search', // Use global setting as default value ), $atts); AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Shortcodes', 'Rendering search button shortcode', array('attributes' => $atts)); // Get custom button settings $icon_type = isset($options['button_icon_type']) ? $options['button_icon_type'] : 'text'; $icon_image = isset($options['button_icon_image']) ? $options['button_icon_image'] : ''; $button_css = isset($options['button_css']) ? $options['button_css'] : ''; // Generate unique button ID $button_id = 'aipa-search-button-' . uniqid(); // Ensure scripts and styles are loaded wp_enqueue_style('aipa-frontend-css', AIPA_PLUGIN_URL . 'assets/css/frontend.css', array(), AIPA_VERSION); wp_enqueue_script('aipa-frontend-js', AIPA_PLUGIN_URL . 'assets/js/frontend.js', array('jquery'), AIPA_VERSION, true); // Determine which icon to display $icon_html = ''; if ($icon_type === 'image' && !empty($icon_image)) { // Custom icon image for shortcode button (user-defined URL, not WordPress media) // phpcs:ignore PluginCheck.CodeAnalysis.ImageFunctions.NonEnqueuedImage $icon_html = 'Search'; } else { // Use shortcode parameter first, then global setting $icon_html = esc_html($atts['button_text']); } // Generate button HTML $output = ''; // Add button inline styles using wp_add_inline_style if (!empty($button_css)) { wp_add_inline_style('aipa-frontend-css', '#' . esc_attr($button_id) . '{' . esc_html($button_css) . '}'); } // Add button JavaScript handling using wp_add_inline_script wp_add_inline_script('aipa-frontend-js', sprintf( 'jQuery(document).ready(function($) { $("#%s").on("click", function() { $("#aipa-search-modal").css("display", "flex").hide().fadeIn(300); $("#aipa-search-input").focus(); }); });', esc_js($button_id) ) ); $execution_time = microtime(true) - $start_time; AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Shortcodes', 'Search button shortcode rendered', array( 'button_id' => $button_id, 'icon_type' => $icon_type, 'has_custom_css' => !empty($button_css), 'execution_time' => $execution_time )); return $output; } /** * Render search form shortcode [aipa_search_form] */ public function render_search_form_shortcode($atts) { $start_time = microtime(true); AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Shortcodes', 'Entering render_search_form_shortcode', array( 'attributes' => $atts )); // Get settings $options = get_option('aipa_settings'); // Default text values $default_title = isset($options['search_modal_title']) ? $options['search_modal_title'] : __('AI Product Search', 'ai-product-assistant'); $default_description = isset($options['search_modal_description']) ? $options['search_modal_description'] : __('Describe what you\'re looking for in natural language.', 'ai-product-assistant'); $default_placeholder = isset($options['search_placeholder']) ? $options['search_placeholder'] : __('e.g., I need a waterproof jacket for hiking in rainy weather', 'ai-product-assistant'); $default_button_text = isset($options['search_button_text']) ? $options['search_button_text'] : __('Search with AI', 'ai-product-assistant'); $default_voice_button_text = isset($options['voice_button_text']) ? $options['voice_button_text'] : __('Voice Search', 'ai-product-assistant'); $atts = shortcode_atts(array( 'title' => $default_title, 'description' => $default_description, 'placeholder' => $default_placeholder, 'button_text' => $default_button_text, 'voice_search' => 'true', 'voice_button_text' => $default_voice_button_text, 'result_container' => 'true' ), $atts); // Ensure scripts and styles are enqueued wp_enqueue_style('aipa-frontend-css', AIPA_PLUGIN_URL . 'assets/css/frontend.css', array(), AIPA_VERSION); wp_enqueue_script('aipa-frontend-js', AIPA_PLUGIN_URL . 'assets/js/frontend.js', array('jquery'), AIPA_VERSION, true); // Localize script if not already done if (!wp_script_is('aipa-frontend-js', 'localized')) { // Performance settings $search_batch_size = isset($options['search_batch_size']) ? intval($options['search_batch_size']) : 100; // Get max batches with dynamic default calculation if (isset($options['max_batches'])) { $max_batches = intval($options['max_batches']); } else { $product_count = (int) wp_count_posts('product')->publish; $max_batches = $product_count > 0 ? ceil($product_count / $search_batch_size) : 1; } wp_localize_script('aipa-frontend-js', 'aipa_data', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('aipa_nonce'), 'searching_text' => __('Searching...', 'ai-product-assistant'), 'search_placeholder' => $atts['placeholder'], 'search_button' => $atts['button_text'], 'error_message' => __('Something went wrong. Please try again.', 'ai-product-assistant'), 'empty_query_message' => __('Please enter a search query.', 'ai-product-assistant'), 'no_results_message' => __('No products found matching your description. Try being more specific or using different terms.', 'ai-product-assistant'), 'voice_search_not_supported' => __('Voice search is not supported in your browser.', 'ai-product-assistant'), 'voice_search_prompt' => __('Speak now...', 'ai-product-assistant'), 'voice_search_button' => $atts['voice_button_text'], 'deep_search_button' => __('Search More Products', 'ai-product-assistant'), 'deep_search_searching' => __('Searching More...', 'ai-product-assistant'), 'search_complete_message' => __('Search complete!', 'ai-product-assistant'), 'no_more_products_message' => __('No more products found matching your description.', 'ai-product-assistant'), 'aipa_service_error_message' => __('Sorry, AI feature is temporarily unavailable. Please try again later.', 'ai-product-assistant'), 'login_url' => function_exists('wc_get_page_permalink') ? wc_get_page_permalink('myaccount') : wp_login_url(get_permalink()), 'login_text' => __('Log in here', 'ai-product-assistant'), 'search_options' => array( 'batch_size' => $search_batch_size, 'max_batches' => $max_batches ) )); } // Generate unique IDs for this instance $unique_id = 'aipa-' . uniqid(); $form_id = $unique_id . '-form'; $input_id = $unique_id . '-input'; $button_id = $unique_id . '-button'; $voice_button_id = $unique_id . '-voice-button'; $error_id = $unique_id . '-error'; $loading_id = $unique_id . '-loading'; $results_id = $unique_id . '-results'; // Start output buffering ob_start(); ?>

$form_id, 'has_voice_search' => $atts['voice_search'] === 'true', 'has_result_container' => $atts['result_container'] === 'true', 'execution_time' => $execution_time )); return $output; } /** * Render search result shortcode [aipa_search_result ids="123,456,789"] */ public function render_search_result_shortcode($atts) { $start_time = microtime(true); AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Shortcodes', 'Entering render_search_result_shortcode', array( 'attributes' => $atts )); // Get global settings $options = get_option('aipa_settings'); // Get default values from settings $default_show_explanation = isset($options['show_explanation']) ? $options['show_explanation'] : true; $default_use_native_template = isset($options['use_native_template']) ? $options['use_native_template'] : true; $default_show_out_of_stock = isset($options['show_out_of_stock']) ? $options['show_out_of_stock'] : false; $default_show_add_to_cart = isset($options['show_add_to_cart']) ? $options['show_add_to_cart'] : true; // If using native template, get WooCommerce settings if($default_use_native_template){ $woo_hide_out_of_stock = get_option('woocommerce_hide_out_of_stock_items', 'no'); $default_show_out_of_stock = ($woo_hide_out_of_stock !== 'yes'); } // Use shortcode_atts to merge default values with passed parameters, prioritizing passed parameters $atts = shortcode_atts(array( 'ids' => '', 'show_explanation' => $default_show_explanation ? 'true' : 'false', 'use_native_template' => $default_use_native_template ? 'true' : 'false', 'show_out_of_stock' => $default_show_out_of_stock ? 'true' : 'false', 'show_add_to_cart' => $default_show_add_to_cart ? 'true' : 'false', 'explanations' => '' // Added: can pass explanation text, format is "product_id:text,product_id:text" ), $atts); // Convert strings to boolean values $show_explanation = filter_var($atts['show_explanation'], FILTER_VALIDATE_BOOLEAN); $use_native_template = filter_var($atts['use_native_template'], FILTER_VALIDATE_BOOLEAN); $show_out_of_stock = filter_var($atts['show_out_of_stock'], FILTER_VALIDATE_BOOLEAN); $show_add_to_cart = filter_var($atts['show_add_to_cart'], FILTER_VALIDATE_BOOLEAN); // Get product IDs $product_ids = array(); if (!empty($atts['ids'])) { $product_ids = explode(',', $atts['ids']); $product_ids = array_map('trim', $product_ids); $product_ids = array_map('absint', $product_ids); $product_ids = array_filter($product_ids); } // Process explanation text (if provided) $explanations = array(); if (!empty($atts['explanations'])) { $explanation_pairs = explode(',', $atts['explanations']); foreach ($explanation_pairs as $pair) { $parts = explode(':', $pair, 2); if (count($parts) == 2) { $product_id = absint(trim($parts[0])); $explanation = sanitize_text_field(trim($parts[1])); if ($product_id > 0) { $explanations[$product_id] = $explanation; } } } } // If show_out_of_stock is set to false, filter out out-of-stock products if (!$show_out_of_stock && !empty($product_ids)) { $filtered_ids = array(); foreach ($product_ids as $id) { $product = wc_get_product($id); if ($product && $product->is_in_stock()) { $filtered_ids[] = $id; } } $product_ids = $filtered_ids; } // If no product IDs provided, return empty string if (empty($product_ids)) { AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Shortcodes', 'No product IDs provided for search result shortcode'); return ''; } // Create a Product_Search instance to use its methods $product_search = new AIPA_Product_Search(); // Get HTML for products if ($use_native_template) { $html = $product_search->get_products_html_native($product_ids, $explanations, $show_explanation, $show_add_to_cart); } else { $html = $product_search->get_products_html_custom($product_ids, $explanations, $show_explanation, $show_add_to_cart); } $execution_time = microtime(true) - $start_time; AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Shortcodes', 'Search result shortcode rendered', array( 'product_ids_count' => count($product_ids), 'use_native_template' => $use_native_template, 'show_explanation' => $show_explanation, 'show_out_of_stock' => $show_out_of_stock, 'show_add_to_cart' => $show_add_to_cart, 'execution_time' => $execution_time )); return $html; } /** * Render cart analysis shortcode [aipa_cart_analysis] */ public function render_cart_analysis_shortcode($atts) { $start_time = microtime(true); AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Shortcodes', 'Entering render_cart_analysis_shortcode', array( 'attributes' => $atts )); // Get settings $options = get_option('aipa_settings'); // Default text values $default_title = isset($options['cart_analysis_title']) ? $options['cart_analysis_title'] : __('AI Cart Analysis', 'ai-product-assistant'); $default_description = isset($options['cart_analysis_description']) ? $options['cart_analysis_description'] : __('Ask AI if your cart items will work for your specific needs.', 'ai-product-assistant'); $default_placeholder = isset($options['cart_analysis_placeholder']) ? $options['cart_analysis_placeholder'] : __('e.g., Can I make a basic home theater with these items?', 'ai-product-assistant'); $default_button_text = isset($options['cart_analysis_button_text']) ? $options['cart_analysis_button_text'] : __('Analyze with AI', 'ai-product-assistant'); $atts = shortcode_atts(array( 'title' => $default_title, 'description' => $default_description, 'placeholder' => $default_placeholder, 'button_text' => $default_button_text ), $atts); // Check if cart analysis is enabled $enable_cart_analysis = isset($options['enable_cart_analysis']) ? $options['enable_cart_analysis'] : true; if (!$enable_cart_analysis) { AIPA_Debug::log(AIPA_Debug::LEVEL_INFO, 'Shortcodes', 'Cart analysis is disabled in settings'); return ''; } // If WooCommerce is not active or cart is empty, return empty string if (!function_exists('WC') || !isset(WC()->cart) || WC()->cart->is_empty()) { AIPA_Debug::log(AIPA_Debug::LEVEL_INFO, 'Shortcodes', 'Cart is empty or WooCommerce not active', array( 'wc_exists' => function_exists('WC'), 'cart_exists' => function_exists('WC') && isset(WC()->cart), 'cart_empty' => function_exists('WC') && isset(WC()->cart) && WC()->cart->is_empty() )); return '
' . __('Your cart is empty. Add some products first.', 'ai-product-assistant') . '
'; } // Ensure scripts and styles are enqueued wp_enqueue_style('aipa-cart-css', AIPA_PLUGIN_URL . 'assets/css/cart-analysis.css', array('aipa-frontend-css'), AIPA_VERSION); wp_enqueue_script('aipa-cart-js', AIPA_PLUGIN_URL . 'assets/js/cart-analysis.js', array('jquery'), AIPA_VERSION, true); // Localize script if not already done if (!wp_script_is('aipa-cart-js', 'localized')) { wp_localize_script('aipa-cart-js', 'aipa_cart_data', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('aipa_cart_nonce'), 'analyzing_text' => __('Analyzing...', 'ai-product-assistant'), 'analysis_placeholder' => $atts['placeholder'], 'analysis_button' => $atts['button_text'], 'cart_analysis_title' => $atts['title'], 'cart_analysis_description' => $atts['description'], 'error_message' => __('Something went wrong. Please try again.', 'ai-product-assistant'), 'empty_query_message' => __('Please enter an analysis question.', 'ai-product-assistant'), 'empty_cart_message' => __('Your cart is empty. Add some products first.', 'ai-product-assistant'), 'aipa_service_error_message' => __('Sorry, AI feature is temporarily unavailable. Please try again later.', 'ai-product-assistant'), 'login_url' => function_exists('wc_get_page_permalink') ? wc_get_page_permalink('myaccount') : wp_login_url(get_permalink()), 'login_text' => __('Log in here', 'ai-product-assistant'), )); } // Generate unique IDs for this instance $unique_id = 'aipa-cart-' . uniqid(); $form_id = $unique_id . '-form'; $input_id = $unique_id . '-input'; $button_id = $unique_id . '-button'; $error_id = $unique_id . '-error'; $loading_id = $unique_id . '-loading'; $results_id = $unique_id . '-results'; // Start output buffering ob_start(); ?>

$form_id, 'cart_items_count' => function_exists('WC') && isset(WC()->cart) ? WC()->cart->get_cart_contents_count() : 0, 'execution_time' => $execution_time )); return $output; } }