Mage_CatalogSearch_Model_Mysql4_Fulltext Class Reference

Inheritance diagram for Mage_CatalogSearch_Model_Mysql4_Fulltext:

Mage_Core_Model_Mysql4_Abstract Mage_Core_Model_Resource_Abstract

List of all members.

Public Member Functions

 rebuildIndex ($storeId=null, $productIds=null)
 resetSearchResults ()
 cleanIndex ($storeId=null, $productId=null)
 prepareResult ($object, $queryText, $query)
 getEavConfig ()

Protected Member Functions

 _construct ()
 _rebuildStoreIndex ($storeId, $productIds=null)
 _getSearchableProducts ($storeId, array $staticFields, $productIds=null, $lastProductId=0, $limit=100)
 _getSearchableAttributes ($backendType=null)
 _getSearchableAttribute ($attribute)
 _getProductAttributes ($storeId, array $productIds, array $atributeTypes)
 _getProductTypeInstance ($typeId)
 _getProductChildIds ($productId, $typeId)
 _getProductEmulator ()
 _prepareProductIndex ($indexData, $productData, $storeId)
 _getAttributeValue ($attributeId, $value, $storeId)
 _saveProductIndex ($productId, $storeId, $index)
 _saveProductIndexes ($storeId, $productIndexes)

Protected Attributes

 $_searchableAttributes = null
 $_separator = ' '
 $_productTypes = array()


Detailed Description

Definition at line 34 of file Fulltext.php.


Member Function Documentation

_construct (  )  [protected]

Init resource model

Reimplemented from Mage_Core_Model_Resource_Abstract.

Definition at line 60 of file Fulltext.php.

00061     {
00062         $this->_init('catalogsearch/fulltext', 'product_id');
00063     }

_getAttributeValue ( attributeId,
value,
storeId 
) [protected]

Retrieve attribute source value for search

Parameters:
int $attributeId
mixed $value
Returns:
mixed

Definition at line 538 of file Fulltext.php.

00539     {
00540         $attribute = $this->_getSearchableAttribute($attributeId);
00541         if (!$attribute->getIsSearchable()) {
00542             return null;
00543         }
00544         if ($attribute->usesSource()) {
00545             $attribute->setStoreId($storeId);
00546             $value = $attribute->getSource()->getOptionText($value);
00547         }
00548 
00549         if (is_array($value)) {
00550             $value = implode($this->_separator, $value);
00551         }
00552 
00553         return preg_replace("#\s+#si", " ", trim(strip_tags($value)));
00554     }

_getProductAttributes ( storeId,
array productIds,
array atributeTypes 
) [protected]

Load product(s) attributes

Parameters:
int $storeId
array $productIds
array $atributeTypes
Returns:
array

Definition at line 403 of file Fulltext.php.

00404     {
00405         $result  = array();
00406         $selects = array();
00407         foreach ($atributeTypes as $backendType => $attributeIds) {
00408             if ($attributeIds) {
00409                 $tableName = $this->getTable('catalog/product') . '_' . $backendType;
00410                 $selects[] = $this->_getReadAdapter()->select()
00411                     ->from(
00412                         array('t_default' => $tableName),
00413                         array('entity_id', 'attribute_id'))
00414                     ->joinLeft(
00415                         array('t_store' => $tableName),
00416                         $this->_getReadAdapter()->quoteInto("t_default.entity_id=t_store.entity_id AND t_default.attribute_id=t_store.attribute_id AND t_store.store_id=?", $storeId),
00417                         array('value'=>'IFNULL(t_store.value, t_default.value)'))
00418                     ->where('t_default.store_id=?', 0)
00419                     ->where('t_default.attribute_id IN(?)', $attributeIds)
00420                     ->where('t_default.entity_id IN(?)', $productIds);
00421             }
00422         }
00423 
00424         if ($selects) {
00425             $select = '('.join(')UNION(', $selects).')';
00426             $query = $this->_getReadAdapter()->query($select);
00427             while ($row = $query->fetch()) {
00428                 $result[$row['entity_id']][$row['attribute_id']] = $row['value'];
00429             }
00430         }
00431 
00432         return $result;
00433     }

_getProductChildIds ( productId,
typeId 
) [protected]

Return all product children ids

Parameters:
int $productId Product Entity Id
string $typeId Super Product Link Type
Returns:
array

