I have looked everywhere for any reviews extension that supported grouped products and could not find any. So trying to hash it out myself.
I need the reviews block on a grouped product to also show reviews for the simple products that are on the page.
The collections classes Magento\Review\Model\ResourceModel\Review\Product\Collection
and Magento\Review\Model\ResourceModel\Review\Collection
build a query via method AddEntityFilter
using exact match.
It seems that "all" that is needed here is to create a new block that calls these factory methods and passes a list of IDs - and then "override" the query in AddEntityFilter
from entity_pk_value=?
to entity_pk_value in (?)
.
That would remain backwards compatible with single value so there is no risk of conflict with anything else relying on these classes. So it could be a plugin or preference override.
I am currently getting a death walk of errors with everything I try - it seems plugins are very hard around query objects because half the methods are protected.
I can't tell if my death walk of errors are because I dont understand "around" plugins well enough and am making rookie mistakes, or because I am trying something that cannot be done by plugin
Here's what didn't work so far for me
Module Alpine\FixGrouped
Alpine\FixGrouped\view\templates\review\product\view\list.phtml
is identical to the core version, except for calling a different block class
layout Alpine\FixGrouped\view\frontend\layout\review_product_list.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="catalog_product_view_type_grouped"/>
<body>
<referenceContainer name="product.info.details">
<block class="Alpine\FixGrouped\Block\Review\Product\View\ListView" name="product.info.product_additional_data" as="product_additional_data" template="Alpine_FixGrouped::review/product/view/list.phtml" ifconfig="catalog/review/active"/>
</referenceContainer>
</body>
</page>
beginning of template: (all identical except @var line)
/** @var Alpine\FixGrouped\Block\Review\Product\View\GroupedListView $block */
$_items = $block->getReviewsCollection()->getItems();
...
Next the custom block - adds a "getGroupIds" method and uses that in the building of the collection instead of single getProductId
namespace Alpine\FixGrouped\Block\Review\Product\View;
class GroupedListView extends \Magento\Review\Block\Product\View
{
/**
* Get grouped product ids
*
* @return string|int|null
*/
public function getGroupIds()
{
$product = $this->_coreRegistry->registry('product');
// get children IDs
if ($product) {
$children = $product->getTypeInstance()->getChildrenIds($product->getId());
$idlist = [$product->getId()];
$idlist[] = $children[0];
return implode(',',$idlist);
}
return null;
}
/**
* Get collection of reviews
*
* @return ReviewCollection
*/
public function getReviewsCollection()
{
if (null === $this->_reviewsCollection) {
$this->_reviewsCollection = $this->_reviewsColFactory->create()->addStoreFilter(
$this->_storeManager->getStore()->getId()
)->addStatusFilter(
\Magento\Review\Model\Review::STATUS_APPROVED
)->addEntityFilter(
'product',
$this->getGroupIds()
)->setDateOrder();
}
return $this->_reviewsCollection;
}
Obviously now the addEntityFilter
method in the review collection needs to be adapted to work with a list.
So I tried was plugin but I admit I am out of my depth here, never done an "around" replacement plugin before.
in frontend\di.xml
<type name="Magento\Review\Model\ResourceModel\Review\Collection">
<plugin sortOrder="1" name="FixGroupedPluginModelReviewCollection" type="Alpine\FixGrouped\Plugin\Model\Review\ResourceModel\Review\Collection" disabled="false" />
</type>
and the code
namespace Alpine\FixGrouped\Plugin\Model\Review\ResourceModel\Review
/**
* Review collection resource model
*
* @api
* @since 100.0.2
*/
class Collection extends Magento\Review\Model\ResourceModel\Review\Collection
{
/**
* Add entity filter
*
* @param int|string $entity
* @param int|string $pkValue
* @return $this
*/
public function aroundAddEntityFilter(\Magento\Review\Model\ResourceModel\Review\Collection $target, \Closure $ignore, $entity, $pkValue)
{
$reviewEntityTable = $target->getReviewEntityTable();
if (is_numeric($entity)) {
$target->addFilter('entity', $target->getConnection()->quoteInto('main_table.entity_id=?', $entity), 'string');
} elseif (is_string($entity)) {
$target->_select->join(
$reviewEntityTable,
'main_table.entity_id=' . $reviewEntityTable . '.entity_id',
['entity_code']
);
$target->addFilter(
'entity',
$target->getConnection()->quoteInto($reviewEntityTable . '.entity_code=?', $entity),
'string'
);
}
$target->addFilter(
'entity_pk_value',
$target->getConnection()->quoteInto('main_table.entity_pk_value in (?)', $pkValue),
'string'
);
return $target;
}
The result at the moment is that no error appears anywhere but also no reviews appear. Different approaches have caused outright error - including warning of protected methods - so at least some of the "plugin" code is executed