Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
ConditionsToSearchCriteriaMapper.php
Go to the documentation of this file.
1 <?php
6 declare(strict_types=1);
7 
9 
17 
22 {
26  private $searchCriteriaBuilderFactory;
27 
31  private $combinedFilterGroupFactory;
32 
36  private $filterFactory;
37 
43  public function __construct(
44  \Magento\Framework\Api\SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
45  \Magento\Framework\Api\CombinedFilterGroupFactory $combinedFilterGroupFactory,
46  \Magento\Framework\Api\FilterFactory $filterFactory
47  ) {
48  $this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
49  $this->combinedFilterGroupFactory = $combinedFilterGroupFactory;
50  $this->filterFactory = $filterFactory;
51  }
52 
60  public function mapConditionsToSearchCriteria(CombinedCondition $conditions): SearchCriteria
61  {
62  $filterGroup = $this->mapCombinedConditionToFilterGroup($conditions);
63 
64  $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create();
65 
66  if ($filterGroup !== null) {
67  $searchCriteriaBuilder->setFilterGroups([$filterGroup]);
68  }
69 
70  return $searchCriteriaBuilder->create();
71  }
72 
78  private function mapConditionToFilterGroup(ConditionInterface $condition)
79  {
80  if ($condition->getType() === CombinedCondition::class) {
81  return $this->mapCombinedConditionToFilterGroup($condition);
82  } elseif ($condition->getType() === SimpleCondition::class) {
83  return $this->mapSimpleConditionToFilterGroup($condition);
84  }
85 
86  throw new InputException(
87  __('Undefined condition type "%1" passed in.', $condition->getType())
88  );
89  }
90 
96  private function mapCombinedConditionToFilterGroup(CombinedCondition $combinedCondition)
97  {
98  $filters = [];
99 
100  foreach ($combinedCondition->getConditions() as $condition) {
101  $filter = $this->mapConditionToFilterGroup($condition);
102 
103  if ($filter === null) {
104  continue;
105  }
106 
107  // This required to solve cases when condition is configured like:
108  // "If ALL/ANY of these conditions are FALSE" - we need to reverse SQL operator for this "FALSE"
109  if ((bool)$combinedCondition->getValue() === false) {
110  $this->reverseSqlOperatorInFilter($filter);
111  }
112 
113  $filters[] = $filter;
114  }
115 
116  if (count($filters) === 0) {
117  return null;
118  }
119 
120  return $this->createCombinedFilterGroup($filters, $combinedCondition->getAggregator());
121  }
122 
128  private function mapSimpleConditionToFilterGroup(ConditionInterface $productCondition)
129  {
130  if (is_array($productCondition->getValue())) {
131  return $this->processSimpleConditionWithArrayValue($productCondition);
132  }
133 
134  return $this->createFilter(
135  $productCondition->getAttribute(),
136  (string) $productCondition->getValue(),
137  $productCondition->getOperator()
138  );
139  }
140 
146  private function processSimpleConditionWithArrayValue(ConditionInterface $productCondition): FilterGroup
147  {
148  $filters = [];
149 
150  foreach ($productCondition->getValue() as $subValue) {
151  $filters[] = $this->createFilter(
152  $productCondition->getAttribute(),
153  (string) $subValue,
154  $productCondition->getOperator()
155  );
156  }
157 
158  $combinationMode = $this->getGlueForArrayValues($productCondition->getOperator());
159 
160  return $this->createCombinedFilterGroup($filters, $combinationMode);
161  }
162 
167  private function getGlueForArrayValues(string $operator): string
168  {
169  if (in_array($operator, ['!=', '!{}', '!()'], true)) {
170  return 'all';
171  }
172 
173  return 'any';
174  }
175 
183  private function reverseSqlOperatorInFilter(Filter $filter)
184  {
185  $operatorsMap = [
186  'eq' => 'neq',
187  'neq' => 'eq',
188  'gteq' => 'lt',
189  'lteq' => 'gt',
190  'gt' => 'lteq',
191  'lt' => 'gteq',
192  'like' => 'nlike',
193  'nlike' => 'like',
194  'in' => 'nin',
195  'nin' => 'in',
196  ];
197 
198  if (!array_key_exists($filter->getConditionType(), $operatorsMap)) {
199  throw new InputException(
200  __(
201  'Undefined SQL operator "%1" passed in. Valid operators are: %2',
202  $filter->getConditionType(),
203  implode(',', array_keys($operatorsMap))
204  )
205  );
206  }
207 
208  $filter->setConditionType(
209  $operatorsMap[$filter->getConditionType()]
210  );
211  }
212 
219  private function createCombinedFilterGroup(array $filters, string $combinationMode): FilterGroup
220  {
221  return $this->combinedFilterGroupFactory->create([
222  'data' => [
223  FilterGroup::FILTERS => $filters,
224  FilterGroup::COMBINATION_MODE => $this->mapRuleAggregatorToSQLAggregator($combinationMode)
225  ]
226  ]);
227  }
228 
236  private function createFilter(string $field, string $value, string $conditionType): Filter
237  {
238  return $this->filterFactory->create([
239  'data' => [
240  Filter::KEY_FIELD => $field,
241  Filter::KEY_VALUE => $value,
242  Filter::KEY_CONDITION_TYPE => $this->mapRuleOperatorToSQLCondition($conditionType)
243  ]
244  ]);
245  }
246 
254  private function mapRuleOperatorToSQLCondition(string $ruleOperator): string
255  {
256  $operatorsMap = [
257  '==' => 'eq', // is
258  '!=' => 'neq', // is not
259  '>=' => 'gteq', // equals or greater than
260  '<=' => 'lteq', // equals or less than
261  '>' => 'gt', // greater than
262  '<' => 'lt', // less than
263  '{}' => 'like', // contains
264  '!{}' => 'nlike', // does not contains
265  '()' => 'in', // is one of
266  '!()' => 'nin', // is not one of
267  ];
268 
269  if (!array_key_exists($ruleOperator, $operatorsMap)) {
270  throw new InputException(
271  __(
272  'Undefined rule operator "%1" passed in. Valid operators are: %2',
273  $ruleOperator,
274  implode(',', array_keys($operatorsMap))
275  )
276  );
277  }
278 
279  return $operatorsMap[$ruleOperator];
280  }
281 
289  private function mapRuleAggregatorToSQLAggregator(string $ruleAggregator): string
290  {
291  $operatorsMap = [
292  'all' => 'AND',
293  'any' => 'OR',
294  ];
295 
296  if (!array_key_exists(strtolower($ruleAggregator), $operatorsMap)) {
297  throw new InputException(
298  __(
299  'Undefined rule aggregator "%1" passed in. Valid operators are: %2',
300  $ruleAggregator,
301  implode(',', array_keys($operatorsMap))
302  )
303  );
304  }
305 
306  return $operatorsMap[$ruleAggregator];
307  }
308 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
__()
Definition: __.php:13
__construct(\Magento\Framework\Api\SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory, \Magento\Framework\Api\CombinedFilterGroupFactory $combinedFilterGroupFactory, \Magento\Framework\Api\FilterFactory $filterFactory)
$value
Definition: gender.phtml:16
$filters
Definition: uploader.phtml:11
$searchCriteriaBuilder