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.
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
I get this error:
Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (magento
.eav_attribute_option_swatch
, CONSTRAINT EAV_ATTRIBUTE_OPTION_SWATCH_STORE_ID_STORE_STORE_ID
FOREIGN KEY (store_id
) REFERENCES store
(store_id
) ON DELETE CASCADE), query was: INSERT INTO eav_attribute_option_swatch
(option_id
, store_id
, type
, value
) VALUES (?, ?, ?, ?)