Magento2: Unable to add new options to swatch attribute

Created on 25 Sep 2017  路  9Comments  路  Source: magento/magento2

ProductAttributeOptionManagementInterface#add() doesn't do anything.

Preconditions

Magento 2.1.9
Create a product attribute named "color" and set its type to "Visual Swatch". Also make sure it has at least one option. Otherwise you'll run into a different issue.

Steps to reproduce

Consider the following class:

<?php declare(strict_types=1);

namespace Acme\AttributeCreator\Model;

use Magento\Catalog\Api\ProductAttributeOptionManagementInterface;
use Magento\Eav\Api\Data\AttributeOptionInterfaceFactory;
use Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory;
use Magento\Store\Api\StoreRepositoryInterface;

class AttributeOptionCreator
{
    /** @var AttributeOptionLabelInterfaceFactory */
    private $optionLabelFactory;
    /** @var AttributeOptionInterfaceFactory */
    private $attributeOptionFactory;
    /** @var ProductAttributeOptionManagementInterface */
    private $attributeOptionManagement;
    /** @var StoreRepositoryInterface */
    private $storeRepository;

    public function __construct(
        AttributeOptionLabelInterfaceFactory $optionLabelFactory,
        AttributeOptionInterfaceFactory $attributeOptionFactory,
        ProductAttributeOptionManagementInterface $attributeOptionManagement,
        StoreRepositoryInterface $storeRepository
    ) {
        $this->optionLabelFactory = $optionLabelFactory;
        $this->attributeOptionFactory = $attributeOptionFactory;
        $this->attributeOptionManagement = $attributeOptionManagement;
        $this->storeRepository = $storeRepository;
    }

    public function createAttributeOption(string $attributeCode, string $label): void
    {
        $labels = [];
        foreach ($this->storeRepository->getList() as $store) {
            $optionLabel = $this->optionLabelFactory->create();
            $optionLabel->setStoreId($store->getId());
            $optionLabel->setLabel($label);
            $labels[] = $optionLabel;
        }
        $option = $this->attributeOptionFactory->create();
        $option->setStoreLabels($labels);
        $option->setLabel($label);
        $option->setIsDefault(false);
        $this->attributeOptionManagement->add($attributeCode, $option);
    }
}

Expected result

$attributeOptionCreator->createAttributeOption('color', 'Blue') adds a new option to the attribute.

Actual result

The option is not added to the attribute.

Fixed in 2.1.x Fixed in 2.2.x Fixed in 2.3.x Clear Description Confirmed Format is valid Ready for Work Reproduced on 2.1.x Reproduced on 2.2.x Reproduced on 2.3.x

Most helpful comment

I am preparing a PR for this one so if you can assign it to me please #SQUASHTOBERFEST

All 9 comments

This still doesn't work in Magento 2.2.0.

I just fount the source of the problem: Magento\Swatches\Model\Plugin\EavAttribute#setProperOptionsArray() (called by beforeBeforeSave()) overrides the option with the optionvisual key.

So it seems to me like options for visual (and text) swatches are supposed to be created differently, but I can't figure out how.

@MidnightDesign, thank you for your report.
We've created internal ticket(s) MAGETWO-80165 to track progress on the issue.

I am preparing a PR for this one so if you can assign it to me please #SQUASHTOBERFEST

Same issue here, I didn't dig much into the problem but renaming the function beforeBeforeSave to beforeSave fix the problem.
Here is the commit where the function has been rename if it can help: https://github.com/magento/magento2/commit/cafbc8f88ce40181b86782141b68698fd8b5576f

I confirm the issue on 2.2.1, it's not possible to add swatch options if the attribute options is not already present/saved into the DB. This happens only when the DB transaction is committed.

However, the method of the plugin \Magento\Swatches\Model\Plugin\EavAttribute::beforeBeforeSave prevent saving the attribute options while saving the attribute. Renaming beforeBeforeSave to beforeSave prevent partially the issue. There is an other issue related to the afterAfterSave and processSwatchOptions methods. The last one need the list of all options but because the DB transaction is not yet committed, the options are not yet available from the database. The method \Magento\Swatches\Model\Plugin\EavAttribute::prepareOptionLinks trigger a notice error because no option id exist YET.

So the solution was to create a di preference of the existing plugin + create a own plugin into a di.xml of a custom module.

SwatchesEavAttribute.php.txt

The issue has been fixed and delivered to 2.1-develop and 2.2-develop branches

it is not fixed in current 2.3.1!
$option = $this->optionDataFactory->create();
$option->setLabel($label);

        $result = $this->attributeOptionManagementInterface->add($attributeCode, $option);

fails with a lock wait timeout on swatch attributes

fix from sylvainraye works

Faced the same issue 2.3.5-p1
Basically options are created but not added to the swathes table. But it seems like it works if you set option Value, the same as option label and it's finally added into my attribute.
So in my case it's something like:

$optionLabel = $this->optionLabelFactory->create();
            $optionLabel->setStoreId(0);
            $optionLabel->setLabel($label);

            $option = $this->optionFactory->create();
            $option->setLabel($label);
            $option->setValue($label);
            $option->setStoreLabels([$optionLabel]);
            $option->setSortOrder(0);
            $option->setIsDefault(false);

            $this->attributeOptionManagement->add(
                $this->getAttribute($attributeCode)->getAttributeId(),
                $option
            );

Not sure is it correct, but this seems to be work solution

Was this page helpful?
0 / 5 - 0 ratings