admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('aipa_product_assistant_nonce'), 'analyzing_text' => __('Analyzing...', 'ai-product-assistant'), 'assistant_placeholder' => $default_placeholder, 'assistant_button' => $default_button_text, 'assistant_title' => $default_title, 'assistant_description' => $default_description, 'error_message' => __('Something went wrong. Please try again.', 'ai-product-assistant'), 'empty_query_message' => __('Please enter a question.', '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'), )); // Add custom CSS $button_css = isset($options['product_assistant_button_css']) ? $options['product_assistant_button_css'] : ''; if (!empty($button_css)) { wp_add_inline_style('aipa-product-assistant-css', '.aipa-product-assistant-btn {' . esc_html($button_css) . '}'); } } } /** * Add product assistant button on product page */ public function add_product_assistant_button() { global $product; if ($product) { $options = get_option('aipa_settings'); $button_text = isset($options['product_assistant_button_text']) ? $options['product_assistant_button_text'] : __('Ask AI', 'ai-product-assistant'); echo '
'; echo ''; echo '
'; // Add modal window HTML $this->add_product_assistant_modal(); } } /** * Add product assistant modal window */ public function add_product_assistant_modal() { $options = get_option('aipa_settings'); $title = isset($options['product_assistant_title']) ? $options['product_assistant_title'] : __('AI Product Assistant', 'ai-product-assistant'); $description = isset($options['product_assistant_description']) ? $options['product_assistant_description'] : __('Ask AI about this product', 'ai-product-assistant'); $placeholder = isset($options['product_assistant_placeholder']) ? $options['product_assistant_placeholder'] : __('e.g., Is this product suitable for beginners?', 'ai-product-assistant'); $button_text = isset($options['product_assistant_button_text']) ? $options['product_assistant_button_text'] : __('Ask AI', 'ai-product-assistant'); ?>
×

