PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Review/Model/Resource/Review.php

https://github.com/rgranadino/magento-mirror
PHP | 441 lines | 241 code | 37 blank | 163 comment | 24 complexity | aab694f1fd96009bb8073cadc4023a1d MD5 | raw file
  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_Review
  23. * @copyright Copyright (c) 2011 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. * Review resource model
  28. *
  29. * @category Mage
  30. * @package Mage_Review
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Review_Model_Resource_Review extends Mage_Core_Model_Resource_Db_Abstract
  34. {
  35. /**
  36. * Review table
  37. *
  38. * @var string
  39. */
  40. protected $_reviewTable;
  41. /**
  42. * Review Detail table
  43. *
  44. * @var string
  45. */
  46. protected $_reviewDetailTable;
  47. /**
  48. * Review status table
  49. *
  50. * @var string
  51. */
  52. protected $_reviewStatusTable;
  53. /**
  54. * Review entity table
  55. *
  56. * @var string
  57. */
  58. protected $_reviewEntityTable;
  59. /**
  60. * Review store table
  61. *
  62. * @var string
  63. */
  64. protected $_reviewStoreTable;
  65. /**
  66. * Review aggregate table
  67. *
  68. * @var string
  69. */
  70. protected $_aggregateTable;
  71. /**
  72. * Cache of deleted rating data
  73. *
  74. * @var array
  75. */
  76. private $_deleteCache = array();
  77. /**
  78. * Define main table. Define other tables name
  79. *
  80. */
  81. protected function _construct()
  82. {
  83. $this->_init('review/review', 'review_id');
  84. $this->_reviewTable = $this->getTable('review/review');
  85. $this->_reviewDetailTable = $this->getTable('review/review_detail');
  86. $this->_reviewStatusTable = $this->getTable('review/review_status');
  87. $this->_reviewEntityTable = $this->getTable('review/review_entity');
  88. $this->_reviewStoreTable = $this->getTable('review/review_store');
  89. $this->_aggregateTable = $this->getTable('review/review_aggregate');
  90. }
  91. /**
  92. * Retrieve select object for load object data
  93. *
  94. * @param string $field
  95. * @param mixed $value
  96. * @param unknown_type $object
  97. * @return Zend_Db_Select
  98. */
  99. protected function _getLoadSelect($field, $value, $object)
  100. {
  101. $select = parent::_getLoadSelect($field, $value, $object);
  102. $select->join(
  103. $this->_reviewDetailTable,
  104. $this->getMainTable().".review_id = {$this->_reviewDetailTable}.review_id"
  105. );
  106. return $select;
  107. }
  108. /**
  109. * Perform actions before object save
  110. *
  111. * @param Varien_Object $object
  112. * @return Mage_Review_Model_Resource_Review
  113. */
  114. protected function _beforeSave(Mage_Core_Model_Abstract $object)
  115. {
  116. if (!$object->getId()) {
  117. $object->setCreatedAt(Mage::getSingleton('core/date')->gmtDate());
  118. }
  119. if ($object->hasData('stores') && is_array($object->getStores())) {
  120. $stores = $object->getStores();
  121. $stores[] = 0;
  122. $object->setStores($stores);
  123. } elseif ($object->hasData('stores')) {
  124. $object->setStores(array($object->getStores(), 0));
  125. }
  126. return $this;
  127. }
  128. /**
  129. * Perform actions after object save
  130. *
  131. * @param Varien_Object $object
  132. * @return Mage_Review_Model_Resource_Review
  133. */
  134. protected function _afterSave(Mage_Core_Model_Abstract $object)
  135. {
  136. $adapter = $this->_getWriteAdapter();
  137. /**
  138. * save detail
  139. */
  140. $detail = array(
  141. 'title' => $object->getTitle(),
  142. 'detail' => $object->getDetail(),
  143. 'nickname' => $object->getNickname(),
  144. );
  145. $select = $adapter->select()
  146. ->from($this->_reviewDetailTable, 'detail_id')
  147. ->where('review_id = :review_id');
  148. $detailId = $adapter->fetchOne($select, array(':review_id' => $object->getId()));
  149. if ($detailId) {
  150. $condition = array("detail_id = ?" => $detailId);
  151. $adapter->update($this->_reviewDetailTable, $detail, $condition);
  152. } else {
  153. $detail['store_id'] = $object->getStoreId();
  154. $detail['customer_id']= $object->getCustomerId();
  155. $detail['review_id'] = $object->getId();
  156. $adapter->insert($this->_reviewDetailTable, $detail);
  157. }
  158. /**
  159. * save stores
  160. */
  161. $stores = $object->getStores();
  162. if (!empty($stores)) {
  163. $condition = array('review_id = ?' => $object->getId());
  164. $adapter->delete($this->_reviewStoreTable, $condition);
  165. $insertedStoreIds = array();
  166. foreach ($stores as $storeId) {
  167. if (in_array($storeId, $insertedStoreIds)) {
  168. continue;
  169. }
  170. $insertedStoreIds[] = $storeId;
  171. $storeInsert = array(
  172. 'store_id' => $storeId,
  173. 'review_id'=> $object->getId()
  174. );
  175. $adapter->insert($this->_reviewStoreTable, $storeInsert);
  176. }
  177. }
  178. // reaggregate ratings, that depend on this review
  179. $this->_aggregateRatings(
  180. $this->_loadVotedRatingIds($object->getId()),
  181. $object->getEntityPkValue()
  182. );
  183. return $this;
  184. }
  185. /**
  186. * Perform actions after object load
  187. *
  188. * @param Varien_Object $object
  189. * @return Mage_Review_Model_Resource_Review
  190. */
  191. protected function _afterLoad(Mage_Core_Model_Abstract $object)
  192. {
  193. $adapter = $this->_getReadAdapter();
  194. $select = $adapter->select()
  195. ->from($this->_reviewStoreTable, array('store_id'))
  196. ->where('review_id = :review_id');
  197. $stores = $adapter->fetchCol($select, array(':review_id' => $object->getId()));
  198. if (empty($stores) && Mage::app()->isSingleStoreMode()) {
  199. $object->setStores(array(Mage::app()->getStore(true)->getId()));
  200. } else {
  201. $object->setStores($stores);
  202. }
  203. return $this;
  204. }
  205. /**
  206. * Action before delete
  207. *
  208. * @param Mage_Core_Model_Abstract $object
  209. * @return Mage_Review_Model_Resource_Review
  210. */
  211. protected function _beforeDelete(Mage_Core_Model_Abstract $object)
  212. {
  213. // prepare rating ids, that depend on review
  214. $this->_deleteCache = array(
  215. 'ratingIds' => $this->_loadVotedRatingIds($object->getId()),
  216. 'entityPkValue' => $object->getEntityPkValue()
  217. );
  218. return $this;
  219. }
  220. /**
  221. * Perform actions after object delete
  222. *
  223. * @param Varien_Object $object
  224. * @return Mage_Review_Model_Resource_Review
  225. */
  226. protected function _afterDelete(Mage_Core_Model_Abstract $object)
  227. {
  228. $this->aggregate($object);
  229. // reaggregate ratings, that depended on this review
  230. $this->_aggregateRatings(
  231. $this->_deleteCache['ratingIds'],
  232. $this->_deleteCache['entityPkValue']
  233. );
  234. $this->_deleteCache = array();
  235. return $this;
  236. }
  237. /**
  238. * Retrieves total reviews
  239. *
  240. * @param int $entityPkValue
  241. * @param bool $approvedOnly
  242. * @param int $storeId
  243. * @return int
  244. */
  245. public function getTotalReviews($entityPkValue, $approvedOnly = false, $storeId = 0)
  246. {
  247. $adapter = $this->_getReadAdapter();
  248. $select = $adapter->select()
  249. ->from($this->_reviewTable,
  250. array(
  251. 'review_count' => new Zend_Db_Expr('COUNT(*)')
  252. ))
  253. ->where("{$this->_reviewTable}.entity_pk_value = :pk_value");
  254. $bind = array(':pk_value' => $entityPkValue);
  255. if ($storeId > 0) {
  256. $select->join(array('store'=>$this->_reviewStoreTable),
  257. $this->_reviewTable.'.review_id=store.review_id AND store.store_id = :store_id',
  258. array());
  259. $bind[':store_id'] = (int)$storeId;
  260. }
  261. if ($approvedOnly) {
  262. $select->where("{$this->_reviewTable}.status_id = :status_id");
  263. $bind[':status_id'] = 1;
  264. }
  265. return $adapter->fetchOne($select, $bind);
  266. }
  267. /**
  268. * Aggregate
  269. *
  270. * @param Mage_Core_Model_Abstract $object
  271. */
  272. public function aggregate($object)
  273. {
  274. $readAdapter = $this->_getReadAdapter();
  275. $writeAdapter = $this->_getWriteAdapter();
  276. if (!$object->getEntityPkValue() && $object->getId()) {
  277. $object->load($object->getReviewId());
  278. }
  279. $ratingModel = Mage::getModel('rating/rating');
  280. $ratingSummaries= $ratingModel->getEntitySummary($object->getEntityPkValue(), false);
  281. foreach ($ratingSummaries as $ratingSummaryObject) {
  282. if ($ratingSummaryObject->getCount()) {
  283. $ratingSummary = round($ratingSummaryObject->getSum() / $ratingSummaryObject->getCount());
  284. } else {
  285. $ratingSummary = $ratingSummaryObject->getSum();
  286. }
  287. $reviewsCount = $this->getTotalReviews($object->getEntityPkValue(), true, $ratingSummaryObject->getStoreId());
  288. $select = $readAdapter->select()
  289. ->from($this->_aggregateTable)
  290. ->where('entity_pk_value = :pk_value')
  291. ->where('entity_type = :entity_type')
  292. ->where('store_id = :store_id');
  293. $bind = array(
  294. ':pk_value' => $object->getEntityPkValue(),
  295. ':entity_type' => $object->getEntityId(),
  296. ':store_id' =>$ratingSummaryObject->getStoreId()
  297. );
  298. $oldData = $readAdapter->fetchRow($select, $bind);
  299. $data = new Varien_Object();
  300. $data->setReviewsCount($reviewsCount)
  301. ->setEntityPkValue($object->getEntityPkValue())
  302. ->setEntityType($object->getEntityId())
  303. ->setRatingSummary(($ratingSummary > 0) ? $ratingSummary : 0)
  304. ->setStoreId($ratingSummaryObject->getStoreId());
  305. $writeAdapter->beginTransaction();
  306. try {
  307. if ($oldData['primary_id'] > 0) {
  308. $condition = array("{$this->_aggregateTable}.primary_id = ?" => $oldData['primary_id']);
  309. $writeAdapter->update($this->_aggregateTable, $data->getData(), $condition);
  310. } else {
  311. $writeAdapter->insert($this->_aggregateTable, $data->getData());
  312. }
  313. $writeAdapter->commit();
  314. } catch (Exception $e) {
  315. $writeAdapter->rollBack();
  316. }
  317. }
  318. }
  319. /**
  320. * Get rating IDs from review votes
  321. *
  322. * @param int $reviewId
  323. * @return array
  324. */
  325. protected function _loadVotedRatingIds($reviewId)
  326. {
  327. $adapter = $this->_getReadAdapter();
  328. if (empty($reviewId)) {
  329. return array();
  330. }
  331. $select = $adapter->select()
  332. ->from(array('v' => $this->getTable('rating/rating_option_vote')), 'r.rating_id')
  333. ->joinInner(array('r' => $this->getTable('rating/rating')), 'v.rating_id=r.rating_id')
  334. ->where('v.review_id = :revire_id');
  335. return $adapter->fetchCol($select, array(':revire_id' => $reviewId));
  336. }
  337. /**
  338. * Aggregate this review's ratings.
  339. * Useful, when changing the review.
  340. *
  341. * @param array $ratingIds
  342. * @param int $entityPkValue
  343. * @return Mage_Review_Model_Resource_Review
  344. */
  345. protected function _aggregateRatings($ratingIds, $entityPkValue)
  346. {
  347. if ($ratingIds && !is_array($ratingIds)) {
  348. $ratingIds = array((int)$ratingIds);
  349. }
  350. if ($ratingIds && $entityPkValue
  351. && ($resource = Mage::getResourceSingleton('rating/rating_option'))
  352. ) {
  353. foreach ($ratingIds as $ratingId) {
  354. $resource->aggregateEntityByRatingId(
  355. $ratingId, $entityPkValue
  356. );
  357. }
  358. }
  359. return $this;
  360. }
  361. /**
  362. * Reaggregate this review's ratings.
  363. *
  364. * @param int $reviewId
  365. * @param int $entityPkValue
  366. */
  367. public function reAggregateReview($reviewId, $entityPkValue)
  368. {
  369. $this->_aggregateRatings($this->_loadVotedRatingIds($reviewId), $entityPkValue);
  370. }
  371. /**
  372. * Get review entity type id by code
  373. *
  374. * @param string $entityCode
  375. * @return int|bool
  376. */
  377. public function getEntityIdByCode($entityCode)
  378. {
  379. $adapter = $this->_getReadAdapter();
  380. $select = $adapter->select()
  381. ->from($this->_reviewEntityTable, array('entity_id'))
  382. ->where('entity_code = :entity_code');
  383. return $adapter->fetchOne($select, array(':entity_code' => $entityCode));
  384. }
  385. /**
  386. * Delete reviews by product id.
  387. * Better to call this method in transaction, because operation performed on two separated tables
  388. *
  389. * @param int $productId
  390. * @return Mage_Review_Model_Resource_Review
  391. */
  392. public function deleteReviewsByProductId($productId)
  393. {
  394. $this->_getWriteAdapter()->delete($this->_reviewTable, array(
  395. 'entity_pk_value=?' => $productId,
  396. 'entity_id=?' => $this->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE)
  397. ));
  398. $this->_getWriteAdapter()->delete($this->getTable('review/review_aggregate'), array(
  399. 'entity_pk_value=?' => $productId,
  400. 'entity_type=?' => $this->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE)
  401. ));
  402. return $this;
  403. }
  404. }