Skip to content

Commit a697877

Browse files
MC-33487: Catalog Rule fatal error - on certain combinations of conditions
1 parent 90334f8 commit a697877

File tree

2 files changed

+81
-14
lines changed

2 files changed

+81
-14
lines changed

app/code/Magento/CatalogRule/Model/Rule/Condition/ConditionsToSearchCriteriaMapper.php

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,46 @@
77

88
namespace Magento\CatalogRule\Model\Rule\Condition;
99

10-
use Magento\Framework\Exception\InputException;
11-
use Magento\Rule\Model\Condition\ConditionInterface;
1210
use Magento\CatalogRule\Model\Rule\Condition\Combine as CombinedCondition;
1311
use Magento\CatalogRule\Model\Rule\Condition\Product as SimpleCondition;
1412
use Magento\Framework\Api\CombinedFilterGroup as FilterGroup;
13+
use Magento\Framework\Api\CombinedFilterGroupFactory;
1514
use Magento\Framework\Api\Filter;
15+
use Magento\Framework\Api\FilterFactory;
1616
use Magento\Framework\Api\SearchCriteria;
17+
use Magento\Framework\Api\SearchCriteriaBuilderFactory;
18+
use Magento\Framework\Exception\InputException;
19+
use Magento\Rule\Model\Condition\ConditionInterface;
1720

1821
/**
1922
* Maps catalog price rule conditions to search criteria
2023
*/
2124
class ConditionsToSearchCriteriaMapper
2225
{
2326
/**
24-
* @var \Magento\Framework\Api\SearchCriteriaBuilderFactory
27+
* @var SearchCriteriaBuilderFactory
2528
*/
2629
private $searchCriteriaBuilderFactory;
2730

2831
/**
29-
* @var \Magento\Framework\Api\CombinedFilterGroupFactory
32+
* @var CombinedFilterGroupFactory
3033
*/
3134
private $combinedFilterGroupFactory;
3235

3336
/**
34-
* @var \Magento\Framework\Api\FilterFactory
37+
* @var FilterFactory
3538
*/
3639
private $filterFactory;
3740

3841
/**
39-
* @param \Magento\Framework\Api\SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
40-
* @param \Magento\Framework\Api\CombinedFilterGroupFactory $combinedFilterGroupFactory
41-
* @param \Magento\Framework\Api\FilterFactory $filterFactory
42+
* @param SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
43+
* @param CombinedFilterGroupFactory $combinedFilterGroupFactory
44+
* @param FilterFactory $filterFactory
4245
*/
4346
public function __construct(
44-
\Magento\Framework\Api\SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
45-
\Magento\Framework\Api\CombinedFilterGroupFactory $combinedFilterGroupFactory,
46-
\Magento\Framework\Api\FilterFactory $filterFactory
47+
SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
48+
CombinedFilterGroupFactory $combinedFilterGroupFactory,
49+
FilterFactory $filterFactory
4750
) {
4851
$this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
4952
$this->combinedFilterGroupFactory = $combinedFilterGroupFactory;
@@ -74,7 +77,7 @@ public function mapConditionsToSearchCriteria(CombinedCondition $conditions): Se
7477
* Convert condition to filter group
7578
*
7679
* @param ConditionInterface $condition
77-
* @return null|\Magento\Framework\Api\CombinedFilterGroup|\Magento\Framework\Api\Filter
80+
* @return null|FilterGroup|Filter
7881
* @throws InputException
7982
*/
8083
private function mapConditionToFilterGroup(ConditionInterface $condition)
@@ -94,7 +97,7 @@ private function mapConditionToFilterGroup(ConditionInterface $condition)
9497
* Convert combined condition to filter group
9598
*
9699
* @param Combine $combinedCondition
97-
* @return null|\Magento\Framework\Api\CombinedFilterGroup
100+
* @return null|FilterGroup
98101
* @throws InputException
99102
*/
100103
private function mapCombinedConditionToFilterGroup(CombinedCondition $combinedCondition)
@@ -111,7 +114,7 @@ private function mapCombinedConditionToFilterGroup(CombinedCondition $combinedCo
111114
// This required to solve cases when condition is configured like:
112115
// "If ALL/ANY of these conditions are FALSE" - we need to reverse SQL operator for this "FALSE"
113116
if ((bool)$combinedCondition->getValue() === false) {
114-
$this->reverseSqlOperatorInFilter($filter);
117+
$this->reverseSqlOperatorInFilterRecursively($filter);
115118
}
116119

117120
$filters[] = $filter;
@@ -183,6 +186,24 @@ private function getGlueForArrayValues(string $operator): string
183186
return 'any';
184187
}
185188

189+
/**
190+
* Recursively reverse sql conditions to their corresponding negative analog for the entire FilterGroup
191+
*
192+
* @param Filter|FilterGroup $filter
193+
* @return void
194+
* @throws InputException
195+
*/
196+
private function reverseSqlOperatorInFilterRecursively($filter): void
197+
{
198+
if ($filter instanceof FilterGroup) {
199+
foreach ($filter->getFilters() as &$currentFilter) {
200+
$this->reverseSqlOperatorInFilterRecursively($currentFilter);
201+
}
202+
} else {
203+
$this->reverseSqlOperatorInFilter($filter);
204+
}
205+
}
206+
186207
/**
187208
* Reverse sql conditions to their corresponding negative analog
188209
*

dev/tests/integration/testsuite/Magento/CatalogRule/Model/ResourceModel/Product/ConditionsToCollectionApplierTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,19 @@ private function conditionProvider()
414414
'simple-product-12'
415415
]
416416
],
417+
418+
// test filter for case "If ALL/ANY of these conditions are FALSE" with multiple levels
419+
'variation 22' => [
420+
'condition' => $this->getConditionsForVariation22(),
421+
'expected-sku' => [
422+
'simple-product-1',
423+
'simple-product-2',
424+
'simple-product-3',
425+
'simple-product-4',
426+
'simple-product-7',
427+
'simple-product-8'
428+
]
429+
],
417430
];
418431
}
419432

@@ -1006,6 +1019,39 @@ private function getConditionsForVariation21()
10061019
return $this->getCombineConditionFromArray($conditions);
10071020
}
10081021

1022+
private function getConditionsForVariation22()
1023+
{
1024+
$category1Name = 'Category 1';
1025+
1026+
$category1Id = $this->categoryCollectionFactory
1027+
->create()
1028+
->addAttributeToFilter('name', $category1Name)
1029+
->getAllIds();
1030+
1031+
$conditions = [
1032+
'type' => \Magento\CatalogRule\Model\Rule\Condition\Combine::class,
1033+
'aggregator' => 'all',
1034+
'value' => 0,
1035+
'conditions' => [
1036+
[
1037+
'type' => \Magento\CatalogRule\Model\Rule\Condition\Combine::class,
1038+
'aggregator' => 'all',
1039+
'value' => 1,
1040+
'conditions' => [
1041+
[
1042+
'type' => \Magento\CatalogRule\Model\Rule\Condition\Product::class,
1043+
'operator' => '==',
1044+
'value' => implode(',', $category1Id),
1045+
'attribute' => 'category_ids'
1046+
]
1047+
]
1048+
]
1049+
]
1050+
];
1051+
1052+
return $this->getCombineConditionFromArray($conditions);
1053+
}
1054+
10091055
private function getCombineConditionFromArray(array $data)
10101056
{
10111057
$combinedCondition = $this->combinedConditionFactory->create();

0 commit comments

Comments
 (0)