Skip to content

Instantly share code, notes, and snippets.

@vbuck
Created March 18, 2021 15:12
Show Gist options
  • Save vbuck/9defd7758d88d4197400b090a219d536 to your computer and use it in GitHub Desktop.
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
<?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