88namespace Magento \CatalogGraphQl \DataProvider \Product ;
99
1010use Magento \Catalog \Api \Data \EavAttributeInterface ;
11- use Magento \Catalog \Model \ Product ;
11+ use Magento \Catalog \Api \ ProductAttributeRepositoryInterface ;
1212use Magento \Catalog \Model \Product \Visibility ;
13- use Magento \Eav \Model \Config ;
13+ use Magento \CatalogSearch \Model \ResourceModel \ Fulltext \ Collection \ SearchCriteriaResolverFactory ;
1414use Magento \Framework \Api \FilterBuilder ;
1515use Magento \Framework \Api \Search \FilterGroupBuilder ;
1616use Magento \Framework \Api \Search \SearchCriteriaInterface ;
1717use Magento \Framework \Api \SortOrder ;
1818use Magento \Framework \Api \SortOrderBuilder ;
1919use Magento \Framework \App \Config \ScopeConfigInterface ;
20- use Magento \Framework \App \ObjectManager ;
2120use Magento \Framework \Exception \LocalizedException ;
22- use Magento \Framework \GraphQl \Query \Resolver \Argument \SearchCriteria \Builder ;
21+ use Magento \Framework \GraphQl \Query \Resolver \Argument \SearchCriteria \ArgumentApplierPool ;
2322use Magento \Framework \Search \Request \Config as SearchConfig ;
2423
2524/**
2625 * Build search criteria
2726 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2827 */
29-
3028class SearchCriteriaBuilder
3129{
3230 /**
33- * @var ScopeConfigInterface
34- */
35- private $ scopeConfig ;
36-
37- /**
38- * @var FilterBuilder
39- */
40- private $ filterBuilder ;
41-
42- /**
43- * @var FilterGroupBuilder
44- */
45- private $ filterGroupBuilder ;
46-
47- /**
48- * @var Builder
49- */
50- private $ builder ;
51-
52- /**
53- * @var Visibility
54- */
55- private $ visibility ;
56-
57- /**
58- * @var SortOrderBuilder
59- */
60- private $ sortOrderBuilder ;
61-
62- /**
63- * @var Config
64- */
65- private Config $ eavConfig ;
66-
67- /**
68- * @var SearchConfig
69- */
70- private SearchConfig $ searchConfig ;
71-
72- /**
73- * @var RequestDataBuilder|mixed
74- */
75- private RequestDataBuilder $ localData ;
76-
77- /**
78- * @param Builder $builder
7931 * @param ScopeConfigInterface $scopeConfig
8032 * @param FilterBuilder $filterBuilder
8133 * @param FilterGroupBuilder $filterGroupBuilder
8234 * @param Visibility $visibility
83- * @param SortOrderBuilder|null $sortOrderBuilder
84- * @param Config|null $eavConfig
85- * @param SearchConfig|null $searchConfig
86- * @param RequestDataBuilder|null $localData
35+ * @param SortOrderBuilder $sortOrderBuilder
36+ * @param ProductAttributeRepositoryInterface $productAttributeRepository
37+ * @param SearchConfig $searchConfig
38+ * @param RequestDataBuilder $localData
39+ * @param SearchCriteriaResolverFactory $criteriaResolverFactory
40+ * @param ArgumentApplierPool $argumentApplierPool
8741 */
8842 public function __construct (
89- Builder $ builder ,
90- ScopeConfigInterface $ scopeConfig ,
91- FilterBuilder $ filterBuilder ,
92- FilterGroupBuilder $ filterGroupBuilder ,
93- Visibility $ visibility ,
94- SortOrderBuilder $ sortOrderBuilder = null ,
95- Config $ eavConfig = null ,
96- SearchConfig $ searchConfig = null ,
97- RequestDataBuilder $ localData = null ,
43+ private readonly ScopeConfigInterface $ scopeConfig ,
44+ private readonly FilterBuilder $ filterBuilder ,
45+ private readonly FilterGroupBuilder $ filterGroupBuilder ,
46+ private readonly Visibility $ visibility ,
47+ private readonly SortOrderBuilder $ sortOrderBuilder ,
48+ private readonly ProductAttributeRepositoryInterface $ productAttributeRepository ,
49+ private readonly SearchConfig $ searchConfig ,
50+ private readonly RequestDataBuilder $ localData ,
51+ private readonly SearchCriteriaResolverFactory $ criteriaResolverFactory ,
52+ private readonly ArgumentApplierPool $ argumentApplierPool ,
9853 ) {
99- $ this ->scopeConfig = $ scopeConfig ;
100- $ this ->filterBuilder = $ filterBuilder ;
101- $ this ->filterGroupBuilder = $ filterGroupBuilder ;
102- $ this ->builder = $ builder ;
103- $ this ->visibility = $ visibility ;
104- $ this ->sortOrderBuilder = $ sortOrderBuilder ?? ObjectManager::getInstance ()->get (SortOrderBuilder::class);
105- $ this ->eavConfig = $ eavConfig ?? ObjectManager::getInstance ()->get (Config::class);
106- $ this ->searchConfig = $ searchConfig ?? ObjectManager::getInstance ()->get (SearchConfig::class);
107- $ this ->localData = $ localData ?? ObjectManager::getInstance ()->get (RequestDataBuilder::class);
10854 }
10955
11056 /**
@@ -117,45 +63,41 @@ public function __construct(
11763 */
11864 public function build (array $ args , bool $ includeAggregation ): SearchCriteriaInterface
11965 {
120- $ partialMatchFilters = [];
66+ $ isSearch = isset ($ args ['search ' ]);
67+ $ requestName = $ includeAggregation ? 'graphql_product_search_with_aggregation ' : 'graphql_product_search ' ;
68+
12169 if (isset ($ args ['filter ' ])) {
12270 $ partialMatchFilters = $ this ->getPartialMatchFilters ($ args );
71+ if (count ($ partialMatchFilters )) {
72+ $ this ->updateMatchTypeRequestConfig ($ requestName , $ partialMatchFilters );
73+ }
12374 $ args = $ this ->removeMatchTypeFromArguments ($ args );
12475 }
125- $ searchCriteria = $ this ->builder ->build ('products ' , $ args );
126- $ isSearch = isset ($ args ['search ' ]);
127- $ this ->updateRangeFilters ($ searchCriteria );
128- if ($ includeAggregation ) {
129- $ attributeData = $ this ->eavConfig ->getAttribute (Product::ENTITY , 'price ' );
130- $ priceOptions = $ attributeData ->getData ();
13176
132- if ($ priceOptions ['is_filterable ' ] != 0 ) {
133- $ this ->preparePriceAggregation ($ searchCriteria );
77+ $ searchCriteria = $ this ->criteriaResolverFactory ->create (
78+ [
79+ 'searchRequestName ' => $ requestName ,
80+ 'currentPage ' => $ args ['currentPage ' ],
81+ 'size ' => $ args ['pageSize ' ],
82+ ]
83+ )->resolve ();
84+ foreach ($ args as $ argumentName => $ argument ) {
85+ if ($ this ->argumentApplierPool ->hasApplier ($ argumentName )) {
86+ $ argumentApplier = $ this ->argumentApplierPool ->getApplier ($ argumentName );
87+ $ argumentApplier ->applyArgument ($ searchCriteria , 'products ' , $ argumentName , $ argument );
13488 }
135- $ requestName = 'graphql_product_search_with_aggregation ' ;
136- } else {
137- $ requestName = 'graphql_product_search ' ;
138- }
139- $ searchCriteria ->setRequestName ($ requestName );
140-
141- if (count ($ partialMatchFilters )) {
142- $ this ->updateMatchTypeRequestConfig ($ requestName , $ partialMatchFilters );
14389 }
144-
90+ $ this ->updateRangeFilters ($ searchCriteria );
91+ $ this ->preparePriceAggregation ($ searchCriteria , $ includeAggregation );
14592 if ($ isSearch ) {
14693 $ this ->addFilter ($ searchCriteria , 'search_term ' , $ args ['search ' ]);
14794 }
148-
14995 if (!$ searchCriteria ->getSortOrders ()) {
150- $ this ->addDefaultSortOrder ($ searchCriteria , $ args, $ isSearch );
96+ $ this ->addDefaultSortOrder ($ searchCriteria , $ args );
15197 }
152-
15398 $ this ->addEntityIdSort ($ searchCriteria );
15499 $ this ->addVisibilityFilter ($ searchCriteria , $ isSearch , !empty ($ args ['filter ' ]['category_id ' ]));
155100
156- $ searchCriteria ->setCurrentPage ($ args ['currentPage ' ] - 1 );
157- $ searchCriteria ->setPageSize ($ args ['pageSize ' ]);
158-
159101 return $ searchCriteria ;
160102 }
161103
@@ -164,7 +106,6 @@ public function build(array $args, bool $includeAggregation): SearchCriteriaInte
164106 *
165107 * @param string $requestName
166108 * @param array $partialMatchFilters
167- *
168109 * @return void
169110 */
170111 private function updateMatchTypeRequestConfig (string $ requestName , array $ partialMatchFilters ): void
@@ -184,7 +125,6 @@ private function updateMatchTypeRequestConfig(string $requestName, array $partia
184125 * Check if and what type of match_type value was requested
185126 *
186127 * @param array $args
187- *
188128 * @return array
189129 */
190130 private function getPartialMatchFilters (array $ args ): array
@@ -202,7 +142,6 @@ private function getPartialMatchFilters(array $args): array
202142 * Remove the match_type to avoid search criteria containing it
203143 *
204144 * @param array $args
205- *
206145 * @return array
207146 */
208147 private function removeMatchTypeFromArguments (array $ args ): array
@@ -264,10 +203,21 @@ private function addEntityIdSort(SearchCriteriaInterface $searchCriteria): void
264203 * Prepare price aggregation algorithm
265204 *
266205 * @param SearchCriteriaInterface $searchCriteria
206+ * @param bool $includeAggregation
267207 * @return void
268208 */
269- private function preparePriceAggregation (SearchCriteriaInterface $ searchCriteria ): void
209+ private function preparePriceAggregation (SearchCriteriaInterface $ searchCriteria, bool $ includeAggregation ): void
270210 {
211+ if (!$ includeAggregation ) {
212+ return ;
213+ }
214+
215+ $ attributeData = $ this ->productAttributeRepository ->get ('price ' );
216+ $ priceOptions = $ attributeData ->getData ();
217+ if ((int ) $ priceOptions ['is_filterable ' ] === 0 ) {
218+ return ;
219+ }
220+
271221 $ priceRangeCalculation = $ this ->scopeConfig ->getValue (
272222 \Magento \Catalog \Model \Layer \Filter \Dynamic \AlgorithmFactory::XML_PATH_RANGE_CALCULATION ,
273223 \Magento \Store \Model \ScopeInterface::SCOPE_STORE
@@ -308,18 +258,17 @@ private function addFilter(
308258 *
309259 * @param SearchCriteriaInterface $searchCriteria
310260 * @param array $args
311- * @param bool $isSearch
312261 */
313- private function addDefaultSortOrder (SearchCriteriaInterface $ searchCriteria , array $ args, $ isSearch = false ): void
262+ private function addDefaultSortOrder (SearchCriteriaInterface $ searchCriteria , array $ args ): void
314263 {
315264 $ defaultSortOrder = [];
316- if ($ isSearch ) {
265+ if (isset ( $ args [ ' search ' ]) ) {
317266 $ defaultSortOrder [] = $ this ->sortOrderBuilder
318267 ->setField ('relevance ' )
319268 ->setDirection (SortOrder::SORT_DESC )
320269 ->create ();
321270 } else {
322- $ categoryIdFilter = isset ( $ args ['filter ' ]['category_id ' ]) ? $ args [ ' filter ' ][ ' category_id ' ] : false ;
271+ $ categoryIdFilter = $ args ['filter ' ]['category_id ' ] ?? false ;
323272 if ($ categoryIdFilter ) {
324273 if (!is_array ($ categoryIdFilter [array_key_first ($ categoryIdFilter )])
325274 || count ($ categoryIdFilter [array_key_first ($ categoryIdFilter )]) <= 1
0 commit comments