Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Review.php
Go to the documentation of this file.
1 <?php
7 
9 
17 {
23  protected $_reviewTable;
24 
31 
38 
45 
51  protected $_reviewStoreTable;
52 
58  protected $_aggregateTable;
59 
65  private $_deleteCache = [];
66 
72  protected $_date;
73 
79  protected $_storeManager;
80 
86  protected $_ratingFactory;
87 
93  protected $_ratingOptions;
94 
103  public function __construct(
104  \Magento\Framework\Model\ResourceModel\Db\Context $context,
105  \Magento\Framework\Stdlib\DateTime\DateTime $date,
106  \Magento\Store\Model\StoreManagerInterface $storeManager,
107  \Magento\Review\Model\RatingFactory $ratingFactory,
108  Rating\Option $ratingOptions,
109  $connectionName = null
110  ) {
111  $this->_date = $date;
112  $this->_storeManager = $storeManager;
113  $this->_ratingFactory = $ratingFactory;
114  $this->_ratingOptions = $ratingOptions;
115 
116  parent::__construct($context, $connectionName);
117  }
118 
124  protected function _construct()
125  {
126  $this->_init('review', 'review_id');
127  $this->_reviewTable = $this->getTable('review');
128  $this->_reviewDetailTable = $this->getTable('review_detail');
129  $this->_reviewStatusTable = $this->getTable('review_status');
130  $this->_reviewEntityTable = $this->getTable('review_entity');
131  $this->_reviewStoreTable = $this->getTable('review_store');
132  $this->_aggregateTable = $this->getTable('review_entity_summary');
133  }
134 
143  protected function _getLoadSelect($field, $value, $object)
144  {
145  $select = parent::_getLoadSelect($field, $value, $object);
146  $select->join(
147  $this->_reviewDetailTable,
148  $this->getMainTable() . ".review_id = {$this->_reviewDetailTable}.review_id"
149  );
150  return $select;
151  }
152 
159  protected function _beforeSave(AbstractModel $object)
160  {
161  if (!$object->getId()) {
162  $object->setCreatedAt($this->_date->gmtDate());
163  }
164  if ($object->hasData('stores') && is_array($object->getStores())) {
165  $stores = $object->getStores();
166  $stores[] = 0;
167  $object->setStores($stores);
168  } elseif ($object->hasData('stores')) {
169  $object->setStores([$object->getStores(), 0]);
170  }
171  return $this;
172  }
173 
180  protected function _afterSave(AbstractModel $object)
181  {
182  $connection = $this->getConnection();
186  $detail = [
187  'title' => $object->getTitle(),
188  'detail' => $object->getDetail(),
189  'nickname' => $object->getNickname(),
190  ];
191  $select = $connection->select()->from($this->_reviewDetailTable, 'detail_id')->where('review_id = :review_id');
192  $detailId = $connection->fetchOne($select, [':review_id' => $object->getId()]);
193 
194  if ($detailId) {
195  $condition = ["detail_id = ?" => $detailId];
196  $connection->update($this->_reviewDetailTable, $detail, $condition);
197  } else {
198  $detail['store_id'] = $object->getStoreId();
199  $detail['customer_id'] = $object->getCustomerId();
200  $detail['review_id'] = $object->getId();
201  $connection->insert($this->_reviewDetailTable, $detail);
202  }
203 
207  $stores = $object->getStores();
208  if (!empty($stores)) {
209  $condition = ['review_id = ?' => $object->getId()];
210  $connection->delete($this->_reviewStoreTable, $condition);
211 
212  $insertedStoreIds = [];
213  foreach ($stores as $storeId) {
214  if (in_array($storeId, $insertedStoreIds)) {
215  continue;
216  }
217 
218  $insertedStoreIds[] = $storeId;
219  $storeInsert = ['store_id' => $storeId, 'review_id' => $object->getId()];
220  $connection->insert($this->_reviewStoreTable, $storeInsert);
221  }
222  }
223 
224  // reaggregate ratings, that depend on this review
225  $this->_aggregateRatings($this->_loadVotedRatingIds($object->getId()), $object->getEntityPkValue());
226 
227  return $this;
228  }
229 
236  protected function _afterLoad(AbstractModel $object)
237  {
238  $connection = $this->getConnection();
239  $select = $connection->select()->from(
240  $this->_reviewStoreTable,
241  ['store_id']
242  )->where(
243  'review_id = :review_id'
244  );
245  $stores = $connection->fetchCol($select, [':review_id' => $object->getId()]);
246  if (empty($stores) && $this->_storeManager->hasSingleStore()) {
247  $object->setStores([$this->_storeManager->getStore(true)->getId()]);
248  } else {
249  $object->setStores($stores);
250  }
251  return $this;
252  }
253 
260  protected function _beforeDelete(AbstractModel $object)
261  {
262  // prepare rating ids, that depend on review
263  $this->_deleteCache = [
264  'ratingIds' => $this->_loadVotedRatingIds($object->getId()),
265  'entityPkValue' => $object->getEntityPkValue(),
266  ];
267  return $this;
268  }
269 
276  public function afterDeleteCommit(AbstractModel $object)
277  {
278  $this->aggregate($object);
279 
280  // reaggregate ratings, that depended on this review
281  $this->_aggregateRatings($this->_deleteCache['ratingIds'], $this->_deleteCache['entityPkValue']);
282  $this->_deleteCache = [];
283 
284  return $this;
285  }
286 
295  public function getTotalReviews($entityPkValue, $approvedOnly = false, $storeId = 0)
296  {
297  $connection = $this->getConnection();
298  $select = $connection->select()->from(
299  $this->_reviewTable,
300  ['review_count' => new \Zend_Db_Expr('COUNT(*)')]
301  )->where(
302  "{$this->_reviewTable}.entity_pk_value = :pk_value"
303  );
304  $bind = [':pk_value' => $entityPkValue];
305  if ($storeId > 0) {
306  $select->join(
307  ['store' => $this->_reviewStoreTable],
308  $this->_reviewTable . '.review_id=store.review_id AND store.store_id = :store_id',
309  []
310  );
311  $bind[':store_id'] = (int) $storeId;
312  }
313  if ($approvedOnly) {
314  $select->where("{$this->_reviewTable}.status_id = :status_id");
315  $bind[':status_id'] = \Magento\Review\Model\Review::STATUS_APPROVED;
316  }
317  return $connection->fetchOne($select, $bind);
318  }
319 
326  public function aggregate($object)
327  {
328  if (!$object->getEntityPkValue() && $object->getId()) {
329  $object->load($object->getReviewId());
330  }
331 
332  $ratingModel = $this->_ratingFactory->create();
333  $ratingSummaries = $ratingModel->getEntitySummary($object->getEntityPkValue(), false);
334 
335  foreach ($ratingSummaries as $ratingSummaryObject) {
336  $this->aggregateReviewSummary($object, $ratingSummaryObject);
337  }
338  }
339 
347  protected function aggregateReviewSummary($object, $ratingSummaryObject)
348  {
349  $connection = $this->getConnection();
350 
351  if ($ratingSummaryObject->getCount()) {
352  $ratingSummary = round($ratingSummaryObject->getSum() / $ratingSummaryObject->getCount());
353  } else {
354  $ratingSummary = $ratingSummaryObject->getSum();
355  }
356 
357  $reviewsCount = $this->getTotalReviews(
358  $object->getEntityPkValue(),
359  true,
360  $ratingSummaryObject->getStoreId()
361  );
362  $select = $connection->select()->from($this->_aggregateTable)
363  ->where('entity_pk_value = :pk_value')
364  ->where('entity_type = :entity_type')
365  ->where('store_id = :store_id');
366  $bind = [
367  ':pk_value' => $object->getEntityPkValue(),
368  ':entity_type' => $object->getEntityId(),
369  ':store_id' => $ratingSummaryObject->getStoreId(),
370  ];
371  $oldData = $connection->fetchRow($select, $bind);
372  $data = new \Magento\Framework\DataObject();
373 
374  $data->setReviewsCount($reviewsCount)
375  ->setEntityPkValue($object->getEntityPkValue())
376  ->setEntityType($object->getEntityId())
377  ->setRatingSummary($ratingSummary > 0 ? $ratingSummary : 0)
378  ->setStoreId($ratingSummaryObject->getStoreId());
379 
380  $this->writeReviewSummary($oldData, $data);
381  }
382 
390  protected function writeReviewSummary($oldData, \Magento\Framework\DataObject $data)
391  {
392  $connection = $this->getConnection();
393  $connection->beginTransaction();
394  try {
395  if (isset($oldData['primary_id']) && $oldData['primary_id'] > 0) {
396  $condition = ["{$this->_aggregateTable}.primary_id = ?" => $oldData['primary_id']];
397  $connection->update($this->_aggregateTable, $data->getData(), $condition);
398  } else {
399  $connection->insert($this->_aggregateTable, $data->getData());
400  }
401  $connection->commit();
402  } catch (\Exception $e) {
403  $connection->rollBack();
404  }
405  }
406 
413  protected function _loadVotedRatingIds($reviewId)
414  {
415  $connection = $this->getConnection();
416  if (empty($reviewId)) {
417  return [];
418  }
419  $select = $connection->select()->from(['v' => $this->getTable('rating_option_vote')], 'r.rating_id')
420  ->joinInner(['r' => $this->getTable('rating')], 'v.rating_id=r.rating_id')
421  ->where('v.review_id = :revire_id');
422  return $connection->fetchCol($select, [':revire_id' => $reviewId]);
423  }
424 
433  protected function _aggregateRatings($ratingIds, $entityPkValue)
434  {
435  if ($ratingIds && !is_array($ratingIds)) {
436  $ratingIds = [(int)$ratingIds];
437  }
438  if ($ratingIds && $entityPkValue) {
439  foreach ($ratingIds as $ratingId) {
440  $this->_ratingOptions->aggregateEntityByRatingId($ratingId, $entityPkValue);
441  }
442  }
443  return $this;
444  }
445 
453  public function reAggregateReview($reviewId, $entityPkValue)
454  {
455  $this->_aggregateRatings($this->_loadVotedRatingIds($reviewId), $entityPkValue);
456  }
457 
464  public function getEntityIdByCode($entityCode)
465  {
466  $connection = $this->getConnection();
467  $select = $connection->select()->from($this->_reviewEntityTable, ['entity_id'])
468  ->where('entity_code = :entity_code');
469  return $connection->fetchOne($select, [':entity_code' => $entityCode]);
470  }
471 
480  {
481  $this->getConnection()->delete(
482  $this->_reviewTable,
483  [
484  'entity_pk_value=?' => $productId,
485  'entity_id=?' => $this->getEntityIdByCode(\Magento\Review\Model\Review::ENTITY_PRODUCT_CODE)
486  ]
487  );
488  $this->getConnection()->delete(
489  $this->getTable('review_entity_summary'),
490  [
491  'entity_pk_value=?' => $productId,
492  'entity_type=?' => $this->getEntityIdByCode(\Magento\Review\Model\Review::ENTITY_PRODUCT_CODE)
493  ]
494  );
495  return $this;
496  }
497 }
_aggregateRatings($ratingIds, $entityPkValue)
Definition: Review.php:433
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
getTotalReviews($entityPkValue, $approvedOnly=false, $storeId=0)
Definition: Review.php:295
$storeManager
__construct(\Magento\Framework\Model\ResourceModel\Db\Context $context, \Magento\Framework\Stdlib\DateTime\DateTime $date, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Review\Model\RatingFactory $ratingFactory, Rating\Option $ratingOptions, $connectionName=null)
Definition: Review.php:103
writeReviewSummary($oldData, \Magento\Framework\DataObject $data)
Definition: Review.php:390
$value
Definition: gender.phtml:16
aggregateReviewSummary($object, $ratingSummaryObject)
Definition: Review.php:347
reAggregateReview($reviewId, $entityPkValue)
Definition: Review.php:453
_beforeSave(AbstractModel $object)
Definition: Review.php:159
_afterLoad(AbstractModel $object)
Definition: Review.php:236
_afterSave(AbstractModel $object)
Definition: Review.php:180
$connection
Definition: bulk.php:13
_getLoadSelect($field, $value, $object)
Definition: Review.php:143
_beforeDelete(AbstractModel $object)
Definition: Review.php:260
afterDeleteCommit(AbstractModel $object)
Definition: Review.php:276