Skip to content

Commit 9d8e284

Browse files
author
Yaroslav Onischenko
committed
Merge remote-tracking branch 'origin/MAGETWO-61058' into SEGFAULT_BANNERS_PR
2 parents 68cc2d9 + 51828c8 commit 9d8e284

File tree

4 files changed

+175
-45
lines changed

4 files changed

+175
-45
lines changed

app/code/Magento/ConfigurableProduct/Model/AttributeOptionProvider.php

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\ConfigurableProduct\Model;
78

89
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
@@ -31,7 +32,7 @@ class AttributeOptionProvider implements AttributeOptionProviderInterface
3132

3233
/**
3334
* @param Attribute $attributeResource
34-
* @param OptionProvider $attributeOptionProvider,
35+
* @param OptionProvider $attributeOptionProvider ,
3536
* @param ScopeResolverInterface $scopeResolver
3637
*/
3738
public function __construct(
@@ -49,10 +50,28 @@ public function __construct(
4950
*/
5051
public function getAttributeOptions(AbstractAttribute $superAttribute, $productId)
5152
{
52-
$scope = $this->scopeResolver->getScope();
53+
$scope = $this->scopeResolver->getScope();
5354
$select = $this->getAttributeOptionsSelect($superAttribute, $productId, $scope);
55+
$data = $this->attributeResource->getConnection()->fetchAll($select);
56+
57+
if ($superAttribute->getSourceModel()) {
58+
$options = $superAttribute->getSource()->getAllOptions(false);
59+
60+
$optionLabels = [];
61+
foreach ($options as $option) {
62+
$optionLabels[$option['value']] = $option['label'];
63+
}
5464

55-
return $this->attributeResource->getConnection()->fetchAll($select);
65+
foreach ($data as $key => $value) {
66+
$optionText = isset($optionLabels[$value['value_index']])
67+
? $optionLabels[$value['value_index']]
68+
: false;
69+
$data[$key]['default_title'] = $optionText;
70+
$data[$key]['option_title'] = $optionText;
71+
}
72+
}
73+
74+
return $data;
5675
}
5776

5877
/**
@@ -72,11 +91,6 @@ private function getAttributeOptionsSelect(AbstractAttribute $superAttribute, $p
7291
'product_id' => 'product_entity.entity_id',
7392
'attribute_code' => 'attribute.attribute_code',
7493
'value_index' => 'entity_value.value',
75-
'option_title' => $this->attributeResource->getConnection()->getIfNullSql(
76-
'option_value.value',
77-
'default_option_value.value'
78-
),
79-
'default_title' => 'default_option_value.value',
8094
'super_attribute_label' => 'attribute_label.value',
8195
]
8296
)->joinInner(
@@ -103,27 +117,7 @@ private function getAttributeOptionsSelect(AbstractAttribute $superAttribute, $p
103117
'entity_value.attribute_id = super_attribute.attribute_id',
104118
'entity_value.store_id = 0',
105119
"entity_value.{$this->attributeOptionProvider->getProductEntityLinkField()} = "
106-
. "entity.{$this->attributeOptionProvider->getProductEntityLinkField()}"
107-
]
108-
),
109-
[]
110-
)->joinLeft(
111-
['option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
112-
implode(
113-
' AND ',
114-
[
115-
'option_value.option_id = entity_value.value',
116-
'option_value.store_id = ' . $scope->getId()
117-
]
118-
),
119-
[]
120-
)->joinLeft(
121-
['default_option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
122-
implode(
123-
' AND ',
124-
[
125-
'default_option_value.option_id = entity_value.value',
126-
'default_option_value.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID
120+
. "entity.{$this->attributeOptionProvider->getProductEntityLinkField()}",
127121
]
128122
),
129123
[]
@@ -133,7 +127,7 @@ private function getAttributeOptionsSelect(AbstractAttribute $superAttribute, $p
133127
' AND ',
134128
[
135129
'super_attribute.product_super_attribute_id = attribute_label.product_super_attribute_id',
136-
'attribute_label.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID
130+
'attribute_label.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID,
137131
]
138132
),
139133
[]
@@ -145,6 +139,38 @@ private function getAttributeOptionsSelect(AbstractAttribute $superAttribute, $p
145139
$superAttribute->getAttributeId()
146140
);
147141

142+
if (!$superAttribute->getSourceModel()) {
143+
$select->columns(
144+
[
145+
'option_title' => $this->attributeResource->getConnection()->getIfNullSql(
146+
'option_value.value',
147+
'default_option_value.value'
148+
),
149+
'default_title' => 'default_option_value.value',
150+
]
151+
)->joinLeft(
152+
['option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
153+
implode(
154+
' AND ',
155+
[
156+
'option_value.option_id = entity_value.value',
157+
'option_value.store_id = ' . $scope->getId(),
158+
]
159+
),
160+
[]
161+
)->joinLeft(
162+
['default_option_value' => $this->attributeResource->getTable('eav_attribute_option_value')],
163+
implode(
164+
' AND ',
165+
[
166+
'default_option_value.option_id = entity_value.value',
167+
'default_option_value.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID,
168+
]
169+
),
170+
[]
171+
);
172+
}
173+
148174
return $select;
149175
}
150176
}

app/code/Magento/ConfigurableProduct/Model/OptionRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public function validateNewOptionData(OptionInterface $option)
279279
$inputException->addError(__('Option values are not specified.'));
280280
} else {
281281
foreach ($option->getValues() as $optionValue) {
282-
if (!$optionValue->getValueIndex()) {
282+
if (null === $optionValue->getValueIndex()) {
283283
$inputException->addError(__('Value index is not specified for an option.'));
284284
}
285285
}

app/code/Magento/ConfigurableProduct/Pricing/Render/FinalPriceBox.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
*/
66
namespace Magento\ConfigurableProduct\Pricing\Render;
77

8+
use Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface;
89
use Magento\Catalog\Pricing\Price\FinalPrice;
10+
use Magento\Catalog\Pricing\Price\MinimalPriceCalculatorInterface;
911
use Magento\Catalog\Pricing\Price\RegularPrice;
1012
use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface;
1113
use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface;
@@ -30,6 +32,8 @@ class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox
3032
* @param ConfigurableOptionsProviderInterface $configurableOptionsProvider
3133
* @param array $data
3234
* @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider
35+
* @param SalableResolverInterface|null $salableResolver
36+
* @param MinimalPriceCalculatorInterface|null $minimalPriceCalculator
3337
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
3438
*/
3539
public function __construct(
@@ -39,9 +43,19 @@ public function __construct(
3943
RendererPool $rendererPool,
4044
ConfigurableOptionsProviderInterface $configurableOptionsProvider,
4145
array $data = [],
42-
LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null
46+
LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null,
47+
SalableResolverInterface $salableResolver = null,
48+
MinimalPriceCalculatorInterface $minimalPriceCalculator = null
4349
) {
44-
parent::__construct($context, $saleableItem, $price, $rendererPool, $data);
50+
parent::__construct(
51+
$context,
52+
$saleableItem,
53+
$price,
54+
$rendererPool,
55+
$data,
56+
$salableResolver,
57+
$minimalPriceCalculator
58+
);
4559
$this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?:
4660
ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class);
4761
}

app/code/Magento/ConfigurableProduct/Test/Unit/Model/AttributeOptionProviderTest.php

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\ConfigurableProduct\Test\Unit\Model;
78

89
use Magento\ConfigurableProduct\Model\AttributeOptionProvider;
10+
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
911
use Magento\Framework\DB\Select;
1012
use Magento\Framework\App\ScopeResolverInterface;
1113
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
@@ -95,7 +97,7 @@ protected function setUp()
9597
->disableOriginalConstructor()
9698
->getMockForAbstractClass();
9799
$this->select = $this->getMockBuilder(Select::class)
98-
->setMethods(['from', 'joinInner', 'joinLeft', 'where'])
100+
->setMethods(['from', 'joinInner', 'joinLeft', 'where', 'columns'])
99101
->disableOriginalConstructor()
100102
->getMock();
101103
$this->connectionMock->expects($this->any())
@@ -109,7 +111,7 @@ protected function setUp()
109111
->disableOriginalConstructor()
110112
->getMockForAbstractClass();
111113
$this->abstractAttribute = $this->getMockBuilder(AbstractAttribute::class)
112-
->setMethods(['getBackendTable', 'getAttributeId'])
114+
->setMethods(['getBackendTable', 'getAttributeId', 'getSourceModel', 'getSource'])
113115
->disableOriginalConstructor()
114116
->getMockForAbstractClass();
115117
$this->scope = $this->getMockBuilder(ScopeInterface::class)
@@ -157,14 +159,65 @@ public function testGetAttributeOptions(array $options)
157159
$this->scopeResolver->expects($this->any())->method('getScope')->willReturn($this->scope);
158160
$this->scope->expects($this->any())->method('getId')->willReturn(123);
159161

160-
$this->select->expects($this->any())->method('from')->willReturnSelf();
161-
$this->select->expects($this->any())->method('joinInner')->willReturnSelf();
162-
$this->select->expects($this->any())->method('joinLeft')->willReturnSelf();
163-
$this->select->expects($this->any())->method('where')->willReturnSelf();
162+
$this->select->expects($this->exactly(1))->method('from')->willReturnSelf();
163+
$this->select->expects($this->exactly(1))->method('columns')->willReturnSelf();
164+
$this->select->expects($this->exactly(5))->method('joinInner')->willReturnSelf();
165+
$this->select->expects($this->exactly(3))->method('joinLeft')->willReturnSelf();
166+
$this->select->expects($this->exactly(2))->method('where')->willReturnSelf();
167+
168+
$this->abstractAttribute->expects($this->any())
169+
->method('getBackendTable')
170+
->willReturn('getBackendTable value');
171+
$this->abstractAttribute->expects($this->any())
172+
->method('getAttributeId')
173+
->willReturn('getAttributeId value');
174+
175+
$this->connectionMock->expects($this->once())
176+
->method('fetchAll')
177+
->willReturn($options);
178+
179+
$this->assertEquals(
180+
$options,
181+
$this->model->getAttributeOptions($this->abstractAttribute, 1)
182+
);
183+
}
184+
185+
/**
186+
* @param array $options
187+
* @dataProvider testOptionsWithBackendModelDataProvider
188+
*/
189+
public function testGetAttributeOptionsWithBackendModel(array $options)
190+
{
191+
$this->scopeResolver->expects($this->any())->method('getScope')->willReturn($this->scope);
192+
$this->scope->expects($this->any())->method('getId')->willReturn(123);
193+
194+
$this->select->expects($this->exactly(1))->method('from')->willReturnSelf();
195+
$this->select->expects($this->exactly(0))->method('columns')->willReturnSelf();
196+
$this->select->expects($this->exactly(5))->method('joinInner')->willReturnSelf();
197+
$this->select->expects($this->exactly(1))->method('joinLeft')->willReturnSelf();
198+
$this->select->expects($this->exactly(2))->method('where')->willReturnSelf();
164199

200+
$source = $this->getMockBuilder(AbstractSource::class)
201+
->disableOriginalConstructor()
202+
->setMethods(['getAllOptions'])
203+
->getMockForAbstractClass();
204+
$source->expects($this->any())
205+
->method('getAllOptions')
206+
->willReturn([
207+
['value' => 13, 'label' => 'Option Value for index 13'],
208+
['value' => 14, 'label' => 'Option Value for index 14'],
209+
['value' => 15, 'label' => 'Option Value for index 15']
210+
]);
211+
212+
$this->abstractAttribute->expects($this->atLeastOnce())
213+
->method('getSource')
214+
->willReturn($source);
165215
$this->abstractAttribute->expects($this->any())
166216
->method('getBackendTable')
167217
->willReturn('getBackendTable value');
218+
$this->abstractAttribute->expects($this->any())
219+
->method('getSourceModel')
220+
->willReturn('getSourceModel value');
168221
$this->abstractAttribute->expects($this->any())
169222
->method('getAttributeId')
170223
->willReturn('getAttributeId value');
@@ -192,24 +245,61 @@ public function testOptionsDataProvider()
192245
'product_id' => 4,
193246
'attribute_code' => 'color',
194247
'value_index' => '13',
195-
'option_title' => 'Black'
248+
'option_title' => 'Black',
196249
],
197250
[
198251
'sku' => 'Configurable1-White',
199252
'product_id' => 4,
200253
'attribute_code' => 'color',
201254
'value_index' => '14',
202-
'option_title' => 'White'
255+
'option_title' => 'White',
203256
],
204257
[
205258
'sku' => 'Configurable1-Red',
206259
'product_id' => 4,
207260
'attribute_code' => 'color',
208261
'value_index' => '15',
209-
'option_title' => 'Red'
210-
]
211-
]
212-
]
262+
'option_title' => 'Red',
263+
],
264+
],
265+
],
266+
];
267+
}
268+
269+
/**
270+
* @return array
271+
*/
272+
public function testOptionsWithBackendModelDataProvider()
273+
{
274+
return [
275+
[
276+
[
277+
[
278+
'sku' => 'Configurable1-Black',
279+
'product_id' => 4,
280+
'attribute_code' => 'color',
281+
'value_index' => '13',
282+
'option_title' => 'Option Value for index 13',
283+
'default_title' => 'Option Value for index 13',
284+
],
285+
[
286+
'sku' => 'Configurable1-White',
287+
'product_id' => 4,
288+
'attribute_code' => 'color',
289+
'value_index' => '14',
290+
'option_title' => 'Option Value for index 14',
291+
'default_title' => 'Option Value for index 14',
292+
],
293+
[
294+
'sku' => 'Configurable1-Red',
295+
'product_id' => 4,
296+
'attribute_code' => 'color',
297+
'value_index' => '15',
298+
'option_title' => 'Option Value for index 15',
299+
'default_title' => 'Option Value for index 15',
300+
],
301+
],
302+
],
213303
];
214304
}
215305
}

0 commit comments

Comments
 (0)