Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_CatalogSearch_AdvancedController
  • Mage_CatalogSearch_AjaxController
  • Mage_CatalogSearch_Block_Advanced_Form
  • Mage_CatalogSearch_Block_Advanced_Result
  • Mage_CatalogSearch_Block_Autocomplete
  • Mage_CatalogSearch_Block_Layer
  • Mage_CatalogSearch_Block_Layer_Filter_Attribute
  • Mage_CatalogSearch_Block_Result
  • Mage_CatalogSearch_Block_Term
  • Mage_CatalogSearch_Helper_Data
  • Mage_CatalogSearch_Model_Advanced
  • Mage_CatalogSearch_Model_Fulltext
  • Mage_CatalogSearch_Model_Fulltext_Observer
  • Mage_CatalogSearch_Model_Indexer_Fulltext
  • Mage_CatalogSearch_Model_Layer
  • Mage_CatalogSearch_Model_Layer_Filter_Attribute
  • Mage_CatalogSearch_Model_Mysql4_Advanced
  • Mage_CatalogSearch_Model_Mysql4_Advanced_Collection
  • Mage_CatalogSearch_Model_Mysql4_Fulltext
  • Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
  • Mage_CatalogSearch_Model_Mysql4_Fulltext_Engine
  • Mage_CatalogSearch_Model_Mysql4_Indexer_Fulltext
  • Mage_CatalogSearch_Model_Mysql4_Query
  • Mage_CatalogSearch_Model_Mysql4_Query_Collection
  • Mage_CatalogSearch_Model_Mysql4_Search_Collection
  • Mage_CatalogSearch_Model_Query
  • Mage_CatalogSearch_Model_Resource_Advanced
  • Mage_CatalogSearch_Model_Resource_Advanced_Collection
  • Mage_CatalogSearch_Model_Resource_Fulltext
  • Mage_CatalogSearch_Model_Resource_Fulltext_Collection
  • Mage_CatalogSearch_Model_Resource_Fulltext_Engine
  • Mage_CatalogSearch_Model_Resource_Indexer_Fulltext
  • Mage_CatalogSearch_Model_Resource_Query
  • Mage_CatalogSearch_Model_Resource_Query_Collection
  • Mage_CatalogSearch_Model_Resource_Search_Collection
  • Mage_CatalogSearch_Model_Session
  • Mage_Catalogsearch_Model_System_Config_Backend_Sitemap
  • Mage_CatalogSearch_ResultController
  • Mage_CatalogSearch_TermController
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Magento
  4:  *
  5:  * NOTICE OF LICENSE
  6:  *
  7:  * This source file is subject to the Open Software License (OSL 3.0)
  8:  * that is bundled with this package in the file LICENSE.txt.
  9:  * It is also available through the world-wide-web at this URL:
 10:  * http://opensource.org/licenses/osl-3.0.php
 11:  * If you did not receive a copy of the license and are unable to
 12:  * obtain it through the world-wide-web, please send an email
 13:  * to license@magentocommerce.com so we can send you a copy immediately.
 14:  *
 15:  * DISCLAIMER
 16:  *
 17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
 18:  * versions in the future. If you wish to customize Magento for your
 19:  * needs please refer to http://www.magentocommerce.com for more information.
 20:  *
 21:  * @category    Mage
 22:  * @package     Mage_CatalogSearch
 23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
 24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 25:  */
 26: 
 27: 
 28: /**
 29:  * CatalogSearch Fulltext Index resource model
 30:  *
 31:  * @category    Mage
 32:  * @package     Mage_CatalogSearch
 33:  * @author      Magento Core Team <core@magentocommerce.com>
 34:  */
 35: class Mage_CatalogSearch_Model_Resource_Fulltext extends Mage_Core_Model_Resource_Db_Abstract
 36: {
 37:     /**
 38:      * Searchable attributes cache
 39:      *
 40:      * @var array
 41:      */
 42:     protected $_searchableAttributes     = null;
 43: 
 44:     /**
 45:      * Index values separator
 46:      *
 47:      * @var string
 48:      */
 49:     protected $_separator                = '|';
 50: 
 51:     /**
 52:      * Array of Zend_Date objects per store
 53:      *
 54:      * @var array
 55:      */
 56:     protected $_dates                    = array();
 57: 
 58:     /**
 59:      * Product Type Instances cache
 60:      *
 61:      * @var array
 62:      */
 63:     protected $_productTypes             = array();
 64: 
 65:     /**
 66:      * Store search engine instance
 67:      *
 68:      * @var object
 69:      */
 70:     protected $_engine                   = null;
 71: 
 72:     /**
 73:      * Whether table changes are allowed
 74:      *
 75:      * @deprecated after 1.6.1.0
 76:      * @var bool
 77:      */
 78:     protected $_allowTableChanges       = true;
 79: 
 80: 
 81: 
 82: 
 83: 
 84:     /**
 85:      * Init resource model
 86:      *
 87:      */
 88:     protected function _construct()
 89:     {
 90:         $this->_init('catalogsearch/fulltext', 'product_id');
 91:         $this->_engine = Mage::helper('catalogsearch')->getEngine();
 92:     }
 93: 
 94:     /**
 95:      * Return options separator
 96:      *
 97:      * @return string
 98:      */
 99:     public function getSeparator()
100:     {
101:         return $this->_separator;
102:     }
103: 
104:     /**
105:      * Regenerate search index for store(s)
106:      *
107:      * @param  int|null $storeId
108:      * @param  int|array|null $productIds
109:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
110:      */
111:     public function rebuildIndex($storeId = null, $productIds = null)
112:     {
113:         if (is_null($storeId)) {
114:             $storeIds = array_keys(Mage::app()->getStores());
115:             foreach ($storeIds as $storeId) {
116:                 $this->_rebuildStoreIndex($storeId, $productIds);
117:             }
118:         } else {
119:             $this->_rebuildStoreIndex($storeId, $productIds);
120:         }
121: 
122:         return $this;
123:     }
124: 
125:     /**
126:      * Regenerate search index for specific store
127:      *
128:      * @param int $storeId Store View Id
129:      * @param int|array $productIds Product Entity Id
130:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
131:      */
132:     protected function _rebuildStoreIndex($storeId, $productIds = null)
133:     {
134:         $this->cleanIndex($storeId, $productIds);
135: 
136:         // prepare searchable attributes
137:         $staticFields = array();
138:         foreach ($this->_getSearchableAttributes('static') as $attribute) {
139:             $staticFields[] = $attribute->getAttributeCode();
140:         }
141:         $dynamicFields = array(
142:             'int'       => array_keys($this->_getSearchableAttributes('int')),
143:             'varchar'   => array_keys($this->_getSearchableAttributes('varchar')),
144:             'text'      => array_keys($this->_getSearchableAttributes('text')),
145:             'decimal'   => array_keys($this->_getSearchableAttributes('decimal')),
146:             'datetime'  => array_keys($this->_getSearchableAttributes('datetime')),
147:         );
148: 
149:         // status and visibility filter
150:         $visibility     = $this->_getSearchableAttribute('visibility');
151:         $status         = $this->_getSearchableAttribute('status');
152:         $statusVals     = Mage::getSingleton('catalog/product_status')->getVisibleStatusIds();
153:         $allowedVisibilityValues = $this->_engine->getAllowedVisibility();
154: 
155:         $lastProductId = 0;
156:         while (true) {
157:             $products = $this->_getSearchableProducts($storeId, $staticFields, $productIds, $lastProductId);
158:             if (!$products) {
159:                 break;
160:             }
161: 
162:             $productAttributes = array();
163:             $productRelations  = array();
164:             foreach ($products as $productData) {
165:                 $lastProductId = $productData['entity_id'];
166:                 $productAttributes[$productData['entity_id']] = $productData['entity_id'];
167:                 $productChildren = $this->_getProductChildIds($productData['entity_id'], $productData['type_id']);
168:                 $productRelations[$productData['entity_id']] = $productChildren;
169:                 if ($productChildren) {
170:                     foreach ($productChildren as $productChildId) {
171:                         $productAttributes[$productChildId] = $productChildId;
172:                     }
173:                 }
174:             }
175: 
176:             $productIndexes    = array();
177:             $productAttributes = $this->_getProductAttributes($storeId, $productAttributes, $dynamicFields);
178:             foreach ($products as $productData) {
179:                 if (!isset($productAttributes[$productData['entity_id']])) {
180:                     continue;
181:                 }
182: 
183:                 $productAttr = $productAttributes[$productData['entity_id']];
184:                 if (!isset($productAttr[$visibility->getId()])
185:                     || !in_array($productAttr[$visibility->getId()], $allowedVisibilityValues)
186:                 ) {
187:                     continue;
188:                 }
189:                 if (!isset($productAttr[$status->getId()]) || !in_array($productAttr[$status->getId()], $statusVals)) {
190:                     continue;
191:                 }
192: 
193:                 $productIndex = array(
194:                     $productData['entity_id'] => $productAttr
195:                 );
196: 
197:                 if ($productChildren = $productRelations[$productData['entity_id']]) {
198:                     foreach ($productChildren as $productChildId) {
199:                         if (isset($productAttributes[$productChildId])) {
200:                             $productIndex[$productChildId] = $productAttributes[$productChildId];
201:                         }
202:                     }
203:                 }
204: 
205:                 $index = $this->_prepareProductIndex($productIndex, $productData, $storeId);
206: 
207:                 $productIndexes[$productData['entity_id']] = $index;
208:             }
209: 
210:             $this->_saveProductIndexes($storeId, $productIndexes);
211:         }
212: 
213:         $this->resetSearchResults();
214: 
215:         return $this;
216:     }
217: 
218:     /**
219:      * Retrieve searchable products per store
220:      *
221:      * @param int $storeId
222:      * @param array $staticFields
223:      * @param array|int $productIds
224:      * @param int $lastProductId
225:      * @param int $limit
226:      * @return array
227:      */
228:     protected function _getSearchableProducts($storeId, array $staticFields, $productIds = null, $lastProductId = 0,
229:         $limit = 100)
230:     {
231:         $websiteId      = Mage::app()->getStore($storeId)->getWebsiteId();
232:         $writeAdapter   = $this->_getWriteAdapter();
233: 
234:         $select = $writeAdapter->select()
235:             ->useStraightJoin(true)
236:             ->from(
237:                 array('e' => $this->getTable('catalog/product')),
238:                 array_merge(array('entity_id', 'type_id'), $staticFields)
239:             )
240:             ->join(
241:                 array('website' => $this->getTable('catalog/product_website')),
242:                 $writeAdapter->quoteInto(
243:                     'website.product_id=e.entity_id AND website.website_id=?',
244:                     $websiteId
245:                 ),
246:                 array()
247:             )
248:             ->join(
249:                 array('stock_status' => $this->getTable('cataloginventory/stock_status')),
250:                 $writeAdapter->quoteInto(
251:                     'stock_status.product_id=e.entity_id AND stock_status.website_id=?',
252:                     $websiteId
253:                 ),
254:                 array('in_stock' => 'stock_status')
255:             );
256: 
257:         if (!is_null($productIds)) {
258:             $select->where('e.entity_id IN(?)', $productIds);
259:         }
260: 
261:         $select->where('e.entity_id>?', $lastProductId)
262:             ->limit($limit)
263:             ->order('e.entity_id');
264: 
265:         $result = $writeAdapter->fetchAll($select);
266: 
267:         return $result;
268:     }
269: 
270:     /**
271:      * Reset search results
272:      *
273:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
274:      */
275:     public function resetSearchResults()
276:     {
277:         $adapter = $this->_getWriteAdapter();
278:         $adapter->update($this->getTable('catalogsearch/search_query'), array('is_processed' => 0));
279:         $adapter->delete($this->getTable('catalogsearch/result'));
280: 
281:         Mage::dispatchEvent('catalogsearch_reset_search_result');
282: 
283:         return $this;
284:     }
285: 
286:     /**
287:      * Delete search index data for store
288:      *
289:      * @param int $storeId Store View Id
290:      * @param int $productId Product Entity Id
291:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
292:      */
293:     public function cleanIndex($storeId = null, $productId = null)
294:     {
295:         if ($this->_engine) {
296:             $this->_engine->cleanIndex($storeId, $productId);
297:         }
298: 
299:         return $this;
300:     }
301: 
302:     /**
303:      * Prepare results for query
304:      *
305:      * @param Mage_CatalogSearch_Model_Fulltext $object
306:      * @param string $queryText
307:      * @param Mage_CatalogSearch_Model_Query $query
308:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
309:      */
310:     public function prepareResult($object, $queryText, $query)
311:     {
312:         $adapter = $this->_getWriteAdapter();
313:         if (!$query->getIsProcessed()) {
314:             $searchType = $object->getSearchType($query->getStoreId());
315: 
316:             $preparedTerms = Mage::getResourceHelper('catalogsearch')
317:                 ->prepareTerms($queryText, $query->getMaxQueryWords());
318: 
319:             $bind = array();
320:             $like = array();
321:             $likeCond  = '';
322:             if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE
323:                 || $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE
324:             ) {
325:                 $helper = Mage::getResourceHelper('core');
326:                 $words = Mage::helper('core/string')->splitWords($queryText, true, $query->getMaxQueryWords());
327:                 foreach ($words as $word) {
328:                     $like[] = $helper->getCILike('s.data_index', $word, array('position' => 'any'));
329:                 }
330:                 if ($like) {
331:                     $likeCond = '(' . join(' OR ', $like) . ')';
332:                 }
333:             }
334:             $mainTableAlias = 's';
335:             $fields = array(
336:                 'query_id' => new Zend_Db_Expr($query->getId()),
337:                 'product_id',
338:             );
339:             $select = $adapter->select()
340:                 ->from(array($mainTableAlias => $this->getMainTable()), $fields)
341:                 ->joinInner(array('e' => $this->getTable('catalog/product')),
342:                     'e.entity_id = s.product_id',
343:                     array())
344:                 ->where($mainTableAlias.'.store_id = ?', (int)$query->getStoreId());
345: 
346:             if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_FULLTEXT
347:                 || $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE
348:             ) {
349:                 $bind[':query'] = implode(' ', $preparedTerms[0]);
350:                 $where = Mage::getResourceHelper('catalogsearch')
351:                     ->chooseFulltext($this->getMainTable(), $mainTableAlias, $select);
352:             }
353: 
354:             if ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
355:                     $where .= ($where ? ' OR ' : '') . $likeCond;
356:             } elseif ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE) {
357:                 $select->columns(array('relevance'  => new Zend_Db_Expr(0)));
358:                 $where = $likeCond;
359:             }
360: 
361:             if ($where != '') {
362:                 $select->where($where);
363:             }
364: 
365:             $sql = $adapter->insertFromSelect($select,
366:                 $this->getTable('catalogsearch/result'),
367:                 array(),
368:                 Varien_Db_Adapter_Interface::INSERT_ON_DUPLICATE);
369:             $adapter->query($sql, $bind);
370: 
371:             $query->setIsProcessed(1);
372:         }
373: 
374:         return $this;
375:     }
376: 
377:     /**
378:      * Retrieve EAV Config Singleton
379:      *
380:      * @return Mage_Eav_Model_Config
381:      */
382:     public function getEavConfig()
383:     {
384:         return Mage::getSingleton('eav/config');
385:     }
386: 
387:     /**
388:      * Retrieve searchable attributes
389:      *
390:      * @param string $backendType
391:      * @return array
392:      */
393:     protected function _getSearchableAttributes($backendType = null)
394:     {
395:         if (is_null($this->_searchableAttributes)) {
396:             $this->_searchableAttributes = array();
397: 
398:             $productAttributeCollection = Mage::getResourceModel('catalog/product_attribute_collection');
399: 
400:             if ($this->_engine && $this->_engine->allowAdvancedIndex()) {
401:                 $productAttributeCollection->addToIndexFilter(true);
402:             } else {
403:                 $productAttributeCollection->addSearchableAttributeFilter();
404:             }
405:             $attributes = $productAttributeCollection->getItems();
406: 
407:             Mage::dispatchEvent('catelogsearch_searchable_attributes_load_after', array(
408:                 'engine' => $this->_engine,
409:                 'attributes' => $attributes
410:             ));
411: 
412:             $entity = $this->getEavConfig()
413:                 ->getEntityType(Mage_Catalog_Model_Product::ENTITY)
414:                 ->getEntity();
415: 
416:             foreach ($attributes as $attribute) {
417:                 $attribute->setEntity($entity);
418:             }
419: 
420:             $this->_searchableAttributes = $attributes;
421:         }
422: 
423:         if (!is_null($backendType)) {
424:             $attributes = array();
425:             foreach ($this->_searchableAttributes as $attributeId => $attribute) {
426:                 if ($attribute->getBackendType() == $backendType) {
427:                     $attributes[$attributeId] = $attribute;
428:                 }
429:             }
430: 
431:             return $attributes;
432:         }
433: 
434:         return $this->_searchableAttributes;
435:     }
436: 
437:     /**
438:      * Retrieve searchable attribute by Id or code
439:      *
440:      * @param int|string $attribute
441:      * @return Mage_Eav_Model_Entity_Attribute
442:      */
443:     protected function _getSearchableAttribute($attribute)
444:     {
445:         $attributes = $this->_getSearchableAttributes();
446:         if (is_numeric($attribute)) {
447:             if (isset($attributes[$attribute])) {
448:                 return $attributes[$attribute];
449:             }
450:         } elseif (is_string($attribute)) {
451:             foreach ($attributes as $attributeModel) {
452:                 if ($attributeModel->getAttributeCode() == $attribute) {
453:                     return $attributeModel;
454:                 }
455:             }
456:         }
457: 
458:         return $this->getEavConfig()->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attribute);
459:     }
460: 
461:     /**
462:      * Returns expresion for field unification
463:      *
464:      * @param string $field
465:      * @param string $backendType
466:      * @return Zend_Db_Expr
467:      */
468:     protected function _unifyField($field, $backendType = 'varchar')
469:     {
470:         if ($backendType == 'datetime') {
471:             $expr = Mage::getResourceHelper('catalogsearch')->castField(
472:                 $this->_getReadAdapter()->getDateFormatSql($field, '%Y-%m-%d %H:%i:%s'));
473:         } else {
474:             $expr = Mage::getResourceHelper('catalogsearch')->castField($field);
475:         }
476:         return $expr;
477:     }
478: 
479:     /**
480:      * Load product(s) attributes
481:      *
482:      * @param int $storeId
483:      * @param array $productIds
484:      * @param array $attributeTypes
485:      * @return array
486:      */
487:     protected function _getProductAttributes($storeId, array $productIds, array $attributeTypes)
488:     {
489:         $result  = array();
490:         $selects = array();
491:         $adapter = $this->_getWriteAdapter();
492:         $ifStoreValue = $adapter->getCheckSql('t_store.value_id > 0', 't_store.value', 't_default.value');
493:         foreach ($attributeTypes as $backendType => $attributeIds) {
494:             if ($attributeIds) {
495:                 $tableName = $this->getTable(array('catalog/product', $backendType));
496:                 $selects[] = $adapter->select()
497:                     ->from(
498:                         array('t_default' => $tableName),
499:                         array('entity_id', 'attribute_id'))
500:                     ->joinLeft(
501:                         array('t_store' => $tableName),
502:                         $adapter->quoteInto(
503:                             't_default.entity_id=t_store.entity_id' .
504:                                 ' AND t_default.attribute_id=t_store.attribute_id' .
505:                                 ' AND t_store.store_id=?',
506:                             $storeId),
507:                         array('value' => $this->_unifyField($ifStoreValue, $backendType)))
508:                     ->where('t_default.store_id=?', 0)
509:                     ->where('t_default.attribute_id IN (?)', $attributeIds)
510:                     ->where('t_default.entity_id IN (?)', $productIds);
511:             }
512:         }
513: 
514:         if ($selects) {
515:             $select = $adapter->select()->union($selects, Zend_Db_Select::SQL_UNION_ALL);
516:             $query = $adapter->query($select);
517:             while ($row = $query->fetch()) {
518:                 $result[$row['entity_id']][$row['attribute_id']] = $row['value'];
519:             }
520:         }
521: 
522:         return $result;
523:     }
524: 
525:     /**
526:      * Retrieve Product Type Instance
527:      *
528:      * @param string $typeId
529:      * @return Mage_Catalog_Model_Product_Type_Abstract
530:      */
531:     protected function _getProductTypeInstance($typeId)
532:     {
533:         if (!isset($this->_productTypes[$typeId])) {
534:             $productEmulator = $this->_getProductEmulator();
535:             $productEmulator->setTypeId($typeId);
536: 
537:             $this->_productTypes[$typeId] = Mage::getSingleton('catalog/product_type')
538:                 ->factory($productEmulator);
539:         }
540:         return $this->_productTypes[$typeId];
541:     }
542: 
543:     /**
544:      * Return all product children ids
545:      *
546:      * @param int $productId Product Entity Id
547:      * @param string $typeId Super Product Link Type
548:      * @return array
549:      */
550:     protected function _getProductChildIds($productId, $typeId)
551:     {
552:         $typeInstance = $this->_getProductTypeInstance($typeId);
553:         $relation = $typeInstance->isComposite()
554:             ? $typeInstance->getRelationInfo()
555:             : false;
556: 
557:         if ($relation && $relation->getTable() && $relation->getParentFieldName() && $relation->getChildFieldName()) {
558:             $select = $this->_getReadAdapter()->select()
559:                 ->from(
560:                     array('main' => $this->getTable($relation->getTable())),
561:                     array($relation->getChildFieldName()))
562:                 ->where("{$relation->getParentFieldName()}=?", $productId);
563:             if (!is_null($relation->getWhere())) {
564:                 $select->where($relation->getWhere());
565:             }
566:             return $this->_getReadAdapter()->fetchCol($select);
567:         }
568: 
569:         return null;
570:     }
571: 
572:     /**
573:      * Retrieve Product Emulator (Varien Object)
574:      *
575:      * @return Varien_Object
576:      */
577:     protected function _getProductEmulator()
578:     {
579:         $productEmulator = new Varien_Object();
580:         $productEmulator->setIdFieldName('entity_id');
581: 
582:         return $productEmulator;
583:     }
584: 
585:     /**
586:      * Prepare Fulltext index value for product
587:      *
588:      * @param array $indexData
589:      * @param array $productData
590:      * @param int $storeId
591:      * @return string
592:      */
593:     protected function _prepareProductIndex($indexData, $productData, $storeId)
594:     {
595:         $index = array();
596: 
597:         foreach ($this->_getSearchableAttributes('static') as $attribute) {
598:             $attributeCode = $attribute->getAttributeCode();
599: 
600:             if (isset($productData[$attributeCode])) {
601:                 $value = $this->_getAttributeValue($attribute->getId(), $productData[$attributeCode], $storeId);
602:                 if ($value) {
603:                     //For grouped products
604:                     if (isset($index[$attributeCode])) {
605:                         if (!is_array($index[$attributeCode])) {
606:                             $index[$attributeCode] = array($index[$attributeCode]);
607:                         }
608:                         $index[$attributeCode][] = $value;
609:                     }
610:                     //For other types of products
611:                     else {
612:                         $index[$attributeCode] = $value;
613:                     }
614:                 }
615:             }
616:         }
617: 
618:         foreach ($indexData as $entityId => $attributeData) {
619:             foreach ($attributeData as $attributeId => $attributeValue) {
620:                 $value = $this->_getAttributeValue($attributeId, $attributeValue, $storeId);
621:                 if (!is_null($value) && $value !== false) {
622:                     $attributeCode = $this->_getSearchableAttribute($attributeId)->getAttributeCode();
623: 
624:                     if (isset($index[$attributeCode])) {
625:                         $index[$attributeCode][$entityId] = $value;
626:                     } else {
627:                         $index[$attributeCode] = array($entityId => $value);
628:                     }
629:                 }
630:             }
631:         }
632: 
633:         if (!$this->_engine->allowAdvancedIndex()) {
634:             $product = $this->_getProductEmulator()
635:                 ->setId($productData['entity_id'])
636:                 ->setTypeId($productData['type_id'])
637:                 ->setStoreId($storeId);
638:             $typeInstance = $this->_getProductTypeInstance($productData['type_id']);
639:             if ($data = $typeInstance->getSearchableData($product)) {
640:                 $index['options'] = $data;
641:             }
642:         }
643: 
644:         if (isset($productData['in_stock'])) {
645:             $index['in_stock'] = $productData['in_stock'];
646:         }
647: 
648:         if ($this->_engine) {
649:             return $this->_engine->prepareEntityIndex($index, $this->_separator);
650:         }
651: 
652:         return Mage::helper('catalogsearch')->prepareIndexdata($index, $this->_separator);
653:     }
654: 
655:     /**
656:      * Retrieve attribute source value for search
657:      *
658:      * @param int $attributeId
659:      * @param mixed $value
660:      * @param int $storeId
661:      * @return mixed
662:      */
663:     protected function _getAttributeValue($attributeId, $value, $storeId)
664:     {
665:         $attribute = $this->_getSearchableAttribute($attributeId);
666:         if (!$attribute->getIsSearchable()) {
667:             if ($this->_engine->allowAdvancedIndex()) {
668:                 if ($attribute->getAttributeCode() == 'visibility') {
669:                     return $value;
670:                 } elseif (!($attribute->getIsVisibleInAdvancedSearch()
671:                     || $attribute->getIsFilterable()
672:                     || $attribute->getIsFilterableInSearch()
673:                     || $attribute->getUsedForSortBy())
674:                 ) {
675:                     return null;
676:                 }
677:             } else {
678:                 return null;
679:             }
680:         }
681: 
682:         if ($attribute->usesSource()) {
683:             if ($this->_engine->allowAdvancedIndex()) {
684:                 return $value;
685:             }
686: 
687:             $attribute->setStoreId($storeId);
688:             $value = $attribute->getSource()->getOptionText($value);
689: 
690:             if (is_array($value)) {
691:                 $value = implode($this->_separator, $value);
692:             } elseif (empty($value)) {
693:                 $inputType = $attribute->getFrontend()->getInputType();
694:                 if ($inputType == 'select' || $inputType == 'multiselect') {
695:                     return null;
696:                 }
697:             }
698:         } elseif ($attribute->getBackendType() == 'datetime') {
699:             $value = $this->_getStoreDate($storeId, $value);
700:         } else {
701:             $inputType = $attribute->getFrontend()->getInputType();
702:             if ($inputType == 'price') {
703:                 $value = Mage::app()->getStore($storeId)->roundPrice($value);
704:             }
705:         }
706: 
707:         $value = preg_replace("#\s+#siu", ' ', trim(strip_tags($value)));
708: 
709:         return $value;
710:     }
711: 
712:     /**
713:      * Save Product index
714:      *
715:      * @param int $productId
716:      * @param int $storeId
717:      * @param string $index
718:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
719:      */
720:     protected function _saveProductIndex($productId, $storeId, $index)
721:     {
722:         if ($this->_engine) {
723:             $this->_engine->saveEntityIndex($productId, $storeId, $index);
724:         }
725: 
726:         return $this;
727:     }
728: 
729:     /**
730:      * Save Multiply Product indexes
731:      *
732:      * @param int $storeId
733:      * @param array $productIndexes
734:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
735:      */
736:     protected function _saveProductIndexes($storeId, $productIndexes)
737:     {
738:         if ($this->_engine) {
739:             $this->_engine->saveEntityIndexes($storeId, $productIndexes);
740:         }
741: 
742:         return $this;
743:     }
744: 
745:     /**
746:      * Retrieve Date value for store
747:      *
748:      * @param int $storeId
749:      * @param string $date
750:      * @return string
751:      */
752:     protected function _getStoreDate($storeId, $date = null)
753:     {
754:         if (!isset($this->_dates[$storeId])) {
755:             $timezone = Mage::getStoreConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE, $storeId);
756:             $locale   = Mage::getStoreConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_LOCALE, $storeId);
757:             $locale   = new Zend_Locale($locale);
758: 
759:             $dateObj = new Zend_Date(null, null, $locale);
760:             $dateObj->setTimezone($timezone);
761:             $this->_dates[$storeId] = array($dateObj, $locale->getTranslation(null, 'date', $locale));
762:         }
763: 
764:         if (!is_empty_date($date)) {
765:             list($dateObj, $format) = $this->_dates[$storeId];
766:             $dateObj->setDate($date, Varien_Date::DATETIME_INTERNAL_FORMAT);
767: 
768:             return $dateObj->toString($format);
769:         }
770: 
771:         return null;
772:     }
773: 
774: 
775: 
776: 
777: 
778:     // Deprecated methods
779: 
780:     /**
781:      * Set whether table changes are allowed
782:      *
783:      * @deprecated after 1.6.1.0
784:      * @param bool $value
785:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
786:      */
787:     public function setAllowTableChanges($value = true)
788:     {
789:         $this->_allowTableChanges = $value;
790:         return $this;
791:     }
792: 
793:     /**
794:      * Update category products indexes
795:      *
796:      * deprecated after 1.6.2.0
797:      *
798:      * @param array $productIds
799:      * @param array $categoryIds
800:      * @return Mage_CatalogSearch_Model_Resource_Fulltext
801:      */
802:     public function updateCategoryIndex($productIds, $categoryIds)
803:     {
804:         return $this;
805:     }
806: }
807: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0