Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 82f3f83

Browse files
committed
Merge branch '2.3-develop-main' into team3-delivery
2 parents 3a6dbb9 + d3248d0 commit 82f3f83

File tree

82 files changed

+1703
-429
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1703
-429
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The members of this team have been recognized for their outstanding commitment t
3535
</a>
3636

3737
<h3>Top Contributors</h3>
38-
Magento team thanks for any contribution that can improve our code base, documentation or increase test coverage. We always recognize our most active members, your contributions are the foundation of the Magento open source platform.
38+
Magento is thankful for any contribution that can improve our code base, documentation or increase test coverage. We always recognize our most active members, as their contributions are the foundation of the Magento Open Source platform.
3939
<a href="https://magento.com/magento-contributors">
4040
<img src="https://raw.githubusercontent.com/wiki/magento/magento2/images/contributors.png"/>
4141
</a>

app/code/Magento/Backend/Model/Url.php

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -202,33 +202,36 @@ public function getUrl($routePath = null, $routeParams = null)
202202
}
203203

204204
$cacheSecretKey = false;
205-
if (is_array($routeParams) && isset($routeParams['_cache_secret_key'])) {
205+
if (isset($routeParams['_cache_secret_key'])) {
206206
unset($routeParams['_cache_secret_key']);
207207
$cacheSecretKey = true;
208208
}
209209
$result = parent::getUrl($routePath, $routeParams);
210210
if (!$this->useSecretKey()) {
211211
return $result;
212212
}
213+
214+
$this->getRouteParamsResolver()->unsetData('route_params');
213215
$this->_setRoutePath($routePath);
216+
$extraParams = $this->getRouteParamsResolver()->getRouteParams();
214217
$routeName = $this->_getRouteName('*');
215218
$controllerName = $this->_getControllerName(self::DEFAULT_CONTROLLER_NAME);
216219
$actionName = $this->_getActionName(self::DEFAULT_ACTION_NAME);
217-
if ($cacheSecretKey) {
218-
$secret = [self::SECRET_KEY_PARAM_NAME => "\${$routeName}/{$controllerName}/{$actionName}\$"];
219-
} else {
220-
$secret = [
221-
self::SECRET_KEY_PARAM_NAME => $this->getSecretKey($routeName, $controllerName, $actionName),
222-
];
223-
}
224-
if (is_array($routeParams)) {
225-
$routeParams = array_merge($secret, $routeParams);
226-
} else {
227-
$routeParams = $secret;
220+
221+
if (!isset($routeParams[self::SECRET_KEY_PARAM_NAME])) {
222+
if (!is_array($routeParams)) {
223+
$routeParams = [];
224+
}
225+
$secretKey = $cacheSecretKey
226+
? "\${$routeName}/{$controllerName}/{$actionName}\$"
227+
: $this->getSecretKey($routeName, $controllerName, $actionName);
228+
$routeParams[self::SECRET_KEY_PARAM_NAME] = $secretKey;
228229
}
229-
if (is_array($this->_getRouteParams())) {
230-
$routeParams = array_merge($this->_getRouteParams(), $routeParams);
230+
231+
if (!empty($extraParams)) {
232+
$routeParams = array_merge($extraParams, $routeParams);
231233
}
234+
232235
return parent::getUrl("{$routeName}/{$controllerName}/{$actionName}", $routeParams);
233236
}
234237

app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ public function testGetCustomAttributes()
468468
);
469469

470470
//Change the attribute value, should reflect in getCustomAttribute
471-
$this->category->setData($customAttributeCode, $newCustomAttributeValue);
471+
$this->category->setCustomAttribute($customAttributeCode, $newCustomAttributeValue);
472472
$this->assertEquals(1, count($this->category->getCustomAttributes()));
473473
$this->assertNotNull($this->category->getCustomAttribute($customAttributeCode));
474474
$this->assertEquals(

app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ public function testGetCustomAttributes()
13051305
);
13061306

13071307
//Change the attribute value, should reflect in getCustomAttribute
1308-
$this->model->setData($customAttributeCode, $newCustomAttributeValue);
1308+
$this->model->setCustomAttribute($customAttributeCode, $newCustomAttributeValue);
13091309
$this->assertEquals(1, count($this->model->getCustomAttributes()));
13101310
$this->assertNotNull($this->model->getCustomAttribute($customAttributeCode));
13111311
$this->assertEquals(

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1703,7 +1703,7 @@ protected function _saveProducts()
17031703
$storeId = !empty($rowData[self::COL_STORE])
17041704
? $this->getStoreIdByCode($rowData[self::COL_STORE])
17051705
: Store::DEFAULT_STORE_ID;
1706-
if (isset($rowData['_media_is_disabled'])) {
1706+
if (isset($rowData['_media_is_disabled']) && strlen(trim($rowData['_media_is_disabled']))) {
17071707
$disabledImages = array_flip(
17081708
explode($this->getMultipleValueSeparator(), $rowData['_media_is_disabled'])
17091709
);

app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ public function prepareAttributesWithDefaultValueForSave(array $rowData, $withDe
503503
if ($attrParams['is_static']) {
504504
continue;
505505
}
506-
if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) {
506+
if (isset($rowData[$attrCode]) && strlen(trim($rowData[$attrCode]))) {
507507
if (in_array($attrParams['type'], ['select', 'boolean'])) {
508508
$resultAttrs[$attrCode] = $attrParams['options'][strtolower($rowData[$attrCode])];
509509
} elseif ('multiselect' == $attrParams['type']) {

app/code/Magento/CatalogInventory/Api/StockConfigurationInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public function getEnableQtyIncrements($storeId = null);
7777

7878
/**
7979
* @param int $storeId
80-
* @return int
80+
* @return float
8181
*/
8282
public function getQtyIncrements($store = null);
8383

app/code/Magento/CatalogInventory/Model/Configuration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public function getEnableQtyIncrements($store = null)
273273

274274
/**
275275
* @param null|string|bool|int|\Magento\Store\Model\Store $store
276-
* @return int
276+
* @return float
277277
*/
278278
public function getQtyIncrements($store = null)
279279
{

app/code/Magento/CatalogInventory/Model/Stock/Item.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ public function getUseConfigQtyIncrements()
392392
/**
393393
* Retrieve Quantity Increments
394394
*
395-
* @return int|false
395+
* @return int|float|false
396396
*/
397397
public function getQtyIncrements()
398398
{
@@ -401,7 +401,13 @@ public function getQtyIncrements()
401401
if ($this->getUseConfigQtyIncrements()) {
402402
$this->qtyIncrements = $this->stockConfiguration->getQtyIncrements($this->getStoreId());
403403
} else {
404-
$this->qtyIncrements = (int) $this->getData(static::QTY_INCREMENTS);
404+
$this->qtyIncrements = $this->getData(static::QTY_INCREMENTS);
405+
}
406+
407+
if ($this->getIsQtyDecimal()) { // Cast accordingly to decimal qty usage
408+
$this->qtyIncrements = (float) $this->qtyIncrements;
409+
} else {
410+
$this->qtyIncrements = (int) $this->qtyIncrements;
405411
}
406412
}
407413
if ($this->qtyIncrements <= 0) {

app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/ItemTest.php

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ public function testGetQtyIncrements($config, $expected)
394394
$this->setDataArrayValue('qty_increments', $config['qty_increments']);
395395
$this->setDataArrayValue('enable_qty_increments', $config['enable_qty_increments']);
396396
$this->setDataArrayValue('use_config_qty_increments', $config['use_config_qty_increments']);
397+
$this->setDataArrayValue('is_qty_decimal', $config['is_qty_decimal']);
397398
if ($config['use_config_qty_increments']) {
398399
$this->stockConfiguration->expects($this->once())
399400
->method('getQtyIncrements')
@@ -415,23 +416,44 @@ public function getQtyIncrementsDataProvider()
415416
[
416417
'qty_increments' => 1,
417418
'enable_qty_increments' => true,
418-
'use_config_qty_increments' => true
419+
'use_config_qty_increments' => true,
420+
'is_qty_decimal' => false,
421+
],
422+
1
423+
],
424+
[
425+
[
426+
'qty_increments' => 1.5,
427+
'enable_qty_increments' => true,
428+
'use_config_qty_increments' => true,
429+
'is_qty_decimal' => true,
430+
],
431+
1.5
432+
],
433+
[
434+
[
435+
'qty_increments' => 1.5,
436+
'enable_qty_increments' => true,
437+
'use_config_qty_increments' => true,
438+
'is_qty_decimal' => false,
419439
],
420440
1
421441
],
422442
[
423443
[
424444
'qty_increments' => -2,
425445
'enable_qty_increments' => true,
426-
'use_config_qty_increments' => true
446+
'use_config_qty_increments' => true,
447+
'is_qty_decimal' => false,
427448
],
428449
false
429450
],
430451
[
431452
[
432453
'qty_increments' => 3,
433454
'enable_qty_increments' => true,
434-
'use_config_qty_increments' => false
455+
'use_config_qty_increments' => false,
456+
'is_qty_decimal' => false,
435457
],
436458
3
437459
],

app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,6 @@
571571
<settings>
572572
<scopeLabel>[GLOBAL]</scopeLabel>
573573
<validation>
574-
<rule name="validate-digits" xsi:type="boolean">true</rule>
575574
<rule name="validate-number" xsi:type="boolean">true</rule>
576575
</validation>
577576
<label translate="true">Qty Increments</label>

app/code/Magento/ConfigurableProduct/Model/Product/SaveHandler.php

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
1111
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable as ResourceModelConfigurable;
1212
use Magento\Framework\EntityManager\Operation\ExtensionInterface;
13+
use Magento\ConfigurableProduct\Api\Data\OptionInterface;
14+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute;
1315

1416
/**
1517
* Class SaveHandler
@@ -76,35 +78,66 @@ public function execute($entity, $arguments = [])
7678
}
7779

7880
/**
79-
* Save attributes for configurable product
81+
* Save only newly created attributes for configurable product.
8082
*
8183
* @param ProductInterface $product
8284
* @param array $attributes
8385
* @return array
8486
*/
85-
private function saveConfigurableProductAttributes(ProductInterface $product, array $attributes)
87+
private function saveConfigurableProductAttributes(ProductInterface $product, array $attributes): array
8688
{
8789
$ids = [];
90+
$existingAttributeIds = [];
91+
foreach ($this->optionRepository->getList($product->getSku()) as $option) {
92+
$existingAttributeIds[$option->getAttributeId()] = $option;
93+
}
8894
/** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $attribute */
8995
foreach ($attributes as $attribute) {
90-
$attribute->setId(null);
91-
$ids[] = $this->optionRepository->save($product->getSku(), $attribute);
96+
if (!in_array($attribute->getAttributeId(), array_keys($existingAttributeIds))
97+
|| $this->isOptionChanged($existingAttributeIds[$attribute->getAttributeId()], $attribute)
98+
) {
99+
$attribute->setId(null);
100+
$ids[] = $this->optionRepository->save($product->getSku(), $attribute);
101+
}
92102
}
93103

94104
return $ids;
95105
}
96106

97107
/**
98-
* Remove product attributes
108+
* Remove product attributes which no longer used.
99109
*
100110
* @param ProductInterface $product
101111
* @return void
102112
*/
103-
private function deleteConfigurableProductAttributes(ProductInterface $product)
113+
private function deleteConfigurableProductAttributes(ProductInterface $product): void
114+
{
115+
$newAttributeIds = [];
116+
foreach ($product->getExtensionAttributes()->getConfigurableProductOptions() as $option) {
117+
$newAttributeIds[$option->getAttributeId()] = $option;
118+
}
119+
foreach ($this->optionRepository->getList($product->getSku()) as $option) {
120+
if (!in_array($option->getAttributeId(), array_keys($newAttributeIds))
121+
|| $this->isOptionChanged($option, $newAttributeIds[$option->getAttributeId()])
122+
) {
123+
$this->optionRepository->deleteById($product->getSku(), $option->getId());
124+
}
125+
}
126+
}
127+
128+
/**
129+
* Check if existing option is changed.
130+
*
131+
* @param OptionInterface $option
132+
* @param Attribute $attribute
133+
* @return bool
134+
*/
135+
private function isOptionChanged(OptionInterface $option, Attribute $attribute): bool
104136
{
105-
$list = $this->optionRepository->getList($product->getSku());
106-
foreach ($list as $item) {
107-
$this->optionRepository->deleteById($product->getSku(), $item->getId());
137+
if ($option->getLabel() == $attribute->getLabel() && $option->getPosition() == $attribute->getPosition()) {
138+
return false;
108139
}
140+
141+
return true;
109142
}
110143
}

app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/SaveHandlerTest.php

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public function testExecuteWithInvalidProductType()
8888
public function testExecuteWithEmptyExtensionAttributes()
8989
{
9090
$sku = 'test';
91+
$configurableProductLinks = [1, 2, 3];
9192
$product = $this->getMockBuilder(Product::class)
9293
->disableOriginalConstructor()
9394
->setMethods(['getTypeId', 'getExtensionAttributes', 'getSku'])
@@ -105,16 +106,16 @@ public function testExecuteWithEmptyExtensionAttributes()
105106
->disableOriginalConstructor()
106107
->getMockForAbstractClass();
107108

108-
$product->expects(static::once())
109+
$product->expects(static::atLeastOnce())
109110
->method('getExtensionAttributes')
110111
->willReturn($extensionAttributes);
111112

112-
$extensionAttributes->expects(static::exactly(2))
113+
$extensionAttributes->expects(static::atLeastOnce())
113114
->method('getConfigurableProductOptions')
114115
->willReturn([]);
115-
$extensionAttributes->expects(static::once())
116+
$extensionAttributes->expects(static::atLeastOnce())
116117
->method('getConfigurableProductLinks')
117-
->willReturn([]);
118+
->willReturn($configurableProductLinks);
118119

119120
$this->optionRepository->expects(static::once())
120121
->method('getList')
@@ -133,7 +134,10 @@ public function testExecuteWithEmptyExtensionAttributes()
133134
public function testExecute()
134135
{
135136
$sku = 'config-1';
136-
$id = 25;
137+
$idOld = 25;
138+
$idNew = 26;
139+
$attributeIdOld = 11;
140+
$attributeIdNew = 22;
137141
$configurableProductLinks = [1, 2, 3];
138142

139143
$product = $this->getMockBuilder(Product::class)
@@ -143,7 +147,7 @@ public function testExecute()
143147
$product->expects(static::once())
144148
->method('getTypeId')
145149
->willReturn(ConfigurableModel::TYPE_CODE);
146-
$product->expects(static::exactly(3))
150+
$product->expects(static::exactly(4))
147151
->method('getSku')
148152
->willReturn($sku);
149153

@@ -156,30 +160,36 @@ public function testExecute()
156160
->method('getExtensionAttributes')
157161
->willReturn($extensionAttributes);
158162

159-
$attribute = $this->getMockBuilder(Attribute::class)
163+
$attributeNew = $this->getMockBuilder(Attribute::class)
160164
->disableOriginalConstructor()
161165
->setMethods(['getAttributeId', 'loadByProductAndAttribute', 'setId', 'getId'])
162166
->getMock();
163-
$this->processSaveOptions($attribute, $sku, $id);
164-
165-
$option = $this->getMockForAbstractClass(OptionInterface::class);
166-
$option->expects(static::once())
167+
$attributeNew->expects(static::atLeastOnce())
168+
->method('getAttributeId')
169+
->willReturn($attributeIdNew);
170+
$this->processSaveOptions($attributeNew, $sku, $idNew);
171+
172+
$optionOld = $this->getMockForAbstractClass(OptionInterface::class);
173+
$optionOld->expects(static::atLeastOnce())
174+
->method('getAttributeId')
175+
->willReturn($attributeIdOld);
176+
$optionOld->expects(static::atLeastOnce())
167177
->method('getId')
168-
->willReturn($id);
178+
->willReturn($idOld);
169179

170-
$list = [$option];
171-
$this->optionRepository->expects(static::once())
180+
$list = [$optionOld];
181+
$this->optionRepository->expects(static::atLeastOnce())
172182
->method('getList')
173183
->with($sku)
174184
->willReturn($list);
175185
$this->optionRepository->expects(static::once())
176186
->method('deleteById')
177-
->with($sku, $id);
187+
->with($sku, $idOld);
178188

179189
$configurableAttributes = [
180-
$attribute
190+
$attributeNew
181191
];
182-
$extensionAttributes->expects(static::exactly(2))
192+
$extensionAttributes->expects(static::atLeastOnce())
183193
->method('getConfigurableProductOptions')
184194
->willReturn($configurableAttributes);
185195

app/code/Magento/Quote/Model/Quote.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2378,8 +2378,9 @@ protected function _afterLoad()
23782378
{
23792379
// collect totals and save me, if required
23802380
if (1 == $this->getTriggerRecollect()) {
2381-
$this->collectTotals()->save();
2382-
$this->setTriggerRecollect(0);
2381+
$this->collectTotals()
2382+
->setTriggerRecollect(0)
2383+
->save();
23832384
}
23842385
return parent::_afterLoad();
23852386
}

0 commit comments

Comments
 (0)