public static function indexation($full = false, $id_product = false) { $db = Db::getInstance(); if ($id_product) { $full = false; } if ($full) { $db->execute('TRUNCATE ' . _DB_PREFIX_ . 'search_index'); $db->execute('TRUNCATE ' . _DB_PREFIX_ . 'search_word'); ObjectModel::updateMultishopTable('Product', array('indexed' => 0)); } else { // Do it even if you already know the product id in order to be sure that it exists and it needs to be indexed $products = $db->executeS(' SELECT p.id_product FROM ' . _DB_PREFIX_ . 'product p ' . Shop::addSqlAssociation('product', 'p') . ' WHERE product_shop.visibility IN ("both", "search") AND ' . ($id_product ? 'p.id_product = ' . (int) $id_product : 'product_shop.indexed = 0')); $ids = array(); if ($products) { foreach ($products as $product) { $ids[] = (int) $product['id_product']; } } if (count($ids)) { $db->execute('DELETE FROM ' . _DB_PREFIX_ . 'search_index WHERE id_product IN (' . implode(',', $ids) . ')'); ObjectModel::updateMultishopTable('Product', array('indexed' => 0), 'a.id_product IN (' . implode(',', $ids) . ')'); } } // Every fields are weighted according to the configuration in the backend $weight_array = array('pname' => Configuration::get('PS_SEARCH_WEIGHT_PNAME'), 'reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'description_short' => Configuration::get('PS_SEARCH_WEIGHT_SHORTDESC'), 'description' => Configuration::get('PS_SEARCH_WEIGHT_DESC'), 'cname' => Configuration::get('PS_SEARCH_WEIGHT_CNAME'), 'mname' => Configuration::get('PS_SEARCH_WEIGHT_MNAME'), 'tags' => Configuration::get('PS_SEARCH_WEIGHT_TAG'), 'attributes' => Configuration::get('PS_SEARCH_WEIGHT_ATTRIBUTE'), 'features' => Configuration::get('PS_SEARCH_WEIGHT_FEATURE')); // Those are kind of global variables required to save the processed data in the database every X occurrences, in order to avoid overloading MySQL $count_words = 0; $query_array3 = array(); // Every indexed words are cached into a PHP array $word_ids = $db->executeS(' SELECT id_word, word, id_lang, id_shop FROM ' . _DB_PREFIX_ . 'search_word', false); $word_ids_by_word = array(); while ($word_id = $db->nextRow($word_ids)) { if (!isset($word_ids_by_word[$word_id['id_shop']][$word_id['id_lang']])) { $word_ids_by_word[$word_id['id_shop']][$word_id['id_lang']] = array(); } $word_ids_by_word[$word_id['id_shop']][$word_id['id_lang']]['_' . $word_id['word']] = (int) $word_id['id_word']; } // Retrieve the number of languages $total_languages = count(Language::getLanguages(false)); // Products are processed 50 by 50 in order to avoid overloading MySQL while (($products = Search::getProductsToIndex($total_languages, $id_product, 50)) && count($products) > 0) { $products_array = array(); // Now each non-indexed product is processed one by one, langage by langage foreach ($products as $product) { $product['tags'] = Search::getTags($db, (int) $product['id_product'], (int) $product['id_lang']); $product['attributes'] = Search::getAttributes($db, (int) $product['id_product'], (int) $product['id_lang']); $product['features'] = Search::getFeatures($db, (int) $product['id_product'], (int) $product['id_lang']); // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array $product_array = array(); foreach ($product as $key => $value) { if (strncmp($key, 'id_', 3) && isset($weight_array[$key])) { $words = explode(' ', Search::sanitize($value, (int) $product['id_lang'], true, $product['iso_code'])); foreach ($words as $word) { if (!empty($word)) { $word = Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH); // Remove accents $word = Tools::replaceAccentedChars($word); if (!isset($product_array[$word])) { $product_array[$word] = 0; } $product_array[$word] += $weight_array[$key]; } } } } // If we find words that need to be indexed, they're added to the word table in the database if (count($product_array)) { $query_array = $query_array2 = array(); foreach ($product_array as $word => $weight) { if ($weight && !isset($word_ids_by_word['_' . $word])) { $query_array[$word] = '(' . (int) $product['id_lang'] . ', ' . (int) $product['id_shop'] . ', \'' . pSQL($word) . '\')'; $query_array2[] = '\'' . pSQL($word) . '\''; $word_ids_by_word[$product['id_shop']][$product['id_lang']]['_' . $word] = 0; } } if ($query_array2) { $existing_words = $db->executeS(' SELECT DISTINCT word FROM ' . _DB_PREFIX_ . 'search_word WHERE word IN (' . implode(',', $query_array2) . ') AND id_lang = ' . (int) $product['id_lang'] . ' AND id_shop = ' . (int) $product['id_shop']); foreach ($existing_words as $data) { unset($query_array[Tools::replaceAccentedChars($data['word'])]); } } if (count($query_array)) { // The words are inserted... $db->execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'search_word (id_lang, id_shop, word) VALUES ' . implode(',', $query_array)); } if (count($query_array2)) { // ...then their IDs are retrieved and added to the cache $added_words = $db->executeS(' SELECT sw.id_word, sw.word FROM ' . _DB_PREFIX_ . 'search_word sw WHERE sw.word IN (' . implode(',', $query_array2) . ') AND sw.id_lang = ' . (int) $product['id_lang'] . ' AND sw.id_shop = ' . (int) $product['id_shop'] . ' LIMIT ' . count($query_array2)); // replace accents from the retrieved words so that words without accents or with differents accents can still be linked foreach ($added_words as $word_id) { $word_ids_by_word[$product['id_shop']][$product['id_lang']]['_' . Tools::replaceAccentedChars($word_id['word'])] = (int) $word_id['id_word']; } } } foreach ($product_array as $word => $weight) { if (!$weight) { continue; } if (!isset($word_ids_by_word[$product['id_shop']][$product['id_lang']]['_' . $word])) { continue; } if (!$word_ids_by_word[$product['id_shop']][$product['id_lang']]['_' . $word]) { continue; } $query_array3[] = '(' . (int) $product['id_product'] . ',' . (int) $word_ids_by_word[$product['id_shop']][$product['id_lang']]['_' . $word] . ',' . (int) $weight . ')'; // Force save every 200 words in order to avoid overloading MySQL if (++$count_words % 200 == 0) { Search::saveIndex($query_array3); } } if (!in_array($product['id_product'], $products_array)) { $products_array[] = (int) $product['id_product']; } } Search::setProductsAsIndexed($products_array); // One last save is done at the end in order to save what's left Search::saveIndex($query_array3); } return true; }
public static function indexation($full = false, $id_product = false) { $db = Db::getInstance(); if ($id_product) { $full = false; } if ($full && Context::getContext()->shop->getContext() == Shop::CONTEXT_SHOP) { $db->execute('DELETE si, sw FROM `' . _DB_PREFIX_ . 'search_index` si INNER JOIN `' . _DB_PREFIX_ . 'product` p ON (p.id_product = si.id_product) ' . Shop::addSqlAssociation('product', 'p') . ' INNER JOIN `' . _DB_PREFIX_ . 'search_word` sw ON (sw.id_word = si.id_word AND product_shop.id_shop = sw.id_shop) WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1'); $db->execute('UPDATE `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' SET p.`indexed` = 0, product_shop.`indexed` = 0 WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1 '); } elseif ($full) { $db->execute('TRUNCATE ' . _DB_PREFIX_ . 'search_index'); $db->execute('TRUNCATE ' . _DB_PREFIX_ . 'search_word'); ObjectModel::updateMultishopTable('Product', array('indexed' => 0)); } else { $db->execute('DELETE si FROM `' . _DB_PREFIX_ . 'search_index` si INNER JOIN `' . _DB_PREFIX_ . 'product` p ON (p.id_product = si.id_product) ' . Shop::addSqlAssociation('product', 'p') . ' WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1 AND ' . ($id_product ? 'p.`id_product` = ' . (int) $id_product : 'product_shop.`indexed` = 0')); $db->execute('UPDATE `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' SET p.`indexed` = 0, product_shop.`indexed` = 0 WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1 AND ' . ($id_product ? 'p.`id_product` = ' . (int) $id_product : 'product_shop.`indexed` = 0')); } // Every fields are weighted according to the configuration in the backend $weight_array = array('pname' => Configuration::get('PS_SEARCH_WEIGHT_PNAME'), 'reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'pa_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'supplier_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'pa_supplier_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'pa_ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'pa_upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'description_short' => Configuration::get('PS_SEARCH_WEIGHT_SHORTDESC'), 'description' => Configuration::get('PS_SEARCH_WEIGHT_DESC'), 'cname' => Configuration::get('PS_SEARCH_WEIGHT_CNAME'), 'mname' => Configuration::get('PS_SEARCH_WEIGHT_MNAME'), 'tags' => Configuration::get('PS_SEARCH_WEIGHT_TAG'), 'attributes' => Configuration::get('PS_SEARCH_WEIGHT_ATTRIBUTE'), 'features' => Configuration::get('PS_SEARCH_WEIGHT_FEATURE')); // Those are kind of global variables required to save the processed data in the database every X occurrences, in order to avoid overloading MySQL $count_words = 0; $query_array3 = array(); // Retrieve the number of languages $total_languages = count(Language::getIDs(false)); $sql_attribute = Search::getSQLProductAttributeFields($weight_array); // Products are processed 50 by 50 in order to avoid overloading MySQL while (($products = Search::getProductsToIndex($total_languages, $id_product, 50, $weight_array)) && count($products) > 0) { $products_array = array(); // Now each non-indexed product is processed one by one, langage by langage foreach ($products as $product) { if ((int) $weight_array['tags']) { $product['tags'] = Search::getTags($db, (int) $product['id_product'], (int) $product['id_lang']); } if ((int) $weight_array['attributes']) { $product['attributes'] = Search::getAttributes($db, (int) $product['id_product'], (int) $product['id_lang']); } if ((int) $weight_array['features']) { $product['features'] = Search::getFeatures($db, (int) $product['id_product'], (int) $product['id_lang']); } if ($sql_attribute) { $attribute_fields = Search::getAttributesFields($db, (int) $product['id_product'], $sql_attribute); if ($attribute_fields) { $product['attributes_fields'] = $attribute_fields; } } // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array $product_array = array(); foreach ($product as $key => $value) { if ($key == 'attributes_fields') { foreach ($value as $pa_array) { foreach ($pa_array as $pa_key => $pa_value) { Search::fillProductArray($product_array, $weight_array, $pa_key, $pa_value, $product['id_lang'], $product['iso_code']); } } } else { Search::fillProductArray($product_array, $weight_array, $key, $value, $product['id_lang'], $product['iso_code']); } } // If we find words that need to be indexed, they're added to the word table in the database if (is_array($product_array) && !empty($product_array)) { $query_array = $query_array2 = array(); foreach ($product_array as $word => $weight) { if ($weight) { $query_array[$word] = '(' . (int) $product['id_lang'] . ', ' . (int) $product['id_shop'] . ', \'' . pSQL($word) . '\')'; $query_array2[] = '\'' . pSQL($word) . '\''; } } if (is_array($query_array) && !empty($query_array)) { // The words are inserted... $db->execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'search_word (id_lang, id_shop, word) VALUES ' . implode(',', $query_array), false); } $word_ids_by_word = array(); if (is_array($query_array2) && !empty($query_array2)) { // ...then their IDs are retrieved $added_words = $db->executeS(' SELECT sw.id_word, sw.word FROM ' . _DB_PREFIX_ . 'search_word sw WHERE sw.word IN (' . implode(',', $query_array2) . ') AND sw.id_lang = ' . (int) $product['id_lang'] . ' AND sw.id_shop = ' . (int) $product['id_shop'], true, false); foreach ($added_words as $word_id) { $word_ids_by_word['_' . $word_id['word']] = (int) $word_id['id_word']; } } } foreach ($product_array as $word => $weight) { if (!$weight) { continue; } if (!isset($word_ids_by_word['_' . $word])) { continue; } $id_word = $word_ids_by_word['_' . $word]; if (!$id_word) { continue; } $query_array3[] = '(' . (int) $product['id_product'] . ',' . (int) $id_word . ',' . (int) $weight . ')'; // Force save every 200 words in order to avoid overloading MySQL if (++$count_words % 200 == 0) { Search::saveIndex($query_array3); } } $products_array[] = (int) $product['id_product']; } $products_array = array_unique($products_array); Search::setProductsAsIndexed($products_array); // One last save is done at the end in order to save what's left Search::saveIndex($query_array3); } return true; }
public static function indexation($full = false) { $db = Db::getInstance(); $dropIndex = false; if ($full) { $db->Execute('TRUNCATE ' . _DB_PREFIX_ . 'search_index'); $db->Execute('TRUNCATE ' . _DB_PREFIX_ . 'search_word'); $db->Execute('UPDATE ' . _DB_PREFIX_ . 'product SET indexed = 0'); $dropIndex = true; } else { $products = $db->ExecuteS('SELECT id_product FROM ' . _DB_PREFIX_ . 'product WHERE indexed = 0'); $ids = array(); if ($products) { foreach ($products as $product) { $ids[] = (int) $product['id_product']; } } if (sizeof($ids)) { //$db->Execute('DELETE FROM '._DB_PREFIX_.'search_index WHERE id_product IN ('.implode(',', $ids).')'); //reindex the products in solr index SolrSearch::updateProducts($ids); $products = $db->ExecuteS('UPDATE ' . _DB_PREFIX_ . 'product set indexed = 1 WHERE indexed = 0'); } if (count($ids)) { Db::getInstance()->Execute('UPDATE ' . _DB_PREFIX_ . 'product SET indexed = 1 WHERE id_product IN (' . implode(',', $ids) . ') LIMIT ' . (int) count($ids)); } if (count($products) > 2000) { $dropIndex = true; } } //do not do anything to the db index return; if ($dropIndex) { $dropIndex = false; $result = $db->ExecuteS('SHOW INDEX FROM `' . _DB_PREFIX_ . 'search_index`'); foreach ($result as $row) { if (strtolower($row['Key_name']) == 'primary') { $dropIndex = true; } } if ($dropIndex) { $db->Execute('ALTER TABLE ' . _DB_PREFIX_ . 'search_index DROP PRIMARY KEY'); } $dropIndex = true; } // Every fields are weighted according to the configuration in the backend $weightArray = array('pname' => Configuration::get('PS_SEARCH_WEIGHT_PNAME'), 'reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'description_short' => Configuration::get('PS_SEARCH_WEIGHT_SHORTDESC'), 'description' => Configuration::get('PS_SEARCH_WEIGHT_DESC'), 'cname' => Configuration::get('PS_SEARCH_WEIGHT_CNAME'), 'mname' => Configuration::get('PS_SEARCH_WEIGHT_MNAME'), 'tags' => Configuration::get('PS_SEARCH_WEIGHT_TAG'), 'attributes' => Configuration::get('PS_SEARCH_WEIGHT_ATTRIBUTE'), 'features' => Configuration::get('PS_SEARCH_WEIGHT_FEATURE')); // All the product not yet indexed are retrieved $products = $db->ExecuteS(' SELECT p.id_product, pl.id_lang, pl.name pname, p.reference, p.ean13, p.upc, pl.description_short, pl.description, cl.name cname, m.name mname FROM ' . _DB_PREFIX_ . 'product p LEFT JOIN ' . _DB_PREFIX_ . 'product_lang pl ON p.id_product = pl.id_product LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON (cl.id_category = p.id_category_default AND pl.id_lang = cl.id_lang) LEFT JOIN ' . _DB_PREFIX_ . 'manufacturer m ON m.id_manufacturer = p.id_manufacturer WHERE p.indexed = 0', false); // Those are kind of global variables required to save the processed data in the database every X occurences, in order to avoid overloading MySQL $countWords = 0; $countProducts = 0; $queryArray3 = array(); $productsArray = array(); // Every indexed words are cached into a PHP array $wordIdsByWord = array(); $wordIds = Db::getInstance()->ExecuteS(' SELECT sw.id_word, sw.word, id_lang FROM ' . _DB_PREFIX_ . 'search_word sw', false); $wordIdsByWord = array(); while ($wordId = $db->nextRow($wordIds)) { if (!isset($wordIdsByWord[$wordId['id_lang']])) { $wordIdsByWord[$wordId['id_lang']] = array(); } $wordIdsByWord[$wordId['id_lang']]['_' . $wordId['word']] = (int) $wordId['id_word']; } // Now each non-indexed product is processed one by one, langage by langage while ($product = $db->nextRow($products)) { $product['tags'] = Search::getTags($db, (int) $product['id_product'], (int) $product['id_lang']); $product['attributes'] = Search::getAttributes($db, (int) $product['id_product'], (int) $product['id_lang']); $product['features'] = Search::getFeatures($db, (int) $product['id_product'], (int) $product['id_lang']); // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array $pArray = array(); foreach ($product as $key => $value) { if (strncmp($key, 'id_', 3)) { $words = explode(' ', Search::sanitize($value, (int) $product['id_lang'], true)); foreach ($words as $word) { if (!empty($word)) { $word = Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH); if (!isset($pArray[$word])) { $pArray[$word] = 0; } $pArray[$word] += $weightArray[$key]; } } } } // If we find words that need to be indexed, they're added to the word table in the database if (sizeof($pArray)) { $list = ''; foreach ($pArray as $word => $weight) { $list .= '\'' . $word . '\','; } $list = rtrim($list, ','); $queryArray = array(); $queryArray2 = array(); foreach ($pArray as $word => $weight) { if ($weight and !isset($wordIdsByWord['_' . $word])) { $queryArray[] = '(' . (int) $product['id_lang'] . ',\'' . pSQL($word) . '\')'; $queryArray2[] = '\'' . pSQL($word) . '\''; $wordIdsByWord[$product['id_lang']]['_' . $word] = 0; } } if (count($queryArray)) { // The words are inserted... $db->Execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'search_word (id_lang, word) VALUES ' . implode(',', $queryArray)); // ...then their IDs are retrieved and added to the cache $addedWords = $db->ExecuteS(' SELECT sw.id_word, sw.word FROM ' . _DB_PREFIX_ . 'search_word sw WHERE sw.word IN (' . implode(',', $queryArray2) . ') AND sw.id_lang = ' . (int) $product['id_lang'] . ' LIMIT ' . count($queryArray2)); foreach ($addedWords as $wordId) { $wordIdsByWord[$product['id_lang']]['_' . $wordId['word']] = (int) $wordId['id_word']; } } } foreach ($pArray as $word => $weight) { if (!$weight) { continue; } if (!isset($wordIdsByWord[$product['id_lang']]['_' . $word])) { continue; } if (!$wordIdsByWord[$product['id_lang']]['_' . $word]) { continue; } $queryArray3[] = '(' . (int) $product['id_product'] . ',' . (int) $wordIdsByWord[$product['id_lang']]['_' . $word] . ',' . (int) $weight . ')'; // Force save every 200 words in order to avoid overloading MySQL if (++$countWords % 200 == 0) { Search::saveIndex($queryArray3); } } if (!in_array($product['id_product'], $productsArray)) { $productsArray[] = (int) $product['id_product']; } // Force save every 50 products in order to avoid overloading MySQL if (++$countProducts % 50 == 0) { Search::setProductsAsIndexed($productsArray); } } // One last save is done at the end in order to save what's left Search::saveIndex($queryArray3); Search::setProductsAsIndexed($productsArray); // If it has been deleted, the index is created again once the indexation is done if (!$dropIndex) { $dropIndex = true; $result = $db->ExecuteS('SHOW INDEX FROM `' . _DB_PREFIX_ . 'search_index`'); foreach ($result as $row) { if (strtolower($row['Key_name']) == 'primary') { $dropIndex = false; } } } if ($dropIndex) { $db->Execute('ALTER TABLE `' . _DB_PREFIX_ . 'search_index` ADD PRIMARY KEY (`id_word`, `id_product`)'); } Configuration::updateValue('PS_NEED_REBUILD_INDEX', 0); return true; }
public static function indexation($full = false) { $db = Db::getInstance(); if ($full) { $db->Execute('TRUNCATE ' . _DB_PREFIX_ . 'search_index'); $db->Execute('TRUNCATE ' . _DB_PREFIX_ . 'search_word'); $db->Execute('UPDATE ' . _DB_PREFIX_ . 'product SET indexed = 0'); } else { $products = $db->ExecuteS('SELECT id_product FROM ' . _DB_PREFIX_ . 'product WHERE indexed = 0'); $ids = array(); if ($products) { foreach ($products as $product) { $ids[] = (int) $product['id_product']; } } if (sizeof($ids)) { $db->Execute('DELETE FROM ' . _DB_PREFIX_ . 'search_index WHERE id_product IN (' . implode(',', $ids) . ')'); } } $weightArray = array('pname' => Configuration::get('PS_SEARCH_WEIGHT_PNAME'), 'reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), 'description_short' => Configuration::get('PS_SEARCH_WEIGHT_SHORTDESC'), 'description' => Configuration::get('PS_SEARCH_WEIGHT_DESC'), 'cname' => Configuration::get('PS_SEARCH_WEIGHT_CNAME'), 'mname' => Configuration::get('PS_SEARCH_WEIGHT_MNAME'), 'tags' => Configuration::get('PS_SEARCH_WEIGHT_TAG'), 'attributes' => Configuration::get('PS_SEARCH_WEIGHT_ATTRIBUTE'), 'features' => Configuration::get('PS_SEARCH_WEIGHT_FEATURE')); $products = $db->ExecuteS(' SELECT p.id_product, pl.id_lang, pl.name pname, p.reference, p.ean13, p.upc, pl.description_short, pl.description, cl.name cname, m.name mname FROM ' . _DB_PREFIX_ . 'product p LEFT JOIN ' . _DB_PREFIX_ . 'product_lang pl ON p.id_product = pl.id_product LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON (cl.id_category = p.id_category_default AND pl.id_lang = cl.id_lang) LEFT JOIN ' . _DB_PREFIX_ . 'manufacturer m ON m.id_manufacturer = p.id_manufacturer WHERE p.indexed = 0', false); $countWords = 0; $countProducts = 0; $queryArray = array(); $queryArray2 = array(); $productsArray = array(); while ($product = $db->nextRow($products)) { $product['tags'] = Search::getTags($db, (int) $product['id_product'], (int) $product['id_lang']); $product['attributes'] = Search::getAttributes($db, (int) $product['id_product'], (int) $product['id_lang']); $product['features'] = Search::getFeatures($db, (int) $product['id_product'], (int) $product['id_lang']); $pArray = array(); foreach ($product as $key => $value) { if (strncmp($key, 'id_', 3)) { $words = explode(' ', Search::sanitize($value, (int) $product['id_lang'], true)); foreach ($words as $word) { if (!empty($word)) { $word = Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH); if (!isset($pArray[$word])) { $pArray[$word] = $weightArray[$key]; } else { $pArray[$word] += $weightArray[$key]; } } } } } foreach ($pArray as $word => $weight) { if (!$weight) { continue; } $queryArray[] = '(' . (int) $product['id_lang'] . ',\'' . pSQL($word) . '\')'; $queryArray2[] = '(' . (int) $product['id_product'] . ',(SELECT id_word FROM ' . _DB_PREFIX_ . 'search_word WHERE word = \'' . pSQL($word) . '\' AND id_lang = ' . (int) $product['id_lang'] . ' LIMIT 1),' . (int) $weight . ')'; // Force save every 40 words in order to avoid overloading MySQL if (++$countWords % 40 == 0) { Search::saveIndex($queryArray, $queryArray2); } } if (!in_array($product['id_product'], $productsArray)) { $productsArray[] = (int) $product['id_product']; } // Force save every 20 products in order to avoid overloading MySQL if (++$countProducts % 20 == 0) { Search::setProductsAsIndexed($productsArray); $productsArray = array(); } } // One last save is done at the end in order to save what's left Search::saveIndex($queryArray, $queryArray2); Search::setProductsAsIndexed($productsArray); $db->Execute('DELETE FROM ' . _DB_PREFIX_ . 'search_word WHERE id_word NOT IN (SELECT id_word FROM ' . _DB_PREFIX_ . 'search_index)'); return true; }