Skip to content

Commit 28a1b6a

Browse files
author
Oleksandr Iegorov
committed
Merge branch 'MAGETWO-77754' of github.com:magento-tango/magento2ce into 2.2-PR-part-3
2 parents da164a0 + ea95961 commit 28a1b6a

File tree

3 files changed

+98
-30
lines changed

3 files changed

+98
-30
lines changed

app/code/Magento/Rule/Model/Condition/Sql/Builder.php

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66

77
namespace Magento\Rule\Model\Condition\Sql;
88

9+
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\DB\Select;
11+
use Magento\Framework\Exception\NoSuchEntityException;
1012
use Magento\Rule\Model\Condition\AbstractCondition;
1113
use Magento\Rule\Model\Condition\Combine;
14+
use Magento\Eav\Api\AttributeRepositoryInterface;
15+
use Magento\Catalog\Model\Product;
16+
use Magento\Eav\Model\Entity\Collection\AbstractCollection;
1217

1318
/**
1419
* Class SQL Builder
@@ -41,12 +46,22 @@ class Builder
4146
*/
4247
protected $_expressionFactory;
4348

49+
/**
50+
* @var AttributeRepositoryInterface
51+
*/
52+
private $attributeRepository;
53+
4454
/**
4555
* @param ExpressionFactory $expressionFactory
56+
* @param AttributeRepositoryInterface|null $attributeRepository
4657
*/
47-
public function __construct(ExpressionFactory $expressionFactory)
48-
{
58+
public function __construct(
59+
ExpressionFactory $expressionFactory,
60+
AttributeRepositoryInterface $attributeRepository = null
61+
) {
4962
$this->_expressionFactory = $expressionFactory;
63+
$this->attributeRepository = $attributeRepository ?:
64+
ObjectManager::getInstance()->get(AttributeRepositoryInterface::class);
5065
}
5166

5267
/**
@@ -88,12 +103,12 @@ protected function _getChildCombineTablesToJoin(Combine $combine, $tables = [])
88103
/**
89104
* Join tables from conditions combination to collection
90105
*
91-
* @param \Magento\Eav\Model\Entity\Collection\AbstractCollection $collection
106+
* @param AbstractCollection $collection
92107
* @param Combine $combine
93108
* @return $this
94109
*/
95110
protected function _joinTablesToCollection(
96-
\Magento\Eav\Model\Entity\Collection\AbstractCollection $collection,
111+
AbstractCollection $collection,
97112
Combine $combine
98113
) {
99114
foreach ($this->_getCombineTablesToJoin($combine) as $alias => $joinTable) {
@@ -112,10 +127,11 @@ protected function _joinTablesToCollection(
112127
*
113128
* @param AbstractCondition $condition
114129
* @param string $value
130+
* @param bool $isDefaultStoreUsed
115131
* @return string
116132
* @throws \Magento\Framework\Exception\LocalizedException
117133
*/
118-
protected function _getMappedSqlCondition(AbstractCondition $condition, $value = '')
134+
protected function _getMappedSqlCondition(AbstractCondition $condition, $value = '', $isDefaultStoreUsed = true)
119135
{
120136
$argument = $condition->getMappedSqlField();
121137

@@ -130,9 +146,16 @@ protected function _getMappedSqlCondition(AbstractCondition $condition, $value =
130146
throw new \Magento\Framework\Exception\LocalizedException(__('Unknown condition operator'));
131147
}
132148

149+
$defaultValue = 0;
150+
// Check if attribute has a table with default value and add it to the query
151+
if ($this->canAttributeHaveDefaultValue($condition->getAttribute(), $isDefaultStoreUsed)) {
152+
$defaultField = 'at_' . $condition->getAttribute() . '_default.value';
153+
$defaultValue = $this->_connection->quoteIdentifier($defaultField);
154+
}
155+
133156
$sql = str_replace(
134157
':field',
135-
$this->_connection->getIfNullSql($this->_connection->quoteIdentifier($argument), 0),
158+
$this->_connection->getIfNullSql($this->_connection->quoteIdentifier($argument), $defaultValue),
136159
$this->_conditionOperatorMap[$conditionOperator]
137160
);
138161

@@ -144,10 +167,11 @@ protected function _getMappedSqlCondition(AbstractCondition $condition, $value =
144167
/**
145168
* @param Combine $combine
146169
* @param string $value
170+
* @param bool $isDefaultStoreUsed
147171
* @return string
148172
* @SuppressWarnings(PHPMD.NPathComplexity)
149173
*/
150-
protected function _getMappedSqlCombination(Combine $combine, $value = '')
174+
protected function _getMappedSqlCombination(Combine $combine, $value = '', $isDefaultStoreUsed = true)
151175
{
152176
$out = (!empty($value) ? $value : '');
153177
$value = ($combine->getValue() ? '' : ' NOT ');
@@ -158,9 +182,9 @@ protected function _getMappedSqlCombination(Combine $combine, $value = '')
158182
$con = ($getAggregator == 'any' ? Select::SQL_OR : Select::SQL_AND);
159183
$con = (isset($conditions[$key+1]) ? $con : '');
160184
if ($condition instanceof Combine) {
161-
$out .= $this->_getMappedSqlCombination($condition, $value);
185+
$out .= $this->_getMappedSqlCombination($condition, $value, $isDefaultStoreUsed);
162186
} else {
163-
$out .= $this->_getMappedSqlCondition($condition, $value);
187+
$out .= $this->_getMappedSqlCondition($condition, $value, $isDefaultStoreUsed);
164188
}
165189
$out .= $out ? (' ' . $con) : '';
166190
}
@@ -170,21 +194,55 @@ protected function _getMappedSqlCombination(Combine $combine, $value = '')
170194
/**
171195
* Attach conditions filter to collection
172196
*
173-
* @param \Magento\Eav\Model\Entity\Collection\AbstractCollection $collection
197+
* @param AbstractCollection $collection
174198
* @param Combine $combine
175-
*
176199
* @return void
177200
*/
178201
public function attachConditionToCollection(
179-
\Magento\Eav\Model\Entity\Collection\AbstractCollection $collection,
202+
AbstractCollection $collection,
180203
Combine $combine
181204
) {
182205
$this->_connection = $collection->getResource()->getConnection();
183206
$this->_joinTablesToCollection($collection, $combine);
184-
$whereExpression = (string)$this->_getMappedSqlCombination($combine);
207+
$isDefaultStoreUsed = $this->checkIsDefaultStoreUsed($collection);
208+
$whereExpression = (string)$this->_getMappedSqlCombination($combine, '', $isDefaultStoreUsed);
185209
if (!empty($whereExpression)) {
186210
// Select ::where method adds braces even on empty expression
187211
$collection->getSelect()->where($whereExpression);
188212
}
189213
}
214+
215+
/**
216+
* Check is default store used
217+
*
218+
* @param AbstractCollection $collection
219+
* @return bool
220+
*/
221+
private function checkIsDefaultStoreUsed(AbstractCollection $collection): bool
222+
{
223+
return (int)$collection->getStoreId() === (int)$collection->getDefaultStoreId();
224+
}
225+
226+
/**
227+
* Check if attribute can have default value
228+
*
229+
* @param string $attributeCode
230+
* @param bool $isDefaultStoreUsed
231+
* @return bool
232+
*/
233+
private function canAttributeHaveDefaultValue(string $attributeCode, bool $isDefaultStoreUsed): bool
234+
{
235+
if ($isDefaultStoreUsed) {
236+
return false;
237+
}
238+
239+
try {
240+
$attribute = $this->attributeRepository->get(Product::ENTITY, $attributeCode);
241+
} catch (NoSuchEntityException $e) {
242+
// It's not exceptional case as we want to check if we have such attribute or not
243+
return false;
244+
}
245+
246+
return !$attribute->isScopeGlobal();
247+
}
190248
}

app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/BuilderTest.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ public function testAttachConditionToCollection()
3535
{
3636
$collection = $this->createPartialMock(
3737
\Magento\Eav\Model\Entity\Collection\AbstractCollection::class,
38-
['getResource', 'getSelect']
38+
[
39+
'getResource',
40+
'getSelect',
41+
'getStoreId',
42+
'getDefaultStoreId',
43+
]
3944
);
4045
$combine = $this->createPartialMock(\Magento\Rule\Model\Condition\Combine::class, ['getConditions']);
4146
$resource = $this->createPartialMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class, ['getConnection']);
@@ -53,10 +58,15 @@ public function testAttachConditionToCollection()
5358
$collection->expects($this->once())
5459
->method('getResource')
5560
->will($this->returnValue($resource));
56-
5761
$collection->expects($this->any())
5862
->method('getSelect')
5963
->will($this->returnValue($select));
64+
$collection->expects($this->once())
65+
->method('getStoreId')
66+
->willReturn(1);
67+
$collection->expects($this->once())
68+
->method('getDefaultStoreId')
69+
->willReturn(1);
6070

6171
$resource->expects($this->once())
6272
->method('getConnection')

dev/tests/integration/testsuite/Magento/Rule/Model/Condition/Sql/BuilderTest.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,49 @@
77
namespace Magento\Rule\Model\Condition\Sql;
88

99
use Magento\TestFramework\Helper\Bootstrap;
10+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
11+
use Magento\CatalogWidget\Model\RuleFactory;
12+
use Magento\CatalogWidget\Model\Rule\Condition\Combine as CombineCondition;
13+
use Magento\CatalogWidget\Model\Rule\Condition\Product as ProductCondition;
1014

1115
class BuilderTest extends \PHPUnit\Framework\TestCase
1216
{
1317
/**
14-
* @var \Magento\Rule\Model\Condition\Sql\Builder
18+
* @var Builder
1519
*/
1620
private $model;
1721

1822
protected function setUp()
1923
{
20-
$this->model = Bootstrap::getObjectManager()->create(\Magento\Rule\Model\Condition\Sql\Builder::class);
24+
$this->model = Bootstrap::getObjectManager()->create(Builder::class);
2125
}
2226

2327
public function testAttachConditionToCollection()
2428
{
25-
/** @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory */
26-
$collectionFactory = Bootstrap::getObjectManager()->create(
27-
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class
28-
);
29-
/** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
29+
/** @var ProductCollectionFactory $collectionFactory */
30+
$collectionFactory = Bootstrap::getObjectManager()->create(ProductCollectionFactory::class);
3031
$collection = $collectionFactory->create();
3132

32-
/** @var \Magento\CatalogWidget\Model\RuleFactory $ruleFactory */
33-
$ruleFactory = Bootstrap::getObjectManager()->create(\Magento\CatalogWidget\Model\RuleFactory::class);
34-
/** @var \Magento\CatalogWidget\Model\Rule $rule */
33+
/** @var RuleFactory $ruleFactory */
34+
$ruleFactory = Bootstrap::getObjectManager()->create(RuleFactory::class);
3535
$rule = $ruleFactory->create();
3636

3737
$ruleConditionArray = [
3838
'conditions' => [
3939
'1' => [
40-
'type' => \Magento\CatalogWidget\Model\Rule\Condition\Combine::class,
40+
'type' => CombineCondition::class,
4141
'aggregator' => 'all',
4242
'value' => '1',
4343
'new_child' => ''
4444
],
4545
'1--1' => [
46-
'type' => \Magento\CatalogWidget\Model\Rule\Condition\Product::class,
46+
'type' => ProductCondition::class,
4747
'attribute' => 'category_ids',
4848
'operator' => '==',
4949
'value' => '3'
5050
],
5151
'1--2' => [
52-
'type' => \Magento\CatalogWidget\Model\Rule\Condition\Product::class,
52+
'type' => ProductCondition::class,
5353
'attribute' => 'special_to_date',
5454
'operator' => '==',
5555
'value' => '2017-09-15'
@@ -60,7 +60,7 @@ public function testAttachConditionToCollection()
6060
$rule->loadPost($ruleConditionArray);
6161
$this->model->attachConditionToCollection($collection, $rule->getConditions());
6262

63-
$whereString = 'WHERE (category_id IN (\'3\')))) AND(IFNULL(`e`.`entity_id`, 0) = \'2017-09-15\') ))';
64-
$this->assertNotFalse(strpos($collection->getSelectSql(true), $whereString));
63+
$whereString = "/\(category_id IN \('3'\).+\(IFNULL\(`e`\.`entity_id`,.+\) = '2017-09-15'\)/";
64+
$this->assertNotFalse(preg_match($whereString, $collection->getSelectSql(true)));
6565
}
6666
}

0 commit comments

Comments
 (0)