Option.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Review\Model\ResourceModel\Rating;
  7. /**
  8. * Rating option resource model
  9. *
  10. * @api
  11. * @since 100.0.2
  12. */
  13. class Option extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
  14. {
  15. /**
  16. * Review table
  17. *
  18. * @var string
  19. */
  20. protected $_reviewTable;
  21. /**
  22. * Rating option table
  23. *
  24. * @var string
  25. */
  26. protected $_ratingOptionTable;
  27. /**
  28. * Rating vote table
  29. *
  30. * @var string
  31. */
  32. protected $_ratingVoteTable;
  33. /**
  34. * Aggregate table
  35. *
  36. * @var string
  37. */
  38. protected $_aggregateTable;
  39. /**
  40. * Review store table
  41. *
  42. * @var string
  43. */
  44. protected $_reviewStoreTable;
  45. /**
  46. * Rating store table
  47. *
  48. * @var string
  49. */
  50. protected $_ratingStoreTable;
  51. /**
  52. * Option data
  53. *
  54. * @var array
  55. */
  56. protected $_optionData;
  57. /**
  58. * Option id
  59. *
  60. * @var int
  61. */
  62. protected $_optionId;
  63. /**
  64. * @var \Magento\Customer\Model\Session
  65. */
  66. protected $_customerSession;
  67. /**
  68. * @var \Magento\Review\Model\Rating\Option\VoteFactory
  69. */
  70. protected $_ratingOptionVoteF;
  71. /**
  72. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  73. * @param \Magento\Customer\Model\Session $customerSession
  74. * @param \Magento\Review\Model\Rating\Option\VoteFactory $ratingOptionVoteF
  75. * @param \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress
  76. * @param string $connectionName
  77. */
  78. public function __construct(
  79. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  80. \Magento\Customer\Model\Session $customerSession,
  81. \Magento\Review\Model\Rating\Option\VoteFactory $ratingOptionVoteF,
  82. \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress,
  83. $connectionName = null
  84. ) {
  85. $this->_customerSession = $customerSession;
  86. $this->_ratingOptionVoteF = $ratingOptionVoteF;
  87. $this->_remoteAddress = $remoteAddress;
  88. parent::__construct($context, $connectionName);
  89. }
  90. /**
  91. * Resource initialization. Define other tables name
  92. *
  93. * @return void
  94. */
  95. protected function _construct()
  96. {
  97. $this->_init('rating_option', 'option_id');
  98. $this->_reviewTable = $this->getTable('review');
  99. $this->_ratingOptionTable = $this->getTable('rating_option');
  100. $this->_ratingVoteTable = $this->getTable('rating_option_vote');
  101. $this->_aggregateTable = $this->getTable('rating_option_vote_aggregated');
  102. $this->_reviewStoreTable = $this->getTable('review_store');
  103. $this->_ratingStoreTable = $this->getTable('rating_store');
  104. }
  105. /**
  106. * Add vote
  107. *
  108. * @param \Magento\Review\Model\Rating\Option $option
  109. * @return $this
  110. */
  111. public function addVote($option)
  112. {
  113. $connection = $this->getConnection();
  114. $optionData = $this->loadDataById($option->getId());
  115. $data = [
  116. 'option_id' => $option->getId(),
  117. 'review_id' => $option->getReviewId(),
  118. 'percent' => $optionData['value'] / 5 * 100,
  119. 'value' => $optionData['value'],
  120. ];
  121. if (!$option->getDoUpdate()) {
  122. $data['remote_ip'] = $this->_remoteAddress->getRemoteAddress();
  123. $data['remote_ip_long'] = $this->_remoteAddress->getRemoteAddress(true);
  124. $data['customer_id'] = $this->_customerSession->getCustomerId();
  125. $data['entity_pk_value'] = $option->getEntityPkValue();
  126. $data['rating_id'] = $option->getRatingId();
  127. }
  128. $connection->beginTransaction();
  129. try {
  130. if ($option->getDoUpdate()) {
  131. $condition = ['vote_id = ?' => $option->getVoteId(), 'review_id = ?' => $option->getReviewId()];
  132. $connection->update($this->_ratingVoteTable, $data, $condition);
  133. $this->aggregate($option);
  134. } else {
  135. $connection->insert($this->_ratingVoteTable, $data);
  136. $option->setVoteId($connection->lastInsertId($this->_ratingVoteTable));
  137. $this->aggregate($option);
  138. }
  139. $connection->commit();
  140. } catch (\Exception $e) {
  141. $connection->rollBack();
  142. throw new \Exception($e->getMessage());
  143. }
  144. return $this;
  145. }
  146. /**
  147. * Aggregate options
  148. *
  149. * @param \Magento\Review\Model\Rating\Option $option
  150. * @return void
  151. */
  152. public function aggregate($option)
  153. {
  154. $vote = $this->_ratingOptionVoteF->create()->load($option->getVoteId());
  155. $this->aggregateEntityByRatingId($vote->getRatingId(), $vote->getEntityPkValue());
  156. }
  157. /**
  158. * Aggregate entity by rating id
  159. *
  160. * @param int $ratingId
  161. * @param int $entityPkValue
  162. * @return void
  163. */
  164. public function aggregateEntityByRatingId($ratingId, $entityPkValue)
  165. {
  166. $connection = $this->getConnection();
  167. $select = $connection->select()->from(
  168. $this->_aggregateTable,
  169. ['store_id', 'primary_id']
  170. )->where(
  171. 'rating_id = :rating_id'
  172. )->where(
  173. 'entity_pk_value = :pk_value'
  174. );
  175. $bind = [':rating_id' => $ratingId, ':pk_value' => $entityPkValue];
  176. $oldData = $connection->fetchPairs($select, $bind);
  177. $appVoteCountCond = $connection->getCheckSql('review.status_id=1', 'vote.vote_id', 'NULL');
  178. $appVoteValueSumCond = $connection->getCheckSql('review.status_id=1', 'vote.value', '0');
  179. $select = $connection->select()->from(
  180. ['vote' => $this->_ratingVoteTable],
  181. [
  182. 'vote_count' => new \Zend_Db_Expr('COUNT(vote.vote_id)'),
  183. 'vote_value_sum' => new \Zend_Db_Expr('SUM(vote.value)'),
  184. 'app_vote_count' => new \Zend_Db_Expr("COUNT({$appVoteCountCond})"),
  185. 'app_vote_value_sum' => new \Zend_Db_Expr("SUM({$appVoteValueSumCond})")
  186. ]
  187. )->join(
  188. ['review' => $this->_reviewTable],
  189. 'vote.review_id=review.review_id',
  190. []
  191. )->joinLeft(
  192. ['store' => $this->_reviewStoreTable],
  193. 'vote.review_id=store.review_id',
  194. 'store_id'
  195. )->join(
  196. ['rstore' => $this->_ratingStoreTable],
  197. 'vote.rating_id=rstore.rating_id AND rstore.store_id=store.store_id',
  198. []
  199. )->where(
  200. 'vote.rating_id = :rating_id'
  201. )->where(
  202. 'vote.entity_pk_value = :pk_value'
  203. )->group(
  204. ['vote.rating_id', 'vote.entity_pk_value', 'store.store_id']
  205. );
  206. $perStoreInfo = $connection->fetchAll($select, $bind);
  207. $usedStores = [];
  208. foreach ($perStoreInfo as $row) {
  209. $saveData = [
  210. 'rating_id' => $ratingId,
  211. 'entity_pk_value' => $entityPkValue,
  212. 'vote_count' => $row['vote_count'],
  213. 'vote_value_sum' => $row['vote_value_sum'],
  214. 'percent' => $row['vote_value_sum'] / $row['vote_count'] / 5 * 100,
  215. 'percent_approved' => $row['app_vote_count'] ? $row['app_vote_value_sum'] /
  216. $row['app_vote_count'] /
  217. 5 *
  218. 100 : 0,
  219. 'store_id' => $row['store_id'],
  220. ];
  221. if (isset($oldData[$row['store_id']])) {
  222. $condition = ['primary_id = ?' => $oldData[$row['store_id']]];
  223. $connection->update($this->_aggregateTable, $saveData, $condition);
  224. } else {
  225. $connection->insert($this->_aggregateTable, $saveData);
  226. }
  227. $usedStores[] = $row['store_id'];
  228. }
  229. $toDelete = array_diff(array_keys($oldData), $usedStores);
  230. foreach ($toDelete as $storeId) {
  231. $condition = ['primary_id = ?' => $oldData[$storeId]];
  232. $connection->delete($this->_aggregateTable, $condition);
  233. }
  234. }
  235. /**
  236. * Load object data by optionId
  237. * Method renamed from 'load'.
  238. *
  239. * @param int $optionId
  240. * @return array
  241. */
  242. public function loadDataById($optionId)
  243. {
  244. if (!$this->_optionData || $this->_optionId != $optionId) {
  245. $connection = $this->getConnection();
  246. $select = $connection->select();
  247. $select->from($this->_ratingOptionTable)->where('option_id = :option_id');
  248. $data = $connection->fetchRow($select, [':option_id' => $optionId]);
  249. $this->_optionData = $data;
  250. $this->_optionId = $optionId;
  251. return $data;
  252. }
  253. return $this->_optionData;
  254. }
  255. }