'
. htmlspecialchars((string)($translations['backup_access_denied'] ?? 'Accès refusé.'), ENT_QUOTES, 'UTF-8')
. '
';
return;
}
if (!isset($pdo)) { $db=realpath(__DIR__.'/../../includes/db.php'); if($db) require_once $db; }
if (!isset($pdo) || !($pdo instanceof PDO)) {
echo ''
. htmlspecialchars((string)($translations['backup_db_unavailable'] ?? 'DB indisponible.'), ENT_QUOTES, 'UTF-8')
. '
';
return;
}
try{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);}catch(Throwable){}
require_once __DIR__.'/_lib_audit.php';
// reauth (10 min)
$mustReauth=function(int $ttl=600){$t=(int)($_SESSION['admin_reauth_at']??0);return ($t===0||(time()-$t)>$ttl);};
if ($mustReauth()){ $qs=http_build_query(['page'=>'reauth','redir'=>($_SERVER['REQUEST_URI']??'index.php?page=maintenance')]); header('Location:?'.$qs); exit; }
$e=static fn($s)=>htmlspecialchars((string)$s,ENT_QUOTES,'UTF-8');
if (empty($_SESSION['csrf_token'])) $_SESSION['csrf_token']=bin2hex(random_bytes(32));
$CSRF=$_SESSION['csrf_token'];
$siteRoot=realpath(__DIR__.'/../../');
$backupDir=$siteRoot.'/backups/db';
@is_dir($backupDir) || @mkdir($backupDir,0755,true);
$msg=null; $ok=null;
// Params
$retentionDays = max(0,(int)($_POST['retention'] ?? ($_GET['retention'] ?? 30)));
$useGzip = true;
if ($_SERVER['REQUEST_METHOD']==='POST') {
if (!hash_equals($CSRF, $_POST['csrf'] ?? '')) {
$msg = (string)($translations['backup_csrf_invalid'] ?? 'CSRF invalide.');
}
else {
$act = $_POST['action'] ?? '';
if ($act==='create') {
// Dump via PDO (fallback si mysqldump non dispo)
$dbName = $pdo->query("SELECT DATABASE()")->fetchColumn();
$fname = 'db_'.$dbName.'_'.date('Ymd_His').'.sql';
$tmp = $backupDir.'/'.$fname;
// --- export ---
$fh = @fopen($tmp,'wb');
if(!$fh){
$tpl = (string)($translations['backup_cannot_write_dir'] ?? "Impossible d'écrire dans {DIR}");
$msg = str_replace('{DIR}', (string)$backupDir, $tpl);
}
else {
fwrite($fh, "-- Backup of `$dbName` on ".date('c')."\nSET FOREIGN_KEY_CHECKS=0;\n");
// tables
$tables = $pdo->query("SHOW FULL TABLES WHERE Table_Type='BASE TABLE'")->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $t) {
// DDL
$row = $pdo->query("SHOW CREATE TABLE `$t`")->fetch(PDO::FETCH_ASSOC);
fwrite($fh, "\n-- Structure `$t`\nDROP TABLE IF EXISTS `$t`;\n".$row['Create Table'].";\n");
// DML
$st = $pdo->query("SELECT * FROM `$t`", PDO::FETCH_ASSOC);
$cols = array_map(fn($c)=>'`'.$c.'`', array_keys($st->fetch() ?: []));
if ($cols) {
// Refaire la requête pour ne pas “perdre” la première ligne
$st = $pdo->query("SELECT * FROM `$t`", PDO::FETCH_ASSOC);
$colList = implode(',', $cols);
$placeholders = '(' . implode(',', array_fill(0, count($cols), '?')) . ')';
$batch=[]; $n=0;
foreach($st as $row){
$vals = array_values($row);
$vals = array_map(function($v) use($pdo){ return isset($v)?$pdo->quote((string)$v):"NULL"; }, $vals);
$batch[] = '('.implode(',', $vals).')';
if (++$n % 200 === 0) { fwrite($fh, "INSERT INTO `$t` ($colList) VALUES\n".implode(",\n",$batch).";\n"); $batch=[]; }
}
if ($batch){ fwrite($fh, "INSERT INTO `$t` ($colList) VALUES\n".implode(",\n",$batch).";\n"); }
}
}
fwrite($fh, "SET FOREIGN_KEY_CHECKS=1;\n");
fclose($fh);
// gzip
if ($useGzip) {
$gz = $tmp.'.gz';
$gzh = gzopen($gz,'wb9');
$src = fopen($tmp,'rb');
while(!feof($src)){ gzwrite($gzh, fread($src, 1<<20)); }
fclose($src); gzclose($gzh);
@unlink($tmp);
$final=$gz;
} else { $final=$tmp; }
$tpl = (string)($translations['backup_created_ok'] ?? 'Sauvegarde créée : {FILE}');
$ok = str_replace('{FILE}', basename($final), $tpl);
AdminAudit::log($pdo, [
'admin_id'=>(int)($_SESSION['user_id']??0),
'action'=>'backup_create',
'scope'=>'maintenance',
'meta'=>['file'=>basename($final),'dir'=>'backups/db']
]);
}
}
elseif ($act==='prune') {
$cut = time()-($retentionDays*86400);
$n=0; foreach (glob($backupDir.'/db_*.sql*') as $f){ if(filemtime($f)<$cut){ @unlink($f); $n++; } }
$tpl = (string)($translations['backup_retention_applied'] ?? 'Rétention appliquée : {N} fichier(s) supprimé(s) (> {D} j)');
$ok = str_replace(['{N}','{D}'], [(string)$n, (string)$retentionDays], $tpl);
AdminAudit::log($pdo, [
'admin_id'=>(int)($_SESSION['user_id']??0),
'action'=>'backup_prune',
'scope'=>'maintenance',
'meta'=>['retention_days'=>$retentionDays]
]);
}
}
}
// Liste
$files = array_map('basename', glob($backupDir.'/db_*.sql*') ?: []);
usort($files, fn($a,$b)=>strcmp($b,$a)); // plus récent d'abord
?>
= $e($translations['backup_title'] ?? 'Sauvegardes de la base') ?>
= $e($ok) ?>
= $e($msg) ?>
| = $e($translations['backup_th_file'] ?? 'Fichier') ?> |
= $e($translations['backup_th_size'] ?? 'Taille') ?> |
= $e($translations['backup_th_date'] ?? 'Date') ?> |
|
= $e($f) ?> |
= number_format((filesize($full)?:0)/1024,1) ?> KB |
= date('Y-m-d H:i:s', filemtime($full)?:time()) ?> |
= $e($translations['backup_btn_download'] ?? 'Télécharger') ?>
|
| = $e($translations['backup_none_yet'] ?? 'Aucun backup encore.') ?> |