Definition at line 460 of file Fulltext.php.

00461     {
00462         $typeInstance = $this->_getProductTypeInstance($typeId);
00463         $relation = $typeInstance->isComposite()
00464             ? $typeInstance->getRelationInfo()
00465             : false;
00466 
00467         if ($relation && $relation->getTable() && $relation->getParentFieldName() && $relation->getChildFieldName()) {
00468             $select = $this->_getReadAdapter()->select()
00469                 ->from(
00470                     array('main' => $this->getTable($relation->getTable())),
00471                     array($relation->getChildFieldName()))
00472                 ->where("{$relation->getParentFieldName()}=?", $productId);
00473             if (!is_null($relation->getWhere())) {
00474                 $select->where($relation->getWhere());
00475             }
00476             return $this->_getReadAdapter()->fetchCol($select);
00477         }
00478 
00479         return null;
00480     }

_getProductEmulator (  )  [protected]

Retrieve Product Emulator (Varien Object)

Returns:
Varien_Object

Definition at line 487 of file Fulltext.php.

00488     {
00489         $productEmulator = new Varien_Object();
00490         $productEmulator->setIdFieldName('entity_id');
00491         return $productEmulator;
00492     }

_getProductTypeInstance ( typeId  )  [protected]

Retrieve Product Type Instance

Parameters:
string $typeId
Returns:
Mage_Catalog_Model_Product_Type_Abstract

Definition at line 441 of file Fulltext.php.

00442     {
00443         if (!isset($this->_productTypes[$typeId])) {
00444             $productEmulator = $this->_getProductEmulator();
00445             $productEmulator->setTypeId($typeId);
00446 
00447             $this->_productTypes[$typeId] = Mage::getSingleton('catalog/product_type')
00448                 ->factory($productEmulator);
00449         }
00450         return $this->_productTypes[$typeId];
00451     }

_getSearchableAttribute ( attribute  )  [protected]

Retrieve searchable attribute by Id or code

Parameters:
int|string $attribute
Returns:
Mage_Eav_Model_Entity_Attribute

Definition at line 376 of file Fulltext.php.

00377     {
00378         $attributes = $this->_getSearchableAttributes();
00379         if (is_numeric($attribute)) {
00380             if (isset($attributes[$attribute])) {
00381                 return $attributes[$attribute];
00382             }
00383         }
00384         elseif (is_string($attribute)) {
00385             foreach ($attributes as $attributeModel) {
00386                 if ($attributeModel->getAttributeCode() == $attribute) {
00387                     return $attributeModel;
00388                 }
00389             }
00390         }
00391         return $this->getEavConfig()->getAttribute('catalog_product', $attribute);
00392     }

_getSearchableAttributes ( backendType = null  )  [protected]

Retrieve Searchable attributes

Returns:
array

Definition at line 332 of file Fulltext.php.

00333     {
00334         if (is_null($this->_searchableAttributes)) {
00335             $this->_searchableAttributes = array();
00336             $entityType = $this->getEavConfig()->getEntityType('catalog_product');
00337             $entity     = $entityType->getEntity();
00338 
00339             $whereCond  = array(
00340                 $this->_getReadAdapter()->quoteInto('is_searchable=?', 1),
00341                 $this->_getReadAdapter()->quoteInto('attribute_code IN(?)', array('status', 'visibility'))
00342             );
00343 
00344             $select = $this->_getReadAdapter()->select()
00345                 ->from($this->getTable('eav/attribute'))
00346                 ->where('entity_type_id=?', $entityType->getEntityTypeId())
00347                 ->where(join(' OR ', $whereCond));
00348             $attributesData = $this->_getReadAdapter()->fetchAll($select);
00349             $this->getEavConfig()->importAttributesData($entityType, $attributesData);
00350             foreach ($attributesData as $attributeData) {
00351                 $attributeCode = $attributeData['attribute_code'];
00352                 $attribute = $this->getEavConfig()->getAttribute($entityType, $attributeCode);
00353                 $attribute->setEntity($entity);
00354                 $this->_searchableAttributes[$attribute->getId()] = $attribute;
00355             }
00356             unset($attributesData);
00357         }
00358         if (!is_null($backendType)) {
00359             $attributes = array();
00360             foreach ($this->_searchableAttributes as $attribute) {
00361                 if ($attribute->getBackendType() == $backendType) {
00362                     $attributes[$attribute->getId()] = $attribute;
00363                 }
00364             }
00365             return $attributes;
00366         }
00367         return $this->_searchableAttributes;
00368     }

