I'm using Magento 2.4.3 and I'm loading a custom module using someone else's code from the link
Override the Review form block with your custom block.
app/code/Vendor/Module/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Review\Block\Form" type="Vendor\Module\Block\Review\Form" />
</config>
Add condition for the customer in your custom block
app/code/Vendor/Module/Block/Review/Form.php
<?php
namespace Vendor\Module\Block\Review;
class Form extends \Magento\Review\Block\Form
{
/**
* Customer Session Factory
*
* @var \Magento\Customer\Model\SessionFactory
*/
protected $_customerSession;
/**
* Order Collection Factory
*
* @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory
*/
protected $_orderCollectionFactory;
/**
* Registry
*
* @var \Magento\Framework\Registry
*/
protected $_registry;
/**
* Review data
*
* @var \Magento\Review\Helper\Data
*/
protected $_reviewData = null;
/**
* Catalog product model
*
* @var \Magento\Catalog\Api\ProductRepositoryInterface
*/
protected $productRepository;
/**
* Rating model
*
* @var \Magento\Review\Model\RatingFactory
*/
protected $_ratingFactory;
/**
* @var \Magento\Framework\Url\EncoderInterface
*/
protected $urlEncoder;
/**
* Message manager interface
*
* @var \Magento\Framework\Message\ManagerInterface
*/
protected $messageManager;
/**
* @var \Magento\Framework\App\Http\Context
*/
protected $httpContext;
/**
* @var \Magento\Customer\Model\Url
*/
protected $customerUrl;
/**
* @var array
*/
protected $jsLayout;
/**
* @var \Magento\Framework\Serialize\Serializer\Json
*/
private $serializer;
/**
* Form constructor.
*
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Framework\Url\EncoderInterface $urlEncoder
* @param \Magento\Review\Helper\Data $reviewData
* @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
* @param \Magento\Review\Model\RatingFactory $ratingFactory
* @param \Magento\Framework\Message\ManagerInterface $messageManager
* @param \Magento\Framework\App\Http\Context $httpContext
* @param Url $customerUrl
* @param array $data
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
* @throws \RuntimeException
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Framework\Url\EncoderInterface $urlEncoder,
\Magento\Review\Helper\Data $reviewData,
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
\Magento\Review\Model\RatingFactory $ratingFactory,
\Magento\Framework\Message\ManagerInterface $messageManager,
\Magento\Framework\App\Http\Context $httpContext,
\Magento\Customer\Model\Url $customerUrl,
array $data = [],
\Magento\Framework\Serialize\Serializer\Json $serializer = null,
\Magento\Customer\Model\SessionFactory $customerSession,
\Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
\Magento\Framework\Registry $registry
) {
$this->_customerSession = $customerSession;
$this->_orderCollectionFactory = $orderCollectionFactory;
$this->_registry = $registry;
parent::__construct($context, $urlEncoder, $reviewData, $productRepository, $ratingFactory, $messageManager, $httpContext, $customerUrl, $data);
$this->jsLayout = isset($data['jsLayout']) ? $data['jsLayout'] : [];
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Framework\Serialize\Serializer\Json::class);
}
protected function _construct()
{
parent::_construct();
if ($this->isCurrentCustomerPurchasedThisProduct()) {
$this->setTemplate('Magento_Review::form.phtml');
} else {
$this->setTemplate('Vendor_Module::no_review_form.phtml');
// You can set null here if you don't want to load any template
// $this->setTemplate(null);
}
}
public function getCurrentCustomerId()
{
return $this->_customerSession->create()->getCustomer()->getId();
}
public function getCustomerOrders()
{
$orders = $this->_orderCollectionFactory->create()->addFieldToSelect(
'*'
)->addFieldToFilter(
'customer_id',
$this->getCurrentCustomerId()
);
return $orders;
}
public function getCurrentProduct()
{
return $this->_registry->registry('current_product');
}
public function isCurrentCustomerPurchasedThisProduct()
{
$product_ids = [];
foreach ($this->getCustomerOrders() as $order) {
foreach ($order->getAllVisibleItems() as $item) {
$product_ids[$item->getProductId()] = $item->getProductId();
}
}
if (in_array($this->getCurrentProduct()->getId(), $product_ids)) {
return true;
} else {
return false;
}
}
}
My custom message in:
app/code/Vendor/Module/view/frontend/templates/no_review_form.phtml
You can not add the review on this product as you have not purchased this product yet.
I added this as a module and had to include a module.xml file in /app/code/Vendor/Module/etc and registration.php in /app/code/Vendor/Module which is pretty standard.
I get an error displayed at the top of the product page on the front end.
"An error has happened during application run. See exception log for details."
Nothing is in the exception.log but the below is in the system.log
main.CRITICAL: Error: Call to a member function getId() on null in /app/code/Vendor/Module/Block/Review/Form.php:163
Line "163" in Form.php from above is:
if (in_array($this->getCurrentProduct()->getId(), $product_ids)) {
Full Stack trace from system.log is below
#0 /bitnami/magento/app/code/Vendor/Module/Block/Review/Form.php(122):Vendor/Module\Block\Review\Form->isCurrentCustomerPurchasedThisProduct()
#1 /bitnami/magento/vendor/magento/framework/View/Element/AbstractBlock.php(225): Vendor/Module\Block\Review\Form->_construct()
#2 /bitnami/magento/vendor/magento/framework/View/Element/Template.php(155): Magento\Framework\View\Element\AbstractBlock->__construct()
#3 /bitnami/magento/vendor/magento/module-review/Block/Form.php(111): Magento\Framework\View\Element\Template->__construct()
#4 /bitnami/magento/app/code/Vendor/Module/Block/Review/Form.php(112): Magento\Review\Block\Form->__construct()
#5 /bitnami/magento/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(121): Vendor/Module\Block\Review\Form->__construct()
#6 /bitnami/magento/vendor/magento/framework/ObjectManager/Factory/Compiled.php(108): Magento\Framework\ObjectManager\Factory\AbstractFactory->createObject()
#7 /bitnami/magento/vendor/magento/framework/ObjectManager/ObjectManager.php(56): Magento\Framework\ObjectManager\Factory\Compiled->create()
#8 /bitnami/magento/vendor/magento/framework/View/Element/BlockFactory.php(46): Magento\Framework\ObjectManager\ObjectManager->create()
#9 /bitnami/magento/vendor/magento/framework/View/Layout/Generator/Block.php(272): Magento\Framework\View\Element\BlockFactory->createBlock()
#10 /bitnami/magento/vendor/magento/framework/View/Layout/Generator/Block.php(252): Magento\Framework\View\Layout\Generator\Block->getBlockInstance()
#11 /bitnami/magento/vendor/magento/framework/View/Layout/Generator/Block.php(229): Magento\Framework\View\Layout\Generator\Block->createBlock()
#12 /bitnami/magento/vendor/magento/framework/View/Layout/Generator/Block.php(134): Magento\Framework\View\Layout\Generator\Block->generateBlock()
#13 /bitnami/magento/vendor/magento/framework/View/Layout/GeneratorPool.php(93): Magento\Framework\View\Layout\Generator\Block->process()
#14 /bitnami/magento/vendor/magento/framework/View/Layout.php(365): Magento\Framework\View\Layout\GeneratorPool->process()
#15 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\View\Layout->generateElements()
#16 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\View\Layout\Interceptor->___callParent()
#17 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\View\Layout\Interceptor->Magento\Framework\Interception\{closure}()
#18 /bitnami/magento/generated/code/Magento/Framework/View/Layout/Interceptor.php(68): Magento\Framework\View\Layout\Interceptor->___callPlugins()
#19 /bitnami/magento/vendor/magento/framework/View/Layout/Builder.php(129): Magento\Framework\View\Layout\Interceptor->generateElements()
#20 /bitnami/magento/vendor/magento/framework/View/Page/Builder.php(65): Magento\Framework\View\Layout\Builder->generateLayoutBlocks()
#21 /bitnami/magento/vendor/magento/framework/View/Layout/Builder.php(65): Magento\Framework\View\Page\Builder->generateLayoutBlocks()
#22 /bitnami/magento/vendor/magento/framework/View/Page/Config.php(224): Magento\Framework\View\Layout\Builder->build()
#23 /bitnami/magento/vendor/magento/framework/View/Page/Config.php(237): Magento\Framework\View\Page\Config->build()
#24 /bitnami/magento/vendor/magento/framework/App/View.php(170): Magento\Framework\View\Page\Config->publicBuild()
#25 /bitnami/magento/vendor/magento/framework/App/View.php(114): Magento\Framework\App\View->loadLayoutUpdates()
#26 /bitnami/magento/vendor/magento/module-page-cache/Controller/Block.php(86): Magento\Framework\App\View->loadLayout()
#27 /bitnami/magento/vendor/magento/module-page-cache/Controller/Block/Esi.php(19): Magento\PageCache\Controller\Block->_getBlocks()
#28 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(58): Magento\PageCache\Controller\Block\Esi->execute()
#29 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(138): Magento\PageCache\Controller\Block\Esi\Interceptor->___callParent()
#30 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(153): Magento\PageCache\Controller\Block\Esi\Interceptor->Magento\Framework\Interception\{closure}()
#31 /bitnami/magento/generated/code/Magento/PageCache/Controller/Block/Esi/Interceptor.php(23): Magento\PageCache\Controller\Block\Esi\Interceptor->___callPlugins()
#32 /bitnami/magento/vendor/magento/framework/App/Action/Action.php(111): Magento\PageCache\Controller\Block\Esi\Interceptor->execute()
#33 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\App\Action\Action->dispatch()
#34 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(138): Magento\PageCache\Controller\Block\Esi\Interceptor->___callParent()
#35 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(153): Magento\PageCache\Controller\Block\Esi\Interceptor->Magento\Framework\Interception\{closure}()
#36 bitnami/magento/generated/code/Magento/PageCache/Controller/Block/Esi/Interceptor.php(32): Magento\PageCache\Controller\Block\Esi\Interceptor->___callPlugins()
#37 /bitnami/magento/vendor/magento/framework/App/FrontController.php(245): Magento\PageCache\Controller\Block\Esi\Interceptor->dispatch()
#38 /bitnami/magento/vendor/magento/framework/App/FrontController.php(212): Magento\Framework\App\FrontController->getActionResponse()
#39 /bitnami/magento/vendor/magento/framework/App/FrontController.php(147): Magento\Framework\App\FrontController->processRequest()
#40 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\App\FrontController->dispatch()
#41 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\App\FrontController\Interceptor->___callParent()
#42 /bitnami/magento/vendor/magento/module-store/App/FrontController/Plugin/RequestPreprocessor.php(99): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}()
#43 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(135): Magento\Store\App\FrontController\Plugin\RequestPreprocessor->aroundDispatch()
#44 /bitnami/magento/vendor/magento/module-page-cache/Model/App/FrontController/BuiltinPlugin.php(71): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}()
#45 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(135): Magento\PageCache\Model\App\FrontController\BuiltinPlugin->aroundDispatch()
#46 /bitnami/magento/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}()
#47 /bitnami/magento/generated/code/Magento/Framework/App/FrontController/Interceptor.php(23): Magento\Framework\App\FrontController\Interceptor->___callPlugins()
#48 /bitnami/magento/vendor/magento/framework/App/Http.php(116): Magento\Framework\App\FrontController\Interceptor->dispatch()
#49 /bitnami/magento/vendor/magento/framework/App/Bootstrap.php(264): Magento\Framework\App\Http->launch()
#50 /bitnami/magento/pub/index.php(29): Magento\Framework\App\Bootstrap->run()
#51 {main} [] []
Any advise would be greatly appreciated.