37684-vm/db/backup_helper.php
2026-03-01 01:15:48 +00:00

82 lines
2.4 KiB
PHP

<?php
/**
* Database Backup Helper
*
* Provides functionality to back up the current database to the /backups directory.
*/
function backup_db() {
// Determine path to backups directory (relative to db/config.php's folder)
$backups_dir = realpath(__DIR__ . '/../backups');
// Ensure the backups directory exists
if (!$backups_dir) {
$backups_dir = __DIR__ . '/../backups';
if (!is_dir($backups_dir)) {
if (!mkdir($backups_dir, 0775, true)) {
throw new Exception("Could not create backups directory: $backups_dir");
}
}
$backups_dir = realpath($backups_dir);
}
// Load DB config if not already loaded (might be called from various places)
require_once __DIR__ . '/config.php';
$timestamp = date('Y-m-d_H-i-s');
$filename = "backup_{$timestamp}.sql";
$filepath = "{$backups_dir}/{$filename}";
// Use mysqldump to create the backup
$command = sprintf(
'mysqldump --host=%s --user=%s --password=%s %s > %s 2>&1',
escapeshellarg(DB_HOST),
escapeshellarg(DB_USER),
escapeshellarg(DB_PASS),
escapeshellarg(DB_NAME),
escapeshellarg($filepath)
);
$output = [];
$return_var = null;
exec($command, $output, $return_var);
if ($return_var !== 0) {
$error_msg = implode("\n", $output);
throw new Exception("Database backup failed with exit code {$return_var}: " . $error_msg);
}
// Automatic cleanup: keep only the last 5 backups
cleanup_backups($backups_dir, 5);
return [
'filename' => $filename,
'filepath' => $filepath,
'size' => filesize($filepath)
];
}
/**
* Cleanup old backups, keeping only the most recent $keep_count files.
*
* @param string $backups_dir Path to backups directory
* @param int $keep_count Number of backups to retain
*/
function cleanup_backups($backups_dir, $keep_count = 5) {
$files = glob("{$backups_dir}/backup_*.sql");
// Sort by modification time (newest first)
usort($files, function($a, $b) {
return filemtime($b) - filemtime($a);
});
// Remove files beyond the keep count
if (count($files) > $keep_count) {
$files_to_remove = array_slice($files, $keep_count);
foreach ($files_to_remove as $file) {
if (is_file($file)) {
unlink($file);
}
}
}
}