_getSearchableProducts ( storeId,
array staticFields,
productIds = null,
lastProductId = 0,
limit = 100 
) [protected]

Retrieve searchable products per store

Parameters:
int $storeId
array $staticFields
array|int $productIds
int $lastProductId
int $limit
Returns:
array

Definition at line 180 of file Fulltext.php.

00181     {
00182         $entityType = $this->getEavConfig()->getEntityType('catalog_product');
00183         $store      = Mage::app()->getStore($storeId);
00184 
00185         $select = $this->_getReadAdapter()->select()
00186             ->from(
00187                 array('e' => $this->getTable('catalog/product')),
00188                 array_merge(array('entity_id', 'type_id'), $staticFields))
00189             ->joinInner(
00190                 array('website' => $this->getTable('catalog/product_website')),
00191                 $this->_getReadAdapter()->quoteInto('website.product_id=e.entity_id AND website.website_id=?', $store->getWebsiteId()),
00192                 array()
00193             );
00194 
00195         if (!is_null($productIds)) {
00196             $select->where('e.entity_id IN(?)', $productIds);
00197         }
00198 
00199         $select->where('e.entity_id>?', $lastProductId)
00200             ->limit($limit)
00201             ->order('e.entity_id');
00202 
00203         return $this->_getReadAdapter()->fetchAll($select);
00204     }

_prepareProductIndex ( indexData,
productData,
storeId 
) [protected]

Prepare Fulltext index value for product

Parameters:
array $indexData
array $productData
Returns:
string

Definition at line 501 of file Fulltext.php.

00502     {
00503         $index = array();
00504         foreach ($this->_getSearchableAttributes('static') as $attribute) {
00505             if (isset($productData[$attribute->getAttributeCode()])) {
00506                 if ($value = $this->_getAttributeValue($attribute->getId(), $productData[$attribute->getAttributeCode()], $storeId)) {
00507                     $index[] = $value;
00508                 }
00509             }
00510         }
00511         foreach ($indexData as $attributeData) {
00512             foreach ($attributeData as $attributeId => $attributeValue) {
00513                 if ($value = $this->_getAttributeValue($attributeId, $attributeValue, $storeId)) {
00514                     $index[] = $value;
00515                 }
00516             }
00517         }
00518 
00519         $product = $this->_getProductEmulator()
00520             ->setId($productData['entity_id'])
00521             ->setTypeId($productData['type_id'])
00522             ->setStoreId($storeId);
00523         $typeInstance = $this->_getProductTypeInstance($productData['type_id']);
00524         if ($data = $typeInstance->getSearchableData($product)) {
00525             $index = array_merge($index, $data);
00526         }
00527 
00528         return join($this->_separator, $index);
00529     }

_rebuildStoreIndex ( storeId,
productIds = null 
) [protected]

Regenerate search index for specific store

Parameters:
int $storeId Store View Id
int|array $productIds Product Entity Id
Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 91 of file Fulltext.php.

