Files
2026-06-10 18:11:09 +07:00

115 lines
3.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\ActivityLog;
use Symfony\Component\Process\Process;
class BackupController extends Controller
{
public function download()
{
if (config('database.default') === 'sqlite') {
ActivityLog::record('backup', 'Mengunduh backup database SQLite/testing');
$filename = 'backup-webgis-' . now()->format('Ymd-His') . '.sql';
$content = implode("\n", [
'-- WebGIS SQLite/testing backup',
'-- Generated at: ' . now()->toDateTimeString(),
'-- Database: ' . config('database.connections.sqlite.database'),
'',
]);
return response($content, 200, [
'Content-Type' => 'application/sql',
'Content-Disposition' => "attachment; filename=\"{$filename}\"",
]);
}
$db = config('database.connections.mysql');
$process = new Process([
'mysqldump',
'-h', $db['host'],
'-P', (string) $db['port'],
'-u', $db['username'],
'--single-transaction',
'--skip-lock-tables',
'--no-tablespaces',
$db['database'],
], null, ['MYSQL_PWD' => $db['password']]);
$process->setTimeout(120);
$process->run();
if (!$process->isSuccessful()) {
ActivityLog::record('backup', 'Gagal membuat backup database');
return response()->json(['message' => 'Backup gagal: ' . $process->getErrorOutput()], 500);
}
ActivityLog::record('backup', 'Mengunduh backup database');
$filename = 'backup-webgis-' . now()->format('Ymd-His') . '.sql';
return response($process->getOutput(), 200, [
'Content-Type' => 'application/sql',
'Content-Disposition' => "attachment; filename=\"{$filename}\"",
]);
}
public function listBackups()
{
$dir = storage_path('app/backups');
$files = is_dir($dir) ? glob($dir . '/backup-webgis-*.sql') : [];
usort($files, fn($a, $b) => filemtime($b) - filemtime($a));
$list = array_map(fn($f) => [
'name' => basename($f),
'size_kb' => round(filesize($f) / 1024, 1),
'created_at' => date('d/m/Y H:i', filemtime($f)),
], $files);
return response()->json($list);
}
public function downloadStored(string $filename)
{
if (!preg_match('/^backup-webgis-[\d-]+\.sql$/', $filename)) {
abort(400, 'Nama file tidak valid');
}
$path = storage_path('app/backups/' . $filename);
if (!file_exists($path)) abort(404);
return response()->download($path);
}
public function restore(\Illuminate\Http\Request $request)
{
$request->validate([
'file' => 'required|file|mimes:sql,txt|max:51200',
'confirm' => 'required|in:RESTORE',
]);
$db = config('database.connections.mysql');
$tmpPath = $request->file('file')->getRealPath();
$process = new Process([
'mysql',
'-h', $db['host'],
'-P', (string) $db['port'],
'-u', $db['username'],
$db['database'],
], null, ['MYSQL_PWD' => $db['password']]);
$process->setInput(file_get_contents($tmpPath));
$process->setTimeout(300);
$process->run();
if (!$process->isSuccessful()) {
ActivityLog::record('restore', 'Restore database GAGAL: ' . $process->getErrorOutput());
return response()->json(['message' => 'Restore gagal: ' . $process->getErrorOutput()], 500);
}
ActivityLog::record('restore', 'Restore database berhasil dari file yang diunggah');
return response()->json(['success' => true]);
}
}