7
7
8
8
namespace Magento \CatalogGraphQl \Model \Category ;
9
9
10
+ use Magento \Catalog \Api \CategoryListInterface ;
10
11
use Magento \Catalog \Api \Data \CategoryInterface ;
11
- use Magento \Catalog \Model \ResourceModel \Category \Collection ;
12
12
use Magento \Framework \App \Config \ScopeConfigInterface ;
13
13
use Magento \Framework \Exception \InputException ;
14
+ use Magento \Framework \GraphQl \Exception \GraphQlInputException ;
15
+ use Magento \Framework \GraphQl \Query \Resolver \Argument \SearchCriteria \ArgumentApplier \Filter ;
16
+ use Magento \Framework \Search \Adapter \Mysql \Query \Builder \Match ;
17
+ use Magento \Search \Model \Query ;
14
18
use Magento \Store \Api \Data \StoreInterface ;
15
19
use Magento \Store \Model \ScopeInterface ;
16
- use Magento \Search \ Model \Query ;
20
+ use Magento \Framework \ GraphQl \Query \ Resolver \ Argument \ SearchCriteria \ Builder ;
17
21
18
22
/**
19
- * Category filter allows to filter collection using 'id, url_key, name' from search criteria .
23
+ * Category filter allows filtering category results by attributes .
20
24
*/
21
25
class CategoryFilter
22
26
{
@@ -25,78 +29,106 @@ class CategoryFilter
25
29
*/
26
30
private $ scopeConfig ;
27
31
32
+ /**
33
+ * @var CategoryListInterface
34
+ */
35
+ private $ categoryList ;
36
+
37
+ /**
38
+ * @var Builder
39
+ */
40
+ private $ searchCriteriaBuilder ;
41
+
28
42
/**
29
43
* @param ScopeConfigInterface $scopeConfig
44
+ * @param CategoryListInterface $categoryList
45
+ * @param Builder $searchCriteriaBuilder
30
46
*/
31
47
public function __construct (
32
- ScopeConfigInterface $ scopeConfig
48
+ ScopeConfigInterface $ scopeConfig ,
49
+ CategoryListInterface $ categoryList ,
50
+ Builder $ searchCriteriaBuilder
33
51
) {
34
52
$ this ->scopeConfig = $ scopeConfig ;
53
+ $ this ->categoryList = $ categoryList ;
54
+ $ this ->searchCriteriaBuilder = $ searchCriteriaBuilder ;
35
55
}
36
56
37
57
/**
38
- * Filter for filtering the requested categories id's based on url_key, ids, name in the result.
58
+ * Search for categories
39
59
*
40
- * @param array $args
41
- * @param Collection $categoryCollection
60
+ * @param array $criteria
42
61
* @param StoreInterface $store
62
+ * @return int[]
43
63
* @throws InputException
44
64
*/
45
- public function applyFilters (array $ args , Collection $ categoryCollection , StoreInterface $ store )
65
+ public function getResult (array $ criteria , StoreInterface $ store )
46
66
{
47
- $ categoryCollection ->addAttributeToFilter (CategoryInterface::KEY_IS_ACTIVE , ['eq ' => 1 ]);
48
- foreach ($ args ['filters ' ] as $ field => $ cond ) {
49
- foreach ($ cond as $ condType => $ value ) {
50
- if ($ field === 'ids ' ) {
51
- $ categoryCollection ->addIdFilter ($ value );
52
- } else {
53
- $ this ->addAttributeFilter ($ categoryCollection , $ field , $ condType , $ value , $ store );
54
- }
55
- }
67
+ $ categoryIds = [];
68
+ $ criteria [Filter::ARGUMENT_NAME ] = $ this ->formatMatchFilters ($ criteria ['filters ' ], $ store );
69
+ $ criteria [Filter::ARGUMENT_NAME ][CategoryInterface::KEY_IS_ACTIVE ] = ['eq ' => 1 ];
70
+ $ searchCriteria = $ this ->searchCriteriaBuilder ->build ('categoryList ' , $ criteria );
71
+ $ pageSize = $ criteria ['pageSize ' ] ?? 20 ;
72
+ $ currentPage = $ criteria ['currentPage ' ] ?? 1 ;
73
+ $ searchCriteria ->setPageSize ($ pageSize )->setCurrentPage ($ currentPage );
74
+
75
+ $ categories = $ this ->categoryList ->getList ($ searchCriteria );
76
+ foreach ($ categories ->getItems () as $ category ) {
77
+ $ categoryIds [] = (int )$ category ->getId ();
56
78
}
57
- }
58
79
59
- /**
60
- * Add filter to category collection
61
- *
62
- * @param Collection $categoryCollection
63
- * @param string $field
64
- * @param string $condType
65
- * @param string|array $value
66
- * @param StoreInterface $store
67
- * @throws InputException
68
- */
69
- private function addAttributeFilter ($ categoryCollection , $ field , $ condType , $ value , $ store )
70
- {
71
- if ($ condType === 'match ' ) {
72
- $ this ->addMatchFilter ($ categoryCollection , $ field , $ value , $ store );
73
- return ;
80
+ $ totalPages = 0 ;
81
+ if ($ categories ->getTotalCount () > 0 && $ searchCriteria ->getPageSize () > 0 ) {
82
+ $ totalPages = ceil ($ categories ->getTotalCount () / $ searchCriteria ->getPageSize ());
74
83
}
75
- $ categoryCollection ->addAttributeToFilter ($ field , [$ condType => $ value ]);
84
+ if ($ searchCriteria ->getCurrentPage () > $ totalPages && $ categories ->getTotalCount () > 0 ) {
85
+ throw new GraphQlInputException (
86
+ __ (
87
+ 'currentPage value %1 specified is greater than the %2 page(s) available. ' ,
88
+ [$ searchCriteria ->getCurrentPage (), $ totalPages ]
89
+ )
90
+ );
91
+ }
92
+
93
+ return [
94
+ 'category_ids ' => $ categoryIds ,
95
+ 'total_count ' => $ categories ->getTotalCount (),
96
+ 'page_info ' => [
97
+ 'total_pages ' => $ totalPages ,
98
+ 'page_size ' => $ searchCriteria ->getPageSize (),
99
+ 'current_page ' => $ searchCriteria ->getCurrentPage (),
100
+ ]
101
+ ];
76
102
}
77
103
78
104
/**
79
- * Add match filter to collection
105
+ * Format match filters to behave like fuzzy match
80
106
*
81
- * @param Collection $categoryCollection
82
- * @param string $field
83
- * @param string $value
107
+ * @param array $filters
84
108
* @param StoreInterface $store
109
+ * @return array
85
110
* @throws InputException
86
111
*/
87
- private function addMatchFilter ( $ categoryCollection , $ field , $ value , $ store )
112
+ private function formatMatchFilters ( array $ filters , StoreInterface $ store ): array
88
113
{
89
114
$ minQueryLength = $ this ->scopeConfig ->getValue (
90
115
Query::XML_PATH_MIN_QUERY_LENGTH ,
91
116
ScopeInterface::SCOPE_STORE ,
92
117
$ store
93
118
);
94
- $ searchValue = str_replace ('% ' , '' , $ value );
95
- $ matchLength = strlen ($ searchValue );
96
- if ($ matchLength < $ minQueryLength ) {
97
- throw new InputException (__ ('Invalid match filter ' ));
98
- }
99
119
100
- $ categoryCollection ->addAttributeToFilter ($ field , ['like ' => "% {$ searchValue }% " ]);
120
+ foreach ($ filters as $ filter => $ condition ) {
121
+ $ conditionType = current (array_keys ($ condition ));
122
+ if ($ conditionType === 'match ' ) {
123
+ $ searchValue = trim (str_replace (Match ::SPECIAL_CHARACTERS , '' , $ condition [$ conditionType ]));
124
+ $ matchLength = strlen ($ searchValue );
125
+ if ($ matchLength < $ minQueryLength ) {
126
+ throw new InputException (__ ('Invalid match filter. Minimum length is %1. ' , $ minQueryLength ));
127
+ }
128
+ unset($ filters [$ filter ]['match ' ]);
129
+ $ filters [$ filter ]['like ' ] = '% ' . $ searchValue . '% ' ;
130
+ }
131
+ }
132
+ return $ filters ;
101
133
}
102
134
}
0 commit comments