00092     {
00093         $this->cleanIndex($storeId, $productIds);
00094 
00095         // preparesearchable attributes
00096         $staticFields   = array();
00097         foreach ($this->_getSearchableAttributes('static') as $attribute) {
00098             $staticFields[] = $attribute->getAttributeCode();
00099         }
00100         $dynamicFields  = array(
00101             'int'       => array_keys($this->_getSearchableAttributes('int')),
00102             'varchar'   => array_keys($this->_getSearchableAttributes('varchar')),
00103             'text'      => array_keys($this->_getSearchableAttributes('text')),
00104         );
00105 
00106         // status and visibility filter
00107         $visibility     = $this->_getSearchableAttribute('visibility');
00108         $status         = $this->_getSearchableAttribute('status');
00109         $visibilityVals = Mage::getSingleton('catalog/product_visibility')->getVisibleInSearchIds();
00110         $statusVals     = Mage::getSingleton('catalog/product_status')->getVisibleStatusIds();
00111 
00112         $lastProductId = 0;
00113         while (true) {
00114             $products = $this->_getSearchableProducts($storeId, $staticFields, $productIds, $lastProductId);
00115             if (!$products) {
00116                 break;
00117             }
00118 
00119             $productAttributes  = array();
00120             $productRelations   = array();
00121             foreach ($products as $productData) {
00122                 $lastProductId = $productData['entity_id'];
00123                 $productAttributes[$productData['entity_id']] = $productData['entity_id'];
00124                 $productChilds = $this->_getProductChildIds($productData['entity_id'], $productData['type_id']);
00125                 $productRelations[$productData['entity_id']] = $productChilds;
00126                 if ($productChilds) {
00127                     foreach ($productChilds as $productChildId) {
00128                         $productAttributes[$productChildId] = $productChildId;
00129                     }
00130                 }
00131             }
00132 
00133             $productIndexes     = array();
00134             $productAttributes  = $this->_getProductAttributes($storeId, $productAttributes, $dynamicFields);
00135             foreach ($products as $productData) {
00136                 if (!isset($productAttributes[$productData['entity_id']])) {
00137                     continue;
00138                 }
00139                 $protductAttr = $productAttributes[$productData['entity_id']];
00140                 if (!isset($protductAttr[$visibility->getId()]) || !in_array($protductAttr[$visibility->getId()], $visibilityVals)) {
00141                     continue;
00142                 }
00143                 if (!isset($protductAttr[$status->getId()]) || !in_array($protductAttr[$status->getId()], $statusVals)) {
00144                     continue;
00145                 }
00146 
00147                 $productIndex = array(
00148                     $productData['entity_id'] => $protductAttr
00149                 );
00150                 if ($productChilds = $productRelations[$productData['entity_id']]) {
00151                     foreach ($productChilds as $productChildId) {
00152                         if (isset($productAttributes[$productChildId])) {
00153                             $productIndex[$productChildId] = $productAttributes[$productChildId];
00154                         }
00155                     }
00156                 }
00157 
00158                 $index = $this->_prepareProductIndex($productIndex, $productData, $storeId);
00159                 $productIndexes[$productData['entity_id']] = $index;
00160                 //$this->_saveProductIndex($productData['entity_id'], $storeId, $index);
00161             }
00162             $this->_saveProductIndexes($storeId, $productIndexes);
00163         }
00164 
00165         $this->resetSearchResults();
00166 
00167         return $this;
00168     }

_saveProductIndex ( productId,
storeId,
index 
) [protected]

Save Product index

Parameters:
int $productId
int $storeId
string $index
Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 564 of file Fulltext.php.

00565     {
00566         $this->_getWriteAdapter()->insert($this->getMainTable(), array(
00567             'product_id'    => $productId,
00568             'store_id'      => $storeId,
00569             'data_index'    => $index
00570         ));
00571         return $this;
00572     }

_saveProductIndexes ( storeId,
productIndexes 
) [protected]

Save Multiply Product indexes

Parameters:
int $storeId
array $productIndexes
Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 581 of file Fulltext.php.

00582     {
00583         $values = array();
00584         $bind   = array();
00585         foreach ($productIndexes as $productId => &$index) {
00586             $values[] = sprintf('(%s,%s,%s)',
00587                 $this->_getWriteAdapter()->quoteInto('?', $productId),
00588                 $this->_getWriteAdapter()->quoteInto('?', $storeId),
00589                 '?'
00590             );
00591             $bind[] = $index;
00592         }
00593 
00594         if ($values) {
00595             $sql = "REPLACE INTO `{$this->getMainTable()}` VALUES"
00596                 . join(',', $values);
00597             $this->_getWriteAdapter()->query($sql, $bind);
00598         }
00599 
00600         return $this;
00601     }

cleanIndex ( storeId = null,
productId = null 
)

Delete search index data for store

Parameters:
int $storeId Store View Id
int $productId Product Entity Id
Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 237 of file Fulltext.php.

00238     {
00239         $where = array();
00240 
00241         if (!is_null($storeId)) {
00242             $where[] = $this->_getWriteAdapter()->quoteInto('store_id=?', $storeId);
00243         }
00244         if (!is_null($productId)) {
00245             $where[] = $this->_getWriteAdapter()->quoteInto('product_id IN(?)', $productId);
00246         }
00247 
00248         $this->_getWriteAdapter()->delete($this->getMainTable(), join(' AND ', $where));
00249         return $this;
00250     }

getEavConfig (  ) 

Retrieve EAV Config Singleton

Returns:
Mage_Eav_Model_Config

