Skip to content

Commit f277964

Browse files
Merge pull request #144 from denisprotassoff/issue-5325
5325 Modified criteria builder to include visibility filter
2 parents b7a0705 + c90394d commit f277964

File tree

2 files changed

+261
-0
lines changed

2 files changed

+261
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
<?php
2+
/**
3+
* @category ScandiPWA
4+
* @package ScandiPWA_CatalogGraphQl
5+
* @author Denis Protassoff <[email protected]>
6+
* @copyright Copyright (c) 2022 Scandiweb, Ltd (https://scandiweb.com)
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace ScandiPWA\CatalogGraphQl\DataProvider\Product;
12+
13+
use Magento\Catalog\Api\Data\EavAttributeInterface;
14+
use Magento\Framework\Api\FilterBuilder;
15+
use Magento\Framework\Api\Search\FilterGroupBuilder;
16+
use Magento\Framework\Api\Search\SearchCriteriaInterface;
17+
use Magento\Framework\Api\SortOrder;
18+
use Magento\Framework\App\Config\ScopeConfigInterface;
19+
use Magento\Framework\GraphQl\Query\Resolver\Argument\SearchCriteria\Builder;
20+
use Magento\Catalog\Model\Product\Visibility;
21+
use Magento\Framework\Api\SortOrderBuilder;
22+
use Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder as MagentoSearchCriteriaBuilder;
23+
24+
/**
25+
* Class SearchCriteriaBuilder
26+
*
27+
* @package ScandiPWA\CatalogGraphQl\DataProvider\Product
28+
*/
29+
class SearchCriteriaBuilder extends MagentoSearchCriteriaBuilder
30+
{
31+
/**
32+
* @var ScopeConfigInterface
33+
*/
34+
protected $scopeConfig;
35+
36+
/**
37+
* @var FilterBuilder
38+
*/
39+
protected $filterBuilder;
40+
41+
/**
42+
* @var FilterGroupBuilder
43+
*/
44+
protected $filterGroupBuilder;
45+
46+
/**
47+
* @var Builder
48+
*/
49+
protected $builder;
50+
/**
51+
* @var Visibility
52+
*/
53+
protected $visibility;
54+
55+
/**
56+
* @var SortOrderBuilder
57+
*/
58+
protected $sortOrderBuilder;
59+
60+
/**
61+
* @param Builder $builder
62+
* @param ScopeConfigInterface $scopeConfig
63+
* @param FilterBuilder $filterBuilder
64+
* @param FilterGroupBuilder $filterGroupBuilder
65+
* @param Visibility $visibility
66+
* @param SortOrderBuilder $sortOrderBuilder
67+
*/
68+
public function __construct(
69+
Builder $builder,
70+
ScopeConfigInterface $scopeConfig,
71+
FilterBuilder $filterBuilder,
72+
FilterGroupBuilder $filterGroupBuilder,
73+
Visibility $visibility,
74+
SortOrderBuilder $sortOrderBuilder
75+
) {
76+
$this->scopeConfig = $scopeConfig;
77+
$this->filterBuilder = $filterBuilder;
78+
$this->filterGroupBuilder = $filterGroupBuilder;
79+
$this->builder = $builder;
80+
$this->visibility = $visibility;
81+
$this->sortOrderBuilder = $sortOrderBuilder;
82+
}
83+
84+
/**
85+
* Build search criteria
86+
*
87+
* @param array $args
88+
* @param bool $includeAggregation
89+
* @return SearchCriteriaInterface
90+
*/
91+
public function build(array $args, bool $includeAggregation): SearchCriteriaInterface
92+
{
93+
$searchCriteria = $this->builder->build('products', $args);
94+
$isSearch = !empty($args['search']);
95+
$this->updateRangeFilters($searchCriteria);
96+
97+
if ($includeAggregation) {
98+
$this->preparePriceAggregation($searchCriteria);
99+
$requestName = 'graphql_product_search_with_aggregation';
100+
} else {
101+
$requestName = 'graphql_product_search';
102+
}
103+
104+
$searchCriteria->setRequestName($requestName);
105+
106+
if ($isSearch) {
107+
$this->addFilter($searchCriteria, 'search_term', $args['search']);
108+
}
109+
110+
if (!$searchCriteria->getSortOrders()) {
111+
$this->addDefaultSortOrder($searchCriteria, $args, $isSearch);
112+
}
113+
114+
$this->addEntityIdSort($searchCriteria, $args);
115+
// Removed $isFilter parameter
116+
$this->addVisibilityFilter($searchCriteria, $isSearch);
117+
118+
$searchCriteria->setCurrentPage($args['currentPage']);
119+
$searchCriteria->setPageSize($args['pageSize']);
120+
121+
return $searchCriteria;
122+
}
123+
124+
/**
125+
* Changed to always add visibility filter
126+
* Add filter by visibility
127+
*
128+
* @param SearchCriteriaInterface $searchCriteria
129+
* @param bool $isSearch
130+
* @param bool $isFilter
131+
*/
132+
protected function addVisibilityFilter(SearchCriteriaInterface $searchCriteria, bool $isSearch): void
133+
{
134+
// Removed $isFilter parameter and related check
135+
$visibilityIds = $isSearch
136+
? $this->visibility->getVisibleInSearchIds()
137+
: $this->visibility->getVisibleInCatalogIds();
138+
139+
$this->addFilter($searchCriteria, 'visibility', $visibilityIds, 'in');
140+
}
141+
142+
/**
143+
* Add sort by Entity ID
144+
*
145+
* @param SearchCriteriaInterface $searchCriteria
146+
* @param array $args
147+
*/
148+
protected function addEntityIdSort(SearchCriteriaInterface $searchCriteria, array $args): void
149+
{
150+
$sortOrder = !empty($args['sort']) ? reset($args['sort']) : SortOrder::SORT_DESC;
151+
$sortOrderArray = $searchCriteria->getSortOrders();
152+
$sortOrderArray[] = $this->sortOrderBuilder
153+
->setField('_id')
154+
->setDirection($sortOrder)
155+
->create();
156+
$searchCriteria->setSortOrders($sortOrderArray);
157+
}
158+
159+
/**
160+
* Prepare price aggregation algorithm
161+
*
162+
* @param SearchCriteriaInterface $searchCriteria
163+
* @return void
164+
*/
165+
protected function preparePriceAggregation(SearchCriteriaInterface $searchCriteria): void
166+
{
167+
$priceRangeCalculation = $this->scopeConfig->getValue(
168+
\Magento\Catalog\Model\Layer\Filter\Dynamic\AlgorithmFactory::XML_PATH_RANGE_CALCULATION,
169+
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
170+
);
171+
172+
if ($priceRangeCalculation) {
173+
$this->addFilter($searchCriteria, 'price_dynamic_algorithm', $priceRangeCalculation);
174+
}
175+
}
176+
177+
/**
178+
* Add filter to search criteria
179+
*
180+
* @param SearchCriteriaInterface $searchCriteria
181+
* @param string $field
182+
* @param mixed $value
183+
* @param string|null $condition
184+
*/
185+
protected function addFilter(
186+
SearchCriteriaInterface $searchCriteria,
187+
string $field,
188+
$value,
189+
?string $condition = null
190+
): void {
191+
$filter = $this->filterBuilder
192+
->setField($field)
193+
->setValue($value)
194+
->setConditionType($condition)
195+
->create();
196+
197+
$this->filterGroupBuilder->addFilter($filter);
198+
$filterGroups = $searchCriteria->getFilterGroups();
199+
$filterGroups[] = $this->filterGroupBuilder->create();
200+
$searchCriteria->setFilterGroups($filterGroups);
201+
}
202+
203+
/**
204+
* Sort by relevance DESC by default
205+
*
206+
* @param SearchCriteriaInterface $searchCriteria
207+
* @param array $args
208+
* @param bool $isSearch
209+
*/
210+
protected function addDefaultSortOrder(SearchCriteriaInterface $searchCriteria, array $args, $isSearch = false): void
211+
{
212+
$defaultSortOrder = [];
213+
214+
if ($isSearch) {
215+
$defaultSortOrder[] = $this->sortOrderBuilder
216+
->setField('relevance')
217+
->setDirection(SortOrder::SORT_DESC)
218+
->create();
219+
} else {
220+
$categoryIdFilter = isset($args['filter']['category_id']) ? $args['filter']['category_id'] : false;
221+
222+
if ($categoryIdFilter) {
223+
if (!is_array($categoryIdFilter[array_key_first($categoryIdFilter)])
224+
|| count($categoryIdFilter[array_key_first($categoryIdFilter)]) <= 1
225+
) {
226+
$defaultSortOrder[] = $this->sortOrderBuilder
227+
->setField(EavAttributeInterface::POSITION)
228+
->setDirection(SortOrder::SORT_ASC)
229+
->create();
230+
}
231+
}
232+
}
233+
234+
$searchCriteria->setSortOrders($defaultSortOrder);
235+
}
236+
237+
/**
238+
* Format range filters so replacement works
239+
*
240+
* Range filter fields in search request must replace value like '%field.from%' or '%field.to%'
241+
*
242+
* @param SearchCriteriaInterface $searchCriteria
243+
*/
244+
protected function updateRangeFilters(SearchCriteriaInterface $searchCriteria): void
245+
{
246+
$filterGroups = $searchCriteria->getFilterGroups();
247+
248+
foreach ($filterGroups as $filterGroup) {
249+
$filters = $filterGroup->getFilters();
250+
251+
foreach ($filters as $filter) {
252+
if (in_array($filter->getConditionType(), ['from', 'to'])) {
253+
$filter->setField($filter->getField() . '.' . $filter->getConditionType());
254+
}
255+
}
256+
}
257+
}
258+
}

src/etc/di.xml

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
<preference for="Magento\CatalogGraphQl\Model\Resolver\Product\MediaGalleryEntries"
2020
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Product\MediaGalleryEntries"/>
2121

22+
<preference for="Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder"
23+
type="ScandiPWA\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder"/>
24+
2225
<!-- <preference for="Magento\CatalogGraphQl\Model\Resolver\Category\Products"-->
2326
<!-- type="ScandiPWA\CatalogGraphQl\Model\Resolver\Category\Products"/>-->
2427

0 commit comments

Comments
 (0)