Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
RequestGenerator.php
Go to the documentation of this file.
1 <?php
7 
10 use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
15 
23 {
25  const FILTER_SUFFIX = '_filter';
26 
28  const BUCKET_SUFFIX = '_bucket';
29 
33  private $productAttributeCollectionFactory;
34 
38  private $generatorResolver;
39 
44  public function __construct(
45  CollectionFactory $productAttributeCollectionFactory,
46  GeneratorResolver $generatorResolver = null
47  ) {
48  $this->productAttributeCollectionFactory = $productAttributeCollectionFactory;
49  $this->generatorResolver = $generatorResolver
50  ?: ObjectManager::getInstance()->get(GeneratorResolver::class);
51  }
52 
58  public function generate()
59  {
60  $requests = [];
61  $requests['catalog_view_container'] =
62  $this->generateRequest(EavAttributeInterface::IS_FILTERABLE, 'catalog_view_container', false);
63  $requests['quick_search_container'] =
64  $this->generateRequest(EavAttributeInterface::IS_FILTERABLE_IN_SEARCH, 'quick_search_container', true);
65  $requests['advanced_search_container'] = $this->generateAdvancedSearchRequest();
66  return $requests;
67  }
68 
77  private function generateRequest($attributeType, $container, $useFulltext)
78  {
79  $request = [];
80  foreach ($this->getSearchableAttributes() as $attribute) {
81  if ($attribute->getData($attributeType)) {
82  if (!in_array($attribute->getAttributeCode(), ['price', 'category_ids'], true)) {
83  $queryName = $attribute->getAttributeCode() . '_query';
84  $request['queries'][$container]['queryReference'][] = [
85  'clause' => 'must',
86  'ref' => $queryName,
87  ];
88  $filterName = $attribute->getAttributeCode() . self::FILTER_SUFFIX;
89  $request['queries'][$queryName] = [
90  'name' => $queryName,
92  'filterReference' => [
93  [
94  'clause' => 'must',
95  'ref' => $filterName,
96  ]
97  ],
98  ];
99  $bucketName = $attribute->getAttributeCode() . self::BUCKET_SUFFIX;
100  $generator = $this->generatorResolver->getGeneratorForType($attribute->getBackendType());
101  $request['filters'][$filterName] = $generator->getFilterData($attribute, $filterName);
102  $request['aggregations'][$bucketName] = $generator->getAggregationData($attribute, $bucketName);
103  }
104  }
106  if (!$attribute->getIsSearchable() || in_array($attribute->getAttributeCode(), ['price', 'sku'], true)) {
107  // Some fields have their own specific handlers
108  continue;
109  }
110  $request = $this->processPriceAttribute($useFulltext, $attribute, $request);
111  }
112 
113  return $request;
114  }
115 
121  protected function getSearchableAttributes()
122  {
124  $productAttributes = $this->productAttributeCollectionFactory->create();
125  $productAttributes->addFieldToFilter(
126  ['is_searchable', 'is_visible_in_advanced_search', 'is_filterable', 'is_filterable_in_search'],
127  [1, 1, [1, 2], 1]
128  );
129 
130  return $productAttributes;
131  }
132 
139  private function generateAdvancedSearchRequest()
140  {
141  $request = [];
142  foreach ($this->getSearchableAttributes() as $attribute) {
144  if (!$attribute->getIsVisibleInAdvancedSearch()) {
145  continue;
146  }
147  if (in_array($attribute->getAttributeCode(), ['price', 'sku'])) {
148  //same fields have special semantics
149  continue;
150  }
151  $queryName = $attribute->getAttributeCode() . '_query';
152  $request['queries']['advanced_search_container']['queryReference'][] = [
153  'clause' => 'must',
154  'ref' => $queryName,
155  ];
156  switch ($attribute->getBackendType()) {
157  case 'static':
158  break;
159  case 'text':
160  case 'varchar':
161  if ($attribute->getFrontendInput() === 'multiselect') {
162  $filterName = $attribute->getAttributeCode() . self::FILTER_SUFFIX;
163  $request['queries'][$queryName] = [
164  'name' => $queryName,
165  'type' => QueryInterface::TYPE_FILTER,
166  'filterReference' => [
167  [
168  'ref' => $filterName,
169  ],
170  ],
171  ];
172  $request['filters'][$filterName] = [
173  'type' => FilterInterface::TYPE_TERM,
174  'name' => $filterName,
175  'field' => $attribute->getAttributeCode(),
176  'value' => '$' . $attribute->getAttributeCode() . '$',
177  ];
178  } else {
179  $request['queries'][$queryName] = [
180  'name' => $queryName,
181  'type' => 'matchQuery',
182  'value' => '$' . $attribute->getAttributeCode() . '$',
183  'match' => [
184  [
185  'field' => $attribute->getAttributeCode(),
186  'boost' => $attribute->getSearchWeight() ?: 1,
187  ],
188  ],
189  ];
190  }
191  break;
192  case 'decimal':
193  case 'datetime':
194  case 'date':
195  $filterName = $attribute->getAttributeCode() . self::FILTER_SUFFIX;
196  $request['queries'][$queryName] = [
197  'name' => $queryName,
198  'type' => QueryInterface::TYPE_FILTER,
199  'filterReference' => [
200  [
201  'ref' => $filterName,
202  ],
203  ],
204  ];
205  $request['filters'][$filterName] = [
206  'field' => $attribute->getAttributeCode(),
207  'name' => $filterName,
208  'type' => FilterInterface::TYPE_RANGE,
209  'from' => '$' . $attribute->getAttributeCode() . '.from$',
210  'to' => '$' . $attribute->getAttributeCode() . '.to$',
211  ];
212  break;
213  default:
214  $filterName = $attribute->getAttributeCode() . self::FILTER_SUFFIX;
215  $request['queries'][$queryName] = [
216  'name' => $queryName,
217  'type' => QueryInterface::TYPE_FILTER,
218  'filterReference' => [
219  [
220  'ref' => $filterName,
221  ],
222  ],
223  ];
224  $request['filters'][$filterName] = [
225  'type' => FilterInterface::TYPE_TERM,
226  'name' => $filterName,
227  'field' => $attribute->getAttributeCode(),
228  'value' => '$' . $attribute->getAttributeCode() . '$',
229  ];
230  }
231  }
232 
233  return $request;
234  }
235 
244  private function processPriceAttribute($useFulltext, $attribute, $request)
245  {
246  // Match search by custom price attribute isn't supported
247  if ($useFulltext && $attribute->getFrontendInput() !== 'price') {
248  $request['queries']['search']['match'][] = [
249  'field' => $attribute->getAttributeCode(),
250  'boost' => $attribute->getSearchWeight() ?: 1,
251  ];
252  }
253 
254  return $request;
255  }
256 }
__construct(CollectionFactory $productAttributeCollectionFactory, GeneratorResolver $generatorResolver=null)