__('Please log in to use AI product assistant feature.', 'ai-product-assistant'), 'code' => 'auth_required' )); } $query = isset($_POST['query']) ? sanitize_text_field(wp_unslash($_POST['query'])) : ''; $product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0; AIPA_Debug::log(AIPA_Debug::LEVEL_INFO, 'Product_Assistant', 'AJAX product assistant request received', array('product_id' => $product_id, 'query_length' => strlen($query))); if (empty($query)) { AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Product_Assistant', 'Empty query provided'); wp_send_json_error(array( 'message' => __('Please enter a question.', 'ai-product-assistant') )); } if (empty($product_id)) { AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Product_Assistant', 'Invalid product ID provided'); wp_send_json_error(array( 'message' => __('Invalid product ID.', 'ai-product-assistant') )); } // Get product data $product = wc_get_product($product_id); if (!$product) { AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Product_Assistant', 'Product not found', array('product_id' => $product_id)); wp_send_json_error(array( 'message' => __('Product not found.', 'ai-product-assistant') )); } // Build product data for AI analysis $product_data = $this->get_product_data_for_analysis($product); // Call API for analysis try { $api = new AIPA_API(); $result = $this->call_api_for_product_analysis($query, $product_data); if (is_wp_error($result)) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'API call returned error in AJAX handler', array( 'error_code' => $result->get_error_code(), 'error_message' => $result->get_error_message() )); wp_send_json_error(array( 'message' => $result->get_error_message(), 'code' => $result->get_error_code() )); return; } // Format result HTML $html = $this->format_analysis_result($result); if (empty($html)) { AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Product_Assistant', 'Empty HTML after formatting'); $html = '
' . __('No analysis results available.', 'ai-product-assistant') . '
'; } AIPA_Debug::log(AIPA_Debug::LEVEL_INFO, 'Product_Assistant', 'AJAX response successful', array( 'html_length' => strlen($html) )); wp_send_json_success(array( 'html' => $html )); } catch (Exception $e) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'Exception in AJAX handler', array( 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() )); wp_send_json_error(array( 'message' => __('An error occurred while processing your request. Please try again.', 'ai-product-assistant') )); } } /** * Get product data for AI analysis */ private function get_product_data_for_analysis($product) { $options = get_option('aipa_settings'); $search_fields = isset($options['search_fields']) ? $options['search_fields'] : array(); $description_length_limit = isset($options['description_length_limit']) ? intval($options['description_length_limit']) : 500; $short_description_length_limit = isset($options['short_description_length_limit']) ? intval($options['short_description_length_limit']) : 200; // Debug logging AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Product_Assistant', 'Configuration loaded', array('search_fields' => $search_fields, 'description_limit' => $description_length_limit)); $product_data = array( 'id' => $product->get_id(), 'data' => array() ); // Add product fields if (isset($search_fields['title']) && $search_fields['title']) { $product_data['data']['title'] = $product->get_name(); } if (isset($search_fields['content']) && $search_fields['content']) { $content = $product->get_description(); $product_data['data']['content'] = substr($content, 0, $description_length_limit); } if (isset($search_fields['short_description']) && $search_fields['short_description']) { $short_description = $product->get_short_description(); $product_data['data']['short_description'] = substr($short_description, 0, $short_description_length_limit); } if (isset($search_fields['categories']) && $search_fields['categories']) { $categories = array(); $terms = get_the_terms($product->get_id(), 'product_cat'); if ($terms && !is_wp_error($terms)) { foreach ($terms as $term) { $categories[] = $term->name; } } $product_data['data']['categories'] = implode(', ', $categories); } if (isset($search_fields['attributes']) && $search_fields['attributes']) { $attributes = array(); $product_attributes = $product->get_attributes(); if (!empty($product_attributes)) { foreach ($product_attributes as $attribute) { if ($attribute->is_taxonomy()) { $taxonomy = $attribute->get_taxonomy_object(); $attribute_name = $taxonomy->attribute_label; $values = array(); $terms = $attribute->get_terms(); if (!empty($terms)) { foreach ($terms as $term) { $values[] = $term->name; } } $attributes[$attribute_name] = implode(', ', $values); } else { $attribute_name = $attribute->get_name(); $attributes[$attribute_name] = implode(', ', $attribute->get_options()); } } } $product_data['data']['attributes'] = $attributes; } if (isset($search_fields['regular_price']) && $search_fields['regular_price']) { $product_data['data']['regular_price'] = $product->get_regular_price(); } if (isset($search_fields['sale_price']) && $search_fields['sale_price']) { $product_data['data']['sale_price'] = $product->get_sale_price(); } // Add tags if selected if (isset($search_fields['tags']) && $search_fields['tags']) { $tags = array(); $terms = get_the_terms($product->get_id(), 'product_tag'); if ($terms && !is_wp_error($terms)) { foreach ($terms as $term) { $tags[] = $term->name; } } $product_data['data']['tags'] = implode(', ', $tags); } // Add brand if selected if (isset($search_fields['brand']) && $search_fields['brand']) { $brands = array(); $terms = get_the_terms($product->get_id(), 'product_brand'); if ($terms && !is_wp_error($terms)) { foreach ($terms as $term) { $brands[] = $term->name; } } $product_data['data']['brand'] = implode(', ', $brands); } // Add weight if selected if (isset($search_fields['weight']) && $search_fields['weight']) { $weight = $product->get_weight(); if ($weight) { $weight_unit = get_option('woocommerce_weight_unit'); $product_data['data']['weight'] = $weight . ' ' . $weight_unit; } } // Add dimensions if selected if (isset($search_fields['dimensions']) && $search_fields['dimensions']) { $dimensions = array(); $length = $product->get_length(); $width = $product->get_width(); $height = $product->get_height(); if ($length || $width || $height) { $dimension_unit = get_option('woocommerce_dimension_unit'); $dimensions_text = ''; if ($length) $dimensions_text .= $length; if ($width) $dimensions_text .= ' x ' . $width; if ($height) $dimensions_text .= ' x ' . $height; $product_data['data']['dimensions'] = trim($dimensions_text, ' x ') . ' ' . $dimension_unit; } } // Add variation data if selected and product is variable if (isset($search_fields['variation_data']) && $search_fields['variation_data'] && $product->is_type('variable')) { $variations = array(); $variation_ids = $product->get_children(); foreach ($variation_ids as $variation_id) { $variation = wc_get_product($variation_id); if ($variation) { $variation_data = array( 'id' => $variation_id, 'attributes' => $variation->get_variation_attributes(), 'price' => $variation->get_price(), 'in_stock' => $variation->is_in_stock() ); $variations[] = $variation_data; } } $product_data['data']['variation_data'] = $variations; } // Add custom fields if configured if (isset($options['custom_fields']) && is_array($options['custom_fields'])) { $all_meta = get_post_meta($product->get_id()); $custom_meta = array(); // Record all selected custom fields foreach ($options['custom_fields'] as $custom_field) { if (isset($custom_field['meta_key'])) { $meta_key = $custom_field['meta_key']; if (isset($all_meta[$meta_key])) { $meta_value = maybe_unserialize($all_meta[$meta_key][0]); if (!empty($meta_value)) { $custom_meta[$meta_key] = $meta_value; } } } } if (!empty($custom_meta)) { $product_data['data']['custom_meta'] = $custom_meta; } } return $product_data; } /** * Call API for product analysis */ private function call_api_for_product_analysis($query, $product_data) { // Debug logging - log final product data AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Product_Assistant', 'Calling API for product analysis', array('query' => $query, 'product_id' => $product_data['id'])); try { // Create WP_REST_Request instance $request = new WP_REST_Request('POST', '/aipa/v1/product-assistant'); $request->set_param('query', $query); $request->set_param('product_data', $product_data); // Send request $response = rest_do_request($request); // Handle errors if (is_wp_error($response)) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'REST request returned WP_Error', array( 'error_code' => $response->get_error_code(), 'error_message' => $response->get_error_message() )); return $response; } // Get response data $data = $response->get_data(); // Log the response data structure AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Product_Assistant', 'REST response received', array( 'has_data' => !empty($data), 'has_analysis' => isset($data['analysis']), 'data_keys' => is_array($data) ? array_keys($data) : 'not_array' )); // Check if the response contains error information (from wp_send_json_error) if (isset($data['code']) && isset($data['message'])) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'REST API returned error response', array( 'error_code' => $data['code'], 'error_message' => $data['message'] )); return new WP_Error($data['code'], $data['message']); } if (empty($data) || !isset($data['analysis'])) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'Invalid response structure', array( 'data' => $data )); return new WP_Error('invalid_response', __('Invalid response from AI API.', 'ai-product-assistant')); } return $data; } catch (Exception $e) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'Exception in call_api_for_product_analysis', array( 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() )); return new WP_Error('api_exception', $e->getMessage()); } } /** * Format analysis result as HTML */ private function format_analysis_result($result) { $output = ''; try { if (empty($result)) { AIPA_Debug::log(AIPA_Debug::LEVEL_WARNING, 'Product_Assistant', 'Empty result in format_analysis_result'); return $output; } // Log the result structure AIPA_Debug::log(AIPA_Debug::LEVEL_DEBUG, 'Product_Assistant', 'Formatting analysis result', array( 'has_analysis' => isset($result['analysis']), 'has_features' => isset($result['features']), 'has_recommendations' => isset($result['recommendations']), 'features_count' => isset($result['features']) ? count($result['features']) : 0, 'recommendations_count' => isset($result['recommendations']) ? count($result['recommendations']) : 0 )); // Main analysis result if (isset($result['analysis']) && !empty($result['analysis'])) { $output .= '
'; $output .= '

