%s', escapeshellarg(DB_HOST), escapeshellarg(DB_USER), escapeshellarg(DB_PASS), escapeshellarg(DB_NAME), escapeshellarg($filePath) ); exec($command, $output, $returnVar); if ($returnVar === 0) { // Get limit from settings $limit = 5; try { $stmt = db()->prepare("SELECT `value` FROM settings WHERE `key` = 'backup_limit'"); $stmt->execute(); $val = $stmt->fetchColumn(); if ($val) $limit = (int)$val; } catch (Exception $e) {} self::rotateBackups($limit); return ['success' => true, 'file' => $filename]; } return ['success' => false, 'error' => 'Failed to create backup.']; } public static function restoreBackup($filename) { $filePath = self::$backupDir . basename($filename); if (!file_exists($filePath)) { return ['success' => false, 'error' => 'Backup file not found.']; } $command = sprintf( 'mysql -h %s -u %s -p%s %s < %s', escapeshellarg(DB_HOST), escapeshellarg(DB_USER), escapeshellarg(DB_PASS), escapeshellarg(DB_NAME), escapeshellarg($filePath) ); exec($command, $output, $returnVar); if ($returnVar === 0) { return ['success' => true]; } return ['success' => false, 'error' => 'Failed to restore backup.']; } public static function rotateBackups($limit = 5) { $files = glob(self::$backupDir . 'backup_*.sql'); if (count($files) <= $limit) { return; } // Sort by modification time (oldest first) usort($files, function($a, $b) { return filemtime($a) - filemtime($b); }); $toDelete = count($files) - $limit; for ($i = 0; $i < $toDelete; $i++) { unlink($files[$i]); } } public static function getBackups() { if (!is_dir(self::$backupDir)) return []; $files = glob(self::$backupDir . 'backup_*.sql'); usort($files, function($a, $b) { return filemtime($b) - filemtime($a); }); $result = []; foreach ($files as $file) { $result[] = [ 'name' => basename($file), 'size' => round(filesize($file) / 1024, 2) . ' KB', 'date' => date('Y-m-d H:i:s', filemtime($file)) ]; } return $result; } }