Add "Category Listing (search engine)" source to the Products content type - #911
Open
lbajsarowicz wants to merge 7 commits into
Open
lbajsarowicz wants to merge 7 commits into
lbajsarowicz wants to merge 7 commits into
Conversation
Add a fourth "Select Products By" option, "Category Listing (search engine)", with a single-category picker. The widget directive mass converters emit a directive for Magento\PageBuilder\Block\Catalog\Product\CategoryListing carrying the category id instead of encoded conditions, and read it back into the form. The stage preview renders for this option when a category is selected.
…type The Products content type builds its collection through CatalogWidget\Block\Product\ProductsList: a MySQL collection with rule conditions. The category page builds its collection through Catalog\Model\Layer::getProductCollection(), whose provider and filter are replaced by CatalogSearch. The two return different product sets and orders, so "products of category X" on a landing page does not match category X. CategoryListing builds its collection through a dedicated Catalog\Model\Layer\Category instance, so every di override (CatalogSearch, third-party search modules) applies, and replicates the sorting the category page applies through ListProduct and Toolbar: the category default_sort_by, falling back to catalog/frontend/default_sort_by, with position handled via addAttributeToSort(). A chosen Page Builder sort_order still wins. The collection building lives in a CollectionBuilder shared by the block and by ProductTotals, so the stage badge cannot drift from the storefront. The block dispatches pagebuilder_products_category_listing_prepare before it touches the layer, so a search module can seed its request-scoped context. The block is declared in widget.xml because the widget directive filter renders only declared widgets; the widget takes a category chooser (id_path) while the Page Builder directive passes category_id. Two plugins inherited from ProductsList are disabled for the block: Page Builder's own sorting plugin (the block owns sorting) and the ConfigurableProduct widget plugin, which loads the collection early and merges parent products, both of which break parity with the category page.
Extend the product-totals admin component so the "Category Listing (search engine)" option refreshes the stage badge: it skips the rule-condition encoder, posts conditionOption and categoryId directly, and tracks its own previous-value signature instead of conditions_encoded, so switching categories still refreshes the count. Add an MFTF test that creates a category with three products, selects the new option, and asserts the same product order on the stage and on the storefront.
Contributor
Author
|
@magento run all tests |
The old header form trips the Magento2Framework copyright sniff, and lines over 120 characters fail the static code style test once the files are part of a change set. Formatting only, no configuration or behaviour change.
Contributor
Author
|
@magento run all tests |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description (*)
The Products content type builds its collection through
Magento\CatalogWidget\Block\Product\ProductsList: a MySQL product collection with rule conditions attached by the SQL condition builder. The category page builds its collection throughMagento\Catalog\Model\Layer::getProductCollection(), whose collection provider and filter are replaced by CatalogSearch (and by third-party search modules such as ElasticSuite) with a search-engine-backed collection. The two paths return different product sets and orders: the category default sort is ignored, position sorting differs, and virtual categories, merchandising and search-engine boosts never apply. Merchants who place "products of category X" on a landing page get a list that does not match category X.This adds a fourth Select Products By option to the Products content type: Category Listing (search engine). Existing options, templates, appearances and stored content are untouched.
How it works:
condition_optionvaluecategory_listingwith a single-category picker. The widget directive mass converters emit{{widget type="Magento\PageBuilder\Block\Catalog\Product\CategoryListing" ... category_id="N" ...}}with noconditions_encoded, and read it back. The stage preview renders for this option, and the "N products" badge is counted through the same collection as the storefront.Block\Catalog\Product\CategoryListingextendsProductsListand delegates toModel\Catalog\CategoryListing\CollectionBuilder, which creates a dedicatedMagento\Catalog\Model\Layer\Category, sets the category, takesgetProductCollection()and callsaddCategoryFilter($category). Every di override that the category page relies on applies. Sorting replicatesListProduct::prepareSortableFieldsByCategory()andToolbar::setCollection(): the categorydefault_sort_by, thencatalog/frontend/default_sort_by, then the first available order;positionthroughaddAttributeToSort(). A Page Buildersort_order, when chosen, wins.pagebuilder_products_category_listing_prepare(category,layer,store_id,block) before touching the layer so a search module can seed request-scoped state (ElasticSuite's search context, see below).etc/widget.xmlbecause the widget directive filter renders only declared widgets. The Insert Widget form gets a category chooser (id_path); the Page Builder directive passescategory_id.ProductsListare disabled for the new block: Page Builder's own sorting plugin (the block owns sorting) andConfigurableProduct's widget plugin, which callsgetAllIds()on the collection early and merges parent configurables of hidden children. Both break parity with the category page.Verified locally on OpenSearch (2.4-develop, developer mode) against a category with a disabled, an out-of-stock and a not-visible product plus custom positions: grid and carousel render the same ids in the same order as the category page for default (position) and name sorts; today's Catalog Products List widget differs on both.
Verified with ElasticSuite 2.11.x installed (modules copied into
app/code): regular category, two virtual categories (rule-based, one spanning the whole catalog) and two widgets for different categories on one page all match their category pages exactly. TheaddCategoryFilter()call is what makes virtual categories resolve; ElasticSuite's collection provider ignores the category otherwise. ElasticSuite's request-scoped search context still latches the store root on a CMS page (itsafterGetCurrentCategoryplugin runs before the layer stores the category), which leaves category-scoped optimizers unapplied; product lists are unaffected. A three-line observer on the new event sets the context and fixes that; it belongs in ElasticSuite or a glue module, not here.Tests: unit tests for the block, the collection builder and the totals branch; an integration test asserting the block's loaded items equal a
ListProduct+Toolbarcollection for the same category (default and name sort, missing category, cache key); Jasmine cases for both directive converters; an MFTF test creating a category with three products, selecting the new option and asserting the order on the stage and the storefront.Fixed Issues (if relevant)
None filed. This is a feature request from agency practice: the Products content type cannot reproduce a category page listing.
Manual testing scenarios (*)
?product_list_order=name.var/log.Questions or comments
PHPCS reports pre-existing line-length warnings in
etc/di.xml,pagebuilder_products_form.xmlandTest/Mftf/Data/ProductsData.xmlondevelop; the new files are clean. The Jasmine and MFTF tests have not been executed locally (no runner in this repository); the unit and integration tests were run in a local 2.4-develop environment with OpenSearch.