' . __('Analysis', 'ai-product-assistant') . '

'; $output .= '
' . nl2br(esc_html($result['analysis'])) . '
'; $output .= '
'; } // Display features list (if any) if (!empty($result['features']) && is_array($result['features'])) { $output .= '
'; $output .= '

' . __('Key Features', 'ai-product-assistant') . '

'; $output .= ''; $output .= '
'; } // Display recommendations (if any) if (!empty($result['recommendations']) && is_array($result['recommendations'])) { $output .= '
'; $output .= '

' . __('Recommendations', 'ai-product-assistant') . '

'; $output .= ''; $output .= '
'; } return $output; } catch (Exception $e) { AIPA_Debug::log(AIPA_Debug::LEVEL_ERROR, 'Product_Assistant', 'Exception in format_analysis_result', array( 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() )); return '
' . __('Error formatting response.', 'ai-product-assistant') . '
'; } } /** * Render product assistant button shortcode */ public function render_product_assistant_button_shortcode($atts) { $atts = shortcode_atts(array( 'product_id' => 0, 'button_text' => '', ), $atts); $product_id = intval($atts['product_id']); if (empty($product_id)) { return '

' . __('Error: Product ID is required for the product assistant button.', 'ai-product-assistant') . '

'; } // Check if product exists $product = wc_get_product($product_id); if (!$product) { return '

