77
88namespace Magento \CatalogGraphQl \Model \Category ;
99
10+ use Magento \Catalog \Api \CategoryListInterface ;
1011use Magento \Catalog \Api \Data \CategoryInterface ;
11- use Magento \Catalog \Model \ResourceModel \Category \Collection ;
1212use Magento \Framework \App \Config \ScopeConfigInterface ;
1313use 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 ;
1418use Magento \Store \Api \Data \StoreInterface ;
1519use Magento \Store \Model \ScopeInterface ;
16- use Magento \Search \ Model \Query ;
20+ use Magento \Framework \ GraphQl \Query \ Resolver \ Argument \ SearchCriteria \ Builder ;
1721
1822/**
19- * Category filter allows to filter collection using 'id, url_key, name' from search criteria .
23+ * Category filter allows filtering category results by attributes .
2024 */
2125class CategoryFilter
2226{
@@ -25,78 +29,106 @@ class CategoryFilter
2529 */
2630 private $ scopeConfig ;
2731
32+ /**
33+ * @var CategoryListInterface
34+ */
35+ private $ categoryList ;
36+
37+ /**
38+ * @var Builder
39+ */
40+ private $ searchCriteriaBuilder ;
41+
2842 /**
2943 * @param ScopeConfigInterface $scopeConfig
44+ * @param CategoryListInterface $categoryList
45+ * @param Builder $searchCriteriaBuilder
3046 */
3147 public function __construct (
32- ScopeConfigInterface $ scopeConfig
48+ ScopeConfigInterface $ scopeConfig ,
49+ CategoryListInterface $ categoryList ,
50+ Builder $ searchCriteriaBuilder
3351 ) {
3452 $ this ->scopeConfig = $ scopeConfig ;
53+ $ this ->categoryList = $ categoryList ;
54+ $ this ->searchCriteriaBuilder = $ searchCriteriaBuilder ;
3555 }
3656
3757 /**
38- * Filter for filtering the requested categories id's based on url_key, ids, name in the result.
58+ * Search for categories
3959 *
40- * @param array $args
41- * @param Collection $categoryCollection
60+ * @param array $criteria
4261 * @param StoreInterface $store
62+ * @return int[]
4363 * @throws InputException
4464 */
45- public function applyFilters (array $ args , Collection $ categoryCollection , StoreInterface $ store )
65+ public function getResult (array $ criteria , StoreInterface $ store )
4666 {
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 ();
5678 }
57- }
5879
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 ());
7483 }
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+ ];
76102 }
77103
78104 /**
79- * Add match filter to collection
105+ * Format match filters to behave like fuzzy match
80106 *
81- * @param Collection $categoryCollection
82- * @param string $field
83- * @param string $value
107+ * @param array $filters
84108 * @param StoreInterface $store
109+ * @return array
85110 * @throws InputException
86111 */
87- private function addMatchFilter ( $ categoryCollection , $ field , $ value , $ store )
112+ private function formatMatchFilters ( array $ filters , StoreInterface $ store ): array
88113 {
89114 $ minQueryLength = $ this ->scopeConfig ->getValue (
90115 Query::XML_PATH_MIN_QUERY_LENGTH ,
91116 ScopeInterface::SCOPE_STORE ,
92117 $ store
93118 );
94- $ searchValue = str_replace ('% ' , '' , $ value );
95- $ matchLength = strlen ($ searchValue );
96- if ($ matchLength < $ minQueryLength ) {
97- throw new InputException (__ ('Invalid match filter ' ));
98- }
99119
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 ;
101133 }
102134}
0 commit comments