2

How to create text swatch programmatically?

If, I follow method from saving controller in the product-attribute module (admin) then, I got first and the third field saved but not actual text swatch.

0

Try to use my code, Basically you'd need to add a select type, then convert it to Text Swatch like SwatchesSampleData module this used some functions from this module

InstallData.php

<?php

namespace Vendor\Module\Setup;

use Magento\Framework\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Catalog\Model\Product\Type;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute as eavAttribute;

class InstallData implements InstallDataInterface
{
    /**
     * @var EavSetupFactory
     */
    protected $eavSetupFactory;

    protected $attrOptionCollectionFactory;
    protected $eavConfig;
    protected $logger;


    protected $optionCollection = [];


    public function __construct(
        EavSetupFactory $eavSetupFactory,
        \Magento\Eav\Model\Config $eavConfig,
        \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory,
        \Psr\Log\LoggerInterface $logger
    )
    {
        $this->eavConfig = $eavConfig;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->attrOptionCollectionFactory = $attrOptionCollectionFactory;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '1.0.0', '<')) {
            /** @var \Magento\Eav\Setup\EavSetup $eavSetup */
            $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

            $this->installSwatches($eavSetup, $setup);
        }

        $setup->endSetup();
    }


    /**
     * @param EavSetup $eavSetup
     * @param ModuleDataSetupInterface $setup
     * @throws \Exception
     */
    private function installSwatches(
        \Magento\Eav\Setup\EavSetup $eavSetup,
        ModuleDataSetupInterface $setup
    ) {

        try {

            $productTypes = [
                \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE,
                \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL,
                \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE,
                \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE,
            ];
            $productTypes = join(',', $productTypes);

            $eavSetup->addAttribute(
                \Magento\Catalog\Model\Product::ENTITY,
                'test_text_swatch',
                [
                    'type' => 'int',
                    'label' => 'Test Text Swatch',
                    'input' => 'select',
                    'required' => false,
                    'user_defined' => true,
                    'searchable' => true,
                    'filterable' => true,
                    'comparable' => true,
                    'visible_in_advanced_search' => true,
                    'apply_to' => $productTypes,
                    'is_used_in_grid' => true,
                    'is_visible_in_grid' => false,
                    'option' => [
                        'values' => [
                            'Test'
                        ]
                    ]
                ]
            );

            $this->eavConfig->clear();

            $this->convertAttributeToSwatches();

        } catch (\Exception $e) {
            $this->logger->critical($e);

        }

    }

    public function convertAttributeToSwatches() {
        $attribute = $this->eavConfig->getAttribute('catalog_product', 'test_text_swatch');
        if (!$attribute) {
            return;
        }

        $attributeData['option'] = $this->addExistingOptions($attribute);
        $attributeData['frontend_input'] = 'select';
        $attributeData['swatch_input_type'] = 'text';
        $attributeData['update_product_preview_image'] = 1;
        $attributeData['use_product_image_for_swatch'] = 0;
        $attributeData['optiontext'] = $this->getOptionSwatch($attributeData);
        $attributeData['defaulttext'] = $this->getOptionDefaultText($attributeData);
        $attributeData['swatchtext'] = $this->getOptionSwatchText($attributeData);
        $this->logger->log(100, print_r($attributeData, true));
        $attribute->addData($attributeData);
        $attribute->save();
    }

    protected function getOptionSwatch(array $attributeData)
    {
        $optionSwatch = ['order' => [], 'value' => [], 'delete' => []];
        $i = 0;
        foreach ($attributeData['option'] as $optionKey => $optionValue) {
            $optionSwatch['delete'][$optionKey] = '';
            $optionSwatch['order'][$optionKey] = (string)$i++;
            $optionSwatch['value']['option_' . $optionKey] = [$optionValue, ''];
        }
        return $optionSwatch;
    }

    /**
     * @param array $attributeData
     * @return array
     */
    private function getOptionSwatchText(array $attributeData)
    {
        $optionSwatch = ['value' => []];
        foreach ($attributeData['option'] as $optionKey => $optionValue) {
            $optionSwatch['value'][$optionKey] = [$optionValue, ''];
        }
        return $optionSwatch;
    }

    /**
     * @param array $attributeData
     * @return array
     */
    private function getOptionDefaultText(array $attributeData)
    {
        $optionSwatch = $this->getOptionSwatchText($attributeData);
        return [array_keys($optionSwatch['value'])[0]];
    }

    /**
     * @param $attributeId
     * @return void
     */
    private function loadOptionCollection($attributeId)
    {
        if (empty($this->optionCollection[$attributeId])) {
            $this->optionCollection[$attributeId] = $this->attrOptionCollectionFactory->create()
                ->setAttributeFilter($attributeId)
                ->setPositionOrder('asc', true)
                ->load();
        }
    }

    /**
     * @param eavAttribute $attribute
     * @return array
     */
    private function addExistingOptions(eavAttribute $attribute)
    {
        $options = [];
        $attributeId = $attribute->getId();
        if ($attributeId) {
            $this->loadOptionCollection($attributeId);
            /** @var \Magento\Eav\Model\Entity\Attribute\Option $option */
            foreach ($this->optionCollection[$attributeId] as $option) {
                $options[$option->getId()] = $option->getValue();
            }
        }
        return $options;
    }
}

Result

Result

  • How to add the new swatch_text option when having several stores? Trying this, it thrown an error "foreign key constraint fails" for the store_id – Gianni Di Falco Aug 12 at 13:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.