Created
February 4, 2025 23:24
-
-
Save ProxiBlue/5754200fd86f4c71555ef30c6ac6cd20 to your computer and use it in GitHub Desktop.
convert dynamic category products rules to elasticsuite rules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace ProxiBlue\MigrateTasks\Console\Command; | |
use Magento\Framework\App\ResourceConnection; | |
use Magento\Framework\Console\Cli; | |
use Magento\Framework\DB\Adapter\AdapterInterface; | |
use Magento\Framework\Exception\LocalizedException; | |
use Magento\Framework\Serialize\Serializer\Json; | |
use Symfony\Component\Console\Command\Command; | |
use Symfony\Component\Console\Input\InputInterface; | |
use Symfony\Component\Console\Output\OutputInterface; | |
class ConvertRulesCommand extends Command | |
{ | |
const SOURCE_ATTRIBUTE_ID = 297; | |
const TARGET_ATTRIBUTE_ID = 780; | |
const IS_VIRTUAL_CATEGORY_ATTRIBUTE_ID = 778; | |
const STORE_ID = 0; | |
private ResourceConnection $resourceConnection; | |
private Json $jsonSerializer; | |
public function __construct( | |
ResourceConnection $resourceConnection, | |
Json $jsonSerializer | |
) { | |
$this->resourceConnection = $resourceConnection; | |
$this->jsonSerializer = $jsonSerializer; | |
parent::__construct(); | |
} | |
protected function configure() | |
{ | |
$this->setName('proxiblue_migratetasks:convert-rules') | |
->setDescription('Convert rules from Magento 1 to Magento 2 module format and set is_virtual_category'); | |
parent::configure(); | |
} | |
protected function execute(InputInterface $input, OutputInterface $output) | |
{ | |
$connection = $this->resourceConnection->getConnection(); | |
$tableName = $this->resourceConnection->getTableName('catalog_category_entity_text'); | |
try { | |
// Fetch rows for conversion | |
$query = $connection->select() | |
->from($tableName) | |
->where('attribute_id = ?', self::SOURCE_ATTRIBUTE_ID) | |
->order('entity_id ASC') | |
->order('store_id DESC'); | |
$rows = $connection->fetchAll($query); | |
foreach ($rows as $row) { | |
$oldValue = $row['value']; | |
$entityId = $row['entity_id']; | |
if(empty($oldValue)) { | |
continue; | |
} | |
// Skip if the rule has already been converted | |
if (strpos($oldValue, 'Converted') === 0) { | |
$output->writeln("<comment>Skipping already converted rule for entity ID {$entityId}.</comment>"); | |
continue; | |
} | |
try { | |
// Decode old Magento 1 rules (unserialize) | |
$ruleData = unserialize($oldValue); | |
} catch (\Exception $e) { | |
$output->writeln("<error>Failed to unserialize rule for entity ID {$entityId}</error>"); | |
continue; | |
} | |
// Check for complex rules or invalid conditions | |
$containsComplex = $this->checkForComplexRules($ruleData); | |
$isValidAggregator = isset($ruleData['1--1']['aggregator']) && $ruleData['1--1']['aggregator'] === 'all'; | |
$isValidValue = isset($ruleData['1--1']['value']) && $ruleData['1--1']['value'] === '1'; | |
if ($containsComplex || !$isValidAggregator || !$isValidValue) { | |
$output->writeln("<comment>Rule for entity ID {$entityId} marked as complex or invalid and not converted.</comment>"); | |
continue; | |
} | |
// Convert rule and handle database updates | |
try { | |
$convertedRule = $this->convertRule($ruleData); | |
$convertedValue = $this->jsonSerializer->serialize($convertedRule); | |
// Update original row with 'Converted:' prefix | |
$connection->update( | |
$tableName, | |
['value' => 'Converted:' . $oldValue], | |
['entity_id = ?' => $entityId, 'attribute_id = ?' => self::SOURCE_ATTRIBUTE_ID] | |
); | |
// Insert the converted rule into the database | |
$connection->insert($tableName, [ | |
'entity_id' => $entityId, | |
'attribute_id' => self::TARGET_ATTRIBUTE_ID, | |
'store_id' => self::STORE_ID, | |
'value' => $convertedValue, | |
]); | |
// Set `is_virtual_category` attribute for the entity | |
$connection->insertOnDuplicate('catalog_category_entity_int', [ | |
'entity_id' => $entityId, | |
'attribute_id' => self::IS_VIRTUAL_CATEGORY_ATTRIBUTE_ID, | |
'store_id' => self::STORE_ID, | |
'value' => '1', // Assuming '1' means it is a virtual category | |
]); | |
$output->writeln("<info>Successfully converted rule for entity ID {$entityId} and set is_virtual_category.</info>"); | |
} catch (\Exception $e) { | |
$output->writeln("<error>Failed to convert rule for entity ID {$entityId}: {$e->getMessage()}</error>"); | |
} | |
} | |
} catch (\Exception $e) { | |
throw new LocalizedException(__('Error occurred during rule conversion: %1', $e->getMessage())); | |
} | |
return Cli::RETURN_SUCCESS; | |
} | |
private function checkForComplexRules(array $ruleData): bool | |
{ | |
$combineRuleCount = 0; | |
foreach ($ruleData as $rule) { | |
if (isset($rule['type']) && $rule['type'] === 'dyncatprod/rule_condition_combine') { | |
$combineRuleCount++; | |
} | |
// If more than one is found, it is complex | |
if ($combineRuleCount > 1) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private function convertRule(array $ruleData): array | |
{ | |
$conditions = []; | |
foreach ($ruleData as $key => $rule) { | |
// Skip combined rules as they're not valid to convert | |
if (isset($rule['type']) && $rule['type'] === 'dyncatprod/rule_condition_product') { | |
$conditions[] = [ | |
'type' => 'Smile\\ElasticsuiteVirtualCategory\\Model\\Rule\\Condition\\Product', | |
'attribute' => $rule['attribute'], | |
'operator' => $this->mapOperator($rule['operator']), | |
'value' => isset($rule['value']) ? (array)$rule['value'] : [], | |
'is_value_processed' => false, | |
]; | |
} | |
} | |
return [ | |
'type' => 'Smile\\ElasticsuiteVirtualCategory\\Model\\Rule\\Condition\\Combine', | |
'attribute' => null, | |
'operator' => null, | |
'value' => '1', | |
'is_value_processed' => null, | |
'aggregator' => 'all', | |
'conditions' => $conditions, | |
]; | |
} | |
private function mapOperator(string $operator): string | |
{ | |
// Example operator mapping - adapt as needed | |
$operatorMap = [ | |
'{}' => '()', | |
'!{}' => '!()', | |
]; | |
return $operatorMap[$operator] ?? $operator; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
is not fancy, used during an m1 to m2 migration from ProxiBlue Dynamic Category products to elasticsuite Virtual category rules
Only handles not complex rules. so basically product attribute rules only. Is all I needed.