' . __('Error: Product not found.', 'ai-product-assistant') . '

'; } // Get settings $options = get_option('aipa_settings'); $default_button_text = isset($options['product_assistant_button_text']) ? $options['product_assistant_button_text'] : __('Ask AI', 'ai-product-assistant'); $button_text = !empty($atts['button_text']) ? $atts['button_text'] : $default_button_text; // Ensure scripts and styles are loaded wp_enqueue_style('aipa-product-assistant-css', AIPA_PLUGIN_URL . 'assets/css/product-assistant.css', array('aipa-frontend-css'), AIPA_VERSION); wp_enqueue_script('aipa-product-assistant-js', AIPA_PLUGIN_URL . 'assets/js/product-assistant.js', array('jquery'), AIPA_VERSION, true); // Ensure frontend and cart scripts are also loaded wp_enqueue_script('aipa-frontend-js', AIPA_PLUGIN_URL . 'assets/js/frontend.js', array('jquery'), AIPA_VERSION, true); wp_enqueue_script('aipa-cart-analysis-js', AIPA_PLUGIN_URL . 'assets/js/cart-analysis.js', array('jquery'), AIPA_VERSION, true); // Generate unique button ID $button_id = 'aipa-product-assistant-btn-' . uniqid(); // Output button HTML $output = '
'; $output .= ''; $output .= '
'; // Add modal window HTML (if not already on page) if (!has_action('wp_footer', array($this, 'add_product_assistant_modal'))) { add_action('wp_footer', array($this, 'add_product_assistant_modal')); } return $output; } /** * Render product assistant form shortcode */ public function render_product_assistant_form_shortcode($atts) { $atts = shortcode_atts(array( 'product_id' => 0, 'title' => '', 'description' => '', 'placeholder' => '', 'button_text' => '', ), $atts); $product_id = intval($atts['product_id']); if (empty($product_id)) { return '

' . __('Error: Product ID is required for the product assistant form.', 'ai-product-assistant') . '

'; } // Check if product exists $product = wc_get_product($product_id); if (!$product) { return '

' . __('Error: Product not found.', 'ai-product-assistant') . '

'; } // Get settings $options = get_option('aipa_settings'); $default_title = isset($options['product_assistant_title']) ? $options['product_assistant_title'] : __('AI Product Assistant', 'ai-product-assistant'); $default_description = isset($options['product_assistant_description']) ? $options['product_assistant_description'] : __('Ask AI about this product', 'ai-product-assistant'); $default_placeholder = isset($options['product_assistant_placeholder']) ? $options['product_assistant_placeholder'] : __('e.g., Is this product suitable for beginners?', 'ai-product-assistant'); $default_button_text = isset($options['product_assistant_button_text']) ? $options['product_assistant_button_text'] : __('Ask AI', 'ai-product-assistant'); // Use shortcode parameters or default values $title = !empty($atts['title']) ? $atts['title'] : $default_title; $description = !empty($atts['description']) ? $atts['description'] : $default_description; $placeholder = !empty($atts['placeholder']) ? $atts['placeholder'] : $default_placeholder; $button_text = !empty($atts['button_text']) ? $atts['button_text'] : $default_button_text; // Ensure scripts and styles are loaded wp_enqueue_style('aipa-product-assistant-css', AIPA_PLUGIN_URL . 'assets/css/product-assistant.css', array('aipa-frontend-css'), AIPA_VERSION); wp_enqueue_script('aipa-product-assistant-js', AIPA_PLUGIN_URL . 'assets/js/product-assistant.js', array('jquery'), AIPA_VERSION, true); // Generate unique form ID $unique_id = 'aipa-product-assistant-' . 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'; // Output form HTML ob_start(); ?>