etechflow / module-product-warning
etechflow/module-product-warning
Per-product and per-category warning banners on the Magento 2 PDP. Admin can write coloured notices, assign them to specific products or whole categories, and the storefront auto-renders them. Theme-agnostic — works on Hyvä, Luma, and any custom theme without template overrides.
Etechflow_ProductWarning — Product Warning Banners for Magento 2
Per-product and per-category warning banners on the storefront PDP. Admin can create coloured notices ("This item ships from a remote warehouse", "Cutting service unavailable for this key", "Backorder — 7 day lead time", etc.), assign them to specific products or whole categories, and the storefront auto-renders them above the price.
- Version: 1.0.0
- Package:
etechflow/module-product-warning - Magento: 2.4.4 – 2.4.8 (newer versions should work; report incompatibilities)
- PHP: 8.1, 8.2, 8.3
- License: proprietary (
LICENSE.txt) — Commercial licenses available at https://etechflow.com - Vendor: ETechFlow — https://etechflow.com
What you get
- Admin grid + edit form under
Catalog → Inventory Warning- Warning name (admin-only label)
- Warning message (customer-facing text)
- Color (hex picker, used for the banner tint + left border)
- Active toggle, sort order
- Assigned categories (multi-tree picker — assigns to every product in those categories)
- Assigned products (search + multi-select picker)
- Storefront PDP rendering (auto-injected via this module's own layout XML — no theme override required)
- Stacks multiple warnings if a product matches several
- Tints background + border using the warning's color
- Scoped CSS namespace (
.epw-*) — won't collide with theme classes
- Resolver model (
ETechFlow\ProductWarning\Model\WarningResolver::getForProduct($product)) for stores that want to render warnings in a custom location (e.g., listing pages, cart, emails) - Theme-agnostic by design — works on Hyvä, Luma, Mage-OS adminhtml, and any custom theme
Theme compatibility
| Theme | Status |
|---|---|
| Magento 2 default (Luma / Blank) | ✅ Works — vanilla CSS, no Knockout dependency |
| Hyvä Theme | ✅ Works — no Alpine / Tailwind required |
| Custom themes | ✅ Works — uses standard product.info.main container which exists in every theme |
| Mage-OS forks | ✅ Works |
| Adobe Commerce | ✅ Works |
| Headless / PWA Studio | ⚠️ Storefront template bypassed; use the WarningResolver PHP API or expose a REST endpoint to surface the warnings in your headless front end |
See COMPATIBILITY.md for the design choices that make this portable.
Quick start
# 1. Extract into your Magento root
unzip etechflow-module-product-warning-1.0.0.zip -d <magento-root>/
# 2. Enable + migrate
bin/magento module:enable Etechflow_ProductWarning
bin/magento setup:upgrade
bin/magento setup:di:compile # production-mode only
bin/magento cache:flush
# 3. Visit the admin
open https://your-store.example.com/admin/etechflow_warning/warning/index
# (or: Admin sidebar → Catalog → Inventory Warning)
A fresh install starts with an empty warnings grid. Click Add New Warning, set name + message + colour, assign it to a product or category, and reload the PDP — the banner renders above the price.
Documentation index
| File | Purpose |
|---|---|
README.md |
Overview, features, compatibility (this file) |
INSTALL.md |
Manual + Composer install + verification + troubleshooting |
USAGE.md |
Admin walk-through — creating warnings, assigning to products / categories |
CONFIGURATION.md |
Module-level customization options + how to move the banner block elsewhere |
COMPATIBILITY.md |
Theme + Magento + PHP matrix and the choices that keep it portable |
CHANGELOG.md |
Version history |
UNINSTALL.md |
Clean removal (disable / drop tables / remove media) |
LICENSE.txt |
proprietary license text |
Support
- Email: [email protected]
- Include: Magento version, PHP version, active theme, steps to reproduce, screenshot of the PDP with browser inspector open.
License
proprietary — free for commercial and non-commercial use. See LICENSE.txt.
Changelog — ETechFlow Product Warning
All notable changes to this module. Adheres to Semantic Versioning.
[1.1.0] — 2026-06-05 — Stripe portal licensing + admin gate + storefront gating
Added
-
Stripe portal subscription licensing. Adds the SP-XXXX subscription-key
flow — same pattern shipped onETechFlow_BackorderEtaDisplayv1.3.0,
ETechFlow_NextDayEligibilityv1.8.0,ETechFlow_ShippingTableRatesv1.2.0,
andETechFlow_Faqv1.1.0. Three plan tiers (Starter $9/mo, Professional
$19/mo, Enterprise $49/mo) with in-admin Stripe Checkout, automatic key
activation, portal-validated server-IP enforcement, IP-block auto-restore,
and 48-hour offline grace when the portal is unreachable. HMAC per-module +
bundle keys (LICENSING_PROTOCOL.md) continue to work for offline / bundle
activation. -
Model/LicenseValidator.php— upgraded constructor from 2-arg to
5-arg (ScopeConfigInterface,StoreManagerInterface,CacheInterface,
Curl,WriterInterface). Adds tri-statevalidateViaPortal(): ?bool
per the enforcement contract. PreservesMODULE_ID = 'product-warning'
and the existingSECRET_FRAGMENTSbyte-for-byte so v1.0.x HMAC keys
remain valid. -
License gate page under Catalog → Inventory Warning → License & Plans
with dark plan-cards UI and a Stripe Checkout button. Visiting any
warning-admin URL without a valid licence redirects here. -
Module Status banner (5-state) at the top of Stores → Configuration →
ETECHFLOW → Product Warning. Tells the merchant exactly why the module is
locked (or that it's active). -
Admin gating plugin (
Plugin/Adminhtml/LicenseGatePlugin.php) — every
admin Warning CRUD controller + every assignment-picker controller (9 in
total) redirects to the license gate when not licensed. -
Storefront gating —
Block/Frontend/Notice.phpnow checks
LicenseValidator::isValid()before calling the resolver. When unlicensed,
getWarnings()returns an empty array and the PDP renders no banner. The
block stays in the layout but produces zero output — the storefront
degrades silently rather than crashing or showing a "module locked" message
to customers. -
<payment>config group for Stripesk_test/sk_live/ publishable
key / currency (Encrypted backend model on the secret key). -
<license>config group expanded — addsissued_key(Encrypted audit
field),issued_at(timestamp),ip_blocked(auto-managed flag),
portal_url, andbundle_license_key(Encrypted, mapped to the shared
etechflow_bundle/license/license_keypath).
Changed
-
Menu restructured.
Catalog → Inventory Warningis now a parent node
with two children: Manage Warnings (the existing grid) and License &
Plans (the new gate). Existing bookmarks to/etechflow_warning/warning/index
continue to work unchanged. -
Module Status backend block added (
Block/Adminhtml/System/Config/ModuleStatus.php)
to render the always-expanded 5-state banner on the Stores → Config page.
Migration
composer update etechflow/module-product-warning
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
After upgrade, on a production host the module is locked by default.
Go to Catalog → Inventory Warning → License & Plans and either paste an
existing SP-XXXX / HMAC / bundle key, or click "Select Plan & Pay" to buy
a subscription via Stripe.
Dev hosts (localhost, *.test, *.local, staging.*, *.ngrok-free.dev,
etc.) auto-bypass licensing. Production hosts that aren't auto-detected can
opt out with Production Environment = No.
Notes
License Portal URLdefaults to
https://license-service.etechflow.com/license/validate
(the eTechFlow portal). For production, change this when eTechFlow
publishes the final portal URL.- Portal IP-revoke + suspend lock the module within ~60 seconds. Re-activating
in the portal restores the module within the same window via the
issued_keyauto-restore.
[1.0.2] — 2026-06-05 — Fix blank admin grid + remove default-data seed
Fixed
-
Admin grid + edit form rendered as blank pages. Five XML files were
still named with the pre-renamekeystation_*prefix while the
module's route id had been changed toetechflow_warning. Magento
builds admin layout handles from{route_id}_{controller}_{action}
and loads UI components by filename — both lookups silently failed
to match, so/admin/etechflow_warning/warning/indexreturned 200
with no errors but rendered no grid, noAdd New Warningbutton,
and no form on the edit page.Renamed (pure file renames — file contents were already correct):
view/adminhtml/layout/ keystation_warning_warning_index.xml → etechflow_warning_warning_index.xml keystation_warning_warning_edit.xml → etechflow_warning_warning_edit.xml keystation_warning_warning_newaction.xml → etechflow_warning_warning_newaction.xml view/adminhtml/ui_component/ keystation_warning_listing.xml → etechflow_warning_listing.xml keystation_warning_form.xml → etechflow_warning_form.xmlBug class to watch for: Magento does not error on a missing
layout handle — it just renders the page chrome without the
declared content. Trivial to ship to production undetected. Catch
it with:bin/magento dev:layout:export-handles | grep <route_id>
after every module rename.
Removed
-
Setup/Patch/Data/SeedDefaultWarnings.php. New installs now land
on an empty warnings grid. The old patch hard-coded 3
automotive-locksmith-flavoured demo rows (Unprogrammed Remote /
Repair Case / Un-cut Blade) that were noise for every other type of
merchant.Existing v1.0.0 / v1.0.1 installs: rows already in
etechflow_warningare not touched on upgrade — the patch is
already recorded inpatch_list, so setup:upgrade does nothing.
Delete the seeded rows from the admin grid if no longer wanted; they
will not come back on future upgrades. -
V101ReleaseMarker::getDependencies()previously returned
[SeedDefaultWarnings::class]. Removed so a new install of v1.0.2
doesn't fatal on the missing class.
Added
Setup/Patch/Data/V102ReleaseMarker.php— always-a-patch
discipline marker. Depends onV101ReleaseMarkerso patches run
in correct version order. No schema change.
Migration
composer update etechflow/module-product-warning
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
No schema migration, no data migration. Strongly recommend upgrade
for any v1.0.0 / v1.0.1 install — the blank-grid bug makes the
admin UI unusable.
[1.0.1] — 2026-06-03 — Critical: Fix class-load fatal in PDP Notice block
Fixed
-
Block/Frontend/Notice.phpclass-load fatal: the$resolver
property was declaredprivate, but Magento's\Magento\Framework\ View\Element\Templateparent class declares its own$resolveras
protected. PHP requires equal-or-weaker visibility on inherited
property overrides, so v1.0.0 causedsetup:di:compileand PDP
render to fatal with:Fatal error: Access level to ETechFlow\ProductWarning\Block\Frontend\ Notice::$resolver must be protected (as in class Magento\Framework\ View\Element\Template) or weakerCaught on first local Docker install —
php -ldoes NOT detect
this class of bug because it's a class-load-time check, not a
syntax check. Same bug class flagged in the eTechFlow memory after
similar issues in earlier modules.Fix: renamed the property
$resolver→$warningResolver
(along with the constructor parameter + every$this->resolver
reference). Side-steps the collision entirely without shadowing the
parent's actual layout resolver. -
Same class of bug to watch for elsewhere: any Magento block
that extendsTemplateorAbstractBlockand declares aprivate
property that shadows an inheritedprotectedone. Most-common
offenders:$resolver,$_resolver,$escaper,$_escaper,
$jsLayout,$_template.php -lwon't catch them.setup:di: compilewill, on every install.
Added
Setup/Patch/Data/V101ReleaseMarker.php— always-a-patch
discipline marker. Depends onSeedDefaultWarningsso patches run
in correct version order.
Migration
composer require etechflow/module-product-warning:^1.0.1
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Pre-flight check:
SELECT module, schema_version, data_version FROM setup_module
WHERE module='ETechFlow_ProductWarning';
Both should read 1.0.1. If data_version is stale, re-run
setup:upgrade — do NOT flush cache yet.
Anyone who installed v1.0.0 hit the class-load fatal on the first
PDP render or setup:di:compile. v1.0.1 fixes it. Strongly
recommend upgrade for any v1.0.0 installs.
Added
- Admin module under
Catalog → Inventory Warning- Grid + edit form (Magento Ui Components)
- Hex color picker, active toggle, sort order
- Multi-tree category assignment picker
- Multi-select product assignment picker (searchable by name / SKU)
- ACL resource
Etechflow_ProductWarning::warnings
- Storefront PDP rendering — auto-injected via this module's own
view/frontend/layout/catalog_product_view.xml. No theme override required. - WarningResolver PHP API for stores that want to render warnings
elsewhere (cart, emails, listing pages, etc.) - DB schema (
etc/db_schema.xml) — 3 tables:etechflow_warning— master record (id, name, message, color, active, sort_order, timestamps)etechflow_warning_category— category assignment pivotetechflow_warning_product— product assignment pivot
- Demo data installer patch — seeds 3 example warnings on first install
- Scoped frontend CSS —
.epw-*namespace, inline<style>block - Zero JavaScript on frontend — pure server-rendered HTML
- Documentation bundle
- README, INSTALL, USAGE, COMPATIBILITY, CONFIGURATION, UNINSTALL, CHANGELOG, LICENSE
Compatibility
- Magento 2.4.4 – 2.4.8
- PHP 8.1, 8.2, 8.3
- Hyvä Theme + Luma + custom themes
- Adobe Commerce + Magento Open Source + Mage-OS
Migration
If you previously had the original Keystation_ProductWarning module on a
store, follow the data-copy SQL in INSTALL.md → Upgrading from Keystation_ProductWarning to bring the data across.
| Version | Stability | QA Status | Compatibility | Released |
|---|---|---|---|---|
| 1.1.5 | stable | Fail | Magento 2.4.7-2.4.8 Details | 2026-06-22 09:37:37 |
| 1.1.3 | stable | Not tested | Not yet tested Details | 2026-06-15 10:47:04 |
| 1.1.2 | stable | Not tested | Not yet tested Details | 2026-06-15 09:28:06 |
| 1.1.1 | stable | Not tested | Not yet tested Details | 2026-06-13 13:58:00 |
| 1.1.0 | stable | Not tested | Not yet tested Details | 2026-06-05 15:40:54 |
| 1.0.2 | stable | Not tested | Not yet tested Details | 2026-06-05 11:59:02 |
| 1.0.1 | stable | Not tested | Not yet tested Details | 2026-06-03 12:13:58 |
| 1.0.0 | stable | Not tested | Not yet tested Details | 2026-06-03 10:17:53 |
Requires 5
| Package | Constraint |
|---|---|
| magento/framework | >=103.0 |
| magento/module-backend | >=102.0 |
| magento/module-catalog | >=104.0 |
| magento/module-ui | >=101.0 |
| php | ~8.1.0||~8.2.0||~8.3.0||~8.4.0 |
No QA results yet
QA pipelines haven't run for this version. Compatibility and quality results appear here once the vendor publishes a tagged release that gets ingested.
More from etechflow
View vendorDynamic 'View Other Options/Finishes/Sizes' PDP buttons driven by per-product link attributes; replaces hardcoded in-description buttons and strips the old ones at render time.
Theme-agnostic mega menu for Magento 2. Renders on Hyvä, Luma, Adobe Commerce default and custom themes via automatic runtime detection. Provides a JSON endpoint for lazy-loaded subcategory + featured-product data.
EtechFlow Store Locator — admin-managed store/branch finder for Magento 2 with a Leaflet + OpenStreetMap map and postcode proximity search (postcodes.io). Hyva and Luma compatible. No paid map API key required.
Universal Product Fitment Finder for Magento 2 — Make/Model/Year/Part filtering on any fitment domain (automotive, motorcycle, marine, RV, phone cases, watches, appliance parts, anywhere a customer asks "will this fit my X?"). Admin-configurable labels + URL prefix so the same module rebrands to any merchant domain. Includes PDP fitment badge, SEO URLs, customer garage with cross-device sync, OEM/part-number search, and admin tooltips throughout. Theme-agnostic — Hyvä, Luma, custom themes. Renamed from "module-vehicle-compat" in v2.0.0.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.