5 min readAug 14, 2026by jakub

Changelog

Current version: 2.0.0

Combined history for qoliber/omnibus-directive and its two optional companions. qoliber/mysql-utils and qoliber/hyva-module-registration are shared dependencies with their own release cycles and are not tracked here.

2.0.0 — 2026-08-13

Omnibus Directive

Findings F1–F24 refer to the repository's code-review audit, which documents each one in full: the defect, the file and line as originally imported, the failure it caused, the fix, and the test (where one exists) that proves it.

Removed

  • BREAKING The Hyvä presentation layer — layouts, templates, and ViewModel\HyvaHistoricalPrice — moved to the new qoliber/omnibus-directive-hyva package. This module no longer renders anything on a Hyvä storefront by itself; stores running Hyvä must also install and enable Qoliber_OmnibusDirectiveHyva. The pricing pool wiring, the registry, GetDynamicPrice, and Model\Configuration stay here and are shared by both storefronts.
  • qoliber/core dependency, replaced by a <tab id="qoliber"> declaration in this module's own system.xml (see F23 below).

Changed

  • BREAKING Model\Configuration's five getters (isEnabled, getProductPricesType, isShowOnPlp, isShowOnPdp, isAlwaysShow) now accept an optional store code and resolve at ScopeInterface::SCOPE_STORE; etc/adminhtml/system.xml opens the section, its group, and all five fields to showInWebsite="1" showInStore="1" (F7). A multi-store install can now set the Omnibus configuration per store view, which was not possible before.
  • BREAKING The price-recording observer was renamed Observer\UpdateHistoricalPriceAdminhtmlObserverObserver\UpdateHistoricalPriceObserver and rebound from catalog_product_save_after (global, but a no-op — see F2) to catalog_product_save_before (global). etc/adminhtml/events.xml, which duplicated the binding for the admin area only, was deleted.
  • composer.json: "license" corrected to "proprietary"; explicit php (~8.1.0||~8.2.0||~8.3.0||~8.4.0||~8.5.0) and magento/framework constraints added; the qoliber.dev "source" block dropped (F19, F20, F21).

Fixed

  • F1 Service\GetDynamicPrice::execute() treated a registry miss as a real price of 0.0 instead of falling back to a per-product query, because HistoricalPriceRegistry::getPrice() (F10) always returned a float, never null. Any product outside a bulk-loaded registry silently lost its historical price. Now branches on isBulkLoaded() && hasPrice().
  • F2 The price-history observer was bound to catalog_product_save_after globally and to catalog_product_save_before only under adminhtml. On save_after its setData() calls are never persisted, so REST, SOAP, bin/magento import, and ERP-driven price changes — most real-world price changes — recorded no history at all. Now bound once, to catalog_product_save_before, globally.
  • F3 Model\Indexer\MinPrice::executeList() issued one SELECT per price row to read the existing minimum (measured: 8278 queries over an 8156-row index). Replaced with one batched SELECT ... WHERE product_id IN (?) per call (1687 queries after).
  • F4 getAllProductIdsBatch() hardcoded entity_type_id = 4 for the status attribute. Now resolved via Magento\Eav\Model\Config.
  • F5 deleteOldPrices() ran once per 1000-product batch inside executeList() instead of once per reindex. Hoisted to execute(), executeFull(), and executeRow().
  • F6 The product-status join filtered attribute_id but not store_id, so a product with a store-scoped status value was yielded once per scope row (12 duplicates measured on this catalogue). Added cpev.store_id = 0.
  • F7 See "Changed" above.
  • F8 Plugin\Block\Product\AbstractProductPlugin was an around plugin that called $subject->getDetailsRenderer('historical_price') with no null guard. getDetailsRenderer() returns null whenever a layout has no renderer-list block at all, which fatals the unguarded call. Converted to after, added a null/instanceof guard, and an explicit isShowOnPlp() check.
  • F9 Pricing\Render\HistoricalPriceBox::__construct() used implicit nullable parameters, deprecated as of PHP 8.4. Made the ?Type nullability explicit.
  • F10 HistoricalPriceRegistry::getPrice() cast a missing entry to 0.0. Now returns ?float; hasPrice() remains the presence check.
  • F11 the Hyvä Tailwind safelist template (now in qoliber/omnibus-directive-hyva) built a $classes array that was never output — Tailwind's regex file scanner picked it up regardless, so the mechanism worked by accident. Now rendered into a hidden element so intent and mechanism agree.
  • F12 system.xml gave three fields the same sortOrder="10". PHP 8's stable sort meant declaration order was preserved regardless, so this was a determinism/hygiene fix, not a live rendering bug. Renumbered 10/20/30/40/50.
  • F22 Categories with Display Mode "Static block only" render their product grid through Magento\CatalogWidget\Block\Product\ProductsList, whose renderer list (category.product.type.widget.details.renderers) this module never targeted — only the native category grid's list was wired. Every such category showed no historical price at all. Added view/frontend/layout/catalog_widget_product_list.xml registering the same renderer on the widget's list.
  • F23 etc/adminhtml/system.xml referenced <tab>qoliber</tab> with no matching <tab id="qoliber"> declared anywhere — previously supplied by the now-dropped qoliber/core package. Magento throws while assembling the tab tree, which broke Stores → Configuration for every admin user, not only this section. The module now declares its own tab and no longer depends on another Qoliber package to be installable.
  • F24 MinPrice::executeList() computed the minimum across price, final_price and min_price. Composite types (grouped, bundle, downloadable) carry NULL in price/final_price in catalog_product_index_price; PHP's min() ranks NULL below any real number, so it was chosen over a genuine min_price, and MySQL coerced that NULL to 0 in the NOT NULL index column — a permanent, silent "price has never dropped" for every composite product. Non-applicable candidates are now filtered out before the minimum is taken, and a row is skipped entirely rather than written as a fabricated 0.

