PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/CatalogSearch/Model/Indexer/Fulltext.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 397 lines | 249 code | 36 blank | 112 comment | 60 complexity | a5229b2c3576aacbab9ca9c5c5f18c89 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  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) 2010 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. * CatalogSearch fulltext indexer model
  28. *
  29. * @category Mage
  30. * @package Mage_CatalogSearch
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_CatalogSearch_Model_Indexer_Fulltext extends Mage_Index_Model_Indexer_Abstract
  34. {
  35. /**
  36. * Retrieve resource instance
  37. *
  38. * @return Mage_CatalogSearch_Model_Mysql4_Indexer_Fulltext
  39. */
  40. protected function _getResource()
  41. {
  42. return Mage::getResourceSingleton('catalogsearch/indexer_fulltext');
  43. }
  44. /**
  45. * Indexer must be match entities
  46. *
  47. * @var array
  48. */
  49. protected $_matchedEntities = array(
  50. Mage_Catalog_Model_Product::ENTITY => array(
  51. Mage_Index_Model_Event::TYPE_SAVE,
  52. Mage_Index_Model_Event::TYPE_MASS_ACTION,
  53. Mage_Index_Model_Event::TYPE_DELETE
  54. ),
  55. Mage_Catalog_Model_Resource_Eav_Attribute::ENTITY => array(
  56. Mage_Index_Model_Event::TYPE_SAVE,
  57. Mage_Index_Model_Event::TYPE_DELETE,
  58. ),
  59. Mage_Core_Model_Store::ENTITY => array(
  60. Mage_Index_Model_Event::TYPE_SAVE,
  61. Mage_Index_Model_Event::TYPE_DELETE
  62. ),
  63. Mage_Core_Model_Store_Group::ENTITY => array(
  64. Mage_Index_Model_Event::TYPE_SAVE
  65. ),
  66. Mage_Core_Model_Config_Data::ENTITY => array(
  67. Mage_Index_Model_Event::TYPE_SAVE
  68. ),
  69. Mage_Catalog_Model_Convert_Adapter_Product::ENTITY => array(
  70. Mage_Index_Model_Event::TYPE_SAVE
  71. ),
  72. Mage_Catalog_Model_Category::ENTITY => array(
  73. Mage_Index_Model_Event::TYPE_SAVE
  74. )
  75. );
  76. /**
  77. * Related Configuration Settings for match
  78. *
  79. * @var array
  80. */
  81. protected $_relatedConfigSettings = array(
  82. Mage_CatalogSearch_Model_Fulltext::XML_PATH_CATALOG_SEARCH_TYPE
  83. );
  84. /**
  85. * Retrieve Fulltext Search instance
  86. *
  87. * @return Mage_CatalogSearch_Model_Fulltext
  88. */
  89. protected function _getIndexer()
  90. {
  91. return Mage::getSingleton('catalogsearch/fulltext');
  92. }
  93. /**
  94. * Retrieve Indexer name
  95. *
  96. * @return string
  97. */
  98. public function getName()
  99. {
  100. return Mage::helper('catalogsearch')->__('Catalog Search Index');
  101. }
  102. /**
  103. * Retrieve Indexer description
  104. *
  105. * @return string
  106. */
  107. public function getDescription()
  108. {
  109. return Mage::helper('catalogsearch')->__('Rebuild Catalog product fulltext search index');
  110. }
  111. /**
  112. * Check if event can be matched by process
  113. * Overwrote for check is flat catalog product is enabled and specific save
  114. * attribute, store, store_group
  115. *
  116. * @param Mage_Index_Model_Event $event
  117. * @return bool
  118. */
  119. public function matchEvent(Mage_Index_Model_Event $event)
  120. {
  121. $data = $event->getNewData();
  122. $resultKey = 'catalogsearch_fulltext_match_result';
  123. if (isset($data[$resultKey])) {
  124. return $data[$resultKey];
  125. }
  126. $result = null;
  127. $entity = $event->getEntity();
  128. if ($entity == Mage_Catalog_Model_Resource_Eav_Attribute::ENTITY) {
  129. /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
  130. $attribute = $event->getDataObject();
  131. if ($event->getType() == Mage_Index_Model_Event::TYPE_SAVE) {
  132. $result = $attribute->dataHasChangedFor('is_searchable');
  133. } else if ($event->getType() == Mage_Index_Model_Event::TYPE_DELETE) {
  134. $result = $attribute->getIsSearchable();
  135. } else {
  136. $result = false;
  137. }
  138. } else if ($entity == Mage_Core_Model_Store::ENTITY) {
  139. if ($event->getType() == Mage_Index_Model_Event::TYPE_DELETE) {
  140. $result = true;
  141. } else {
  142. /* @var $store Mage_Core_Model_Store */
  143. $store = $event->getDataObject();
  144. if ($store->isObjectNew()) {
  145. $result = true;
  146. } else {
  147. $result = false;
  148. }
  149. }
  150. } else if ($entity == Mage_Core_Model_Store_Group::ENTITY) {
  151. /* @var $storeGroup Mage_Core_Model_Store_Group */
  152. $storeGroup = $event->getDataObject();
  153. if ($storeGroup->dataHasChangedFor('website_id')) {
  154. $result = true;
  155. } else {
  156. $result = false;
  157. }
  158. } else if ($entity == Mage_Core_Model_Config_Data::ENTITY) {
  159. $data = $event->getDataObject();
  160. if (in_array($data->getPath(), $this->_relatedConfigSettings)) {
  161. $result = $data->isValueChanged();
  162. } else {
  163. $result = false;
  164. }
  165. } else {
  166. $result = parent::matchEvent($event);
  167. }
  168. $event->addNewData($resultKey, $result);
  169. return $result;
  170. }
  171. /**
  172. * Register data required by process in event object
  173. *
  174. * @param Mage_Index_Model_Event $event
  175. */
  176. protected function _registerEvent(Mage_Index_Model_Event $event)
  177. {
  178. switch ($event->getEntity()) {
  179. case Mage_Catalog_Model_Product::ENTITY:
  180. $this->_registerCatalogProductEvent($event);
  181. break;
  182. case Mage_Catalog_Model_Convert_Adapter_Product::ENTITY:
  183. $event->addNewData('catalogsearch_fulltext_reindex_all', true);
  184. break;
  185. case Mage_Core_Model_Config_Data::ENTITY:
  186. case Mage_Core_Model_Store::ENTITY:
  187. case Mage_Catalog_Model_Resource_Eav_Attribute::ENTITY:
  188. case Mage_Core_Model_Store_Group::ENTITY:
  189. $event->addNewData('catalogsearch_fulltext_skip_call_event_handler', true);
  190. $process = $event->getProcess();
  191. $process->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX);
  192. break;
  193. case Mage_Catalog_Model_Category::ENTITY:
  194. $this->_registerCatalogCategoryEvent($event);
  195. break;
  196. }
  197. }
  198. /**
  199. * Get data required for category'es products reindex
  200. *
  201. * @param Mage_Index_Model_Event $event
  202. * @return Mage_CatalogSearch_Model_Indexer_Search
  203. */
  204. protected function _registerCatalogCategoryEvent(Mage_Index_Model_Event $event)
  205. {
  206. switch ($event->getType()) {
  207. case Mage_Index_Model_Event::TYPE_SAVE:
  208. /* @var $category Mage_Catalog_Model_Category */
  209. $category = $event->getDataObject();
  210. $productIds = $category->getAffectedProductIds();
  211. if ($productIds) {
  212. $event->addNewData('catalogsearch_category_update_product_ids', $productIds);
  213. $event->addNewData('catalogsearch_category_update_category_ids', array($category->getId()));
  214. } else {
  215. $movedCategoryId = $category->getMovedCategoryId();
  216. if ($movedCategoryId) {
  217. $event->addNewData('catalogsearch_category_update_product_ids', array());
  218. $event->addNewData('catalogsearch_category_update_category_ids', array($movedCategoryId));
  219. }
  220. }
  221. break;
  222. }
  223. return $this;
  224. }
  225. /**
  226. * Register data required by catatalog product process in event object
  227. *
  228. * @param Mage_Index_Model_Event $event
  229. * @return Mage_CatalogSearch_Model_Indexer_Search
  230. */
  231. protected function _registerCatalogProductEvent(Mage_Index_Model_Event $event)
  232. {
  233. switch ($event->getType()) {
  234. case Mage_Index_Model_Event::TYPE_SAVE:
  235. /* @var $product Mage_Catalog_Model_Product */
  236. $product = $event->getDataObject();
  237. $event->addNewData('catalogsearch_update_product_id', $product->getId());
  238. break;
  239. case Mage_Index_Model_Event::TYPE_DELETE:
  240. /* @var $product Mage_Catalog_Model_Product */
  241. $product = $event->getDataObject();
  242. $event->addNewData('catalogsearch_delete_product_id', $product->getId());
  243. break;
  244. case Mage_Index_Model_Event::TYPE_MASS_ACTION:
  245. /* @var $actionObject Varien_Object */
  246. $actionObject = $event->getDataObject();
  247. $reindexData = array();
  248. $rebuildIndex = false;
  249. // check if status changed
  250. $attrData = $actionObject->getAttributesData();
  251. if (isset($attrData['status'])) {
  252. $rebuildIndex = true;
  253. $reindexData['catalogsearch_status'] = $attrData['status'];
  254. }
  255. // check changed websites
  256. if ($actionObject->getWebsiteIds()) {
  257. $rebuildIndex = true;
  258. $reindexData['catalogsearch_website_ids'] = $actionObject->getWebsiteIds();
  259. $reindexData['catalogsearch_action_type'] = $actionObject->getActionType();
  260. }
  261. // register affected products
  262. if ($rebuildIndex) {
  263. $reindexData['catalogsearch_product_ids'] = $actionObject->getProductIds();
  264. foreach ($reindexData as $k => $v) {
  265. $event->addNewData($k, $v);
  266. }
  267. }
  268. break;
  269. }
  270. return $this;
  271. }
  272. /**
  273. * Check if product is composite
  274. *
  275. * @param int $productId
  276. * @return bool
  277. */
  278. protected function _isProductComposite($productId)
  279. {
  280. $product = Mage::getModel('catalog/product')->load($productId);
  281. return $product->isComposite();
  282. }
  283. /**
  284. * Process event
  285. *
  286. * @param Mage_Index_Model_Event $event
  287. */
  288. protected function _processEvent(Mage_Index_Model_Event $event)
  289. {
  290. $data = $event->getNewData();
  291. if (!empty($data['catalogsearch_fulltext_reindex_all'])) {
  292. $this->reindexAll();
  293. } else if (!empty($data['catalogsearch_delete_product_id'])) {
  294. $productId = $data['catalogsearch_delete_product_id'];
  295. if (!$this->_isProductComposite($productId)) {
  296. $parentIds = $this->_getResource()->getRelationsByChild($productId);
  297. if (!empty($parentIds)) {
  298. $this->_getIndexer()->rebuildIndex(null, $parentIds);
  299. }
  300. }
  301. $this->_getIndexer()->cleanIndex(null, $productId)
  302. ->resetSearchResults();
  303. } else if (!empty($data['catalogsearch_update_product_id'])) {
  304. $productId = $data['catalogsearch_update_product_id'];
  305. $productIds = array($productId);
  306. if (!$this->_isProductComposite($productId)) {
  307. $parentIds = $this->_getResource()->getRelationsByChild($productId);
  308. if (!empty($parentIds)) {
  309. $productIds = array_merge($productIds, $parentIds);
  310. }
  311. }
  312. $this->_getIndexer()->rebuildIndex(null, $productIds)
  313. ->resetSearchResults();
  314. } else if (!empty($data['catalogsearch_product_ids'])) {
  315. // mass action
  316. $productIds = $data['catalogsearch_product_ids'];
  317. if (!empty($data['catalogsearch_website_ids'])) {
  318. $websiteIds = $data['catalogsearch_website_ids'];
  319. $actionType = $data['catalogsearch_action_type'];
  320. foreach ($websiteIds as $websiteId) {
  321. foreach (Mage::app()->getWebsite($websiteId)->getStoreIds() as $storeId) {
  322. if ($actionType == 'remove') {
  323. $this->_getIndexer()
  324. ->cleanIndex($storeId, $productIds)
  325. ->resetSearchResults();
  326. } else if ($actionType == 'add') {
  327. $this->_getIndexer()
  328. ->rebuildIndex($storeId, $productIds)
  329. ->resetSearchResults();
  330. }
  331. }
  332. }
  333. }
  334. if (isset($data['catalogsearch_status'])) {
  335. $status = $data['catalogsearch_status'];
  336. if ($status == Mage_Catalog_Model_Product_Status::STATUS_ENABLED) {
  337. $this->_getIndexer()
  338. ->rebuildIndex(null, $productIds)
  339. ->resetSearchResults();
  340. } else {
  341. $this->_getIndexer()
  342. ->cleanIndex(null, $productIds)
  343. ->resetSearchResults();
  344. }
  345. }
  346. } else if (isset($data['catalogsearch_category_update_product_ids'])) {
  347. $productIds = $data['catalogsearch_category_update_product_ids'];
  348. $categoryIds = $data['catalogsearch_category_update_category_ids'];
  349. $this->_getIndexer()
  350. ->updateCategoryIndex($productIds, $categoryIds);
  351. }
  352. }
  353. /**
  354. * Rebuild all index data
  355. *
  356. */
  357. public function reindexAll()
  358. {
  359. $this->_getIndexer()->rebuildIndex();
  360. }
  361. }