Skip to content

Commit 086f5ef

Browse files
authored
Merge pull request #8536 from magento-l3/L3-PR-2023-09-13
L3 pr 2023 09 13
2 parents 75c365f + f78499e commit 086f5ef

File tree

18 files changed

+916
-69
lines changed

18 files changed

+916
-69
lines changed

app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
use Magento\Framework\Api\SortOrderBuilder;
1919
use Magento\Framework\App\Config\ScopeConfigInterface;
2020
use Magento\Framework\App\ObjectManager;
21+
use Magento\Framework\Exception\LocalizedException;
2122
use Magento\Framework\GraphQl\Query\Resolver\Argument\SearchCriteria\Builder;
23+
use Magento\Framework\Search\Request\Config as SearchConfig;
2224

2325
/**
2426
* Build search criteria
@@ -46,6 +48,7 @@ class SearchCriteriaBuilder
4648
* @var Builder
4749
*/
4850
private $builder;
51+
4952
/**
5053
* @var Visibility
5154
*/
@@ -61,14 +64,20 @@ class SearchCriteriaBuilder
6164
*/
6265
private Config $eavConfig;
6366

67+
/**
68+
* @var SearchConfig
69+
*/
70+
private SearchConfig $searchConfig;
71+
6472
/**
6573
* @param Builder $builder
6674
* @param ScopeConfigInterface $scopeConfig
6775
* @param FilterBuilder $filterBuilder
6876
* @param FilterGroupBuilder $filterGroupBuilder
6977
* @param Visibility $visibility
70-
* @param SortOrderBuilder $sortOrderBuilder
71-
* @param Config $eavConfig
78+
* @param SortOrderBuilder|null $sortOrderBuilder
79+
* @param Config|null $eavConfig
80+
* @param SearchConfig|null $searchConfig
7281
*/
7382
public function __construct(
7483
Builder $builder,
@@ -77,7 +86,8 @@ public function __construct(
7786
FilterGroupBuilder $filterGroupBuilder,
7887
Visibility $visibility,
7988
SortOrderBuilder $sortOrderBuilder = null,
80-
Config $eavConfig = null
89+
Config $eavConfig = null,
90+
SearchConfig $searchConfig = null
8191
) {
8292
$this->scopeConfig = $scopeConfig;
8393
$this->filterBuilder = $filterBuilder;
@@ -86,6 +96,7 @@ public function __construct(
8696
$this->visibility = $visibility;
8797
$this->sortOrderBuilder = $sortOrderBuilder ?? ObjectManager::getInstance()->get(SortOrderBuilder::class);
8898
$this->eavConfig = $eavConfig ?? ObjectManager::getInstance()->get(Config::class);
99+
$this->searchConfig = $searchConfig ?? ObjectManager::getInstance()->get(SearchConfig::class);
89100
}
90101

91102
/**
@@ -94,9 +105,15 @@ public function __construct(
94105
* @param array $args
95106
* @param bool $includeAggregation
96107
* @return SearchCriteriaInterface
108+
* @throws LocalizedException
97109
*/
98110
public function build(array $args, bool $includeAggregation): SearchCriteriaInterface
99111
{
112+
$partialMatchFilters = [];
113+
if (isset($args['filter'])) {
114+
$partialMatchFilters = $this->getPartialMatchFilters($args);
115+
$args = $this->removeMatchTypeFromArguments($args);
116+
}
100117
$searchCriteria = $this->builder->build('products', $args);
101118
$isSearch = isset($args['search']);
102119
$this->updateRangeFilters($searchCriteria);
@@ -113,6 +130,10 @@ public function build(array $args, bool $includeAggregation): SearchCriteriaInte
113130
}
114131
$searchCriteria->setRequestName($requestName);
115132

133+
if (count($partialMatchFilters)) {
134+
$this->updateMatchTypeRequestConfig($requestName, $partialMatchFilters);
135+
}
136+
116137
if ($isSearch) {
117138
$this->addFilter($searchCriteria, 'search_term', $args['search']);
118139
}
@@ -130,6 +151,63 @@ public function build(array $args, bool $includeAggregation): SearchCriteriaInte
130151
return $searchCriteria;
131152
}
132153

154+
/**
155+
* Update dynamically the search match type based on requested params
156+
*
157+
* @param string $requestName
158+
* @param array $partialMatchFilters
159+
*
160+
* @return void
161+
*/
162+
private function updateMatchTypeRequestConfig(string $requestName, array $partialMatchFilters): void
163+
{
164+
$data = $this->searchConfig->get($requestName);
165+
foreach ($data['queries'] as $queryName => $query) {
166+
foreach ($query['match'] ?? [] as $index => $matchItem) {
167+
if (in_array($matchItem['field'] ?? null, $partialMatchFilters, true)) {
168+
$data['queries'][$queryName]['match'][$index]['matchCondition'] = 'match_phrase_prefix';
169+
}
170+
}
171+
}
172+
$this->searchConfig->merge([$requestName => $data]);
173+
}
174+
175+
/**
176+
* Check if and what type of match_type value was requested
177+
*
178+
* @param array $args
179+
*
180+
* @return array
181+
*/
182+
private function getPartialMatchFilters(array $args): array
183+
{
184+
$partialMatchFilters = [];
185+
foreach ($args['filter'] as $fieldName => $conditions) {
186+
if (isset($conditions['match_type']) && $conditions['match_type'] === 'PARTIAL') {
187+
$partialMatchFilters[] = $fieldName;
188+
}
189+
}
190+
return $partialMatchFilters;
191+
}
192+
193+
/**
194+
* Remove the match_type to avoid search criteria containing it
195+
*
196+
* @param array $args
197+
*
198+
* @return array
199+
*/
200+
private function removeMatchTypeFromArguments(array $args): array
201+
{
202+
foreach ($args['filter'] as &$conditions) {
203+
if (isset($conditions['match_type'])) {
204+
unset($conditions['match_type']);
205+
}
206+
}
207+
208+
return $args;
209+
}
210+
133211
/**
134212
* Add filter by visibility
135213
*

app/code/Magento/CatalogWidget/Block/Product/ProductsList.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,15 +324,26 @@ protected function _beforeToHtml()
324324
*/
325325
public function createCollection()
326326
{
327-
/** @var $collection Collection */
328-
$collection = $this->productCollectionFactory->create();
327+
$collection = $this->getBaseCollection();
328+
329+
$collection->setVisibility($this->catalogProductVisibility->getVisibleInCatalogIds());
330+
331+
return $collection;
332+
}
329333

334+
/**
335+
* Prepare and return product collection without visibility filter
336+
*
337+
* @return Collection
338+
* @throws LocalizedException
339+
*/
340+
public function getBaseCollection(): Collection
341+
{
342+
$collection = $this->productCollectionFactory->create();
330343
if ($this->getData('store_id') !== null) {
331344
$collection->setStoreId($this->getData('store_id'));
332345
}
333346

334-
$collection->setVisibility($this->catalogProductVisibility->getVisibleInCatalogIds());
335-
336347
/**
337348
* Change sorting attribute to entity_id because created_at can be the same for products fastly created
338349
* one by one and sorting by created_at is indeterministic in this case.

app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use Magento\Framework\App\Action\Action;
1515
// phpcs:disable Magento2.Templates.ThisInTemplate.FoundHelper
1616
// phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis
1717
?>
18-
<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->getSize())): ?>
18+
<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->count())): ?>
1919
<?php
2020
$type = 'widget-product-grid';
2121

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\ConfigurableProduct\Plugin\CatalogWidget\Block\Product;
10+
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Catalog\Model\Product\Visibility;
13+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
14+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
15+
use Magento\CatalogWidget\Block\Product\ProductsList;
16+
use Magento\Framework\App\ResourceConnection;
17+
use Magento\Framework\EntityManager\MetadataPool;
18+
use Magento\Framework\Exception\LocalizedException;
19+
20+
class ProductsListPlugin
21+
{
22+
/**
23+
* @var CollectionFactory
24+
*/
25+
private CollectionFactory $productCollectionFactory;
26+
27+
/**
28+
* @var Visibility
29+
*/
30+
private Visibility $catalogProductVisibility;
31+
32+
/**
33+
* @var ResourceConnection
34+
*/
35+
private ResourceConnection $resource;
36+
37+
/**
38+
* @var MetadataPool
39+
*/
40+
private MetadataPool $metadataPool;
41+
42+
/**
43+
* @param CollectionFactory $productCollectionFactory
44+
* @param Visibility $catalogProductVisibility
45+
* @param ResourceConnection $resource
46+
* @param MetadataPool $metadataPool
47+
*/
48+
public function __construct(
49+
CollectionFactory $productCollectionFactory,
50+
Visibility $catalogProductVisibility,
51+
ResourceConnection $resource,
52+
MetadataPool $metadataPool
53+
) {
54+
$this->productCollectionFactory = $productCollectionFactory;
55+
$this->catalogProductVisibility = $catalogProductVisibility;
56+
$this->resource = $resource;
57+
$this->metadataPool = $metadataPool;
58+
}
59+
60+
/**
61+
* Adds configurable products to the item list if child products are already part of the collection
62+
*
63+
* @param ProductsList $subject
64+
* @param Collection $result
65+
* @return Collection
66+
* @throws LocalizedException
67+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
68+
*/
69+
public function afterCreateCollection(ProductsList $subject, Collection $result): Collection
70+
{
71+
$notVisibleCollection = $subject->getBaseCollection();
72+
$currentIds = $result->getAllIds();
73+
$searchProducts = array_merge($currentIds, $notVisibleCollection->getAllIds());
74+
75+
if (!empty($searchProducts)) {
76+
$linkField = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
77+
->getLinkField();
78+
$connection = $this->resource->getConnection();
79+
$productIds = $connection->fetchCol(
80+
$connection
81+
->select()
82+
->from(['e' => $this->resource->getTableName('catalog_product_entity')], ['link_table.parent_id'])
83+
->joinInner(
84+
['link_table' => $this->resource->getTableName('catalog_product_super_link')],
85+
'link_table.product_id = e.' . $linkField,
86+
[]
87+
)
88+
->where('link_table.product_id IN (?)', $searchProducts)
89+
);
90+
91+
$configurableProductCollection = $this->productCollectionFactory->create();
92+
$configurableProductCollection->setVisibility($this->catalogProductVisibility->getVisibleInCatalogIds());
93+
$configurableProductCollection->addIdFilter($productIds);
94+
95+
/** @var Product $item */
96+
foreach ($configurableProductCollection->getItems() as $item) {
97+
if (false === in_array($item->getId(), $currentIds)) {
98+
$result->addItem($item->load($item->getId()));
99+
}
100+
}
101+
}
102+
103+
return $result;
104+
}
105+
}

0 commit comments

Comments
 (0)