Exemplo n.º 1
0
 public static function indexation($full = false, $product_id = false)
 {
     $db = JFactory::getDBO();
     if ($product_id) {
         $full = false;
     }
     if ($full) {
         $db->execute('TRUNCATE ' . $db->quoteName('#__jeproshop_search_index'));
         $db->execute('TRUNCATE ' . $db->quoteName('#__jeproshop_search_word'));
         self::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
         $query = "SELECT product.product_id FROM " . $db->quoteName('#__jeproshop_product') . " AS product ";
         $query .= JeproshopShopModelShop::addSqlAssociation('product') . " WHERE product_shop.visibility IN (\"both\", \"search\") ";
         $query .= " AND product_shop." . $db->quoteName('published') . " = 1 AND ";
         $query .= $product_id ? "product.product_id = " . (int) $product_id : "product_shop.indexed = 0";
         $db->setQuery($query);
         $products = $db->loadObjectList();
         $ids = array();
         if ($products) {
             foreach ($products as $product) {
                 $ids[] = (int) $product->product_id;
             }
         }
         if (count($ids)) {
             $query = "DELETE FROM " . $db->quoteName('#__jeproshop_search_index') . " WHERE product_id IN (" . implode(',', $ids) . ")";
             $db->setQuery($query);
             $db->query();
             $data = " SET product." . $db->quoteName('indexed') . " = 0";
             $where = ' WHERE product.product_id IN (' . implode(',', $ids) . ')';
             JeproshopProductModelProduct::updateMultishopTable($data, $where, '', true);
         }
     }
     // Every fields are weighted according to the configuration in the backend
     $weight_array = array('product_name' => JeproshopSettingModelSetting::getValue('search_weight_product_name'), 'reference' => JeproshopSettingModelSetting::getValue('search_weight_reference'), 'product_attribute_reference' => JeproshopSettingModelSetting::getValue('search_weight_reference'), 'ean13' => JeproshopSettingModelSetting::getValue('search_weight_reference'), 'upc' => JeproshopSettingModelSetting::getValue('search_weight_reference'), 'short_description' => JeproshopSettingModelSetting::getValue('search_weight_short_description'), 'description' => JeproshopSettingModelSetting::getValue('search_weight_description'), 'category_name' => JeproshopSettingModelSetting::getValue('search_weight_category_name'), 'manufacture_name' => JeproshopSettingModelSetting::getValue('search_weight_manufacturer_name'), 'tag' => JeproshopSettingModelSetting::getValue('search_weight_tag'), 'attributes' => JeproshopSettingModelSetting::getValue('search_weight_attribute'), 'features' => JeproshopSettingModelSetting::getValue('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
     $query = "SELECT word_id, word, lang_id, shop_id FROM " . $db->quoteName('#__jeproshop_search_word');
     $db->setQuery($query);
     $word_ids = $db->loadObjectList();
     $word_ids_by_word = array();
     while ($word_id = $db->nextRow($word_ids)) {
         if (!isset($word_ids_by_word[$word_id->shop_id][$word_id->lang_id])) {
             $word_ids_by_word[$word_id['id_shop']][$word_id['id_lang']] = array();
         }
         $word_ids_by_word[$word_id->shop_id][$word_id->lang_id]['_' . $word_id->word] = (int) $word_id->word_id;
     }
     // Retrieve the number of languages
     $total_languages = count(JeproshopLanguageModelLanguage::getLanguages(false));
     // Products are processed 50 by 50 in order to avoid overloading MySQL
     while (($products = JeproshopSearch::getProductsToIndex($total_languages, $product_id, 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['tag']) {
                 $product->tags = JeproshopSearch::getTags($db, (int) $product->product_id, (int) $product->lang_id);
             }
             if ((int) $weight_array['attributes']) {
                 $product->attributes = JeproshopSearch::getAttributes($db, (int) $product->product_id, (int) $product->lang_id);
             }
             if ((int) $weight_array['features']) {
                 $product->features = JeproshopSearch::getFeatures($db, (int) $product->product_id, (int) $product->lang_id);
             }
             // 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(' ', JeproshopSearch::sanitize($value, (int) $product->lang_id, true, JeproshopContext::getContext()->language->iso_code));
                     foreach ($words as $word) {
                         if (!empty($word)) {
                             $word = substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH);
                             // Remove accents
                             $word = JeproshopValidator::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->lang_id . ', ' . (int) $product->shop_id . ', ' . $db->quote($word) . ')';
                         $query_array2[] = $db->quote($word);
                         $word_ids_by_word[$product->shop_id][$product->lang_id]['_' . $word] = 0;
                     }
                 }
                 if ($query_array2) {
                     $query = "SELECT DISTINCT word FROM " . $db->quoteName('#__jeproshop_search_word') . " WHERE word IN (";
                     $query .= implode(',', $query_array2) . ") AND lang_id = " . (int) $product->lang_id . " AND shop_id = " . (int) $product->shop_id;
                     $db->setQuery($query);
                     $existing_words = $db->loadObjectList();
                     foreach ($existing_words as $data) {
                         unset($query_array[JeproshopValidator::replaceAccentedChars($data->word)]);
                     }
                 }
                 if (count($query_array)) {
                     // The words are inserted...
                     $query = "INSERT IGNORE INTO " . $db->quoteName('#__jeproshop_search_word') . " (lang_id, shop_id, word) VALUES " . implode(',', $query_array);
                     $db->setQuery($query);
                     $db->query();
                 }
                 if (count($query_array2)) {
                     // ...then their IDs are retrieved and added to the cache
                     $query = "SELECT search_word.word_id, search_word.word FROM " . $db->quoteName('#__jeproshop_search_word') . " AS search_word ";
                     $query .= " WHERE search_word.word IN (" . implode(',', $query_array2) . ") AND search_word.lang_id = " . (int) $product->lang_id;
                     $query .= " AND search_word.shop_id = " . (int) $product->shop_id . " LIMIT " . count($query_array2);
                     $db->setQuery($query);
                     $added_words = $db->loadObjectList();
                     // 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->shop_id][$product->lang_id]['_' . JeproshopValidator::replaceAccentedChars($word_id->word)] = (int) $word_id->word_id;
                     }
                 }
             }
             foreach ($product_array as $word => $weight) {
                 if (!$weight) {
                     continue;
                 }
                 if (!isset($word_ids_by_word[$product->shop_id][$product->lang_id]['_' . $word])) {
                     continue;
                 }
                 if (!$word_ids_by_word[$product->shop_id][$product->lang_id]['_' . $word]) {
                     continue;
                 }
                 $query_array3[] = '(' . (int) $product->product_id . ',' . (int) $word_ids_by_word[$product->shop_id][$product->lang_id]['_' . $word] . ',' . (int) $weight . ')';
                 // Force save every 200 words in order to avoid overloading MySQL
                 if (++$count_words % 200 == 0) {
                     JeproshopSearch::saveIndex($query_array3);
                 }
             }
             if (!in_array($product->product_id, $products_array)) {
                 $products_array[] = (int) $product->product_id;
             }
         }
         JeproshopSearch::setProductsAsIndexed($products_array);
         // One last save is done at the end in order to save what's left
         JeproshopSearch::saveIndex($query_array3);
     }
     return true;
 }