![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-review/Model/ResourceModel/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Review\Model\ResourceModel; use Magento\Framework\Model\AbstractModel; /** * Review resource model * * @api * @since 100.0.2 */ class Review extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { /** * Review table * * @var string */ protected $_reviewTable; /** * Review Detail table * * @var string */ protected $_reviewDetailTable; /** * Review status table * * @var string */ protected $_reviewStatusTable; /** * Review entity table * * @var string */ protected $_reviewEntityTable; /** * Review store table * * @var string */ protected $_reviewStoreTable; /** * Review aggregate table * * @var string */ protected $_aggregateTable; /** * Cache of deleted rating data * * @var array */ private $_deleteCache = []; /** * Core date model * * @var \Magento\Framework\Stdlib\DateTime\DateTime */ protected $_date; /** * Core model store manager interface * * @var \Magento\Store\Model\StoreManagerInterface */ protected $_storeManager; /** * Rating model * * @var \Magento\Review\Model\RatingFactory */ protected $_ratingFactory; /** * Rating resource model * * @var \Magento\Review\Model\ResourceModel\Rating\Option */ protected $_ratingOptions; /** * @param \Magento\Framework\Model\ResourceModel\Db\Context $context * @param \Magento\Framework\Stdlib\DateTime\DateTime $date * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Review\Model\RatingFactory $ratingFactory * @param \Magento\Review\Model\ResourceModel\Rating\Option $ratingOptions * @param string $connectionName */ public function __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 ) { $this->_date = $date; $this->_storeManager = $storeManager; $this->_ratingFactory = $ratingFactory; $this->_ratingOptions = $ratingOptions; parent::__construct($context, $connectionName); } /** * Define main table. Define other tables name * * @return void */ protected function _construct() { $this->_init('review', 'review_id'); $this->_reviewTable = $this->getTable('review'); $this->_reviewDetailTable = $this->getTable('review_detail'); $this->_reviewStatusTable = $this->getTable('review_status'); $this->_reviewEntityTable = $this->getTable('review_entity'); $this->_reviewStoreTable = $this->getTable('review_store'); $this->_aggregateTable = $this->getTable('review_entity_summary'); } /** * Retrieve select object for load object data * * @param string $field * @param mixed $value * @param AbstractModel $object * @return \Magento\Framework\DB\Select */ protected function _getLoadSelect($field, $value, $object) { $select = parent::_getLoadSelect($field, $value, $object); $select->join( $this->_reviewDetailTable, $this->getMainTable() . ".review_id = {$this->_reviewDetailTable}.review_id" ); return $select; } /** * Perform actions before object save * * @param AbstractModel $object * @return $this */ protected function _beforeSave(AbstractModel $object) { if (!$object->getId()) { $object->setCreatedAt($this->_date->gmtDate()); } if ($object->hasData('stores') && is_array($object->getStores())) { $stores = $object->getStores(); $stores[] = 0; $object->setStores($stores); } elseif ($object->hasData('stores')) { $object->setStores([$object->getStores(), 0]); } return $this; } /** * Perform actions after object save * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ protected function _afterSave(AbstractModel $object) { $connection = $this->getConnection(); /** * save detail */ $detail = [ 'title' => $object->getTitle(), 'detail' => $object->getDetail(), 'nickname' => $object->getNickname(), ]; $select = $connection->select()->from($this->_reviewDetailTable, 'detail_id')->where('review_id = :review_id'); $detailId = $connection->fetchOne($select, [':review_id' => $object->getId()]); if ($detailId) { $condition = ["detail_id = ?" => $detailId]; $connection->update($this->_reviewDetailTable, $detail, $condition); } else { $detail['store_id'] = $object->getStoreId(); $detail['customer_id'] = $object->getCustomerId(); $detail['review_id'] = $object->getId(); $connection->insert($this->_reviewDetailTable, $detail); } /** * save stores */ $stores = $object->getStores(); if (!empty($stores)) { $condition = ['review_id = ?' => $object->getId()]; $connection->delete($this->_reviewStoreTable, $condition); $insertedStoreIds = []; foreach ($stores as $storeId) { if (in_array($storeId, $insertedStoreIds)) { continue; } $insertedStoreIds[] = $storeId; $storeInsert = ['store_id' => $storeId, 'review_id' => $object->getId()]; $connection->insert($this->_reviewStoreTable, $storeInsert); } } // reaggregate ratings, that depend on this review $this->_aggregateRatings($this->_loadVotedRatingIds($object->getId()), $object->getEntityPkValue()); return $this; } /** * Perform actions after object load * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ protected function _afterLoad(AbstractModel $object) { $connection = $this->getConnection(); $select = $connection->select()->from( $this->_reviewStoreTable, ['store_id'] )->where( 'review_id = :review_id' ); $stores = $connection->fetchCol($select, [':review_id' => $object->getId()]); if (empty($stores) && $this->_storeManager->hasSingleStore()) { $object->setStores([$this->_storeManager->getStore(true)->getId()]); } else { $object->setStores($stores); } return $this; } /** * Action before delete * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ protected function _beforeDelete(AbstractModel $object) { // prepare rating ids, that depend on review $this->_deleteCache = [ 'ratingIds' => $this->_loadVotedRatingIds($object->getId()), 'entityPkValue' => $object->getEntityPkValue(), ]; return $this; } /** * Perform actions after object delete * * @param \Magento\Framework\Model\AbstractModel $object * @return $this */ public function afterDeleteCommit(AbstractModel $object) { $this->aggregate($object); // reaggregate ratings, that depended on this review $this->_aggregateRatings($this->_deleteCache['ratingIds'], $this->_deleteCache['entityPkValue']); $this->_deleteCache = []; return $this; } /** * Retrieves total reviews * * @param int $entityPkValue * @param bool $approvedOnly * @param int $storeId * @return int */ public function getTotalReviews($entityPkValue, $approvedOnly = false, $storeId = 0) { $connection = $this->getConnection(); $select = $connection->select()->from( $this->_reviewTable, ['review_count' => new \Zend_Db_Expr('COUNT(*)')] )->where( "{$this->_reviewTable}.entity_pk_value = :pk_value" ); $bind = [':pk_value' => $entityPkValue]; if ($storeId > 0) { $select->join( ['store' => $this->_reviewStoreTable], $this->_reviewTable . '.review_id=store.review_id AND store.store_id = :store_id', [] ); $bind[':store_id'] = (int) $storeId; } if ($approvedOnly) { $select->where("{$this->_reviewTable}.status_id = :status_id"); $bind[':status_id'] = \Magento\Review\Model\Review::STATUS_APPROVED; } return $connection->fetchOne($select, $bind); } /** * Aggregate * * @param \Magento\Framework\Model\AbstractModel $object * @return void */ public function aggregate($object) { if (!$object->getEntityPkValue() && $object->getId()) { $object->load($object->getReviewId()); } $ratingModel = $this->_ratingFactory->create(); $ratingSummaries = $ratingModel->getEntitySummary($object->getEntityPkValue(), false); foreach ($ratingSummaries as $ratingSummaryObject) { $this->aggregateReviewSummary($object, $ratingSummaryObject); } } /** * Aggregate review summary * * @param \Magento\Framework\Model\AbstractModel $object * @param \Magento\Review\Model\Rating $ratingSummaryObject * @return void */ protected function aggregateReviewSummary($object, $ratingSummaryObject) { $connection = $this->getConnection(); if ($ratingSummaryObject->getCount()) { $ratingSummary = round($ratingSummaryObject->getSum() / $ratingSummaryObject->getCount()); } else { $ratingSummary = $ratingSummaryObject->getSum(); } $reviewsCount = $this->getTotalReviews( $object->getEntityPkValue(), true, $ratingSummaryObject->getStoreId() ); $select = $connection->select()->from($this->_aggregateTable) ->where('entity_pk_value = :pk_value') ->where('store_id = :store_id') ->where('entity_type = :entity_type'); $bind = [ ':pk_value' => $object->getEntityPkValue(), ':store_id' => $ratingSummaryObject->getStoreId(), ':entity_type' => $object->getEntityId(), ]; $oldData = $connection->fetchRow($select, $bind); $data = new \Magento\Framework\DataObject(); $data->setReviewsCount($reviewsCount) ->setEntityPkValue($object->getEntityPkValue()) ->setEntityType($object->getEntityId()) ->setRatingSummary($ratingSummary > 0 ? $ratingSummary : 0) ->setStoreId($ratingSummaryObject->getStoreId()); $this->writeReviewSummary($oldData, $data); } /** * Write rating summary * * @param array|bool $oldData * @param \Magento\Framework\DataObject $data * @return void */ protected function writeReviewSummary($oldData, \Magento\Framework\DataObject $data) { $connection = $this->getConnection(); $connection->beginTransaction(); try { if (isset($oldData['primary_id']) && $oldData['primary_id'] > 0) { $condition = ["{$this->_aggregateTable}.primary_id = ?" => $oldData['primary_id']]; $connection->update($this->_aggregateTable, $data->getData(), $condition); } else { $connection->insert($this->_aggregateTable, $data->getData()); } $connection->commit(); } catch (\Exception $e) { $connection->rollBack(); } } /** * Get rating IDs from review votes * * @param int $reviewId * @return array */ protected function _loadVotedRatingIds($reviewId) { $connection = $this->getConnection(); if (empty($reviewId)) { return []; } $select = $connection->select()->from(['v' => $this->getTable('rating_option_vote')], 'r.rating_id') ->joinInner(['r' => $this->getTable('rating')], 'v.rating_id=r.rating_id') ->where('v.review_id = :revire_id'); return $connection->fetchCol($select, [':revire_id' => $reviewId]); } /** * Aggregate this review's ratings. * * Useful, when changing the review. * * @param int[] $ratingIds * @param int $entityPkValue * @return $this */ protected function _aggregateRatings($ratingIds, $entityPkValue) { if ($ratingIds && !is_array($ratingIds)) { $ratingIds = [(int)$ratingIds]; } if ($ratingIds && $entityPkValue) { foreach ($ratingIds as $ratingId) { $this->_ratingOptions->aggregateEntityByRatingId($ratingId, $entityPkValue); } } return $this; } /** * Reaggregate this review's ratings. * * @param int $reviewId * @param int $entityPkValue * @return void */ public function reAggregateReview($reviewId, $entityPkValue) { $this->_aggregateRatings($this->_loadVotedRatingIds($reviewId), $entityPkValue); } /** * Get review entity type id by code * * @param string $entityCode * @return int|bool */ public function getEntityIdByCode($entityCode) { $connection = $this->getConnection(); $select = $connection->select()->from($this->_reviewEntityTable, ['entity_id']) ->where('entity_code = :entity_code'); return $connection->fetchOne($select, [':entity_code' => $entityCode]); } /** * Delete reviews by product id. * * Better to call this method in transaction, because operation performed on two separated tables * * @param int $productId * @return $this */ public function deleteReviewsByProductId($productId) { $this->getConnection()->delete( $this->_reviewTable, [ 'entity_pk_value=?' => $productId, 'entity_id=?' => $this->getEntityIdByCode(\Magento\Review\Model\Review::ENTITY_PRODUCT_CODE) ] ); $this->getConnection()->delete( $this->getTable('review_entity_summary'), [ 'entity_pk_value=?' => $productId, 'entity_type=?' => $this->getEntityIdByCode(\Magento\Review\Model\Review::ENTITY_PRODUCT_CODE) ] ); return $this; } }