141 lines
7.6 KiB
PHP
141 lines
7.6 KiB
PHP
<?php
|
|
$configuredRetention = AppSettings::int('backup_retention', 1, 50);
|
|
$formatSize = static function (int $bytes): string {
|
|
$decimal = I18n::locale() === 'fr' ? ',' : '.';
|
|
if ($bytes >= 1_048_576) {
|
|
return number_format($bytes / 1_048_576, 1, $decimal, ' ') . ' ' . t('unit.mb');
|
|
}
|
|
return number_format($bytes / 1024, 0, $decimal, ' ') . ' ' . t('unit.kb');
|
|
};
|
|
?>
|
|
<?php require __DIR__ . '/settings_nav.php'; ?>
|
|
<div class="mb-3">
|
|
<h2 class="mb-1"><?= h(t('backups.heading')) ?></h2>
|
|
<div class="text-muted"><?= h(t('backups.intro')) ?></div>
|
|
</div>
|
|
|
|
<?php if ($status === 'created'): ?><div class="alert alert-success">✅ <?= h(t('backups.created')) ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($status === 'deleted'): ?><div class="alert alert-success">✅ <?= h(t('backups.deleted')) ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($status === 'verified'): ?><div class="alert alert-success">✅ <?= h(t('backups.verified')) ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($status === 'schedule'): ?><div class="alert alert-success">✅ <?= h(t('backups.schedule_saved')) ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($error !== ''): ?><div class="alert alert-danger"><strong><?= h(t('backups.failed')) ?></strong>
|
|
<?= h($error) ?></div><?php endif; ?>
|
|
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-lg-7">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<h3 class="card-title"><?= h(t('backups.create')) ?></h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<p><?= h(t('backups.create_help')) ?></p>
|
|
<div class="text-muted small"><?= h(t('backups.manifest_help', ['count' => $configuredRetention])) ?>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer text-end">
|
|
<form method="post" action="/settings/backups/create"><button class="btn btn-primary">💾
|
|
<?= h(t('backups.create_now')) ?></button></form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-5">
|
|
<div class="card border-danger h-100 overflow-hidden">
|
|
<div class="card-header">
|
|
<h3 class="card-title text-danger"><?= h(t('backups.restore')) ?></h3>
|
|
</div>
|
|
<form method="post" action="/settings/backups/restore" enctype="multipart/form-data"
|
|
onsubmit="return confirm(<?= h(json_encode(t('backups.restore_confirm'), JSON_HEX_APOS | JSON_HEX_QUOT)) ?>);">
|
|
<div class="card-body">
|
|
<label class="form-label"><?= h(t('backups.archive')) ?></label>
|
|
<input class="form-control" type="file" name="backup" accept=".zip,application/zip" required>
|
|
<label class="form-check mt-3"><input class="form-check-input" type="checkbox" required><span
|
|
class="form-check-label"><?= h(t('backups.understand')) ?></span></label>
|
|
</div>
|
|
<div class="card-footer text-end"><button class="btn btn-danger">♻
|
|
<?= h(t('backups.restore_archive')) ?></button></div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mb-3">
|
|
<div class="card-header">
|
|
<h3 class="card-title">⏱ <?= h(t('backups.automatic')) ?></h3>
|
|
</div>
|
|
<form method="post" action="/settings/backups/schedule"><input type="hidden" name="csrf"
|
|
value="<?= h(Auth::csrf()) ?>">
|
|
<div class="card-body row g-3 align-items-end">
|
|
<div class="col-md"><label class="form-check"><input class="form-check-input" type="checkbox"
|
|
name="backup_schedule_enabled"
|
|
<?= AppSettings::get('backup_schedule_enabled') === '1' ? 'checked' : '' ?>><span
|
|
class="form-check-label"><?= h(t('backups.enable_schedule')) ?></span></label>
|
|
<div class="form-hint"><?= h(t('backups.schedule_help')) ?></div>
|
|
</div>
|
|
<div class="col-md-3"><label class="form-label"><?= h(t('notification.frequency')) ?></label><select
|
|
class="form-select" name="backup_schedule_frequency">
|
|
<option value="daily"
|
|
<?= AppSettings::get('backup_schedule_frequency') === 'daily' ? 'selected' : '' ?>>
|
|
<?= h(t('notification.daily')) ?></option>
|
|
<option value="weekly"
|
|
<?= AppSettings::get('backup_schedule_frequency') === 'weekly' ? 'selected' : '' ?>>
|
|
<?= h(t('notification.weekly')) ?></option>
|
|
</select></div>
|
|
<div class="col-auto"><button class="btn btn-primary"><?= h(t('common.save')) ?></button></div>
|
|
<div class="col-12 small text-muted"><code>php <?= h(dirname(__DIR__, 2) . '/scripts/maintenance.php') ?>
|
|
run</code> · <?= h(t('backups.last_verified')) ?> :
|
|
<?= h(AppSettings::get('backup_last_verified_at') ?: '—') ?></div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title"><?= h(t('backups.available')) ?></h3>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-vcenter card-table">
|
|
<thead>
|
|
<tr>
|
|
<th><?= h(t('common.date')) ?></th>
|
|
<th><?= h(t('backups.archive_column')) ?></th>
|
|
<th><?= h(t('backups.size')) ?></th>
|
|
<th class="w-1"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($backups as $backup): ?>
|
|
<tr>
|
|
<td class="text-nowrap"><?= h($backup['date']) ?></td>
|
|
<td><strong><?= h($backup['name']) ?></strong><?php if (str_contains($backup['name'], 'avant-restauration')): ?>
|
|
<span class="badge bg-orange-lt"><?= h(t('backups.emergency')) ?></span><?php endif; ?></td>
|
|
<td><?= h($formatSize((int)$backup['size'])) ?></td>
|
|
<td>
|
|
<div class="d-flex gap-1">
|
|
<form method="post" action="/settings/backups/verify"><input type="hidden" name="csrf"
|
|
value="<?= h(Auth::csrf()) ?>"><input type="hidden" name="file"
|
|
value="<?= h($backup['name']) ?>"><button class="btn btn-outline-success btn-sm">✓
|
|
<?= h(t('backups.verify')) ?></button></form><a
|
|
class="btn btn-outline-primary btn-sm text-nowrap"
|
|
href="/settings/backups/download?file=<?= rawurlencode($backup['name']) ?>">⬇
|
|
<?= h(t('backups.download')) ?></a>
|
|
<form method="post" action="/settings/backups/delete"
|
|
onsubmit="return confirm(<?= h(json_encode(t('backups.delete_confirm'), JSON_HEX_APOS | JSON_HEX_QUOT)) ?>);">
|
|
<input type="hidden" name="csrf" value="<?= h(Auth::csrf()) ?>"><input type="hidden"
|
|
name="file" value="<?= h($backup['name']) ?>"><button
|
|
class="btn btn-outline-danger btn-sm" title="<?= h(t('common.delete')) ?>"
|
|
aria-label="<?= h(t('common.delete')) ?>">🗑</button></form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (!$backups): ?><tr>
|
|
<td colspan="4" class="text-center text-muted py-4"><?= h(t('backups.none')) ?></td>
|
|
</tr><?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|