diff --git a/controllers/front/SearchController.php b/controllers/front/SearchController.php index 67189e0710..ff69e42712 100644 --- a/controllers/front/SearchController.php +++ b/controllers/front/SearchController.php @@ -83,6 +83,10 @@ public function initContent() $query = Tools::replaceAccentedChars(urldecode($originalQuery)); if ($this->ajax_search) { $searchResults = Search::find((int) (Tools::getValue('id_lang')), $query, 1, 10, 'position', 'desc', true); + + if(empty($searchResults)) + $searchResults = Search::find((int) (Tools::getValue('id_lang')), self::findFirstClosestWords($query), 1, 10, 'position', 'desc', true); + if (is_array($searchResults)) { foreach ($searchResults as &$product) { $product['product_link'] = $this->context->link->getProductLink($product['id_product'], $product['prewrite'], $product['crewrite']); @@ -227,4 +231,60 @@ public function setMedia() $this->addCSS(_THEME_CSS_DIR_.'product_list.css'); } } + + /** + * findFirstClosestWord + * + * @param $searchString + * + * @return string + */ + static function findFirstClosestWords($searchString) + { + $cache = array(); + $closestWords = ""; + $lenghtWordCoefMin = 0.7; + $lenghtWordCoefMax = 1.5; + $MINWORDLEN = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); + + $queries = explode(' ', Search::sanitize($searchString, (int)Context::getContext()->language->id, false, Context::getContext()->language->iso_code)); + + foreach ($queries as $query) + { + if(strlen($query) < $MINWORDLEN) + continue; + + $targetLenghtMin = (int)(strlen($query) * $lenghtWordCoefMin); + $targetLenghtMax = (int)(strlen($query) * $lenghtWordCoefMax); + + if($targetLenghtMin < $MINWORDLEN) + $targetLenghtMin = $MINWORDLEN; + + $sql = 'SELECT `word` FROM `'._DB_PREFIX_.'search_word` + WHERE `id_lang` = '.(int)Context::getContext()->language->id.' + AND `id_shop` = '.(int)Context::getContext()->shop->id.' + AND LENGTH(`word`) > '.$targetLenghtMin.' + AND LENGTH(`word`) < '.$targetLenghtMax.';'; + + $selectedWords = Db::getInstance()->executeS($sql); + + $closestWords .= array_reduce($selectedWords, function($a, $b) use ($query, &$cache){ + + if (!isset($cache[$a['word']])) + $cache[$a['word']] = levenshtein($a['word'], $query); + if (!isset($cache[$b['word']])) + $cache[$b['word']] = levenshtein($b['word'], $query); + + return $cache[$a['word']] < $cache[$b['word']] ? $a : $b; + + }, array ("word" => 'initial'))['word']; + + if(next($queries)) { + unset($cache); + $closestWords .= ' '; + } + } + + return $closestWords; + } }