113 lines
3.0 KiB
PHP
113 lines
3.0 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Modules\Core\Command;
|
||
|
|
|
||
|
|
use Illuminate\Console\Command;
|
||
|
|
use Illuminate\Support\Facades\Storage;
|
||
|
|
use Modules\Core\ResultType\Error;
|
||
|
|
use Modules\Core\ResultType\Result;
|
||
|
|
use Modules\Core\ResultType\Success;
|
||
|
|
use ZipArchive;
|
||
|
|
|
||
|
|
class ExportCommand extends Command
|
||
|
|
{
|
||
|
|
protected $signature = "boboko:export";
|
||
|
|
|
||
|
|
protected $description = "Export data and files";
|
||
|
|
|
||
|
|
public function handle(): void
|
||
|
|
{
|
||
|
|
$db = config("database.connections.pgsql");
|
||
|
|
|
||
|
|
$disk = Storage::disk("local");
|
||
|
|
$exportDir = $disk->path("exports");
|
||
|
|
if (!is_dir($exportDir)) {
|
||
|
|
mkdir($exportDir, 0755, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
$stamp = now()->format("Y_m_d_His");
|
||
|
|
$sqlFile = $exportDir . "/dump_{$stamp}.sql";
|
||
|
|
$zipFile = $exportDir . "/export_{$stamp}.zip";
|
||
|
|
$publicDisk = Storage::disk("public");
|
||
|
|
$filesDir = $publicDisk->path("");
|
||
|
|
|
||
|
|
$result = $this->dumpDatabase($db, $sqlFile)->flatMap(
|
||
|
|
fn($sql) => $this->buildZip($sql, $filesDir, $zipFile),
|
||
|
|
);
|
||
|
|
|
||
|
|
if (file_exists($sqlFile)) {
|
||
|
|
unlink($sqlFile);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($result->error()->isDefined()) {
|
||
|
|
$this->error($result->error()->get());
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->info("Exported to {$zipFile}");
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @return Result<string, string> */
|
||
|
|
private function dumpDatabase(array $db, string $sqlFile): Result
|
||
|
|
{
|
||
|
|
$command = sprintf(
|
||
|
|
"PGPASSWORD=%s pg_dump -h %s -p %s -U %s -d %s --no-owner --no-acl > %s",
|
||
|
|
$db["password"],
|
||
|
|
$db["host"],
|
||
|
|
$db["port"],
|
||
|
|
$db["username"],
|
||
|
|
$db["database"],
|
||
|
|
$sqlFile,
|
||
|
|
);
|
||
|
|
|
||
|
|
exec($command, result_code: $code);
|
||
|
|
|
||
|
|
if ($code !== 0) {
|
||
|
|
return Error::create("pg_dump failed.");
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->info("Database dumped.");
|
||
|
|
|
||
|
|
return Success::create($sqlFile);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @return Result<string, string> */
|
||
|
|
private function buildZip(
|
||
|
|
string $sqlFile,
|
||
|
|
string $filesDir,
|
||
|
|
string $zipFile,
|
||
|
|
): Result {
|
||
|
|
$zip = new ZipArchive();
|
||
|
|
if (
|
||
|
|
$zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !==
|
||
|
|
true
|
||
|
|
) {
|
||
|
|
return Error::create("Could not create zip archive.");
|
||
|
|
}
|
||
|
|
|
||
|
|
$zip->addFile($sqlFile, basename($sqlFile));
|
||
|
|
|
||
|
|
if (is_dir($filesDir)) {
|
||
|
|
$iterator = new \RecursiveIteratorIterator(
|
||
|
|
new \RecursiveDirectoryIterator(
|
||
|
|
$filesDir,
|
||
|
|
\FilesystemIterator::SKIP_DOTS,
|
||
|
|
),
|
||
|
|
);
|
||
|
|
foreach ($iterator as $file) {
|
||
|
|
$relativePath =
|
||
|
|
"files/" .
|
||
|
|
ltrim(
|
||
|
|
str_replace($filesDir, "", $file->getRealPath()),
|
||
|
|
DIRECTORY_SEPARATOR,
|
||
|
|
);
|
||
|
|
$zip->addFile($file->getRealPath(), $relativePath);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$zip->close();
|
||
|
|
|
||
|
|
return Success::create($zipFile);
|
||
|
|
}
|
||
|
|
}
|