diff --git a/app/code/Magento/Review/Block/Customer/View.php b/app/code/Magento/Review/Block/Customer/View.php index 237b972f16573..da5aff1f4d2f8 100644 --- a/app/code/Magento/Review/Block/Customer/View.php +++ b/app/code/Magento/Review/Block/Customer/View.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Review\Block\Customer; use Magento\Catalog\Model\Product; @@ -160,6 +161,7 @@ public function getRating() /** * Get rating summary * + * @deprecated * @return array */ public function getRatingSummary() @@ -201,26 +203,7 @@ public function dateFormat($date) } /** - * Get product reviews summary - * - * @param \Magento\Catalog\Model\Product $product - * @param bool $templateType - * @param bool $displayIfNoReviews - * @return string - */ - public function getReviewsSummaryHtml( - \Magento\Catalog\Model\Product $product, - $templateType = false, - $displayIfNoReviews = false - ) { - if (!$product->getRatingSummary()) { - $this->_reviewFactory->create()->getEntitySummary($product, $this->_storeManager->getStore()->getId()); - } - return parent::getReviewsSummaryHtml($product, $templateType, $displayIfNoReviews); - } - - /** - * @return string + * @inheritDoc */ protected function _toHtml() { diff --git a/app/code/Magento/Review/Block/Product/Compare/ListCompare/Plugin/Review.php b/app/code/Magento/Review/Block/Product/Compare/ListCompare/Plugin/Review.php deleted file mode 100644 index 8393f87f8d45d..0000000000000 --- a/app/code/Magento/Review/Block/Product/Compare/ListCompare/Plugin/Review.php +++ /dev/null @@ -1,58 +0,0 @@ -storeManager = $storeManager; - $this->reviewFactory = $reviewFactory; - } - - /** - * Initialize product review - * - * @param \Magento\Catalog\Block\Product\Compare\ListCompare $subject - * @param \Magento\Catalog\Model\Product $product - * @param bool $templateType - * @param bool $displayIfNoReviews - * - * @return void - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforeGetReviewsSummaryHtml( - \Magento\Catalog\Block\Product\Compare\ListCompare $subject, - \Magento\Catalog\Model\Product $product, - $templateType = false, - $displayIfNoReviews = false - ) { - if (!$product->getRatingSummary()) { - $this->reviewFactory->create()->getEntitySummary($product, $this->storeManager->getStore()->getId()); - } - } -} diff --git a/app/code/Magento/Review/Block/Product/ReviewRenderer.php b/app/code/Magento/Review/Block/Product/ReviewRenderer.php index 3183196ebf30c..0fd6327e1f777 100644 --- a/app/code/Magento/Review/Block/Product/ReviewRenderer.php +++ b/app/code/Magento/Review/Block/Product/ReviewRenderer.php @@ -5,10 +5,13 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Review\Block\Product; use Magento\Catalog\Block\Product\ReviewRendererInterface; use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; +use Magento\Review\Model\ReviewSummaryFactory; use Magento\Review\Observer\PredispatchReviewObserver; /** @@ -33,17 +36,26 @@ class ReviewRenderer extends \Magento\Framework\View\Element\Template implements */ protected $_reviewFactory; + /** + * @var ReviewSummaryFactory + */ + private $reviewSummaryFactory; + /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Review\Model\ReviewFactory $reviewFactory * @param array $data + * @param ReviewSummaryFactory $reviewSummaryFactory */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Review\Model\ReviewFactory $reviewFactory, - array $data = [] + array $data = [], + ReviewSummaryFactory $reviewSummaryFactory = null ) { $this->_reviewFactory = $reviewFactory; + $this->reviewSummaryFactory = $reviewSummaryFactory ?? + ObjectManager::getInstance()->get(ReviewSummaryFactory::class); parent::__construct($context, $data); } @@ -52,7 +64,7 @@ public function __construct( * * @return string */ - public function isReviewEnabled() : string + public function isReviewEnabled(): string { return $this->_scopeConfig->getValue( PredispatchReviewObserver::XML_PATH_REVIEW_ACTIVE, @@ -68,17 +80,22 @@ public function isReviewEnabled() : string * @param bool $displayIfNoReviews * * @return string + * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function getReviewsSummaryHtml( \Magento\Catalog\Model\Product $product, $templateType = self::DEFAULT_VIEW, $displayIfNoReviews = false ) { - if (!$product->getRatingSummary()) { - $this->_reviewFactory->create()->getEntitySummary($product, $this->_storeManager->getStore()->getId()); + if ($product->getRatingSummary() === null) { + $this->reviewSummaryFactory->create()->appendSummaryDataToObject( + $product, + $this->_storeManager->getStore()->getId() + ); } - if (!$product->getRatingSummary() && !$displayIfNoReviews) { + if (null === $product->getRatingSummary() && !$displayIfNoReviews) { return ''; } // pick template among available @@ -101,7 +118,7 @@ public function getReviewsSummaryHtml( */ public function getRatingSummary() { - return $this->getProduct()->getRatingSummary()->getRatingSummary(); + return $this->getProduct()->getRatingSummary(); } /** @@ -111,7 +128,7 @@ public function getRatingSummary() */ public function getReviewsCount() { - return $this->getProduct()->getRatingSummary()->getReviewsCount(); + return $this->getProduct()->getReviewsCount(); } /** diff --git a/app/code/Magento/Review/Block/View.php b/app/code/Magento/Review/Block/View.php index 95b7176b48c44..82a5f37f9b6bf 100644 --- a/app/code/Magento/Review/Block/View.php +++ b/app/code/Magento/Review/Block/View.php @@ -119,6 +119,7 @@ public function getRating() /** * Retrieve rating summary for current product * + * @deprecated * @return string */ public function getRatingSummary() @@ -160,23 +161,4 @@ public function dateFormat($date) { return $this->formatDate($date, \IntlDateFormatter::LONG); } - - /** - * Get product reviews summary - * - * @param \Magento\Catalog\Model\Product $product - * @param bool $templateType - * @param bool $displayIfNoReviews - * @return string - */ - public function getReviewsSummaryHtml( - \Magento\Catalog\Model\Product $product, - $templateType = false, - $displayIfNoReviews = false - ) { - if (!$product->getRatingSummary()) { - $this->_reviewFactory->create()->getEntitySummary($product, $this->_storeManager->getStore()->getId()); - } - return parent::getReviewsSummaryHtml($product, $templateType, $displayIfNoReviews); - } } diff --git a/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php b/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php index b69065fbaf6cd..f18bc2094930a 100644 --- a/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php +++ b/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Review\Model\ResourceModel\Review; use Magento\Framework\Model\AbstractModel; @@ -73,4 +74,46 @@ public function reAggregate($summary) } return $this; } + + /** + * Append review summary fields to product collection + * + * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection + * @param string $storeId + * @param string $entityCode + * @return Summary + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function appendSummaryFieldsToCollection( + \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection, + string $storeId, + string $entityCode + ) { + if (!$productCollection->isLoaded()) { + $summaryEntitySubSelect = $this->getConnection()->select(); + $summaryEntitySubSelect + ->from( + ['review_entity' => $this->getTable('review_entity')], + ['entity_id'] + )->where( + 'entity_code = ?', + $entityCode + ); + $joinCond = new \Zend_Db_Expr( + "e.entity_id = review_summary.entity_pk_value AND review_summary.store_id = {$storeId}" + . " AND review_summary.entity_type = ({$summaryEntitySubSelect})" + ); + $productCollection->getSelect() + ->joinLeft( + ['review_summary' => $this->getMainTable()], + $joinCond, + [ + 'reviews_count' => new \Zend_Db_Expr("IFNULL(review_summary.reviews_count, 0)"), + 'rating_summary' => new \Zend_Db_Expr("IFNULL(review_summary.rating_summary, 0)") + ] + ); + } + + return $this; + } } diff --git a/app/code/Magento/Review/Model/Review.php b/app/code/Magento/Review/Model/Review.php index e689d4ed460ac..0c581f570ef0c 100644 --- a/app/code/Magento/Review/Model/Review.php +++ b/app/code/Magento/Review/Model/Review.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Review\Model; use Magento\Framework\DataObject; @@ -100,6 +101,7 @@ class Review extends \Magento\Framework\Model\AbstractModel implements IdentityI /** * Review model summary * + * @deprecated Summary factory injected as separate property * @var \Magento\Review\Model\Review\Summary */ protected $_reviewSummary; @@ -214,6 +216,7 @@ public function aggregate() /** * Get entity summary * + * @deprecated * @param Product $product * @param int $storeId * @return void @@ -301,10 +304,12 @@ public function afterDeleteCommit() } /** - * Append review summary to product collection + * Append review summary data object to product collection * + * @deprecated * @param ProductCollection $collection * @return $this + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function appendSummary($collection) { @@ -313,7 +318,7 @@ public function appendSummary($collection) $entityIds[] = $item->getEntityId(); } - if (sizeof($entityIds) == 0) { + if (count($entityIds) === 0) { return $this; } @@ -356,7 +361,7 @@ public function isAvailableOnStore($store = null) { $store = $this->_storeManager->getStore($store); if ($store) { - return in_array($store->getId(), (array) $this->getStores()); + return in_array($store->getId(), (array)$this->getStores()); } return false; } diff --git a/app/code/Magento/Review/Model/ReviewSummary.php b/app/code/Magento/Review/Model/ReviewSummary.php new file mode 100644 index 0000000000000..46851339ae6d7 --- /dev/null +++ b/app/code/Magento/Review/Model/ReviewSummary.php @@ -0,0 +1,52 @@ +summaryCollectionFactory = $sumColFactory; + } + + /** + * Append review summary data to product + * + * @param AbstractModel $object + * @param int $storeId + * @param int $entityType + */ + public function appendSummaryDataToObject(AbstractModel $object, int $storeId, int $entityType = 1): void + { + $summary = $this->summaryCollectionFactory->create() + ->addEntityFilter($object->getId(), $entityType) + ->addStoreFilter($storeId) + ->getFirstItem(); + $object->addData( + [ + 'reviews_count' => $summary->getData('reviews_count'), + 'rating_summary' => $summary->getData('rating_summary') + ] + ); + } +} diff --git a/app/code/Magento/Review/Observer/CatalogBlockProductCollectionBeforeToHtmlObserver.php b/app/code/Magento/Review/Observer/CatalogBlockProductCollectionBeforeToHtmlObserver.php deleted file mode 100644 index f35d6eac27ea8..0000000000000 --- a/app/code/Magento/Review/Observer/CatalogBlockProductCollectionBeforeToHtmlObserver.php +++ /dev/null @@ -1,49 +0,0 @@ -_reviewFactory = $reviewFactory; - } - - /** - * Append review summary before rendering html - * - * @param \Magento\Framework\Event\Observer $observer - * @return $this - */ - public function execute(\Magento\Framework\Event\Observer $observer) - { - $productCollection = $observer->getEvent()->getCollection(); - if ($productCollection instanceof \Magento\Framework\Data\Collection) { - if (!$productCollection->isLoaded()) { - $productCollection->load(); - } - $this->_reviewFactory->create()->appendSummary($productCollection); - } - - return $this; - } -} diff --git a/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php b/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php new file mode 100644 index 0000000000000..bb69284b5f0b8 --- /dev/null +++ b/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php @@ -0,0 +1,62 @@ +sumResourceFactory = $sumResourceFactory; + $this->storeManager = $storeManager; + } + + /** + * Append review summary to collection + * + * @param EventObserver $observer + * @return $this + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function execute(EventObserver $observer) + { + $productCollection = $observer->getEvent()->getCollection(); + $this->sumResourceFactory->create()->appendSummaryFieldsToCollection( + $productCollection, + $this->storeManager->getStore()->getId(), + \Magento\Review\Model\Review::ENTITY_PRODUCT_CODE + ); + + return $this; + } +} diff --git a/app/code/Magento/Review/Observer/TagProductCollectionLoadAfterObserver.php b/app/code/Magento/Review/Observer/TagProductCollectionLoadAfterObserver.php deleted file mode 100644 index 52d6f09a08557..0000000000000 --- a/app/code/Magento/Review/Observer/TagProductCollectionLoadAfterObserver.php +++ /dev/null @@ -1,41 +0,0 @@ -_reviewFactory = $reviewFactory; - } - - /** - * Add review summary info for tagged product collection - * - * @param \Magento\Framework\Event\Observer $observer - * @return $this - */ - public function execute(\Magento\Framework\Event\Observer $observer) - { - $collection = $observer->getEvent()->getCollection(); - $this->_reviewFactory->create()->appendSummary($collection); - - return $this; - } -} diff --git a/app/code/Magento/Review/Test/Unit/Model/ReviewSummaryTest.php b/app/code/Magento/Review/Test/Unit/Model/ReviewSummaryTest.php new file mode 100644 index 0000000000000..9723ece0c4904 --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Model/ReviewSummaryTest.php @@ -0,0 +1,94 @@ +reviewSummaryCollectionFactoryMock = $this->createPartialMock( + \Magento\Review\Model\ResourceModel\Review\Summary\CollectionFactory::class, + ['create'] + ); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->reviewSummary = $this->objectManagerHelper->getObject( + \Magento\Review\Model\ReviewSummary::class, + [ + 'sumColFactory' => $this->reviewSummaryCollectionFactoryMock + ] + ); + } + + public function testAppendSummaryDataToObject() + { + $productId = 6; + $storeId = 4; + $testSummaryData = [ + 'reviews_count' => 2, + 'rating_summary' => 80 + ]; + $product = $this->createPartialMock( + \Magento\Catalog\Model\Product::class, + ['getId', 'addData', '__wakeup'] + ); + $product->expects($this->once())->method('getId')->will($this->returnValue($productId)); + $product->expects($this->once())->method('addData') + ->with($testSummaryData) + ->will($this->returnSelf()); + + $summaryData = $this->createPartialMock( + \Magento\Review\Model\Review\Summary::class, + ['getData', '__wakeup'] + ); + $summaryData->expects($this->atLeastOnce())->method('getData')->will( + $this->returnValueMap( + [ + ['reviews_count', null, $testSummaryData['reviews_count']], + ['rating_summary', null, $testSummaryData['rating_summary']] + ] + ) + ); + $summaryCollection = $this->createPartialMock( + \Magento\Review\Model\ResourceModel\Review\Summary\Collection::class, + ['addEntityFilter', 'addStoreFilter', 'getFirstItem', '__wakeup'] + ); + $summaryCollection->expects($this->once())->method('addEntityFilter') + ->will($this->returnSelf()); + $summaryCollection->expects($this->once())->method('addStoreFilter') + ->will($this->returnSelf()); + $summaryCollection->expects($this->once())->method('getFirstItem') + ->will($this->returnValue($summaryData)); + + $this->reviewSummaryCollectionFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($summaryCollection)); + + $this->assertNull($this->reviewSummary->appendSummaryDataToObject($product, $storeId)); + } +} diff --git a/app/code/Magento/Review/Test/Unit/Model/ReviewTest.php b/app/code/Magento/Review/Test/Unit/Model/ReviewTest.php index 9f57b289fa749..3302ba7e6a036 100644 --- a/app/code/Magento/Review/Test/Unit/Model/ReviewTest.php +++ b/app/code/Magento/Review/Test/Unit/Model/ReviewTest.php @@ -51,7 +51,7 @@ class ReviewTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Review\Model\ResourceModel\Review|\PHPUnit_Framework_MockObject_MockObject */ protected $resource; - /** @var int */ + /** @var int */ protected $reviewId = 8; protected function setUp() @@ -135,6 +135,9 @@ public function testAggregate() $this->assertSame($this->review, $this->review->aggregate()); } + /** + * @deprecated + */ public function testGetEntitySummary() { $productId = 6; diff --git a/app/code/Magento/Review/etc/frontend/di.xml b/app/code/Magento/Review/etc/frontend/di.xml index e6efb36e88d56..4ea0f4449cdd8 100644 --- a/app/code/Magento/Review/etc/frontend/di.xml +++ b/app/code/Magento/Review/etc/frontend/di.xml @@ -40,7 +40,4 @@ - - - diff --git a/app/code/Magento/Review/etc/frontend/events.xml b/app/code/Magento/Review/etc/frontend/events.xml index 8e883ce328a2c..44cc888fb323f 100644 --- a/app/code/Magento/Review/etc/frontend/events.xml +++ b/app/code/Magento/Review/etc/frontend/events.xml @@ -6,11 +6,8 @@ */ --> - - - - + diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 1b28e367dcc3a..6082c2c6c5205 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -16,6 +16,7 @@ /** * Base items collection class * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -217,7 +218,7 @@ public function getSize() { if ($this->_totalRecords === null) { $sql = $this->getSelectCountSql(); - $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams); + $this->_totalRecords = $this->_totalRecords ?? $this->getConnection()->fetchOne($sql, $this->_bindParams); } return (int)$this->_totalRecords; } @@ -367,10 +368,12 @@ protected function _renderFilters() * Hook for operations before rendering filters * * @return void + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ protected function _renderFiltersBefore() { } + // phpcs:enable /** * Add field filter to collection @@ -730,6 +733,7 @@ public function loadData($printQuery = false, $logQuery = false) public function printLogQuery($printQuery = false, $logQuery = false, $sql = null) { if ($printQuery || $this->getFlag('print_query')) { + // phpcs:ignore Magento2.Security.LanguageConstruct echo $sql === null ? $this->getSelect()->__toString() : $sql; } @@ -822,11 +826,13 @@ public function __clone() * Init select * * @return void + * phpcs:disable Magento2.CodeAnalysis.EmptyBlock */ protected function _initSelect() { // no implementation, should be overridden in children classes } + // phpcs:enable /** * Join extension attribute.