123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Review\Model\ResourceModel;
- use Magento\Framework\App\Config\ScopeConfigInterface;
- use Magento\Framework\App\ObjectManager;
- /**
- * Rating resource model
- *
- * @api
- *
- * @author Magento Core Team <core@magentocommerce.com>
- * @since 100.0.2
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class Rating extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
- {
- const RATING_STATUS_APPROVED = 'Approved';
- /**
- * Store manager
- *
- * @var \Magento\Store\Model\StoreManagerInterface
- */
- protected $_storeManager;
- /**
- * @var \Magento\Framework\Module\Manager
- */
- protected $moduleManager;
- /**
- * @var \Psr\Log\LoggerInterface
- */
- protected $_logger;
- /**
- * @var ScopeConfigInterface
- */
- private $scopeConfig;
- /**
- * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
- * @param \Psr\Log\LoggerInterface $logger
- * @param \Magento\Framework\Module\Manager $moduleManager
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param Review\Summary $reviewSummary
- * @param string $connectionName
- * @param ScopeConfigInterface|null $scopeConfig
- */
- public function __construct(
- \Magento\Framework\Model\ResourceModel\Db\Context $context,
- \Psr\Log\LoggerInterface $logger,
- \Magento\Framework\Module\Manager $moduleManager,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
- \Magento\Review\Model\ResourceModel\Review\Summary $reviewSummary,
- $connectionName = null,
- ScopeConfigInterface $scopeConfig = null
- ) {
- $this->moduleManager = $moduleManager;
- $this->_storeManager = $storeManager;
- $this->_logger = $logger;
- $this->_reviewSummary = $reviewSummary;
- $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class);
- parent::__construct($context, $connectionName);
- }
- /**
- * Resource initialization
- *
- * @return void
- */
- protected function _construct()
- {
- $this->_init('rating', 'rating_id');
- }
- /**
- * Initialize unique fields
- *
- * @return $this
- */
- protected function _initUniqueFields()
- {
- $this->_uniqueFields = [['field' => 'rating_code', 'title' => '']];
- return $this;
- }
- /**
- * Retrieve select object for load object data
- *
- * @param string $field
- * @param mixed $value
- * @param \Magento\Review\Model\Rating $object
- * @return \Magento\Framework\DB\Select
- */
- protected function _getLoadSelect($field, $value, $object)
- {
- $connection = $this->getConnection();
- $table = $this->getMainTable();
- $storeId = (int)$this->_storeManager->getStore(\Magento\Store\Model\Store::ADMIN_CODE)->getId();
- $select = parent::_getLoadSelect($field, $value, $object);
- $codeExpr = $connection->getIfNullSql('title.value', "{$table}.rating_code");
- $select->joinLeft(
- ['title' => $this->getTable('rating_title')],
- $connection->quoteInto("{$table}.rating_id = title.rating_id AND title.store_id = ?", $storeId),
- ['rating_code' => $codeExpr]
- );
- return $select;
- }
- /**
- * Actions after load
- *
- * @param \Magento\Framework\Model\AbstractModel|\Magento\Review\Model\Rating $object
- * @return $this
- */
- protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
- {
- parent::_afterLoad($object);
- if (!$object->getId()) {
- return $this;
- }
- $connection = $this->getConnection();
- $bind = [':rating_id' => (int)$object->getId()];
- // load rating titles
- $select = $connection->select()->from(
- $this->getTable('rating_title'),
- ['store_id', 'value']
- )->where(
- 'rating_id=:rating_id'
- );
- $result = $connection->fetchPairs($select, $bind);
- if ($result) {
- $object->setRatingCodes($result);
- }
- // load rating available in stores
- $object->setStores($this->getStores((int)$object->getId()));
- return $this;
- }
- /**
- * Retrieve store IDs related to given rating
- *
- * @param int $ratingId
- * @return array
- */
- public function getStores($ratingId)
- {
- $select = $this->getConnection()->select()->from(
- $this->getTable('rating_store'),
- 'store_id'
- )->where(
- 'rating_id = ?',
- $ratingId
- );
- return $this->getConnection()->fetchCol($select);
- }
- /**
- * Actions after save
- *
- * @param \Magento\Framework\Model\AbstractModel|\Magento\Review\Model\Rating $object
- * @return $this
- */
- protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
- {
- parent::_afterSave($object);
- if ($object->hasRatingCodes()) {
- $this->processRatingCodes($object);
- }
- if ($object->hasStores()) {
- $this->processRatingStores($object);
- }
- return $this;
- }
- /**
- * Process rating codes
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function processRatingCodes(\Magento\Framework\Model\AbstractModel $object)
- {
- $connection = $this->getConnection();
- $ratingId = (int)$object->getId();
- $table = $this->getTable('rating_title');
- $select = $connection->select()->from($table, ['store_id', 'value'])
- ->where('rating_id = :rating_id');
- $old = $connection->fetchPairs($select, [':rating_id' => $ratingId]);
- $new = array_filter(array_map('trim', $object->getRatingCodes()));
- $this->deleteRatingData($ratingId, $table, array_keys(array_diff_assoc($old, $new)));
- $insert = [];
- foreach (array_diff_assoc($new, $old) as $storeId => $title) {
- $insert[] = ['rating_id' => $ratingId, 'store_id' => (int)$storeId, 'value' => $title];
- }
- $this->insertRatingData($table, $insert);
- return $this;
- }
- /**
- * Process rating stores
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function processRatingStores(\Magento\Framework\Model\AbstractModel $object)
- {
- $connection = $this->getConnection();
- $ratingId = (int)$object->getId();
- $table = $this->getTable('rating_store');
- $select = $connection->select()->from($table, ['store_id'])
- ->where('rating_id = :rating_id');
- $old = $connection->fetchCol($select, [':rating_id' => $ratingId]);
- $new = $object->getStores();
- $this->deleteRatingData($ratingId, $table, array_diff($old, $new));
- $insert = [];
- foreach (array_diff($new, $old) as $storeId) {
- $insert[] = ['rating_id' => $ratingId, 'store_id' => (int)$storeId];
- }
- $this->insertRatingData($table, $insert);
- return $this;
- }
- /**
- * Delete rating data
- *
- * @param int $ratingId
- * @param string $table
- * @param array $storeIds
- * @return void
- */
- protected function deleteRatingData($ratingId, $table, array $storeIds)
- {
- if (empty($storeIds)) {
- return;
- }
- $connection = $this->getConnection();
- $connection->beginTransaction();
- try {
- $where = ['rating_id = ?' => $ratingId, 'store_id IN(?)' => $storeIds];
- $connection->delete($table, $where);
- $connection->commit();
- } catch (\Exception $e) {
- $this->_logger->critical($e);
- $connection->rollBack();
- }
- }
- /**
- * Insert rating data
- *
- * @param string $table
- * @param array $data
- * @return void
- */
- protected function insertRatingData($table, array $data)
- {
- if (empty($data)) {
- return;
- }
- $connection = $this->getConnection();
- $connection->beginTransaction();
- try {
- $connection->insertMultiple($table, $data);
- $connection->commit();
- } catch (\Exception $e) {
- $this->_logger->critical($e);
- $connection->rollBack();
- }
- }
- /**
- * Perform actions after object delete
- *
- * Prepare rating data for reaggregate all data for reviews
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function _afterDelete(\Magento\Framework\Model\AbstractModel $object)
- {
- parent::_afterDelete($object);
- if (!$this->moduleManager->isEnabled('Magento_Review') &&
- !$this->scopeConfig->getValue(
- \Magento\Review\Observer\PredispatchReviewObserver::XML_PATH_REVIEW_ACTIVE,
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- )
- ) {
- return $this;
- }
- $data = $this->_getEntitySummaryData($object);
- $summary = [];
- foreach ($data as $row) {
- $clone = clone $object;
- $clone->addData($row);
- $summary[$clone->getStoreId()][$clone->getEntityPkValue()] = $clone;
- }
- $this->_reviewSummary->reAggregate($summary);
- return $this;
- }
- /**
- * Return array of rating summary
- *
- * @param \Magento\Review\Model\Rating $object
- * @param boolean $onlyForCurrentStore
- * @return array
- */
- public function getEntitySummary($object, $onlyForCurrentStore = true)
- {
- $data = $this->_getEntitySummaryData($object);
- if ($onlyForCurrentStore) {
- foreach ($data as $row) {
- if ($row['store_id'] == $this->_storeManager->getStore()->getId()) {
- $object->addData($row);
- }
- }
- return $object;
- }
- $stores = $this->_storeManager->getStores();
- $result = [];
- foreach ($data as $row) {
- $clone = clone $object;
- $clone->addData($row);
- $result[$clone->getStoreId()] = $clone;
- }
- $usedStoresId = array_keys($result);
- foreach ($stores as $store) {
- if (!in_array($store->getId(), $usedStoresId)) {
- $clone = clone $object;
- $clone->setCount(0);
- $clone->setSum(0);
- $clone->setStoreId($store->getId());
- $result[$store->getId()] = $clone;
- }
- }
- return array_values($result);
- }
- /**
- * Return data of rating summary
- *
- * @param \Magento\Review\Model\Rating $object
- * @return array
- */
- protected function _getEntitySummaryData($object)
- {
- $connection = $this->getConnection();
- $sumColumn = new \Zend_Db_Expr("SUM(rating_vote.{$connection->quoteIdentifier('percent')})");
- $countColumn = new \Zend_Db_Expr("COUNT(*)");
- $select = $connection->select()->from(
- ['rating_vote' => $this->getTable('rating_option_vote')],
- ['entity_pk_value' => 'rating_vote.entity_pk_value', 'sum' => $sumColumn, 'count' => $countColumn]
- )->join(
- ['review' => $this->getTable('review')],
- 'rating_vote.review_id=review.review_id',
- []
- )->joinLeft(
- ['review_store' => $this->getTable('review_store')],
- 'rating_vote.review_id=review_store.review_id',
- ['review_store.store_id']
- );
- if (!$this->_storeManager->isSingleStoreMode()) {
- $select->join(
- ['rating_store' => $this->getTable('rating_store')],
- 'rating_store.rating_id = rating_vote.rating_id AND rating_store.store_id = review_store.store_id',
- []
- );
- }
- $select->join(
- ['review_status' => $this->getTable('review_status')],
- 'review.status_id = review_status.status_id',
- []
- )->where(
- 'review_status.status_code = :status_code'
- )->group(
- 'rating_vote.entity_pk_value'
- )->group(
- 'review_store.store_id'
- );
- $bind = [':status_code' => self::RATING_STATUS_APPROVED];
- $entityPkValue = $object->getEntityPkValue();
- if ($entityPkValue) {
- $select->where('rating_vote.entity_pk_value = :pk_value');
- $bind[':pk_value'] = $entityPkValue;
- }
- return $connection->fetchAll($select, $bind);
- }
- /**
- * Review summary
- *
- * @param \Magento\Review\Model\Rating $object
- * @param boolean $onlyForCurrentStore
- * @return array
- */
- public function getReviewSummary($object, $onlyForCurrentStore = true)
- {
- $connection = $this->getConnection();
- $sumColumn = new \Zend_Db_Expr("SUM(rating_vote.{$connection->quoteIdentifier('percent')})");
- $countColumn = new \Zend_Db_Expr('COUNT(*)');
- $select = $connection->select()->from(
- ['rating_vote' => $this->getTable('rating_option_vote')],
- ['sum' => $sumColumn, 'count' => $countColumn]
- )->joinLeft(
- ['review_store' => $this->getTable('review_store')],
- 'rating_vote.review_id = review_store.review_id',
- ['review_store.store_id']
- );
- if (!$this->_storeManager->isSingleStoreMode()) {
- $select->join(
- ['rating_store' => $this->getTable('rating_store')],
- 'rating_store.rating_id = rating_vote.rating_id AND rating_store.store_id = review_store.store_id',
- []
- );
- }
- $select->where(
- 'rating_vote.review_id = :review_id'
- )->group(
- 'rating_vote.review_id'
- )->group(
- 'review_store.store_id'
- );
- $data = $connection->fetchAll($select, [':review_id' => $object->getReviewId()]);
- $currentStore = $this->_storeManager->isSingleStoreMode() ? $this->_storeManager->getStore()->getId() : null;
- if ($onlyForCurrentStore) {
- foreach ($data as $row) {
- if ($row['store_id'] !== $currentStore) {
- $object->addData($row);
- }
- }
- return $object;
- }
- $result = [];
- $stores = $this->_storeManager->getStore()->getResourceCollection()->load();
- foreach ($data as $row) {
- $clone = clone $object;
- $clone->addData($row);
- $result[$clone->getStoreId()] = $clone;
- }
- $usedStoresId = array_keys($result);
- foreach ($stores as $store) {
- if (!in_array($store->getId(), $usedStoresId)) {
- $clone = clone $object;
- $clone->setCount(0);
- $clone->setSum(0);
- $clone->setStoreId($store->getId());
- $result[$store->getId()] = $clone;
- }
- }
- return array_values($result);
- }
- /**
- * Get rating entity type id by code
- *
- * @param string $entityCode
- * @return int
- */
- public function getEntityIdByCode($entityCode)
- {
- $select = $this->getConnection()->select()->from(
- $this->getTable('rating_entity'),
- ['entity_id']
- )->where(
- 'entity_code = :entity_code'
- );
- return $this->getConnection()->fetchOne($select, [':entity_code' => $entityCode]);
- }
- /**
- * Delete ratings by product id
- *
- * @param int $productId
- * @return $this
- */
- public function deleteAggregatedRatingsByProductId($productId)
- {
- $entityId = $this->getEntityIdByCode(\Magento\Review\Model\Rating::ENTITY_PRODUCT_CODE);
- $connection = $this->getConnection();
- $select = $connection->select()->from($this->getMainTable(), 'rating_id')->where('entity_id = :entity_id');
- $ratingIds = $connection->fetchCol($select, [':entity_id' => $entityId]);
- if ($ratingIds) {
- $where = ['entity_pk_value = ?' => (int)$productId, 'rating_id IN(?)' => $ratingIds];
- $connection->delete($this->getTable('rating_option_vote_aggregated'), $where);
- }
- return $this;
- }
- }
|