156 lines
4.2 KiB
PHP
156 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace Lucent\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use ZipArchive;
|
|
|
|
class Import extends Command
|
|
{
|
|
protected $signature = "lucent:import";
|
|
|
|
protected $description = "Import data and files from an export archive";
|
|
|
|
public function handle(): void
|
|
{
|
|
$exportDir = storage_path("exports");
|
|
|
|
if (!is_dir($exportDir)) {
|
|
$this->error("No exports directory found at {$exportDir}");
|
|
return;
|
|
}
|
|
|
|
$zips = glob($exportDir . "/export_*.zip");
|
|
|
|
if (empty($zips)) {
|
|
$this->error("No export archives found in {$exportDir}");
|
|
return;
|
|
}
|
|
|
|
rsort($zips);
|
|
$choices = array_map(fn($p) => basename($p), $zips);
|
|
|
|
$chosen = $this->choice("Select an export to import", $choices, 0);
|
|
$zipFile = $exportDir . "/" . $chosen;
|
|
|
|
$this->warn("This will REPLACE all records, revisions, edges, files data and uploaded files.");
|
|
|
|
if (!$this->confirm("Import {$chosen}?", false)) {
|
|
$this->info("Aborted.");
|
|
return;
|
|
}
|
|
|
|
// Extract to temp directory
|
|
$tempDir = storage_path("exports/.import_tmp_" . uniqid());
|
|
mkdir($tempDir, 0755, true);
|
|
|
|
$zip = new ZipArchive();
|
|
if ($zip->open($zipFile) !== true) {
|
|
$this->error("Could not open zip archive.");
|
|
$this->cleanup($tempDir);
|
|
return;
|
|
}
|
|
|
|
$zip->extractTo($tempDir);
|
|
$zip->close();
|
|
|
|
// Restore database
|
|
$sqlFiles = glob($tempDir . "/*.sql");
|
|
if (empty($sqlFiles)) {
|
|
$this->error("No SQL dump found inside the archive.");
|
|
$this->cleanup($tempDir);
|
|
return;
|
|
}
|
|
|
|
$db = config("database.connections.pgsql");
|
|
$tables = [
|
|
"lucent_records",
|
|
"lucent_revisions",
|
|
"lucent_files",
|
|
"lucent_edges",
|
|
];
|
|
|
|
// Truncate existing tables before restore
|
|
$truncate = collect($tables)
|
|
->map(fn($t) => "TRUNCATE TABLE {$t} CASCADE;")
|
|
->join(" ");
|
|
|
|
$truncateCmd = sprintf(
|
|
"PGPASSWORD=%s psql -h %s -p %s -U %s -d %s -c \"%s\"",
|
|
$db["password"],
|
|
$db["host"],
|
|
$db["port"],
|
|
$db["username"],
|
|
$db["database"],
|
|
$truncate,
|
|
);
|
|
|
|
exec($truncateCmd, result_code: $truncateCode);
|
|
|
|
if ($truncateCode !== 0) {
|
|
$this->error("Failed to truncate existing tables.");
|
|
$this->cleanup($tempDir);
|
|
return;
|
|
}
|
|
|
|
$restoreCmd = sprintf(
|
|
"PGPASSWORD=%s psql -h %s -p %s -U %s -d %s -f %s",
|
|
$db["password"],
|
|
$db["host"],
|
|
$db["port"],
|
|
$db["username"],
|
|
$db["database"],
|
|
$sqlFiles[0],
|
|
);
|
|
|
|
exec($restoreCmd, result_code: $restoreCode);
|
|
|
|
if ($restoreCode !== 0) {
|
|
$this->error("Database restore failed.");
|
|
$this->cleanup($tempDir);
|
|
return;
|
|
}
|
|
|
|
$this->info("Database restored.");
|
|
|
|
// Replace files
|
|
$srcFilesDir = $tempDir . "/files";
|
|
|
|
if (is_dir($srcFilesDir)) {
|
|
$disk = Storage::disk(config("lucent.disk"));
|
|
$destFilesDir = $disk->path("files");
|
|
|
|
// Remove existing files directory
|
|
if (is_dir($destFilesDir)) {
|
|
exec("rm -rf " . escapeshellarg($destFilesDir));
|
|
}
|
|
|
|
exec(
|
|
sprintf("cp -R %s %s", escapeshellarg($srcFilesDir), escapeshellarg($destFilesDir)),
|
|
result_code: $copyCode,
|
|
);
|
|
|
|
if ($copyCode !== 0) {
|
|
$this->error("Failed to restore files.");
|
|
$this->cleanup($tempDir);
|
|
return;
|
|
}
|
|
|
|
$this->info("Files restored.");
|
|
} else {
|
|
$this->warn("No files directory found in archive — skipping file restore.");
|
|
}
|
|
|
|
$this->cleanup($tempDir);
|
|
$this->info("Import complete.");
|
|
}
|
|
|
|
private function cleanup(string $dir): void
|
|
{
|
|
if (is_dir($dir)) {
|
|
exec("rm -rf " . escapeshellarg($dir));
|
|
}
|
|
}
|
|
}
|