Add UPC, SKU, and manufacturer index builder
This commit is contained in:
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated exports
|
||||
/exports/*
|
||||
!/exports/.gitkeep
|
||||
|
||||
# Generated indexes
|
||||
/indexes/*
|
||||
!/indexes/.gitkeep
|
||||
!/indexes/upc-index.json
|
||||
!/indexes/sku-index.json
|
||||
!/indexes/manufacturer-index.json
|
||||
|
||||
# Local and temporary files
|
||||
*.tmp
|
||||
*.bak
|
||||
*.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.vscode/
|
||||
.idea/
|
||||
1
indexes/manufacturer-index.json
Normal file
1
indexes/manufacturer-index.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
indexes/sku-index.json
Normal file
1
indexes/sku-index.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
indexes/upc-index.json
Normal file
1
indexes/upc-index.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
140
tools/build-indexes.php
Normal file
140
tools/build-indexes.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$root = dirname(__DIR__);
|
||||
$catalogDir = $root . '/catalog';
|
||||
$indexesDir = $root . '/indexes';
|
||||
|
||||
$upcIndex = [];
|
||||
$skuIndex = [];
|
||||
$manufacturerIndex = [];
|
||||
$errors = [];
|
||||
$checked = 0;
|
||||
|
||||
if (!is_dir($catalogDir)) {
|
||||
fwrite(STDERR, "Catalog directory not found: {$catalogDir}\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!is_dir($indexesDir) && !mkdir($indexesDir, 0775, true) && !is_dir($indexesDir)) {
|
||||
fwrite(STDERR, "Unable to create indexes directory: {$indexesDir}\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$catalogDir,
|
||||
FilesystemIterator::SKIP_DOTS
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if (!$file->isFile() || strtolower($file->getExtension()) !== 'json') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$checked++;
|
||||
$path = $file->getPathname();
|
||||
$relativePath = substr($path, strlen($root) + 1);
|
||||
|
||||
$raw = file_get_contents($path);
|
||||
|
||||
if ($raw === false) {
|
||||
$errors[] = "{$relativePath}: unable to read file";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$record = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $exception) {
|
||||
$errors[] = "{$relativePath}: invalid JSON: {$exception->getMessage()}";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_array($record)) {
|
||||
$errors[] = "{$relativePath}: root value must be an object";
|
||||
continue;
|
||||
}
|
||||
|
||||
$upc = $record['upc'] ?? null;
|
||||
$sku = $record['sku'] ?? null;
|
||||
$manufacturer = $record['manufacturer'] ?? null;
|
||||
|
||||
if (is_string($upc) && $upc !== '') {
|
||||
if (isset($upcIndex[$upc])) {
|
||||
$errors[] = "{$relativePath}: duplicate UPC {$upc}, already used by {$upcIndex[$upc]}";
|
||||
} else {
|
||||
$upcIndex[$upc] = $relativePath;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
is_string($manufacturer) &&
|
||||
trim($manufacturer) !== ''
|
||||
) {
|
||||
$manufacturerKey = strtolower(trim($manufacturer));
|
||||
|
||||
if (!isset($manufacturerIndex[$manufacturerKey])) {
|
||||
$manufacturerIndex[$manufacturerKey] = [];
|
||||
}
|
||||
|
||||
$manufacturerIndex[$manufacturerKey][] = $relativePath;
|
||||
|
||||
if (is_string($sku) && trim($sku) !== '') {
|
||||
$skuKey = $manufacturerKey . ':' . strtolower(trim($sku));
|
||||
|
||||
if (isset($skuIndex[$skuKey])) {
|
||||
$errors[] = "{$relativePath}: duplicate SKU key {$skuKey}, already used by {$skuIndex[$skuKey]}";
|
||||
} else {
|
||||
$skuIndex[$skuKey] = $relativePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors !== []) {
|
||||
fwrite(STDERR, "Index build failed:\n\n");
|
||||
|
||||
foreach ($errors as $error) {
|
||||
fwrite(STDERR, " - {$error}\n");
|
||||
}
|
||||
|
||||
fwrite(STDERR, "\nChecked {$checked} product file(s).\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ksort($upcIndex, SORT_STRING);
|
||||
ksort($skuIndex, SORT_STRING);
|
||||
ksort($manufacturerIndex, SORT_STRING);
|
||||
|
||||
foreach ($manufacturerIndex as &$paths) {
|
||||
sort($paths, SORT_STRING);
|
||||
}
|
||||
unset($paths);
|
||||
|
||||
$files = [
|
||||
$indexesDir . '/upc-index.json' => $upcIndex,
|
||||
$indexesDir . '/sku-index.json' => $skuIndex,
|
||||
$indexesDir . '/manufacturer-index.json' => $manufacturerIndex,
|
||||
];
|
||||
|
||||
foreach ($files as $outputPath => $data) {
|
||||
$json = json_encode(
|
||||
$data,
|
||||
JSON_PRETTY_PRINT |
|
||||
JSON_UNESCAPED_SLASHES |
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
if (file_put_contents($outputPath, $json . PHP_EOL) === false) {
|
||||
fwrite(STDERR, "Unable to write {$outputPath}\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
echo "Index build complete.\n";
|
||||
echo "Products checked: {$checked}\n";
|
||||
echo "UPC entries: " . count($upcIndex) . "\n";
|
||||
echo "SKU entries: " . count($skuIndex) . "\n";
|
||||
echo "Manufacturers: " . count($manufacturerIndex) . "\n";
|
||||
Reference in New Issue
Block a user