From 07a4b3b595407fac5383b09d9bf0669f68dd94f4 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 1 Nov 2017 16:25:02 +0530 Subject: [PATCH 01/17] #8810 - REST API - Attribute option creation -> no ID returned --- .../Api/ProductAttributeOptionManagementInterface.php | 2 +- .../Eav/Api/AttributeOptionManagementInterface.php | 2 +- .../Eav/Model/Entity/Attribute/OptionManagement.php | 8 ++++++-- .../Unit/Model/Entity/Attribute/OptionManagementTest.php | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php b/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php index 07b7d591c3fd7..9e0014f242ba7 100644 --- a/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php +++ b/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php @@ -29,7 +29,7 @@ public function getItems($attributeCode); * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException - * @return bool + * @return \Magento\Eav\Api\Data\AttributeOptionInterface */ public function add($attributeCode, $option); diff --git a/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php b/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php index aac6e2174b1ea..566149bbd2e14 100644 --- a/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php +++ b/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php @@ -20,7 +20,7 @@ interface AttributeOptionManagementInterface * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException - * @return bool + * @return \Magento\Eav\Api\Data\AttributeOptionInterface */ public function add($entityType, $attributeCode, $option); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index b0508fd8cc626..11b72754a95a3 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -49,9 +49,10 @@ public function add($entityType, $attributeCode, $option) throw new StateException(__('Attribute %1 doesn\'t work with options', $attributeCode)); } + $optionLabel = $option->getLabel(); $optionId = $this->getOptionId($option); $options = []; - $options['value'][$optionId][0] = $option->getLabel(); + $options['value'][$optionId][0] = $optionLabel; $options['order'][$optionId] = $option->getSortOrder(); if (is_array($option->getStoreLabels())) { @@ -67,11 +68,14 @@ public function add($entityType, $attributeCode, $option) $attribute->setOption($options); try { $this->resourceModel->save($attribute); + if ($optionLabel && $attribute->getAttributeCode()) { + $option->setValue($attribute->getSource()->getOptionId($optionLabel)); + } } catch (\Exception $e) { throw new StateException(__('Cannot save attribute %1', $attributeCode)); } - return true; + return $option; } /** diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php index 36eb78fd435e7..ed15d372f3f6b 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php @@ -80,7 +80,7 @@ public function testAdd() $attributeMock->expects($this->once())->method('setDefault')->with(['new_option']); $attributeMock->expects($this->once())->method('setOption')->with($option); $this->resourceModelMock->expects($this->once())->method('save')->with($attributeMock); - $this->assertTrue($this->model->add($entityType, $attributeCode, $optionMock)); + $this->assertEquals($optionMock, $this->model->add($entityType, $attributeCode, $optionMock)); } /** From b9e0abe7d92458d075a2c5b472d07baadfcf9771 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 8 Jan 2018 21:47:56 +0530 Subject: [PATCH 02/17] #8810 - Solved api functional test issue --- .../Entity/Attribute/OptionManagement.php | 24 ++++++++++++++++++- ...AttributeOptionManagementInterfaceTest.php | 2 +- ...AttributeOptionManagementInterfaceTest.php | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index 11b72754a95a3..467de64b45c6d 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -69,7 +69,7 @@ public function add($entityType, $attributeCode, $option) try { $this->resourceModel->save($attribute); if ($optionLabel && $attribute->getAttributeCode()) { - $option->setValue($attribute->getSource()->getOptionId($optionLabel)); + $this->setOptionValue($option, $attribute, $optionLabel); } } catch (\Exception $e) { throw new StateException(__('Cannot save attribute %1', $attributeCode)); @@ -151,4 +151,26 @@ private function getOptionId($option) { return $option->getValue() ?: 'new_option'; } + + /** + * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option + * @param \Magento\Eav\Api\Data\AttributeInterface $attribute + * @param string $optionLabel + * @return void + */ + public function setOptionValue($option, $attribute, $optionLabel) + { + if ($optionId = $attribute->getSource()->getOptionId($optionLabel)) { + $option->setValue($attribute->getSource()->getOptionId($optionId)); + } else { + if (is_array($option->getStoreLabels())) { + foreach ($option->getStoreLabels() as $label) { + if ($optionId = $attribute->getSource()->getOptionId($label->getLabel())) { + $option->setValue($attribute->getSource()->getOptionId($optionId)); + break; + } + } + } + } + } } diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php index 6c1e351ccd1ee..7de3f864b20a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php @@ -74,7 +74,7 @@ public function testAdd($optionData) ] ); - $this->assertTrue($response); + $this->assertNotNull($response[AttributeOptionInterface::VALUE]); $updatedData = $this->getAttributeOptions($testAttributeCode); $lastOption = array_pop($updatedData); $this->assertEquals( diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php index 63e5282c22104..2a749b0b95177 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php @@ -42,7 +42,7 @@ public function testAdd($optionData) ] ); - $this->assertTrue($response); + $this->assertNotNull($response[AttributeOptionInterface::VALUE]); $updatedData = $this->getAttributeOptions($testAttributeCode); $lastOption = array_pop($updatedData); $this->assertEquals( From e31ea928984ceed9f5a20c49c7bc3483d2bbe49d Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 9 Jan 2018 12:18:00 +0530 Subject: [PATCH 03/17] #8810 - fixed php code style issue --- .../Model/Entity/Attribute/OptionManagement.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index 467de64b45c6d..46b1d3c7a539f 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -158,17 +158,16 @@ private function getOptionId($option) * @param string $optionLabel * @return void */ - public function setOptionValue($option, $attribute, $optionLabel) + protected function setOptionValue($option, $attribute, $optionLabel) { - if ($optionId = $attribute->getSource()->getOptionId($optionLabel)) { + $optionId = $attribute->getSource()->getOptionId($optionLabel); + if ($optionId) { $option->setValue($attribute->getSource()->getOptionId($optionId)); - } else { - if (is_array($option->getStoreLabels())) { - foreach ($option->getStoreLabels() as $label) { - if ($optionId = $attribute->getSource()->getOptionId($label->getLabel())) { - $option->setValue($attribute->getSource()->getOptionId($optionId)); - break; - } + } elseif (is_array($option->getStoreLabels())) { + foreach ($option->getStoreLabels() as $label) { + if ($optionId = $attribute->getSource()->getOptionId($label->getLabel())) { + $option->setValue($attribute->getSource()->getOptionId($optionId)); + break; } } } From 5eef1d9fd7fbe7a39344a02fab6e3795465d5af1 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Wed, 25 Apr 2018 17:25:45 +0300 Subject: [PATCH 04/17] magento/magento2#12920: Fixed review issues --- .../Api/ProductAttributeOptionManagementInterface.php | 2 +- .../Eav/Api/AttributeOptionManagementInterface.php | 2 +- .../Eav/Model/Entity/Attribute/OptionManagement.php | 11 +++++++---- .../Model/Entity/Attribute/OptionManagementTest.php | 2 +- .../ProductAttributeOptionManagementInterfaceTest.php | 2 +- ...ctSwatchAttributeOptionManagementInterfaceTest.php | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php b/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php index 9e0014f242ba7..3f255d93f96b0 100644 --- a/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php +++ b/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php @@ -29,7 +29,7 @@ public function getItems($attributeCode); * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException - * @return \Magento\Eav\Api\Data\AttributeOptionInterface + * @return string */ public function add($attributeCode, $option); diff --git a/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php b/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php index 566149bbd2e14..84aefa700a52a 100644 --- a/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php +++ b/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php @@ -20,7 +20,7 @@ interface AttributeOptionManagementInterface * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException - * @return \Magento\Eav\Api\Data\AttributeOptionInterface + * @return string */ public function add($entityType, $attributeCode, $option); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index f1cab45b3f341..a2c9611d26f5d 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -75,7 +75,7 @@ public function add($entityType, $attributeCode, $option) throw new StateException(__('The "%1" attribute can\'t be saved.', $attributeCode)); } - return $option; + return $this->getOptionId($option); } /** @@ -151,7 +151,7 @@ protected function validateOption($attribute, $optionId) * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @return string */ - private function getOptionId($option) + private function getOptionId(\Magento\Eav\Api\Data\AttributeOptionInterface $option) : string { return $option->getValue() ?: 'new_option'; } @@ -162,8 +162,11 @@ private function getOptionId($option) * @param string $optionLabel * @return void */ - protected function setOptionValue($option, $attribute, $optionLabel) - { + private function setOptionValue( + \Magento\Eav\Api\Data\AttributeOptionInterface $option, + \Magento\Eav\Api\Data\AttributeInterface $attribute, + string $optionLabel + ) { $optionId = $attribute->getSource()->getOptionId($optionLabel); if ($optionId) { $option->setValue($attribute->getSource()->getOptionId($optionId)); diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php index 035232708e30a..2ae31a05d957f 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php @@ -81,7 +81,7 @@ public function testAdd() $attributeMock->expects($this->once())->method('setDefault')->with(['new_option']); $attributeMock->expects($this->once())->method('setOption')->with($option); $this->resourceModelMock->expects($this->once())->method('save')->with($attributeMock); - $this->assertEquals($optionMock, $this->model->add($entityType, $attributeCode, $optionMock)); + $this->assertEquals('new_option', $this->model->add($entityType, $attributeCode, $optionMock)); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php index 7de3f864b20a7..f9442d8b6499a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php @@ -74,7 +74,7 @@ public function testAdd($optionData) ] ); - $this->assertNotNull($response[AttributeOptionInterface::VALUE]); + $this->assertNotNull($response); $updatedData = $this->getAttributeOptions($testAttributeCode); $lastOption = array_pop($updatedData); $this->assertEquals( diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php index 2a749b0b95177..6b8388e2f4345 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php @@ -42,7 +42,7 @@ public function testAdd($optionData) ] ); - $this->assertNotNull($response[AttributeOptionInterface::VALUE]); + $this->assertNotNull($response); $updatedData = $this->getAttributeOptions($testAttributeCode); $lastOption = array_pop($updatedData); $this->assertEquals( From f0c1879ccd9fee9ff42ba2a7c38a7881df85f4fc Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Fri, 27 Apr 2018 17:20:33 +0300 Subject: [PATCH 05/17] ENGCOM-1360: [Forwardport] Add argument on app:config:dump to skip dumping all system settings. #14807 --- setup/performance-toolkit/benchmark.jmx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 5dc1199c0e9da..8976a4cfb824c 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -37918,9 +37918,9 @@ adminUserList.add(vars.get("admin_user")); - + - true + ^[a-z0-9_\"]+$ Assertion.response_data false @@ -37992,9 +37992,9 @@ adminUserList.add(vars.get("admin_user")); - + - true + ^[a-z0-9_\"]+$ Assertion.response_data false From 3be7c52cc7b8011bea3631ce3ab52f9e68fc843a Mon Sep 17 00:00:00 2001 From: Pieter Cappelle Date: Fri, 2 Feb 2018 14:40:13 +0100 Subject: [PATCH 06/17] Allow import of empty attributes --- .../Model/Import/Product.php | 13 ++++ .../Import/Product/Type/AbstractType.php | 4 ++ .../Model/Import/Product/Validator.php | 5 ++ .../Import/Product/Validator/Quantity.php | 4 +- .../Model/Import/Product/Validator/Weight.php | 4 +- .../Import/Product/Validator/QuantityTest.php | 8 +++ .../Import/Product/Validator/WeightTest.php | 67 +++++++++++++++++++ .../Test/Unit/Model/Import/ProductTest.php | 22 ++++++ .../Block/Adminhtml/Import/Edit/Form.php | 13 ++++ .../Magento/ImportExport/Model/Import.php | 10 +++ 10 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 4d42330cd00bf..b6c72d88f81f1 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -908,6 +908,19 @@ public function getMultipleValueSeparator() return Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; } + /** + * Return empty attribute value constant + * + * @return string + */ + public function getEmptyAttributeValueConstant() + { + if (!empty($this->_parameters[Import::FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT])) { + return $this->_parameters[Import::FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT]; + } + return Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT; + } + /** * Retrieve instance of product custom options import entity * diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index 17d084002926a..a944af0120f9d 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -537,6 +537,10 @@ public function clearEmptyData(array $rowData) if (!$attrParams['is_static'] && !isset($rowData[$attrCode])) { unset($rowData[$attrCode]); } + + if (isset($rowData[$attrCode]) && $rowData[$attrCode] === $this->_entityModel->getEmptyAttributeValueConstant()) { + $rowData[$attrCode] = null; + } } return $rowData; } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php index 60bfdd56a718e..a07c28b02ec82 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php @@ -188,6 +188,11 @@ public function isAttributeValid($attrCode, array $attrParams, array $rowData) if (!strlen(trim($rowData[$attrCode]))) { return true; } + + if ($rowData[$attrCode] === $this->context->getEmptyAttributeValueConstant() && !$attrParams['is_required']) { + return true; + } + switch ($attrParams['type']) { case 'varchar': case 'text': diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Quantity.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Quantity.php index 728d3e4d17621..21566c955ba2f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Quantity.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Quantity.php @@ -18,7 +18,9 @@ class Quantity extends AbstractImportValidator implements RowValidatorInterface public function isValid($value) { $this->_clearMessages(); - if (!empty($value['qty']) && !is_numeric($value['qty'])) { + if (!empty($value['qty']) && (!is_numeric($value['qty']) + && $value['qty'] !== $this->context->getEmptyAttributeValueConstant()) + ) { $this->_addMessages( [ sprintf( diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Weight.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Weight.php index 07d038a05d2f0..5cc91d4598701 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Weight.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Weight.php @@ -15,7 +15,9 @@ class Weight extends AbstractImportValidator implements RowValidatorInterface public function isValid($value) { $this->_clearMessages(); - if (!empty($value['weight']) && (!is_numeric($value['weight']) || $value['weight'] < 0)) { + if (!empty($value['weight']) && (!is_numeric($value['weight']) || $value['weight'] < 0) + && $value['weight'] !== $this->context->getEmptyAttributeValueConstant() + ) { $this->_addMessages( [ sprintf( diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/QuantityTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/QuantityTest.php index 144214fd6e318..b550102cb1a15 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/QuantityTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/QuantityTest.php @@ -7,6 +7,7 @@ use Magento\CatalogImportExport\Model\Import\Product; use Magento\CatalogImportExport\Model\Import\Product\Validator\Quantity; +use Magento\ImportExport\Model\Import; /** * Class QuantityTest @@ -25,6 +26,10 @@ protected function setUp() $contextStub = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->getMock(); + $contextStub->expects($this->any()) + ->method('getEmptyAttributeValueConstant') + ->willReturn(Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT); + $contextStub->method('retrieveMessageTemplate')->willReturn(null); $this->quantity->init($contextStub); } @@ -54,6 +59,9 @@ public function isValidDataProvider() [true, ['qty' => '']], [false, ['qty' => 'abc']], [false, ['qty' => true]], + [false, ['qty' => true]], + [true, ['qty' => Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT]], + [false, ['qty' => '__EMPTY__VALUE__TEST__']], ]; } } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php new file mode 100644 index 0000000000000..823ccf5bc827d --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php @@ -0,0 +1,67 @@ +weight = new Weight(); + + $contextStub = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->getMock(); + $contextStub->expects($this->any()) + ->method('getEmptyAttributeValueConstant') + ->willReturn(Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT); + + $contextStub->method('retrieveMessageTemplate')->willReturn(null); + $this->weight->init($contextStub); + } + + /** + * @param bool $expectedResult + * @param array $value + * @dataProvider isValidDataProvider + */ + public function testIsValid($expectedResult, $value) + { + $result = $this->weight->isValid($value); + $this->assertEquals($expectedResult, $result); + } + + /** + * @return array + */ + public function isValidDataProvider() + { + return [ + [true, ['weight' => 0]], + [true, ['weight' => 1]], + [true, ['weight' => 5]], + [false, ['weight' => -1]], + [false, ['weight' => -10]], + [true, ['weight' => '']], + [false, ['weight' => 'abc']], + [false, ['weight' => true]], + [false, ['weight' => true]], + [true, ['weight' => Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT]], + [false, ['weight' => '__EMPTY__VALUE__TEST__']], + ]; + } +} diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php index 9282c5cb5c02e..9d6ba88fc4a69 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php @@ -600,6 +600,28 @@ public function testGetMultipleValueSeparatorFromParameters() ); } + public function testGetEmptyAttributeValueConstantDefault() + { + $this->setPropertyValue($this->importProduct, '_parameters', null); + $this->assertEquals( + Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT, + $this->importProduct->getEmptyAttributeValueConstant() + ); + } + + public function testGetEmptyAttributeValueConstantFromParameters() + { + $expectedSeparator = '__EMPTY__VALUE__TEST__'; + $this->setPropertyValue($this->importProduct, '_parameters', [ + \Magento\ImportExport\Model\Import::FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT => $expectedSeparator, + ]); + + $this->assertEquals( + $expectedSeparator, + $this->importProduct->getEmptyAttributeValueConstant() + ); + } + public function testDeleteProductsForReplacement() { $importProduct = $this->getMockBuilder(\Magento\CatalogImportExport\Model\Import\Product::class) diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php index 822795abb0b44..39d0d5c7feaee 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php @@ -174,6 +174,19 @@ protected function _prepareForm() 'value' => Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, ] ); + $fieldsets[$behaviorCode]->addField( + $behaviorCode . \Magento\ImportExport\Model\Import::FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT, + 'text', + [ + 'name' => \Magento\ImportExport\Model\Import::FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT, + 'label' => __('Empty attribute value constant'), + 'title' => __('Empty attribute value constant'), + 'required' => true, + 'disabled' => true, + 'class' => $behaviorCode, + 'value' => Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT, + ] + ); $fieldsets[$behaviorCode]->addField( $behaviorCode . \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE, 'checkbox', diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index 12f34955f81f0..b5e8220e0e9b0 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -77,6 +77,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ const FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR = '_import_multiple_value_separator'; + /** + * Import empty attribute value constant. + */ + const FIELD_EMPTY_ATTRIBUTE_VALUE_CONSTANT = '_import_empty_attribute_value_constant'; + /** * Allow multiple values wrapping in double quotes for additional attributes. */ @@ -89,6 +94,11 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ const DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR = ','; + /** + * default empty attribute value constant + */ + const DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT = '__EMPTY__VALUE__'; + /**#@+ * Import constants */ From dad61f8abcb620786b598620c5b014c4cb5851fd Mon Sep 17 00:00:00 2001 From: David Manners Date: Mon, 12 Mar 2018 11:46:37 +0100 Subject: [PATCH 07/17] magento-engcom/import-export-improvements#49: update line length of clearEmptyData if statement Updating the formatting for the new if in clearEmptyData so that it fits the coding standards. --- .../Model/Import/Product/Type/AbstractType.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index a944af0120f9d..285cd190c088b 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -538,7 +538,9 @@ public function clearEmptyData(array $rowData) unset($rowData[$attrCode]); } - if (isset($rowData[$attrCode]) && $rowData[$attrCode] === $this->_entityModel->getEmptyAttributeValueConstant()) { + if (isset($rowData[$attrCode]) + && $rowData[$attrCode] === $this->_entityModel->getEmptyAttributeValueConstant()) + { $rowData[$attrCode] = null; } } From ed1a4250965c67348ded54a0ad0916f5b533c97b Mon Sep 17 00:00:00 2001 From: David Manners Date: Mon, 12 Mar 2018 12:48:03 +0100 Subject: [PATCH 08/17] magento-engcom/import-export-improvements#49: update line length of clearEmptyData if statement --- .../Model/Import/Product/Type/AbstractType.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index 285cd190c088b..dd33b94423696 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -539,8 +539,8 @@ public function clearEmptyData(array $rowData) } if (isset($rowData[$attrCode]) - && $rowData[$attrCode] === $this->_entityModel->getEmptyAttributeValueConstant()) - { + && $rowData[$attrCode] === $this->_entityModel->getEmptyAttributeValueConstant() + ) { $rowData[$attrCode] = null; } } From 93ba0ab9e50fcf4b5927e1564abec8c3cc70d278 Mon Sep 17 00:00:00 2001 From: David Manners Date: Mon, 9 Apr 2018 14:41:50 +0000 Subject: [PATCH 09/17] magento-engcom/import-export-improvements#49: check to make sure the product options match expected style - if product options is equal to our new empty value constant than do not try to process it as normal --- .../CatalogImportExport/Model/Import/Product/Option.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index adb660dd118f9..1800efd9bef4a 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -1090,7 +1090,7 @@ protected function _getMultiRowFormat($rowData) // Parse custom options. $rowData = $this->_parseCustomOptions($rowData); $multiRow = []; - if (empty($rowData['custom_options'])) { + if (empty($rowData['custom_options']) || !is_array($rowData['custom_options'])) { return $multiRow; } @@ -1923,7 +1923,8 @@ protected function _updateProducts(array $data) protected function _parseCustomOptions($rowData) { $beforeOptionValueSkuDelimiter = ';'; - if (empty($rowData['custom_options'])) { + if (empty($rowData['custom_options']) + || $rowData['custom_options'] === \Magento\ImportExport\Model\Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT) { return $rowData; } $rowData['custom_options'] = str_replace( From a557d4089aa4566c604884afdb29212fba1923d1 Mon Sep 17 00:00:00 2001 From: David Manners Date: Mon, 9 Apr 2018 16:00:23 +0000 Subject: [PATCH 10/17] magento-engcom/import-export-improvements#49: update line length to match coding standards --- .../CatalogImportExport/Model/Import/Product/Option.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 1800efd9bef4a..b4b9a5c3e97b4 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -13,6 +13,7 @@ use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection as ProductOptionValueCollection; use Magento\Catalog\Model\ResourceModel\Product\Option\Value\CollectionFactory as ProductOptionValueCollectionFactory; use Magento\Store\Model\Store; +use Magento\ImportExport\Model\Import; /** * Entity class which provide possibility to import product custom options @@ -1924,7 +1925,7 @@ protected function _parseCustomOptions($rowData) { $beforeOptionValueSkuDelimiter = ';'; if (empty($rowData['custom_options']) - || $rowData['custom_options'] === \Magento\ImportExport\Model\Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT) { + || $rowData['custom_options'] === Import::DEFAULT_EMPTY_ATTRIBUTE_VALUE_CONSTANT) { return $rowData; } $rowData['custom_options'] = str_replace( From c07aea84222c3aec2368dcbb660d9f5f3027cf09 Mon Sep 17 00:00:00 2001 From: David Manners Date: Wed, 6 Jun 2018 12:22:00 +0000 Subject: [PATCH 11/17] magento-engcom/import-export-improvements#49: Add strict type to new test case --- .../Test/Unit/Model/Import/Product/Validator/WeightTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php index 823ccf5bc827d..78174828ae26e 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/WeightTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product\Validator; use Magento\CatalogImportExport\Model\Import\Product; From 73e934344ed8ab094f68d4e75fe8920c7702ab77 Mon Sep 17 00:00:00 2001 From: David Manners Date: Wed, 6 Jun 2018 13:30:39 +0000 Subject: [PATCH 12/17] magento-engcom/import-export-improvements#49: Add removal of custom options via csv via constant --- .../CatalogImportExport/Model/Import/Product/Option.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index b4b9a5c3e97b4..a20f5dfb530f8 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -1236,7 +1236,13 @@ protected function _importData() $multiRowData = $this->_getMultiRowFormat($rowData); if (!empty($rowData[self::COLUMN_SKU]) && isset($this->_productsSkuToId[$rowData[self::COLUMN_SKU]])) { $this->_rowProductId = $this->_productsSkuToId[$rowData[self::COLUMN_SKU]]; - if (array_key_exists('custom_options', $rowData) && trim($rowData['custom_options']) === '') { + if ( + array_key_exists('custom_options', $rowData) + && ( + trim($rowData['custom_options']) === '' + || trim ($rowData['custom_options']) === $this->_productEntity->getEmptyAttributeValueConstant() + ) + ) { $optionsToRemove[] = $this->_rowProductId; } } From 51f4ac89303ea333a0a0181e198d4d85898f1b93 Mon Sep 17 00:00:00 2001 From: David Manners Date: Wed, 6 Jun 2018 13:52:14 +0000 Subject: [PATCH 13/17] magento-engcom/import-export-improvements#49: Add failure if sku is empty value constant --- .../Model/Import/Product/Type/AbstractType.php | 6 +++++- .../CatalogImportExport/Model/Import/Product/Validator.php | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index dd33b94423696..f233c00d98f95 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -444,7 +444,11 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) $error = false; $rowScope = $this->_entityModel->getRowScope($rowData); if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_NULL != $rowScope - && !empty($rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]) + && ( + !empty($rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]) + || $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU] + !== $this->_entityModel->getEmptyAttributeValueConstant() + ) ) { foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) { // check value for non-empty in the case of required attribute? diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php index a07c28b02ec82..e1a6188551c0c 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php @@ -150,7 +150,12 @@ public function isRequiredAttributeValid($attrCode, array $attributeParams, arra $doCheck = true; } - return $doCheck ? isset($rowData[$attrCode]) && strlen(trim($rowData[$attrCode])) : true; + if ($doCheck === true) { + return isset($rowData[$attrCode]) + && strlen(trim($rowData[$attrCode])) + && trim($rowData[$attrCode]) !== $this->context->getEmptyAttributeValueConstant(); + } + return true; } /** From 20094b76ab070033fc76a6194f4166ce73c304e9 Mon Sep 17 00:00:00 2001 From: David Manners Date: Wed, 6 Jun 2018 13:53:30 +0000 Subject: [PATCH 14/17] magento-engcom/import-export-improvements#49: Add failure if sku is empty value constant --- .../Model/Import/Product/Type/AbstractType.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index f233c00d98f95..dd33b94423696 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -444,11 +444,7 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) $error = false; $rowScope = $this->_entityModel->getRowScope($rowData); if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_NULL != $rowScope - && ( - !empty($rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]) - || $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU] - !== $this->_entityModel->getEmptyAttributeValueConstant() - ) + && !empty($rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]) ) { foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) { // check value for non-empty in the case of required attribute? From 4b54d148183471ff7ea0890d65df0cec143bfbdc Mon Sep 17 00:00:00 2001 From: David Manners Date: Wed, 6 Jun 2018 15:49:17 +0000 Subject: [PATCH 15/17] magento-engcom/import-export-improvements#49: Update code styles in option import --- .../CatalogImportExport/Model/Import/Product/Option.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index a20f5dfb530f8..ae29fd2ef4bd4 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -1236,11 +1236,10 @@ protected function _importData() $multiRowData = $this->_getMultiRowFormat($rowData); if (!empty($rowData[self::COLUMN_SKU]) && isset($this->_productsSkuToId[$rowData[self::COLUMN_SKU]])) { $this->_rowProductId = $this->_productsSkuToId[$rowData[self::COLUMN_SKU]]; - if ( - array_key_exists('custom_options', $rowData) + if (array_key_exists('custom_options', $rowData) && ( - trim($rowData['custom_options']) === '' - || trim ($rowData['custom_options']) === $this->_productEntity->getEmptyAttributeValueConstant() + trim($rowData['custom_options']) === '' || + trim($rowData['custom_options']) === $this->_productEntity->getEmptyAttributeValueConstant() ) ) { $optionsToRemove[] = $this->_rowProductId; From a0946c1eda9bdab3f4c1c9f3feef20721b044800 Mon Sep 17 00:00:00 2001 From: "al.kravchuk" Date: Mon, 25 Jun 2018 17:28:57 +0300 Subject: [PATCH 16/17] magento/magento2#?: Login with wishlist raise report after logout. - fix error message after login with wishlist; - fix possibility to logout after login with wishlist; --- app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php b/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php index b7b462b3cc317..641a91d2e6554 100644 --- a/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php +++ b/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php @@ -45,7 +45,7 @@ public function aroundExecute(FlushFormKey $subject, callable $proceed, ...$args $currentFormKey = $this->dataFormKey->getFormKey(); $proceed(...$args); $beforeParams = $this->session->getBeforeRequestParams(); - if ($beforeParams['form_key'] == $currentFormKey) { + if (isset($beforeParams['form_key']) && $beforeParams['form_key'] == $currentFormKey) { $beforeParams['form_key'] = $this->dataFormKey->getFormKey(); $this->session->setBeforeRequestParams($beforeParams); } From d8e87dcc8aa73f4804bcd81beb66d06cbd64d1e7 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Tue, 26 Jun 2018 09:18:47 +0300 Subject: [PATCH 17/17] Strict comparison for form_key --- app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php b/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php index 641a91d2e6554..2d000ccfb4b93 100644 --- a/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php +++ b/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php @@ -45,7 +45,7 @@ public function aroundExecute(FlushFormKey $subject, callable $proceed, ...$args $currentFormKey = $this->dataFormKey->getFormKey(); $proceed(...$args); $beforeParams = $this->session->getBeforeRequestParams(); - if (isset($beforeParams['form_key']) && $beforeParams['form_key'] == $currentFormKey) { + if (isset($beforeParams['form_key']) && $beforeParams['form_key'] === $currentFormKey) { $beforeParams['form_key'] = $this->dataFormKey->getFormKey(); $this->session->setBeforeRequestParams($beforeParams); }