diff --git a/app/code/Magento/Swatches/Plugin/Catalog/AddSwatchDataToAddOption.php b/app/code/Magento/Swatches/Plugin/Catalog/AddSwatchDataToAddOption.php new file mode 100644 index 0000000000000..7a6446e9fad3e --- /dev/null +++ b/app/code/Magento/Swatches/Plugin/Catalog/AddSwatchDataToAddOption.php @@ -0,0 +1,218 @@ +eavConfig = $eavConfig; + $this->swatchHelper = $swatchHelper; + $this->optionCollectionFactory = $attrOptionCollectionFactory; + } + + /** + * @param OptionManagement $subject + * @param int $entityType + * @param string $attributeCode + * @param AttributeOptionInterface $option + * + * @return array [] + * @throws \Magento\Framework\Exception\LocalizedException + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeAdd(OptionManagement $subject, $entityType, $attributeCode, $option) + { + $attribute = $this->eavConfig->getAttribute(Product::ENTITY, $attributeCode); + + if (! $this->isSwatch($attribute)) { + return [$entityType, $attributeCode, $option]; + } + + $swatchType = $this->getSwatchType($attribute); + $optionKey = self::PREFIX_OPTION . $swatchType; + $swatchKey = self::PREFIX_SWATCH . $swatchType; + + if ($attribute->getData($optionKey) !== null || $attribute->getData($swatchKey) !== null) { + return [$entityType, $attributeCode, $option]; + } + + $optionId = $option->getValue(); + $optionOrder = $option->getSortOrder(); + $prefix = $optionId; + if ($optionId === '') { + $attributeData = $this->prepareAttributeDataForNewOption($attribute->getAttributeId(), $optionKey); + $optionId = count($attributeData[$optionKey]['value']); + if ($optionOrder === null) { + $optionOrder = $optionId + 1; + } + $prefix = 'option_' . $optionId; + $option->setValue($prefix); + } + + $storeLabels = $option->getStoreLabels(); + $attributeData[$optionKey]['delete'][$prefix] = ''; + $attributeData[$optionKey]['order'][$prefix] = $optionOrder; + if ($swatchType === self::SWATCH_VISUAL) { + $attributeData[$swatchKey]['value'][$prefix] = ''; + } + foreach ($storeLabels as $storeLabel) { + $attributeData[$optionKey]['value'][$prefix][$storeLabel->getStoreId()] = $storeLabel->getLabel(); + if ($swatchType === self::SWATCH_TEXT) { + $attributeData[$swatchKey]['value'][$prefix][$storeLabel->getStoreId()] = $storeLabel->getLabel(); + } + } + $attribute->addData($attributeData); + + return [$entityType, $attributeCode, $option]; + } + + /** + * @param $attribute + * + * @return boolean + */ + private function isSwatch($attribute) + { + if ($this->swatchHelper->isVisualSwatch($attribute)) { + return true; + } elseif ($this->swatchHelper->isTextSwatch($attribute)) { + return true; + } + + return false; + } + + /** + * @param $attribute + * + * @return null|string + */ + private function getSwatchType($attribute) + { + if ($this->swatchHelper->isVisualSwatch($attribute)) { + return self::SWATCH_VISUAL; + } elseif ($this->swatchHelper->isTextSwatch($attribute)) { + return self::SWATCH_TEXT; + } + + return null; + } + + /** + * @param int $attributeId + * @param string $optionKey + * + * @return array + */ + private function prepareAttributeDataForNewOption($attributeId, $optionKey) + { + $options = $this->getOptionsByAttributeIdWithSortOrder($attributeId); + return $this->getOptionsForSwatch($options, $optionKey); + } + + /** + * @param [] $options + * @param string $optionKey + * + * @return array + */ + private function getOptionsForSwatch(array $options, $optionKey) + { + $optionsArray = []; + + if (count($options) === 0) { + $optionsArray[$optionKey]['value'] = []; + $optionsArray[$optionKey]['delete'] = []; + + return $optionsArray; + } + + foreach ($options as $sortOrder => $optionId) { + $optionsArray[$optionKey]['value'][$optionId] = $this->getStoreLabels($optionId); + $optionsArray[$optionKey]['delete'][$optionId] = ''; + $optionsArray[$optionKey]['order'][$optionId] = (string)$sortOrder; + } + + return $optionsArray; + } + + /** + * @param int $optionId + * + * @return array + */ + private function getStoreLabels($optionId) + { + $optionCollectionFactory = $this->optionCollectionFactory->create(); + $connection = $optionCollectionFactory->getConnection(); + $optionValueTable = $optionCollectionFactory->getTable('eav_attribute_option_value'); + $select = $connection->select()->from( + ['eaov' => $optionValueTable], + [] + )->where('option_id = ?', $optionId)->columns(['store_id', 'value']); + + return $connection->fetchPairs($select); + } + + /** + * @param int $attributeId + * + * @return array + */ + private function getOptionsByAttributeIdWithSortOrder($attributeId) + { + $optionCollectionFactory = $this->optionCollectionFactory->create(); + $options = $optionCollectionFactory + ->setAttributeFilter($attributeId) + ->setPositionOrder() + ->addFieldToSelect('option_id') + ->getAllIds(); + + return array_values($options); + } +} diff --git a/app/code/Magento/Swatches/etc/di.xml b/app/code/Magento/Swatches/etc/di.xml index 5292bfafb6a0f..f64fa40edd684 100644 --- a/app/code/Magento/Swatches/etc/di.xml +++ b/app/code/Magento/Swatches/etc/di.xml @@ -81,4 +81,7 @@ + + + diff --git a/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php new file mode 100644 index 0000000000000..cbc82db68b32a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php @@ -0,0 +1,102 @@ + [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $testAttributeCode . '/options', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'add', + ], + ]; + + $response = $this->_webApiCall( + $serviceInfo, + [ + 'attributeCode' => $testAttributeCode, + 'option' => $optionData, + ] + ); + + $this->assertTrue($response); + $updatedData = $this->getAttributeOptions($testAttributeCode); + $lastOption = array_pop($updatedData); + $this->assertEquals( + $optionData[AttributeOptionInterface::STORE_LABELS][1][AttributeOptionLabelInterface::LABEL], + $lastOption['label'] + ); + } + + /** + * @return array + */ + public function addDataProvider() + { + $optionPayload = [ + AttributeOptionInterface::LABEL => 'new color', + AttributeOptionInterface::SORT_ORDER => 100, + AttributeOptionInterface::IS_DEFAULT => true, + AttributeOptionInterface::STORE_LABELS => [ + [ + AttributeOptionLabelInterface::LABEL => 'new color', + AttributeOptionLabelInterface::STORE_ID => 0, + ], + [ + AttributeOptionLabelInterface::LABEL => 'DE label', + AttributeOptionLabelInterface::STORE_ID => 1, + ], + ], + AttributeOptionInterface::VALUE => '' + ]; + + return [ + 'option_without_value_node' => [ + $optionPayload + ] + ]; + } + + /** + * @param $testAttributeCode + * @return array|bool|float|int|string + */ + private function getAttributeOptions($testAttributeCode) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $testAttributeCode . '/options', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'getItems', + ], + ]; + return $this->_webApiCall($serviceInfo, ['attributeCode' => $testAttributeCode]); + } +}