297 lines
8.3 KiB
PHP
297 lines
8.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
|
|
|
const LEGACY_CODE_ALIASES = [
|
|
'tiffany_co' => ['1'],
|
|
];
|
|
|
|
$dryRun = in_array('--dry-run', $argv, true);
|
|
$brandFile = dirname(__DIR__) . '/resources/catalog/known_brands.php';
|
|
|
|
if (!is_file($brandFile)) {
|
|
fwrite(STDERR, "Known brand file not found: {$brandFile}\n");
|
|
exit(1);
|
|
}
|
|
|
|
$brands = require $brandFile;
|
|
if (!is_array($brands)) {
|
|
fwrite(STDERR, "Known brand file must return an array.\n");
|
|
exit(1);
|
|
}
|
|
|
|
$dotenv = Dotenv\Dotenv::createImmutable(dirname(__DIR__));
|
|
$dotenv->safeLoad();
|
|
|
|
$dsn = sprintf(
|
|
'mysql:host=%s;port=%s;dbname=%s;charset=%s',
|
|
$_ENV['DB_HOST'] ?? '127.0.0.1',
|
|
$_ENV['DB_PORT'] ?? '3306',
|
|
$_ENV['DB_DATABASE'] ?? '',
|
|
$_ENV['DB_CHARSET'] ?? 'utf8mb4'
|
|
);
|
|
|
|
$pdo = new PDO(
|
|
$dsn,
|
|
$_ENV['DB_USERNAME'] ?? '',
|
|
$_ENV['DB_PASSWORD'] ?? '',
|
|
[
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
]
|
|
);
|
|
|
|
function normalize_list(mixed $value): array
|
|
{
|
|
if (!is_array($value)) {
|
|
return [];
|
|
}
|
|
|
|
$items = [];
|
|
foreach ($value as $item) {
|
|
$text = trim((string)$item);
|
|
if ($text !== '') {
|
|
$items[] = $text;
|
|
}
|
|
}
|
|
|
|
return array_values(array_unique($items));
|
|
}
|
|
|
|
function decode_json_list(mixed $value): array
|
|
{
|
|
if (is_array($value)) {
|
|
return normalize_list($value);
|
|
}
|
|
if (!is_string($value) || trim($value) === '') {
|
|
return [];
|
|
}
|
|
|
|
$decoded = json_decode($value, true);
|
|
return normalize_list(is_array($decoded) ? $decoded : []);
|
|
}
|
|
|
|
function stable_json_list(array $value): string
|
|
{
|
|
$items = normalize_list($value);
|
|
sort($items, SORT_STRING);
|
|
return json_encode($items, JSON_UNESCAPED_UNICODE);
|
|
}
|
|
|
|
function load_enabled_categories(PDO $pdo): array
|
|
{
|
|
$rows = $pdo->query(
|
|
"SELECT id, name, code, supported_service_types
|
|
FROM catalog_categories
|
|
WHERE is_enabled = 1
|
|
ORDER BY sort_order ASC, id ASC"
|
|
)->fetchAll();
|
|
|
|
$byCode = [];
|
|
$byName = [];
|
|
$byId = [];
|
|
foreach ($rows as $row) {
|
|
$category = [
|
|
'id' => (int)$row['id'],
|
|
'name' => (string)$row['name'],
|
|
'code' => (string)$row['code'],
|
|
'supported_service_types' => decode_json_list($row['supported_service_types'] ?? null),
|
|
];
|
|
$byId[$category['id']] = $category;
|
|
$byCode[strtolower($category['code'])] = $category;
|
|
$byName[$category['name']] = $category;
|
|
}
|
|
|
|
return [$byCode, $byName, $byId];
|
|
}
|
|
|
|
function match_categories(array $brand, array $categoriesByCode, array $categoriesByName): array
|
|
{
|
|
$matched = [];
|
|
|
|
foreach (normalize_list($brand['category_codes'] ?? []) as $code) {
|
|
$key = strtolower($code);
|
|
if (isset($categoriesByCode[$key])) {
|
|
$matched[$categoriesByCode[$key]['id']] = $categoriesByCode[$key];
|
|
}
|
|
}
|
|
|
|
foreach (normalize_list($brand['category_names'] ?? []) as $name) {
|
|
if (isset($categoriesByName[$name])) {
|
|
$matched[$categoriesByName[$name]['id']] = $categoriesByName[$name];
|
|
}
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
function infer_supported_service_types(array $categories): array
|
|
{
|
|
$serviceTypes = [];
|
|
foreach ($categories as $category) {
|
|
foreach ($category['supported_service_types'] as $serviceType) {
|
|
$serviceTypes[$serviceType] = $serviceType;
|
|
}
|
|
}
|
|
|
|
if (!$serviceTypes) {
|
|
$serviceTypes['anxinyan'] = 'anxinyan';
|
|
}
|
|
|
|
return array_values($serviceTypes);
|
|
}
|
|
|
|
function find_existing_brand(PDO $pdo, string $code): ?array
|
|
{
|
|
$stmt = $pdo->prepare('SELECT * FROM catalog_brands WHERE code = ? LIMIT 1');
|
|
$stmt->execute([$code]);
|
|
$row = $stmt->fetch();
|
|
if ($row) {
|
|
return $row;
|
|
}
|
|
|
|
foreach (LEGACY_CODE_ALIASES[$code] ?? [] as $legacyCode) {
|
|
$stmt->execute([$legacyCode]);
|
|
$legacy = $stmt->fetch();
|
|
if ($legacy) {
|
|
return $legacy;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function existing_relation_ids(PDO $pdo, int $brandId): array
|
|
{
|
|
$stmt = $pdo->prepare('SELECT category_id FROM catalog_brand_categories WHERE brand_id = ?');
|
|
$stmt->execute([$brandId]);
|
|
|
|
$ids = [];
|
|
foreach ($stmt->fetchAll() as $row) {
|
|
$ids[(int)$row['category_id']] = true;
|
|
}
|
|
|
|
return $ids;
|
|
}
|
|
|
|
[$categoriesByCode, $categoriesByName, $categoriesById] = load_enabled_categories($pdo);
|
|
|
|
$stats = [
|
|
'brands_total' => count($brands),
|
|
'inserted' => 0,
|
|
'updated' => 0,
|
|
'enabled_existing' => 0,
|
|
'legacy_code_repaired' => 0,
|
|
'relations_inserted' => 0,
|
|
'skipped_no_enabled_category' => 0,
|
|
'skipped_invalid' => 0,
|
|
];
|
|
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
$insertBrand = $pdo->prepare(
|
|
'INSERT INTO catalog_brands (name, en_name, code, logo, sort_order, is_enabled, supported_service_types, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?)'
|
|
);
|
|
$updateBrand = $pdo->prepare(
|
|
'UPDATE catalog_brands
|
|
SET name = ?, en_name = ?, code = ?, sort_order = ?, is_enabled = 1, supported_service_types = ?, updated_at = ?
|
|
WHERE id = ?'
|
|
);
|
|
$insertRelation = $pdo->prepare(
|
|
'INSERT INTO catalog_brand_categories (brand_id, category_id, created_at)
|
|
VALUES (?, ?, ?)'
|
|
);
|
|
|
|
if (!$dryRun) {
|
|
$pdo->beginTransaction();
|
|
}
|
|
|
|
try {
|
|
foreach ($brands as $brand) {
|
|
$code = trim((string)($brand['code'] ?? ''));
|
|
$name = trim((string)($brand['name'] ?? ''));
|
|
$enName = trim((string)($brand['en_name'] ?? ''));
|
|
if ($code === '' || $name === '' || $enName === '') {
|
|
$stats['skipped_invalid']++;
|
|
continue;
|
|
}
|
|
|
|
$matchedCategories = match_categories($brand, $categoriesByCode, $categoriesByName);
|
|
if (!$matchedCategories) {
|
|
$stats['skipped_no_enabled_category']++;
|
|
continue;
|
|
}
|
|
|
|
$serviceTypes = infer_supported_service_types($matchedCategories);
|
|
$serviceTypesJson = stable_json_list($serviceTypes);
|
|
$sortOrder = (int)($brand['sort_order'] ?? 0);
|
|
$existing = find_existing_brand($pdo, $code);
|
|
|
|
if ($existing) {
|
|
$brandId = (int)$existing['id'];
|
|
$wasDisabled = (int)$existing['is_enabled'] !== 1;
|
|
$wasLegacyCode = (string)$existing['code'] !== $code;
|
|
|
|
$existingJson = stable_json_list(decode_json_list($existing['supported_service_types'] ?? null));
|
|
$needsUpdate = $wasDisabled
|
|
|| $wasLegacyCode
|
|
|| (string)$existing['name'] !== $name
|
|
|| (string)$existing['en_name'] !== $enName
|
|
|| (int)$existing['sort_order'] !== $sortOrder
|
|
|| $existingJson !== $serviceTypesJson;
|
|
|
|
if ($needsUpdate) {
|
|
$stats['updated']++;
|
|
if ($wasDisabled) {
|
|
$stats['enabled_existing']++;
|
|
}
|
|
if ($wasLegacyCode) {
|
|
$stats['legacy_code_repaired']++;
|
|
}
|
|
if (!$dryRun) {
|
|
$updateBrand->execute([$name, $enName, $code, $sortOrder, $serviceTypesJson, $now, $brandId]);
|
|
}
|
|
}
|
|
} else {
|
|
$stats['inserted']++;
|
|
if ($dryRun) {
|
|
$brandId = 0;
|
|
} else {
|
|
$insertBrand->execute([$name, $enName, $code, '', $sortOrder, $serviceTypesJson, $now, $now]);
|
|
$brandId = (int)$pdo->lastInsertId();
|
|
}
|
|
}
|
|
|
|
$existingCategoryIds = $brandId > 0 ? existing_relation_ids($pdo, $brandId) : [];
|
|
foreach (array_keys($matchedCategories) as $categoryId) {
|
|
if (isset($existingCategoryIds[(int)$categoryId])) {
|
|
continue;
|
|
}
|
|
$stats['relations_inserted']++;
|
|
if (!$dryRun && $brandId > 0) {
|
|
$insertRelation->execute([$brandId, (int)$categoryId, $now]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$dryRun) {
|
|
$pdo->commit();
|
|
}
|
|
} catch (Throwable $e) {
|
|
if (!$dryRun && $pdo->inTransaction()) {
|
|
$pdo->rollBack();
|
|
}
|
|
fwrite(STDERR, "IMPORT_KNOWN_BRANDS_FAILED\n");
|
|
fwrite(STDERR, $e->getMessage() . PHP_EOL);
|
|
exit(1);
|
|
}
|
|
|
|
echo $dryRun ? "DRY_RUN\n" : "IMPORT_KNOWN_BRANDS_OK\n";
|
|
echo "ENABLED_CATEGORIES=" . count($categoriesById) . PHP_EOL;
|
|
foreach ($stats as $key => $value) {
|
|
echo strtoupper($key) . '=' . $value . PHP_EOL;
|
|
}
|