From 0f28b61565c3108281ef24c5f846ba2034e9ba9c Mon Sep 17 00:00:00 2001 From: EugeneShab Date: Wed, 22 Aug 2018 18:15:27 +0300 Subject: [PATCH 1/2] Unable to change attribute type from swatch --- .../Swatches/Model/Plugin/EavAttribute.php | 43 ++++++++++++++++++- .../Swatches/Model/ResourceModel/Swatch.php | 20 +++++++++ .../Model/SwatchAttributesProviderTest.php | 25 ++++++----- 3 files changed, 73 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php b/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php index 599406f455281..3e21cdc12de90 100644 --- a/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php +++ b/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php @@ -9,6 +9,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\InputException; use Magento\Framework\Serialize\Serializer\Json; +use Magento\Swatches\Model\ResourceModel\Swatch as SwatchResource; use Magento\Swatches\Model\Swatch; /** @@ -18,6 +19,11 @@ class EavAttribute { const DEFAULT_STORE_ID = 0; + /** + * @var SwatchResource + */ + private $swatchResource; + /** * Base option title used for string operations to detect is option already exists or new */ @@ -64,17 +70,20 @@ class EavAttribute * @param \Magento\Swatches\Model\SwatchFactory $swatchFactory * @param \Magento\Swatches\Helper\Data $swatchHelper * @param Json|null $serializer + * @param SwatchResource|null $swatchResource */ public function __construct( \Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory $collectionFactory, \Magento\Swatches\Model\SwatchFactory $swatchFactory, \Magento\Swatches\Helper\Data $swatchHelper, - Json $serializer = null + Json $serializer = null, + SwatchResource $swatchResource = null ) { $this->swatchCollectionFactory = $collectionFactory; $this->swatchFactory = $swatchFactory; $this->swatchHelper = $swatchHelper; $this->serializer = $serializer ?: ObjectManager::getInstance()->create(Json::class); + $this->swatchResource = $swatchResource ?: ObjectManager::getInstance()->create(SwatchResource::class); } /** @@ -148,6 +157,7 @@ protected function setProperOptionsArray(Attribute $attribute) * Prepare attribute for conversion from any swatch type to dropdown * * @param Attribute $attribute + * @throws \Magento\Framework\Exception\LocalizedException * @return void */ protected function convertSwatchToDropdown(Attribute $attribute) @@ -157,6 +167,7 @@ protected function convertSwatchToDropdown(Attribute $attribute) if (!empty($additionalData)) { $additionalData = $this->serializer->unserialize($additionalData); if (is_array($additionalData) && isset($additionalData[Swatch::SWATCH_INPUT_TYPE_KEY])) { + $this->cleanEavAttributeOptionSwatchValues($attribute->getOption()); unset($additionalData[Swatch::SWATCH_INPUT_TYPE_KEY]); $attribute->setData('additional_data', $this->serializer->serialize($additionalData)); } @@ -235,6 +246,7 @@ protected function saveSwatchParams(Attribute $attribute) { if ($this->swatchHelper->isVisualSwatch($attribute)) { $this->processVisualSwatch($attribute); + $this->cleanTextSwatchValuesAfterSwitch($attribute->getOptiontext()); } elseif ($this->swatchHelper->isTextSwatch($attribute)) { $this->processTextualSwatch($attribute); } @@ -267,6 +279,33 @@ protected function processVisualSwatch(Attribute $attribute) } } + /** + * Clean swatch option values after switching to the dropdown type. + * + * @param array $attributeOptions + * @param null $swatchType + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function cleanEavAttributeOptionSwatchValues($attributeOptions, $swatchType = null) + { + if (count($attributeOptions) && isset($attributeOptions['value'])) { + $optionsIDs = array_keys($attributeOptions['value']); + + $this->swatchResource->clearSwatchOptionByOptionIdAndType($optionsIDs, $swatchType); + } + } + + /** + * Cleaning the text type of swatch option values after switching. + * + * @param array $attributeOptions + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function cleanTextSwatchValuesAfterSwitch($attributeOptions) + { + $this->cleanEavAttributeOptionSwatchValues($attributeOptions, Swatch::SWATCH_TYPE_TEXTUAL); + } + /** * @param string $value * @return int @@ -432,7 +471,7 @@ protected function validateOptions(Attribute $attribute) $options = $attribute->getData('optiontext'); } if ($options && !$this->isOptionsValid($options, $attribute)) { - throw new InputException(__('Admin is a required field in the each row')); + throw new InputException(__('Admin is a required field in each row')); } return true; } diff --git a/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php b/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php index 22eb1d4c7eef9..8ca694725511d 100644 --- a/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php +++ b/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php @@ -37,4 +37,24 @@ public function saveDefaultSwatchOption($id, $defaultValue) $this->getConnection()->update($this->getTable('eav_attribute'), $bind, $where); } } + + /** + * Cleaned swatch option values when switching to dropdown input type + * + * @param $optionIDs + * @param $type + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function clearSwatchOptionByOptionIdAndType($optionIDs, $type = null) + { + if (count($optionIDs)) { + foreach ($optionIDs as $optionId) { + $where = ['option_id' => $optionId]; + if ($type !== null) { + $where['type = ?'] = $type; + } + $this->getConnection()->delete($this->getMainTable(), $where); + } + } + } } diff --git a/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php b/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php index b87fd84ce892f..e9f5b580204d5 100644 --- a/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php @@ -3,10 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Swatches\Test\Unit\Model; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Swatches\Model\SwatchAttributeCodes; use Magento\Swatches\Model\SwatchAttributesProvider; @@ -35,26 +35,26 @@ class SwatchAttributesProviderTest extends \PHPUnit\Framework\TestCase private $productMock; /** - * @var SwatchAttributeType|\PHPUnit_Framework_MockObject_MockObject + * @var SwatchAttributeType | \PHPUnit_Framework_MockObject_MockObject */ - private $swatchTypeCheckerMock; + private $swatchTypeChecker; protected function setUp() { $this->typeConfigurable = $this->createPartialMock( Configurable::class, - ['getConfigurableAttributes', 'getCodes'] + ['getConfigurableAttributes', 'getCodes', 'getProductAttribute'] ); $this->swatchAttributeCodes = $this->createMock(SwatchAttributeCodes::class); $this->productMock = $this->createPartialMock(\Magento\Catalog\Model\Product::class, ['getId', 'getTypeId']); - $this->swatchTypeCheckerMock = $this->createMock(SwatchAttributeType::class); + $this->swatchTypeChecker = $this->createMock(SwatchAttributeType::class); $this->swatchAttributeProvider = (new ObjectManager($this))->getObject(SwatchAttributesProvider::class, [ 'typeConfigurable' => $this->typeConfigurable, 'swatchAttributeCodes' => $this->swatchAttributeCodes, - 'swatchTypeChecker' => $this->swatchTypeCheckerMock, + 'swatchTypeChecker' => $this->swatchTypeChecker, ]); } @@ -64,8 +64,9 @@ public function testProvide() $this->productMock->method('getTypeId') ->willReturn(Configurable::TYPE_CODE); - $productAttributeMock = $this->getMockBuilder(Attribute::class) + $attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class) ->disableOriginalConstructor() + ->setMethods(['setStoreId', 'getData', 'setData', 'getSource', 'hasData']) ->getMock(); $configAttributeMock = $this->createPartialMock( @@ -78,7 +79,7 @@ public function testProvide() $configAttributeMock ->method('getProductAttribute') - ->willReturn($productAttributeMock); + ->willReturn($attributeMock); $this->typeConfigurable ->method('getConfigurableAttributes') @@ -90,12 +91,10 @@ public function testProvide() ->method('getCodes') ->willReturn($swatchAttributes); - $this->swatchTypeCheckerMock->expects($this->once())->method('isSwatchAttribute')->willReturn(true); + $this->swatchTypeChecker->expects($this->once())->method('isSwatchAttribute')->willReturn(true); + $result = $this->swatchAttributeProvider->provide($this->productMock); - $this->assertEquals( - [1 => $productAttributeMock], - $result - ); + $this->assertEquals([1 => $attributeMock], $result); } } From d159921f79c68e9aec489192c223ce5535ff47d9 Mon Sep 17 00:00:00 2001 From: nmalevanec Date: Thu, 23 Aug 2018 11:21:57 +0300 Subject: [PATCH 2/2] Fix incorrect language on swatch error. Fix failed tests. --- .../Magento/Swatches/Model/Plugin/EavAttribute.php | 12 +++++++----- .../Magento/Swatches/Model/ResourceModel/Swatch.php | 8 ++++---- .../Test/Unit/Model/Plugin/EavAttributeTest.php | 2 +- app/code/Magento/Swatches/i18n/en_US.csv | 2 +- app/code/Magento/Ui/i18n/en_US.csv | 2 +- lib/web/i18n/en_US.csv | 2 +- lib/web/mage/validation.js | 6 +++--- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php b/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php index 3e21cdc12de90..ebbb1775aa7f8 100644 --- a/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php +++ b/app/code/Magento/Swatches/Model/Plugin/EavAttribute.php @@ -167,7 +167,8 @@ protected function convertSwatchToDropdown(Attribute $attribute) if (!empty($additionalData)) { $additionalData = $this->serializer->unserialize($additionalData); if (is_array($additionalData) && isset($additionalData[Swatch::SWATCH_INPUT_TYPE_KEY])) { - $this->cleanEavAttributeOptionSwatchValues($attribute->getOption()); + $option = $attribute->getOption() ?: []; + $this->cleanEavAttributeOptionSwatchValues($option); unset($additionalData[Swatch::SWATCH_INPUT_TYPE_KEY]); $attribute->setData('additional_data', $this->serializer->serialize($additionalData)); } @@ -246,7 +247,8 @@ protected function saveSwatchParams(Attribute $attribute) { if ($this->swatchHelper->isVisualSwatch($attribute)) { $this->processVisualSwatch($attribute); - $this->cleanTextSwatchValuesAfterSwitch($attribute->getOptiontext()); + $attributeOptions = $attribute->getOptiontext() ?: []; + $this->cleanTextSwatchValuesAfterSwitch($attributeOptions); } elseif ($this->swatchHelper->isTextSwatch($attribute)) { $this->processTextualSwatch($attribute); } @@ -283,10 +285,10 @@ protected function processVisualSwatch(Attribute $attribute) * Clean swatch option values after switching to the dropdown type. * * @param array $attributeOptions - * @param null $swatchType + * @param int|null $swatchType * @throws \Magento\Framework\Exception\LocalizedException */ - private function cleanEavAttributeOptionSwatchValues($attributeOptions, $swatchType = null) + private function cleanEavAttributeOptionSwatchValues(array $attributeOptions, int $swatchType = null) { if (count($attributeOptions) && isset($attributeOptions['value'])) { $optionsIDs = array_keys($attributeOptions['value']); @@ -301,7 +303,7 @@ private function cleanEavAttributeOptionSwatchValues($attributeOptions, $swatchT * @param array $attributeOptions * @throws \Magento\Framework\Exception\LocalizedException */ - private function cleanTextSwatchValuesAfterSwitch($attributeOptions) + private function cleanTextSwatchValuesAfterSwitch(array $attributeOptions) { $this->cleanEavAttributeOptionSwatchValues($attributeOptions, Swatch::SWATCH_TYPE_TEXTUAL); } diff --git a/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php b/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php index 8ca694725511d..804bd71e737be 100644 --- a/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php +++ b/app/code/Magento/Swatches/Model/ResourceModel/Swatch.php @@ -39,13 +39,13 @@ public function saveDefaultSwatchOption($id, $defaultValue) } /** - * Cleaned swatch option values when switching to dropdown input type + * Cleaned swatch option values when switching to dropdown input type. * - * @param $optionIDs - * @param $type + * @param array $optionIDs + * @param int $type * @throws \Magento\Framework\Exception\LocalizedException */ - public function clearSwatchOptionByOptionIdAndType($optionIDs, $type = null) + public function clearSwatchOptionByOptionIdAndType(array $optionIDs, int $type = null) { if (count($optionIDs)) { foreach ($optionIDs as $optionId) { diff --git a/app/code/Magento/Swatches/Test/Unit/Model/Plugin/EavAttributeTest.php b/app/code/Magento/Swatches/Test/Unit/Model/Plugin/EavAttributeTest.php index 21df8c795506b..317ea77107222 100644 --- a/app/code/Magento/Swatches/Test/Unit/Model/Plugin/EavAttributeTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Model/Plugin/EavAttributeTest.php @@ -191,7 +191,7 @@ public function testBeforeSaveTextSwatch() /** * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Admin is a required field in the each row + * @expectedExceptionMessage Admin is a required field in each row */ public function testBeforeSaveWithFailedValidation() { diff --git a/app/code/Magento/Swatches/i18n/en_US.csv b/app/code/Magento/Swatches/i18n/en_US.csv index 9fe2ec7067570..f35e9a0a46d48 100644 --- a/app/code/Magento/Swatches/i18n/en_US.csv +++ b/app/code/Magento/Swatches/i18n/en_US.csv @@ -1,4 +1,4 @@ -"Admin is a required field in the each row","Admin is a required field in the each row" +"Admin is a required field in each row","Admin is a required field in each row" "Update Product Preview Image","Update Product Preview Image" "Filtering by this attribute will update the product image on catalog page","Filtering by this attribute will update the product image on catalog page" "Use Product Image for Swatch if Possible","Use Product Image for Swatch if Possible" diff --git a/app/code/Magento/Ui/i18n/en_US.csv b/app/code/Magento/Ui/i18n/en_US.csv index 106526f66e708..2197999c73505 100644 --- a/app/code/Magento/Ui/i18n/en_US.csv +++ b/app/code/Magento/Ui/i18n/en_US.csv @@ -180,7 +180,7 @@ CSV,CSV "Please enter a valid value from list","Please enter a valid value from list" "Please enter valid SKU key.","Please enter valid SKU key." "Please enter a valid number.","Please enter a valid number." -"Admin is a required field in the each row.","Admin is a required field in the each row." +"Admin is a required field in each row.","Admin is a required field in each row." "Please fix this field.","Please fix this field." "Please enter a valid date (ISO).","Please enter a valid date (ISO)." "Please enter only digits.","Please enter only digits." diff --git a/lib/web/i18n/en_US.csv b/lib/web/i18n/en_US.csv index 5c63a191420a4..4acc62aa6dc81 100644 --- a/lib/web/i18n/en_US.csv +++ b/lib/web/i18n/en_US.csv @@ -95,7 +95,7 @@ Submit,Submit "Please enter valid SKU key.","Please enter valid SKU key." "Please enter a valid number.","Please enter a valid number." "This is required field","This is required field" -"Admin is a required field in the each row.","Admin is a required field in the each row." +"Admin is a required field in each row.","Admin is a required field in each row." "Password cannot be the same as email address.","Password cannot be the same as email address." "Please fix this field.","Please fix this field." "Please enter a valid email address.","Please enter a valid email address." diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index d08819ebe94aa..86dd5a3b03681 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1562,15 +1562,15 @@ ], 'required-text-swatch-entry': [ tableSingleValidation, - $.mage.__('Admin is a required field in the each row.') + $.mage.__('Admin is a required field in each row.') ], 'required-visual-swatch-entry': [ tableSingleValidation, - $.mage.__('Admin is a required field in the each row.') + $.mage.__('Admin is a required field in each row.') ], 'required-dropdown-attribute-entry': [ tableSingleValidation, - $.mage.__('Admin is a required field in the each row.') + $.mage.__('Admin is a required field in each row.') ], 'validate-item-quantity': [ function (value, element, params) {