$dbConfig */ $dbConfig = require $basePath . '/config/database.php'; $dryRun = in_array('--dry-run', $argv, true); $useRemote = in_array('--use-remote', $argv, true); if ($useRemote) { $remoteHost = (string) Env::get('DB_HOST_REMOTE', ''); if ($remoteHost !== '') { $dbConfig['host'] = $remoteHost; } } $pdo = ConnectionFactory::make($dbConfig); echo 'Fix status codes script' . PHP_EOL; echo $dryRun ? '[mode] dry-run (no DB changes)' . PHP_EOL : '[mode] apply' . PHP_EOL; if ($useRemote) { echo '[db] using DB_HOST_REMOTE for this run' . PHP_EOL; } try { $resultGroups = fixGroupCodes($pdo, $dryRun); $resultStatuses = fixStatusCodes($pdo, $dryRun); echo PHP_EOL . 'Summary:' . PHP_EOL; echo ' groups updated: ' . $resultGroups['updated'] . PHP_EOL; echo ' statuses updated: ' . $resultStatuses['updated'] . PHP_EOL; echo 'Done.' . PHP_EOL; } catch (Throwable $exception) { fwrite(STDERR, '[error] ' . $exception->getMessage() . PHP_EOL); exit(1); } /** * @return array{updated:int} */ function fixGroupCodes(PDO $pdo, bool $dryRun): array { $stmt = $pdo->query('SELECT id, name, code FROM order_status_groups ORDER BY id ASC'); $rows = $stmt !== false ? $stmt->fetchAll(PDO::FETCH_ASSOC) : []; if (!is_array($rows)) { $rows = []; } $usedCodes = []; foreach ($rows as $row) { $existing = strtolower(trim((string) ($row['code'] ?? ''))); if ($existing !== '') { $usedCodes[$existing] = true; } } $updated = 0; $updateStmt = $pdo->prepare('UPDATE order_status_groups SET code = :code, updated_at = :updated_at WHERE id = :id'); foreach ($rows as $row) { $id = max(0, (int) ($row['id'] ?? 0)); if ($id <= 0) { continue; } $currentCode = strtolower(trim((string) ($row['code'] ?? ''))); $base = normalizeCodeFromName((string) ($row['name'] ?? ''), 'group_' . $id); $targetCode = ensureUniqueCode($base, $currentCode, $usedCodes); if ($targetCode === $currentCode) { continue; } echo ' [group #' . $id . '] ' . ($currentCode !== '' ? $currentCode : '(empty)') . ' -> ' . $targetCode . PHP_EOL; if (!$dryRun) { $updateStmt->execute([ 'id' => $id, 'code' => $targetCode, 'updated_at' => date('Y-m-d H:i:s'), ]); } if ($currentCode !== '') { unset($usedCodes[$currentCode]); } $usedCodes[$targetCode] = true; $updated++; } return ['updated' => $updated]; } /** * @return array{updated:int} */ function fixStatusCodes(PDO $pdo, bool $dryRun): array { $stmt = $pdo->query('SELECT id, name, code FROM order_statuses ORDER BY id ASC'); $rows = $stmt !== false ? $stmt->fetchAll(PDO::FETCH_ASSOC) : []; if (!is_array($rows)) { $rows = []; } $usedCodes = []; foreach ($rows as $row) { $existing = strtolower(trim((string) ($row['code'] ?? ''))); if ($existing !== '') { $usedCodes[$existing] = true; } } $updated = 0; $updateStmt = $pdo->prepare('UPDATE order_statuses SET code = :code, updated_at = :updated_at WHERE id = :id'); foreach ($rows as $row) { $id = max(0, (int) ($row['id'] ?? 0)); if ($id <= 0) { continue; } $currentCode = strtolower(trim((string) ($row['code'] ?? ''))); $base = normalizeCodeFromName((string) ($row['name'] ?? ''), 'status_' . $id); $targetCode = ensureUniqueCode($base, $currentCode, $usedCodes); if ($targetCode === $currentCode) { continue; } echo ' [status #' . $id . '] ' . ($currentCode !== '' ? $currentCode : '(empty)') . ' -> ' . $targetCode . PHP_EOL; if (!$dryRun) { $updateStmt->execute([ 'id' => $id, 'code' => $targetCode, 'updated_at' => date('Y-m-d H:i:s'), ]); } if ($currentCode !== '') { unset($usedCodes[$currentCode]); } $usedCodes[$targetCode] = true; $updated++; } return ['updated' => $updated]; } /** * @param array $usedCodes */ function ensureUniqueCode(string $base, string $currentCode, array $usedCodes): string { $normalizedCurrent = strtolower(trim($currentCode)); $candidate = $base; $index = 2; while ($candidate !== $normalizedCurrent && isset($usedCodes[$candidate])) { $suffix = '_' . $index; $candidate = mb_substr($base, 0, max(1, 64 - mb_strlen($suffix))) . $suffix; $index++; } return $candidate; } function normalizeCodeFromName(string $name, string $fallback): string { $value = mb_strtolower(trim($name)); if ($value === '') { $value = $fallback; } $value = strtr($value, [ mb_chr(261, 'UTF-8') => 'a', // ą mb_chr(263, 'UTF-8') => 'c', // ć mb_chr(281, 'UTF-8') => 'e', // ę mb_chr(322, 'UTF-8') => 'l', // ł mb_chr(324, 'UTF-8') => 'n', // ń mb_chr(243, 'UTF-8') => 'o', // ó mb_chr(347, 'UTF-8') => 's', // ś mb_chr(378, 'UTF-8') => 'z', // ź mb_chr(380, 'UTF-8') => 'z', // ż ]); $value = preg_replace('/[^a-z0-9_\-\.]+/u', '_', $value) ?? ''; $value = trim($value, '_'); if ($value === '') { $value = $fallback; } return mb_substr($value, 0, 64); }