Skip to content

Review Module Decoupling Report

Modules Scanned

  • Magento_Review — 107 PHP files
  • Magento_ReviewAnalytics — 1 PHP file (just an analytics data provider)
  • Magento_ReviewGraphQl — 16 PHP files

Can It Be Removed Entirely? YES

Review is remarkably well-isolated. Only 2 non-Review modules have a composer dependency on it, and Catalog already has a null-object pattern in place for when Review is absent.


Who Depends on Review

Module composer.json PHP imports XML Severity
Reports hard require 2 ResourceModel collections extend Review classes ACL, controllers, blocks Moderate
ReviewGraphQl hard require 10 files module.xml sequence Expected (GraphQL layer)
ReviewAnalytics hard require 0 (just 1 file using Review data) Trivial

Nobody else. No Catalog, Customer, Sales, Checkout, or any other core module requires Review.


How Catalog Already Handles "No Reviews"

Catalog has a built-in null-object pattern for reviews:

Catalog\Block\Product\ReviewRendererInterface — interface in Catalog (not Review):

interface ReviewRendererInterface
{
    public function getReviewsSummaryHtml(Product $product, $templateType, $displayIfNoReviews = false);
}

Catalog\Block\Product\ReviewRenderer\DefaultProvider — returns empty string:

class DefaultProvider implements ReviewRendererInterface
{
    public function getReviewsSummaryHtml(Product $product, $templateType, $displayIfNoReviews = false)
    {
        return '';  // No reviews = no HTML
    }
}

DI preference in Catalog/etc/di.xml:

<preference for="ReviewRendererInterface" type="DefaultProvider" />

When Review module IS installed, it overrides this preference with its own renderer that shows star ratings. When Review is disabled — DefaultProvider returns empty string. This already works.

Templates like product/list.phtml, product/view/review.phtml, widget templates all call $block->getReviewsSummaryHtml() which goes through this interface. No Review module = no output. Clean.


The Two Coupling Points to Fix

1. Reports Module → Review (Moderate)

Reports has a dedicated review reporting section:

PHP (2 files extending Review classes): - Reports/Model/ResourceModel/Review/Collection.php — extends Review\Model\ResourceModel\Review\Collection - Reports/Model/ResourceModel/Review/Customer/Collection.php — extends Review\Model\ResourceModel\Review\Collection

Controllers (10 files): - Reports/Controller/Adminhtml/Report/Review.php — base review report controller - Reports/Controller/Adminhtml/Report/Review/Product.php — review by product - Reports/Controller/Adminhtml/Report/Review/Customer.php — review by customer - Reports/Controller/Adminhtml/Report/Review/ProductDetail.php - 6 export controllers (CSV/Excel for each report)

Blocks (4 files): - Reports/Block/Adminhtml/Review/Product.php - Reports/Block/Adminhtml/Review/Customer.php - Reports/Block/Adminhtml/Review/Detail.php - Reports/Block/Adminhtml/Review/Detail/Grid.php

XML: - Reports/etc/acl.xml — ACL resources for review reports

Fix: Move all review reporting code from Reports into the Review module itself (or a ReviewReports bridge module). Reports module removes magento/module-review from composer.json. Review reports only exist when Review is installed.

2. Review → Newsletter (Already Documented)

Review has a phantom dependency on Newsletter (inherited SubscriberFactory constructor param from Customer\Block\Account\Dashboard). Already documented in newsletter.md — resolves automatically when Newsletter is decoupled from Customer.


Decoupling Plan

Phase 1: Move Review Reports to Review Module

Move FROM Reports/ TO Review/:

Current (Reports) New (Review)
Model/ResourceModel/Review/Collection.php Review/Model/ResourceModel/Report/Collection.php
Model/ResourceModel/Review/Customer/Collection.php Review/Model/ResourceModel/Report/Customer/Collection.php
Controller/Adminhtml/Report/Review/*.php (10 files) Review/Controller/Adminhtml/Report/*.php
Block/Adminhtml/Review/*.php (4 files) Review/Block/Adminhtml/Report/*.php
ACL resources in acl.xml Review's own acl.xml

Phase 2: Remove Composer Dependencies

Module Change
Reports/composer.json Remove magento/module-review from require
Review/composer.json Remove magento/module-newsletter from require (phantom — inherited constructor)

Phase 3: Verify Clean Removal

After phases 1-2, disabling Review module means: - Product listing/detail pages show no review stars (DefaultProvider returns '') - No review admin section - No review reports (they live in Review now) - ReviewAnalytics and ReviewGraphQl auto-disable (they depend on Review) - Reports module works without Review — just no review reports in the menu - Catalog, Customer, Sales, Checkout — zero impact


Architecture After Decoupling

Catalog module (zero Review dependency)
    └── ReviewRendererInterface → DefaultProvider returns ''
         │ DI preference override (only when Review installed)
Review module (optional)
    ├── ReviewRenderer (overrides DefaultProvider → shows stars)
    ├── Review admin (CRUD for reviews)
    ├── Review reports (moved from Reports module)
    ├── Frontend review form + listing
    └── layout XML contributions to product pages

ReviewGraphQl (optional, requires Review)
ReviewAnalytics (optional, requires Review)

Difficulty Assessment

Phase Effort Risk
Move review reports (16 files) Medium Low — admin routes stay the same, just different module
Remove composer deps Trivial Zero — no code references remain
Overall Medium effort, low risk Review becomes fully optional

Key Insight

Magento's developers actually got this one mostly right. The ReviewRendererInterface + DefaultProvider null-object pattern in Catalog is exactly the correct approach. The only mistake was putting review reports inside the Reports module instead of the Review module, creating the one hard dependency that prevents clean removal.