container = $container; } /** * Executes a search and formats the output. * * @param string $keyword * @return array */ public function search($keyword, $category = '') { if (empty(trim($keyword))) { return []; } $settings = get_option('awas_settings', []); $cache_enabled = !empty($settings['performance']['cache']); $cache_key = 'awas_search_' . md5($keyword . '_' . $category . '_' . wp_json_encode($settings['layouts'] ?? [])); if ($cache_enabled) { $cached_results = get_transient($cache_key); if ($cached_results !== false) { return $cached_results; } } $queryBuilder = $this->container->get(QueryBuilder::class); $sql = $queryBuilder->build_query($keyword, $settings, $category); if (empty($sql)) { return []; } global $wpdb; $results = $wpdb->get_results($sql); $final_results = []; if (empty($results) && !empty($settings['suggestions']['did_you_mean'])) { // Did you mean logic using SOUNDEX $did_you_mean = $wpdb->get_var($wpdb->prepare(" SELECT title FROM {$wpdb->prefix}awas_search_index WHERE SOUNDEX(title) = SOUNDEX(%s) AND status = 'publish' LIMIT 1 ", $keyword)); if ($did_you_mean && strtolower(trim($did_you_mean)) !== strtolower(trim($keyword))) { $final_results = ['did_you_mean' => $did_you_mean]; } } else { $final_results = $this->format_results($results, $settings); } if ($cache_enabled && !empty($final_results)) { // Cache for 12 hours set_transient($cache_key, $final_results, 12 * HOUR_IN_SECONDS); } return $final_results; } /** * Formats DB results into a structured array for the frontend UI. * * @param array $db_results * @param array $settings * @return array */ private function format_results($db_results, $settings) { $formatted = []; $desc_length = isset($settings['logic']['desc_length']) ? absint($settings['logic']['desc_length']) : 20; foreach ($db_results as $row) { $product_id = ($row->variation_id > 0) ? $row->variation_id : $row->object_id; $product = wc_get_product($product_id); if (!$product) continue; $image = wp_get_attachment_image_src($product->get_image_id(), 'thumbnail'); $description = wp_trim_words($product->get_short_description() ?: $product->get_description(), $desc_length); // Get Categories with URLs $categories_data = []; $terms = get_the_terms($product->get_parent_id() ?: $product->get_id(), 'product_cat'); if ($terms && !is_wp_error($terms)) { foreach ($terms as $term) { $categories_data[] = [ 'name' => $term->name, 'url' => get_term_link($term, 'product_cat') ]; } } // Stock status text $stock_text = ''; if ($product->is_in_stock()) { $stock_text = __('In stock', 'awas-woo'); } else { $stock_text = __('Out of stock', 'awas-woo'); } // Product Type and Add to Cart $type = $product->get_type(); $add_to_cart_url = $product->add_to_cart_url(); $add_to_cart_text = $product->add_to_cart_text(); // For variable products, we might want to return variations $attributes_string = ''; if ($type === 'variation') { $attributes = $product->get_attributes(); $attr_names = []; foreach ($attributes as $key => $value) { $taxonomy = str_replace('attribute_', '', $key); if (taxonomy_exists($taxonomy)) { $term = get_term_by('slug', $value, $taxonomy); $attr_names[] = wc_attribute_label($taxonomy) . ': ' . ($term ? $term->name : $value); } else { $attr_names[] = wc_attribute_label($taxonomy) . ': ' . $value; } } $attributes_string = implode(', ', $attr_names); } $formatted[] = [ 'id' => $product_id, 'title' => $product->get_name(), 'price_html' => $product->get_price_html(), 'image' => $image ? $image[0] : wc_placeholder_img_src(), 'url' => $product->get_permalink(), 'sku' => $product->get_sku(), 'description' => $description, 'is_in_stock' => $product->is_in_stock(), 'stock_text' => $stock_text, 'is_on_sale' => $product->is_on_sale(), 'categories' => $categories_data, 'type' => $type, 'add_to_cart_url' => $add_to_cart_url, 'add_to_cart_text' => $add_to_cart_text, 'attributes_string' => $attributes_string ]; } return $formatted; } }