Definition at line 322 of file Fulltext.php.

00323     {
00324         return Mage::getSingleton('eav/config');
00325     }

prepareResult ( object,
queryText,
query 
)

Prepare results for query

Parameters:
Mage_CatalogSearch_Model_Fulltext $object
string $queryText
Mage_CatalogSearch_Model_Query $query
Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 260 of file Fulltext.php.

00261     {
00262         if (!$query->getIsProcessed()) {
00263             $searchType = $object->getSearchType($query->getStoreId());
00264 
00265             $stringHelper = Mage::helper('core/string');
00266             /* @var $stringHelper Mage_Core_Helper_String */
00267 
00268             $bind = array(
00269                 ':query'     => $queryText
00270             );
00271             $like = array();
00272 
00273             $fulltextCond   = '';
00274             $likeCond       = '';
00275             $separateCond   = '';
00276 
00277             if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE
00278                 || $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
00279                 $words = $stringHelper->splitWords($queryText, true, $query->getMaxQueryWords());
00280                 $likeI = 0;
00281                 foreach ($words as $word) {
00282                     $like[] = '`s`.`data_index` LIKE :likew' . $likeI;
00283                     $bind[':likew' . $likeI] = '%' . $word . '%';
00284                     $likeI ++;
00285                 }
00286                 if ($like) {
00287                     $likeCond = '(' . join(' AND ', $like) . ')';
00288                 }
00289             }
00290             if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_FULLTEXT
00291                 || $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
00292                 $fulltextCond = 'MATCH (`s`.`data_index`) AGAINST (:query IN BOOLEAN MODE)';
00293             }
00294             if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE && $likeCond) {
00295                 $separateCond = ' OR ';
00296             }
00297 
00298             $sql = sprintf("REPLACE INTO `{$this->getTable('catalogsearch/result')}` "
00299                 . "(SELECT '%d', `s`.`product_id`, MATCH (`s`.`data_index`) AGAINST (:query IN BOOLEAN MODE) "
00300                 . "FROM `{$this->getMainTable()}` AS `s` INNER JOIN `{$this->getTable('catalog/product')}` AS `e`"
00301                 . "ON `e`.`entity_id`=`s`.`product_id` WHERE (%s%s%s) AND `s`.`store_id`='%d')",
00302                 $query->getId(),
00303                 $fulltextCond,
00304                 $separateCond,
00305                 $likeCond,
00306                 $query->getStoreId()
00307             );
00308 
00309             $this->_getWriteAdapter()->query($sql, $bind);
00310 
00311             $query->setIsProcessed(1);
00312         }
00313 
00314         return $this;
00315     }

rebuildIndex ( storeId = null,
productIds = null 
)

Regenerate search index for store(s)

Parameters:
int $storeId Store View Id
int|array $productIds Product Entity Id(s)
Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 72 of file Fulltext.php.

00073     {
00074         if (is_null($storeId)) {
00075             foreach (Mage::app()->getStores(false) as $store) {
00076                 $this->_rebuildStoreIndex($store->getId(), $productIds);
00077             }
00078         } else {
00079             $this->_rebuildStoreIndex($storeId, $productIds);
00080         }
00081         return $this;
00082     }

resetSearchResults (  ) 

Reset search results

Returns:
Mage_CatalogSearch_Model_Mysql4_Fulltext

Definition at line 211 of file Fulltext.php.

00212     {
00213         $this->beginTransaction();
00214         try {
00215             $this->_getWriteAdapter()->update($this->getTable('catalogsearch/search_query'), array('is_processed' => 0));
00216             $this->_getWriteAdapter()->query("TRUNCATE TABLE {$this->getTable('catalogsearch/result')}");
00217 
00218             $this->commit();
00219         }
00220         catch (Exception $e) {
00221             $this->rollBack();
00222             throw $e;
00223         }
00224 
00225         Mage::dispatchEvent('catalogsearch_reset_search_result');
00226 
00227         return $this;
00228     }


Member Data Documentation

$_productTypes = array() [protected]

Definition at line 55 of file Fulltext.php.

$_searchableAttributes = null [protected]

Definition at line 41 of file Fulltext.php.

$_separator = ' ' [protected]

Definition at line 48 of file Fulltext.php.


The documentation for this class was generated from the following file:

Generated on Sat Jul 4 17:23:49 2009 for Magento by  doxygen 1.5.8