kundenkarte/admin/backup.php
data b0dc03bebe Fix undefined property enable_autocomplete warning
Add isset() check for enable_autocomplete property to handle
cases where database migration has not been applied yet.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-20 12:11:57 +01:00

364 lines
11 KiB
PHP
Executable file

<?php
/* Copyright (C) 2026 Alles Watt lauft
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/
/**
* \file kundenkarte/admin/backup.php
* \ingroup kundenkarte
* \brief Backup and restore page for KundenKarte data
*/
// Load Dolibarr environment
$res = 0;
if (!$res && file_exists("../../main.inc.php")) {
$res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
$res = @include "../../../main.inc.php";
}
if (!$res) {
die("Include of main fails");
}
// Libraries
require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
require_once DOL_DOCUMENT_ROOT."/core/class/html.form.class.php";
require_once '../lib/kundenkarte.lib.php';
dol_include_once('/kundenkarte/class/anlagebackup.class.php');
// Translations
$langs->loadLangs(array("admin", "kundenkarte@kundenkarte"));
// Access control
if (!$user->admin && !$user->hasRight('kundenkarte', 'admin')) {
accessforbidden();
}
// Parameters
$action = GETPOST('action', 'aZ09');
$confirm = GETPOST('confirm', 'alpha');
$form = new Form($db);
$backup = new AnlageBackup($db);
/*
* Actions
*/
// Create backup
if ($action == 'create_backup') {
$includeFiles = GETPOSTINT('include_files');
$result = $backup->createBackup($includeFiles);
if ($result) {
setEventMessages($langs->trans('BackupCreatedSuccess', basename($result)), null, 'mesgs');
} else {
setEventMessages($langs->trans('BackupCreatedError').': '.$backup->error, null, 'errors');
}
header('Location: '.$_SERVER['PHP_SELF']);
exit;
}
// Download backup
if ($action == 'download') {
$filename = GETPOST('file', 'alpha');
$filepath = $conf->kundenkarte->dir_output.'/backups/'.basename($filename);
if (file_exists($filepath) && strpos($filename, 'kundenkarte_backup_') === 0) {
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Content-Length: '.filesize($filepath));
readfile($filepath);
exit;
} else {
setEventMessages($langs->trans('FileNotFound'), null, 'errors');
}
}
// Delete backup
if ($action == 'confirm_delete' && $confirm == 'yes') {
$filename = GETPOST('file', 'alpha');
if ($backup->deleteBackup($filename)) {
setEventMessages($langs->trans('BackupDeleted'), null, 'mesgs');
} else {
setEventMessages($langs->trans('Error'), null, 'errors');
}
header('Location: '.$_SERVER['PHP_SELF']);
exit;
}
// Restore backup
if ($action == 'confirm_restore' && $confirm == 'yes') {
$filename = GETPOST('file', 'alpha');
$clearExisting = GETPOSTINT('clear_existing');
$filepath = $conf->kundenkarte->dir_output.'/backups/'.basename($filename);
if ($backup->restoreBackup($filepath, $clearExisting)) {
setEventMessages($langs->trans('RestoreSuccess'), null, 'mesgs');
} else {
setEventMessages($langs->trans('RestoreError').': '.$backup->error, null, 'errors');
}
header('Location: '.$_SERVER['PHP_SELF']);
exit;
}
// Upload backup
if ($action == 'upload_backup' && !empty($_FILES['backupfile']['name'])) {
$backupDir = $conf->kundenkarte->dir_output.'/backups';
if (!is_dir($backupDir)) {
dol_mkdir($backupDir);
}
$filename = $_FILES['backupfile']['name'];
// Validate filename format
if (!preg_match('/^kundenkarte_backup_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.zip$/', $filename)) {
setEventMessages($langs->trans('InvalidBackupFile'), null, 'errors');
} elseif ($_FILES['backupfile']['error'] !== UPLOAD_ERR_OK) {
setEventMessages($langs->trans('ErrorUploadFailed'), null, 'errors');
} else {
$targetPath = $backupDir.'/'.$filename;
if (move_uploaded_file($_FILES['backupfile']['tmp_name'], $targetPath)) {
setEventMessages($langs->trans('BackupUploaded'), null, 'mesgs');
} else {
setEventMessages($langs->trans('ErrorUploadFailed'), null, 'errors');
}
}
header('Location: '.$_SERVER['PHP_SELF']);
exit;
}
/*
* View
*/
$title = $langs->trans("BackupRestore");
llxHeader('', $title);
// Subheader
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
print load_fiche_titre($title, $linkback, 'title_setup');
// Configuration header
$head = kundenkarteAdminPrepareHead();
print dol_get_fiche_head($head, 'backup', $langs->trans('ModuleKundenKarteName'), -1, "fa-address-card");
// Confirmation dialogs
if ($action == 'delete') {
$filename = GETPOST('file', 'alpha');
print $form->formconfirm(
$_SERVER['PHP_SELF'].'?file='.urlencode($filename),
$langs->trans('DeleteBackup'),
$langs->trans('ConfirmDeleteBackup', $filename),
'confirm_delete',
'',
'yes',
1
);
}
if ($action == 'restore') {
$filename = GETPOST('file', 'alpha');
$formquestion = array(
array(
'type' => 'checkbox',
'name' => 'clear_existing',
'label' => $langs->trans('ClearExistingData'),
'value' => 0
)
);
print $form->formconfirm(
$_SERVER['PHP_SELF'].'?file='.urlencode($filename),
$langs->trans('RestoreBackup'),
$langs->trans('ConfirmRestoreBackup', $filename),
'confirm_restore',
$formquestion,
'yes',
1
);
}
// Statistics
$stats = $backup->getStatistics();
print '<div class="fichecenter">';
// Stats cards
print '<div style="display:flex;gap:20px;flex-wrap:wrap;margin-bottom:30px;">';
print '<div class="info-box" style="min-width:200px;">';
print '<span class="info-box-icon bg-primary"><i class="fa fa-sitemap"></i></span>';
print '<div class="info-box-content">';
print '<span class="info-box-text">'.$langs->trans('TotalElements').'</span>';
print '<span class="info-box-number">'.$stats['total_anlagen'].'</span>';
print '</div>';
print '</div>';
print '<div class="info-box" style="min-width:200px;">';
print '<span class="info-box-icon bg-success"><i class="fa fa-file"></i></span>';
print '<div class="info-box-content">';
print '<span class="info-box-text">'.$langs->trans('TotalFiles').'</span>';
print '<span class="info-box-number">'.$stats['total_files'].'</span>';
print '</div>';
print '</div>';
print '<div class="info-box" style="min-width:200px;">';
print '<span class="info-box-icon bg-warning"><i class="fa fa-plug"></i></span>';
print '<div class="info-box-content">';
print '<span class="info-box-text">'.$langs->trans('TotalConnections').'</span>';
print '<span class="info-box-number">'.$stats['total_connections'].'</span>';
print '</div>';
print '</div>';
print '<div class="info-box" style="min-width:200px;">';
print '<span class="info-box-icon bg-info"><i class="fa fa-building"></i></span>';
print '<div class="info-box-content">';
print '<span class="info-box-text">'.$langs->trans('CustomersWithAnlagen').'</span>';
print '<span class="info-box-number">'.$stats['total_customers'].'</span>';
print '</div>';
print '</div>';
print '<div class="info-box" style="min-width:200px;">';
print '<span class="info-box-icon bg-secondary"><i class="fa fa-hdd-o"></i></span>';
print '<div class="info-box-content">';
print '<span class="info-box-text">'.$langs->trans('FilesStorageSize').'</span>';
print '<span class="info-box-number">'.dol_print_size($stats['files_size']).'</span>';
print '</div>';
print '</div>';
print '</div>';
// Create Backup Section
print '<div class="titre inline-block">'.$langs->trans("CreateBackup").'</div>';
print '<br><br>';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="create_backup">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans("BackupOptions").'</td>';
print '</tr>';
print '<tr class="oddeven">';
print '<td style="width:300px;">'.$langs->trans("IncludeUploadedFiles").'</td>';
print '<td>';
print '<input type="checkbox" name="include_files" value="1" checked> ';
print '<span class="opacitymedium">'.$langs->trans("IncludeFilesHelp").'</span>';
print '</td>';
print '</tr>';
print '</table>';
print '<br>';
print '<div class="center">';
print '<button type="submit" class="button button-primary">';
print '<i class="fa fa-download"></i> '.$langs->trans("CreateBackupNow");
print '</button>';
print '</div>';
print '</form>';
// Upload Backup Section
print '<br><br>';
print '<div class="titre inline-block">'.$langs->trans("UploadBackup").'</div>';
print '<br><br>';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="upload_backup">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans("UploadBackupFile").'</td>';
print '</tr>';
print '<tr class="oddeven">';
print '<td style="width:300px;">'.$langs->trans("SelectBackupFile").'</td>';
print '<td>';
print '<input type="file" name="backupfile" accept=".zip" class="flat">';
print ' <button type="submit" class="button buttongen smallpaddingimp">'.$langs->trans("Upload").'</button>';
print '</td>';
print '</tr>';
print '</table>';
print '</form>';
// Existing Backups Section
print '<br><br>';
print '<div class="titre inline-block">'.$langs->trans("ExistingBackups").'</div>';
print '<br><br>';
$backups = $backup->getBackupList();
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Filename").'</td>';
print '<td>'.$langs->trans("Date").'</td>';
print '<td class="right">'.$langs->trans("Size").'</td>';
print '<td class="center">'.$langs->trans("Actions").'</td>';
print '</tr>';
if (empty($backups)) {
print '<tr class="oddeven">';
print '<td colspan="4" class="opacitymedium center">'.$langs->trans("NoBackupsFound").'</td>';
print '</tr>';
} else {
foreach ($backups as $bk) {
print '<tr class="oddeven">';
print '<td><i class="fa fa-file-archive-o"></i> '.dol_escape_htmltag($bk['filename']).'</td>';
print '<td>'.dol_print_date(strtotime($bk['date']), 'dayhour').'</td>';
print '<td class="right">'.dol_print_size($bk['size']).'</td>';
print '<td class="center nowraponall">';
// Download button
print '<a href="'.$_SERVER['PHP_SELF'].'?action=download&file='.urlencode($bk['filename']).'&token='.newToken().'" class="button buttongen smallpaddingimp" title="'.$langs->trans('Download').'">';
print '<i class="fa fa-download"></i>';
print '</a> ';
// Restore button
print '<a href="'.$_SERVER['PHP_SELF'].'?action=restore&file='.urlencode($bk['filename']).'&token='.newToken().'" class="button buttongen smallpaddingimp" title="'.$langs->trans('Restore').'">';
print '<i class="fa fa-undo"></i>';
print '</a> ';
// Delete button
print '<a href="'.$_SERVER['PHP_SELF'].'?action=delete&file='.urlencode($bk['filename']).'&token='.newToken().'" class="button buttongen smallpaddingimp" title="'.$langs->trans('Delete').'">';
print '<i class="fa fa-trash"></i>';
print '</a>';
print '</td>';
print '</tr>';
}
}
print '</table>';
// Info section
print '<br>';
print '<div class="info">';
print '<strong><i class="fa fa-info-circle"></i> '.$langs->trans("BackupInfo").':</strong><br>';
print '&bull; '.$langs->trans("BackupInfoContent").'<br>';
print '&bull; '.$langs->trans("BackupInfoFiles").'<br>';
print '&bull; '.$langs->trans("BackupInfoRestore").'<br>';
print '</div>';
print '</div>';
print dol_get_fiche_end();
llxFooter();
$db->close();