Known limitations

  • F4, F9, F11, F21 have no dedicated falsifying test — each is a portability, hygiene, or packaging fix with no observable behavioural difference on the reference installation.

Omnibus Directive for ElasticSuite

Fixed

  • ElasticSearch lookups never executed: the service called Layer\Resolver::create() at view time, which throws once the catalog controller has created the layer, and a bare catch (\Exception) silently fell back to MySQL. The service now consumes the resolved layer.
  • The database fallback queried website_id = 0 because a null website id was cast to int.
  • Fallbacks are logged instead of discarded.

Removed

  • BREAKING GetDynamicPricePlugin, which walked the whole layer collection once per product on a listing page while bypassing the registry.
  • BREAKING ElasticSearchHistoricalPriceService::getHistoricalPriceForProduct(), whose only caller was that plugin.

Changed

  • Depends on RequestInterface rather than the concrete Http request.
  • Requires qoliber/omnibus-directive ^2.0 and PHP 8.1–8.5.

1.0.2 — 2025-10-16

Omnibus Directive for ElasticSuite

Fixed

  • Fixed ElasticSearchHistoricalPriceService for better compatibility with ElasticSuite

1.0.1 — 2025-09-17

Omnibus Directive for ElasticSuite

Changed

  • Updated HistoricalPriceData datasource to align with changes in main OmnibusDirective module
  • Improved integration with OmnibusDirective configuration changes

1.0.0 — 2026-08-13

Omnibus Directive for Hyvä

Released 2026-08-13.

Added

  • Initial release. The Hyvä presentation layer moves here out of qoliber/omnibus-directive, which shipped it up to and including 1.0.6.
  • ViewModel\HyvaHistoricalPrice, exposing the historical price to Hyvä templates without pulling Hyva\Theme classes into the core module.
  • Hyvä layout handles for the product page, category page, search results page, and the Tailwind safelist template (hyva_catalog_product_view.xml, hyva_catalog_category_view.xml, hyva_catalogsearch_result_index.xml, hyva_default.xml).
  • Product list renderer templates (historical-price.phtml and the Alpine.js variant historical-price-alpine.phtml) rendered through the core module's theme-agnostic Block\Product\List\Renderer\HistoricalPrice.

Notes

  • The pricing pool wiring, the registry, the dynamic price service and the configuration model stay in qoliber/omnibus-directive and are shared with the Luma templates; only the Hyvä view layer and its HyvaHistoricalPrice view model live here.

Omnibus Directive for ElasticSuite

Released 2025-08-28.

Added

  • Initial release of Omnibus Directive ElasticSuite integration module
  • Implemented ElasticSearch index integration for historical prices
  • Added HistoricalPriceData datasource for Smile ElasticSuite fulltext indexing
  • Implemented ElasticSearchHistoricalPriceService for retrieving prices from ElasticSearch
  • Added plugin for BulkLoadHistoricalPrices to use ElasticSearch when available
  • Added plugin for GetDynamicPrice to leverage ElasticSearch for price retrieval
  • Implemented elasticsuite_indices.xml configuration for historical price indexing
  • Added historical price fields to the ElasticSearch product index: historical_price (decimal) and historical_price_date (date)
  • Enabled high-performance price retrieval from ElasticSearch instead of MySQL
  • Added automatic fallback to the database when ElasticSearch is unavailable
  • Implemented dependency on smile/elasticsuite and qoliber/omnibus-directive modules

Performance

  • Significantly improved historical price loading performance on category pages using ElasticSearch
  • Reduced database queries by leveraging ElasticSearch for bulk price operations
  • Optimized price data retrieval for large product catalogs

Integration

  • Seamless integration with the Smile ElasticSuite search engine
  • Compatible with the OmnibusDirective module's registry and service layer
  • Automatic detection and usage of ElasticSearch when the module is enabled
Changelog — Omnibus Directive — Compliance & Legal — Extensions | qoliber Docs