Created
March 18, 2021 15:12
-
-
Save vbuck/9defd7758d88d4197400b090a219d536 to your computer and use it in GitHub Desktop.
Calculate the diff between 2 Magento core_config_data tables and generate as SQL
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 MagentoTools; | |
class Generator | |
{ | |
private $config = [ | |
'type' => CsvSnapshotConfig::class, | |
'left' => null, | |
'right' => null, | |
]; | |
public function configureFromEnv() | |
{ | |
if (!empty(\getenv('LEFT_PATH'))) { | |
if (empty(\getenv('RIGHT_PATH'))) { | |
throw new \Exception('Cannot specify LEFT_PATH without RIGHT_PATH'); | |
} | |
$this->config['type'] = CsvSnapshotConfig::class; | |
$this->config['left'] = new CsvSnapshotConfig(\getenv('LEFT_PATH')); | |
$this->config['right'] = new CsvSnapshotConfig(\getenv('RIGHT_PATH')); | |
} else { | |
echo 'No config specified.' . PHP_EOL; | |
$this->help(); | |
exit(1); | |
} | |
} | |
public function help() | |
{ | |
echo PHP_EOL; | |
echo 'Magento Config Table Diff Generator'; | |
echo PHP_EOL; | |
echo 'Compare 2 sets of config data and generate SQL to preserve the diff from original (left).' . PHP_EOL; | |
echo 'Syntax:' . PHP_EOL; | |
echo 'LEFT_PATH="/path/to/table.csv" RIGHT_PATH="/path/to/table.csv" ' . \basename(__FILE__) . ' > diff.sql' . PHP_EOL; | |
echo PHP_EOL; | |
} | |
public function run() | |
{ | |
if ($this->config['type'] === CsvSnapshotConfig::class) { | |
$this->compareCsv(); | |
} else { | |
throw new \Exception(\sprintf('Invalid config type: %s', $this->config['type'])); | |
} | |
} | |
private function compareCsv() | |
{ | |
/** @var CsvSnapshotConfig $left */ | |
$left = $this->config['left']; | |
$leftResource = \fopen($left->path, 'r'); | |
$rows = []; | |
while ($row = \fgetcsv($leftResource)) { | |
$rows[] = $row; | |
} | |
$header = \array_shift($rows); | |
$leftData = []; | |
foreach ($rows as $row) { | |
if (empty($row)) { | |
continue; | |
} | |
$row = \array_filter( | |
\array_combine($header, $row), | |
function ($key) use ($left) { | |
return \in_array($key, $left->map); | |
}, | |
ARRAY_FILTER_USE_KEY | |
); | |
$key = \implode(';', \array_diff_key($row, ['value' => true])); | |
$leftData[$key] = $row['value']; | |
} | |
/** @var CsvSnapshotConfig $right */ | |
$right = $this->config['right']; | |
$rightResource = \fopen($right->path, 'r'); | |
$rows = []; | |
while ($row = \fgetcsv($rightResource)) { | |
$rows[] = $row; | |
} | |
$header = \array_shift($rows); | |
$rightData = []; | |
foreach ($rows as $row) { | |
if (empty($row)) { | |
continue; | |
} | |
$row = \array_filter( | |
\array_combine($header, $row), | |
function ($key) use ($right) { | |
return \in_array($key, $right->map); | |
}, | |
ARRAY_FILTER_USE_KEY | |
); | |
$key = \implode(';', \array_diff_key($row, ['value' => true])); | |
$rightData[$key] = $row['value']; | |
} | |
$this->generateResult(\array_diff_assoc($leftData, $rightData), $left->map); | |
} | |
private function generateResult(array $result = [], array $map = []) | |
{ | |
$template = 'INSERT INTO core_config_data (%s) VALUES (%s) ON DUPLICATE KEY UPDATE value = %s;'; | |
foreach ($result as $key => $value) { | |
$conditions = \array_combine(\array_diff($map, ['value']), \explode(';', $key)); | |
$sql = \sprintf( | |
$template, | |
\implode(', ', $map), | |
\implode( | |
', ', | |
\array_map( | |
function ($data) { | |
return '"' . \addslashes($data) . '"'; | |
}, | |
\array_merge($conditions, ['value' => $value]) | |
) | |
), | |
'"' . \addslashes($value) . '"' | |
); | |
echo $sql . PHP_EOL; | |
} | |
} | |
} | |
class CsvSnapshotConfig | |
{ | |
/** @var array */ | |
public $map; | |
/** @var string */ | |
public $path; | |
private $defaultMap = [ | |
'scope', | |
'scope_id', | |
'path', | |
'value' | |
]; | |
public function __construct( | |
string $path, | |
array $map = [] | |
) | |
{ | |
if (!\is_readable($path)) { | |
throw new \InvalidArgumentException(\sprintf('File "%s" does not exist.', $path)); | |
} | |
$this->path = $path; | |
if (empty($map)) { | |
$map = $this->defaultMap; | |
} | |
$this->map = $map; | |
} | |
} | |
$app = new Generator(); | |
$app->configureFromEnv(); | |
$app->run(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment