epcqr/admin/setup.php
2026-01-29 20:37:59 +01:00

503 lines
19 KiB
PHP
Executable file

<?php
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 Eduard Wisch <data@data-it-solution.de>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file epcqr/admin/setup.php
* \ingroup epcqr
* \brief EPCQR Modul Einstellungen
*/
// Load Dolibarr environment
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
$tmp2 = realpath(__FILE__);
$i = strlen($tmp) - 1;
$j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
$i--;
$j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
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/epcqr.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
// Translations
$langs->loadLangs(array("admin", "epcqr@epcqr"));
// Access control
if (!$user->admin) {
accessforbidden();
}
// Parameters
$action = GETPOST('action', 'aZ09');
$error = 0;
/*
* Actions
*/
if ($action == 'update') {
$bankDataSource = GETPOST('EPCQR_BANK_DATA_SOURCE', 'alpha');
$accountHolder = GETPOST('EPCQR_ACCOUNT_HOLDER', 'alphanohtml');
$iban = GETPOST('EPCQR_IBAN', 'alphanohtml');
$bic = GETPOST('EPCQR_BIC', 'alphanohtml');
$imageRatio = GETPOST('EPCQR_IMAGE_RATIO', 'alphanohtml');
// Validate IBAN format (basic check)
if ($bankDataSource == 'manual' && !empty($iban)) {
$iban = str_replace(' ', '', strtoupper($iban));
if (!preg_match('/^[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}$/', $iban)) {
setEventMessages($langs->trans("InvalidIBAN"), null, 'errors');
$error++;
}
}
// Validate BIC format (basic check)
if ($bankDataSource == 'manual' && !empty($bic)) {
$bic = str_replace(' ', '', strtoupper($bic));
if (!preg_match('/^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$/', $bic)) {
setEventMessages($langs->trans("InvalidBIC"), null, 'errors');
$error++;
}
}
// Validate image ratio
if (!empty($imageRatio)) {
$imageRatio = str_replace(',', '.', $imageRatio);
if (!is_numeric($imageRatio) || (float)$imageRatio <= 0 || (float)$imageRatio > 2) {
setEventMessages($langs->trans("InvalidImageRatio"), null, 'errors');
$error++;
}
}
// Extra field visibility settings
$hideQrcode = GETPOST('EPCQR_HIDE_QRCODE', 'int') ? 1 : 0;
$hideQrcodepfad = GETPOST('EPCQR_HIDE_QRCODEPFAD', 'int') ? 1 : 0;
$hideQrcodepath = GETPOST('EPCQR_HIDE_QRCODEPATH', 'int') ? 1 : 0;
// QR Code styling settings
$fgColorPost = GETPOST('EPCQR_FG_COLOR', 'alphanohtml');
$bgTransparent = GETPOST('EPCQR_BG_TRANSPARENT', 'int') ? 1 : 0;
$bgColorPost = $bgTransparent ? 'transparent' : GETPOST('EPCQR_BG_COLOR', 'alphanohtml');
$logoPathPost = GETPOST('EPCQR_LOGO_PATH', 'alphanohtml');
$logoSizePost = GETPOST('EPCQR_LOGO_SIZE', 'int');
// Validate colors (hex format)
if (!preg_match('/^#[0-9A-Fa-f]{6}$/', $fgColorPost)) {
$fgColorPost = '#000000';
}
if (!$bgTransparent && !preg_match('/^#[0-9A-Fa-f]{6}$/', $bgColorPost)) {
$bgColorPost = '#FFFFFF';
}
// Validate logo size
if ($logoSizePost < 5) $logoSizePost = 5;
if ($logoSizePost > 30) $logoSizePost = 30;
// Module style
$moduleStylePost = GETPOST('EPCQR_MODULE_STYLE', 'alpha');
if (!in_array($moduleStylePost, array('square', 'rounded', 'dots', 'diamond'))) {
$moduleStylePost = 'square';
}
// Border style
$borderStylePost = GETPOST('EPCQR_BORDER_STYLE', 'alpha');
if (!in_array($borderStylePost, array('none', 'simple', 'rounded', 'double', 'dashed'))) {
$borderStylePost = 'none';
}
if (!$error) {
dolibarr_set_const($db, 'EPCQR_BANK_DATA_SOURCE', $bankDataSource, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_ACCOUNT_HOLDER', $accountHolder, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_IBAN', $iban, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_BIC', $bic, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_IMAGE_RATIO', $imageRatio, 'chaine', 0, '', $conf->entity);
// Save visibility settings
dolibarr_set_const($db, 'EPCQR_HIDE_QRCODE', $hideQrcode, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_HIDE_QRCODEPFAD', $hideQrcodepfad, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_HIDE_QRCODEPATH', $hideQrcodepath, 'chaine', 0, '', $conf->entity);
// Save styling settings
dolibarr_set_const($db, 'EPCQR_FG_COLOR', $fgColorPost, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_BG_COLOR', $bgColorPost, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_LOGO_PATH', $logoPathPost, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_LOGO_SIZE', $logoSizePost, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_MODULE_STYLE', $moduleStylePost, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'EPCQR_BORDER_STYLE', $borderStylePost, 'chaine', 0, '', $conf->entity);
// Update extrafield visibility in database
$extrafieldsToUpdate = array(
'qrcode' => $hideQrcode,
'qrcodepfad' => $hideQrcodepfad,
'qrcodepath' => $hideQrcodepath
);
foreach ($extrafieldsToUpdate as $fieldname => $hidden) {
// enabled = '0' means hidden, '1' means visible
$enabled = $hidden ? '0' : '1';
$sql = "UPDATE ".MAIN_DB_PREFIX."extrafields SET enabled = '".$db->escape($enabled)."'";
$sql .= " WHERE name = '".$db->escape($fieldname)."' AND elementtype = 'facture'";
$db->query($sql);
}
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
}
}
// Clear cache action
if ($action == 'clearcache') {
require_once __DIR__.'/../lib/qrcode.class.php';
$qrGen = new QRCodeGenerator($db);
$deleted = $qrGen->clearCache();
setEventMessages($langs->trans("CacheCleared", $deleted), null, 'mesgs');
}
/*
* View
*/
$form = new Form($db);
$title = "EpcqrSetup";
llxHeader('', $langs->trans($title), '', '', 0, 0, '', '', '', 'mod-epcqr page-admin');
// Subheader
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
print load_fiche_titre($langs->trans($title), $linkback, 'title_setup');
// Configuration header
$head = epcqrAdminPrepareHead();
print dol_get_fiche_head($head, 'settings', $langs->trans($title), -1, "epcqr@epcqr");
// Current values
$bankDataSource = getDolGlobalString('EPCQR_BANK_DATA_SOURCE', 'manual');
$accountHolder = getDolGlobalString('EPCQR_ACCOUNT_HOLDER', '');
$iban = getDolGlobalString('EPCQR_IBAN', '');
$bic = getDolGlobalString('EPCQR_BIC', '');
$imageRatio = getDolGlobalString('EPCQR_IMAGE_RATIO', '0.3');
// Extra field visibility settings
$hideQrcode = getDolGlobalInt('EPCQR_HIDE_QRCODE', 0);
$hideQrcodepfad = getDolGlobalInt('EPCQR_HIDE_QRCODEPFAD', 0);
$hideQrcodepath = getDolGlobalInt('EPCQR_HIDE_QRCODEPATH', 0);
// QR Code styling settings
$fgColor = getDolGlobalString('EPCQR_FG_COLOR', '#000000');
$bgColor = getDolGlobalString('EPCQR_BG_COLOR', '#FFFFFF');
$logoPath = getDolGlobalString('EPCQR_LOGO_PATH', '');
$logoSize = getDolGlobalInt('EPCQR_LOGO_SIZE', 20);
$moduleStyle = getDolGlobalString('EPCQR_MODULE_STYLE', 'square');
$borderStyle = getDolGlobalString('EPCQR_BORDER_STYLE', 'none');
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="update">';
// Bank Data Section
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans("BankDataSettings").'</td>';
print '</tr>';
// Bank Data Source Selection
print '<tr class="oddeven">';
print '<td width="30%">'.$langs->trans("BankDataSource").'</td>';
print '<td>';
print '<select name="EPCQR_BANK_DATA_SOURCE" id="bankDataSource" class="flat minwidth200">';
print '<option value="system"'.($bankDataSource == 'system' ? ' selected' : '').'>'.$langs->trans("UseSystemBankAccount").'</option>';
print '<option value="manual"'.($bankDataSource == 'manual' ? ' selected' : '').'>'.$langs->trans("ManualEntry").'</option>';
print '</select>';
print '</td>';
print '</tr>';
// Manual Bank Data Fields
print '<tr class="oddeven manual-fields">';
print '<td>'.$langs->trans("AccountHolder").'</td>';
print '<td>';
print '<input type="text" name="EPCQR_ACCOUNT_HOLDER" class="flat minwidth300" value="'.dol_escape_htmltag($accountHolder).'" placeholder="'.$langs->trans("AccountHolderPlaceholder").'">';
print '</td>';
print '</tr>';
print '<tr class="oddeven manual-fields">';
print '<td>'.$langs->trans("IBAN").'</td>';
print '<td>';
print '<input type="text" name="EPCQR_IBAN" class="flat minwidth300" value="'.dol_escape_htmltag($iban).'" placeholder="DE89 3704 0044 0532 0130 00">';
print '</td>';
print '</tr>';
print '<tr class="oddeven manual-fields">';
print '<td>'.$langs->trans("BIC").'</td>';
print '<td>';
print '<input type="text" name="EPCQR_BIC" class="flat minwidth200" value="'.dol_escape_htmltag($bic).'" placeholder="COBADEFFXXX">';
print '</td>';
print '</tr>';
print '</table>';
// QR Code Settings Section
print '<br>';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans("QRCodeSettings").'</td>';
print '</tr>';
// Image Ratio
print '<tr class="oddeven">';
print '<td width="30%">'.$langs->trans("QRCodeSize").'</td>';
print '<td>';
print '<input type="text" name="EPCQR_IMAGE_RATIO" class="flat width75" value="'.dol_escape_htmltag($imageRatio).'">';
print ' <span class="opacitymedium">'.$langs->trans("QRCodeSizeHelp").'</span>';
print '</td>';
print '</tr>';
// Foreground Color
print '<tr class="oddeven">';
print '<td>'.$langs->trans("QRCodeFgColor").'</td>';
print '<td>';
print '<input type="color" name="EPCQR_FG_COLOR" value="'.dol_escape_htmltag($fgColor).'" style="width: 60px; height: 30px; padding: 0; border: 1px solid #ccc;">';
print ' <input type="text" name="EPCQR_FG_COLOR_TEXT" class="flat width100" value="'.dol_escape_htmltag($fgColor).'" onchange="document.getElementsByName(\'EPCQR_FG_COLOR\')[0].value=this.value">';
print ' <span class="opacitymedium">'.$langs->trans("QRCodeFgColorHelp").'</span>';
print '</td>';
print '</tr>';
// Background Color
print '<tr class="oddeven">';
print '<td>'.$langs->trans("QRCodeBgColor").'</td>';
print '<td>';
$isTransparent = (strtolower($bgColor) === 'transparent' || $bgColor === '');
print '<input type="checkbox" name="EPCQR_BG_TRANSPARENT" id="bgTransparent" value="1"'.($isTransparent ? ' checked' : '').' onchange="toggleBgColor(this.checked)">';
print ' <label for="bgTransparent">'.$langs->trans("Transparent").'</label>';
print ' &nbsp; ';
print '<input type="color" name="EPCQR_BG_COLOR" id="bgColorPicker" value="'.dol_escape_htmltag($isTransparent ? '#FFFFFF' : $bgColor).'" style="width: 60px; height: 30px; padding: 0; border: 1px solid #ccc;"'.($isTransparent ? ' disabled' : '').'>';
print ' <input type="text" name="EPCQR_BG_COLOR_TEXT" id="bgColorText" class="flat width100" value="'.dol_escape_htmltag($isTransparent ? '' : $bgColor).'"'.($isTransparent ? ' disabled' : '').' onchange="document.getElementById(\'bgColorPicker\').value=this.value">';
print ' <span class="opacitymedium">'.$langs->trans("QRCodeBgColorHelp").'</span>';
print '</td>';
print '</tr>';
print '<script>
function toggleBgColor(isTransparent) {
document.getElementById("bgColorPicker").disabled = isTransparent;
document.getElementById("bgColorText").disabled = isTransparent;
if (isTransparent) {
document.getElementById("bgColorText").value = "";
}
}
</script>';
// Logo Path
print '<tr class="oddeven">';
print '<td>'.$langs->trans("QRCodeLogo").'</td>';
print '<td>';
print '<input type="text" name="EPCQR_LOGO_PATH" class="flat minwidth400" value="'.dol_escape_htmltag($logoPath).'" placeholder="/var/www/dolibarr/documents/mycompany/logos/logo.png">';
print '<br><span class="opacitymedium">'.$langs->trans("QRCodeLogoHelp").'</span>';
if (!empty($logoPath)) {
if (file_exists($logoPath)) {
print '<br><span style="color: green;">✓ '.$langs->trans("FileExists").'</span>';
} else {
print '<br><span style="color: red;">✗ '.$langs->trans("FileNotFound").'</span>';
}
}
print '</td>';
print '</tr>';
// Logo Size
print '<tr class="oddeven">';
print '<td>'.$langs->trans("QRCodeLogoSize").'</td>';
print '<td>';
print '<input type="number" name="EPCQR_LOGO_SIZE" class="flat width75" value="'.dol_escape_htmltag($logoSize).'" min="5" max="30">';
print ' % <span class="opacitymedium">'.$langs->trans("QRCodeLogoSizeHelp").'</span>';
print '</td>';
print '</tr>';
// Module Style
print '<tr class="oddeven">';
print '<td>'.$langs->trans("QRCodeModuleStyle").'</td>';
print '<td>';
print '<select name="EPCQR_MODULE_STYLE" class="flat minwidth150">';
print '<option value="square"'.($moduleStyle == 'square' ? ' selected' : '').'>'.$langs->trans("StyleSquare").'</option>';
print '<option value="rounded"'.($moduleStyle == 'rounded' ? ' selected' : '').'>'.$langs->trans("StyleRounded").'</option>';
print '<option value="dots"'.($moduleStyle == 'dots' ? ' selected' : '').'>'.$langs->trans("StyleDots").'</option>';
print '<option value="diamond"'.($moduleStyle == 'diamond' ? ' selected' : '').'>'.$langs->trans("StyleDiamond").'</option>';
print '</select>';
print ' <span class="opacitymedium">'.$langs->trans("QRCodeModuleStyleHelp").'</span>';
print '</td>';
print '</tr>';
// Border Style
print '<tr class="oddeven">';
print '<td>'.$langs->trans("QRCodeBorderStyle").'</td>';
print '<td>';
print '<select name="EPCQR_BORDER_STYLE" class="flat minwidth150">';
print '<option value="none"'.($borderStyle == 'none' ? ' selected' : '').'>'.$langs->trans("BorderNone").'</option>';
print '<option value="simple"'.($borderStyle == 'simple' ? ' selected' : '').'>'.$langs->trans("BorderSimple").'</option>';
print '<option value="rounded"'.($borderStyle == 'rounded' ? ' selected' : '').'>'.$langs->trans("BorderRounded").'</option>';
print '<option value="double"'.($borderStyle == 'double' ? ' selected' : '').'>'.$langs->trans("BorderDouble").'</option>';
print '<option value="dashed"'.($borderStyle == 'dashed' ? ' selected' : '').'>'.$langs->trans("BorderDashed").'</option>';
print '</select>';
print ' <span class="opacitymedium">'.$langs->trans("QRCodeBorderStyleHelp").'</span>';
print '</td>';
print '</tr>';
print '</table>';
// Clear Cache Button
print '<br>';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans("QRCodeCache").'</td>';
print '</tr>';
print '<tr class="oddeven">';
print '<td width="30%">'.$langs->trans("ClearQRCodeCache").'</td>';
print '<td>';
print '<a class="button" href="'.$_SERVER["PHP_SELF"].'?action=clearcache&token='.newToken().'">'.$langs->trans("ClearCache").'</a>';
print ' <span class="opacitymedium">'.$langs->trans("ClearCacheHelp").'</span>';
print '</td>';
print '</tr>';
print '</table>';
// Extra Field Visibility Section
print '<br>';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans("ExtraFieldVisibility").'</td>';
print '</tr>';
// Hide QR Code field (HTML with image)
print '<tr class="oddeven">';
print '<td width="30%">'.$langs->trans("HideQRCodeField").'</td>';
print '<td>';
print '<input type="checkbox" name="EPCQR_HIDE_QRCODE" value="1"'.($hideQrcode ? ' checked' : '').'>';
print ' <span class="opacitymedium">'.$langs->trans("HideQRCodeFieldHelp").'</span>';
print '</td>';
print '</tr>';
// Hide QR Code URL field
print '<tr class="oddeven">';
print '<td>'.$langs->trans("HideQRCodePfadField").'</td>';
print '<td>';
print '<input type="checkbox" name="EPCQR_HIDE_QRCODEPFAD" value="1"'.($hideQrcodepfad ? ' checked' : '').'>';
print ' <span class="opacitymedium">'.$langs->trans("HideQRCodePfadFieldHelp").'</span>';
print '</td>';
print '</tr>';
// Hide QR Code Path field (local file path)
print '<tr class="oddeven">';
print '<td>'.$langs->trans("HideQRCodePathField").'</td>';
print '<td>';
print '<input type="checkbox" name="EPCQR_HIDE_QRCODEPATH" value="1"'.($hideQrcodepath ? ' checked' : '').'>';
print ' <span class="opacitymedium">'.$langs->trans("HideQRCodePathFieldHelp").'</span>';
print '</td>';
print '</tr>';
print '</table>';
// Submit button
print '<br>';
print '<div class="center">';
print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
print '</div>';
print '</form>';
// JavaScript to show/hide manual fields based on selection
print '<script type="text/javascript">
$(document).ready(function() {
function toggleManualFields() {
var source = $("#bankDataSource").val();
if (source == "manual") {
$(".manual-fields").show();
} else {
$(".manual-fields").hide();
}
}
toggleManualFields();
$("#bankDataSource").on("change", function() {
toggleManualFields();
});
});
</script>';
// Info box about system bank account
if ($bankDataSource == 'system') {
print '<br>';
print '<div class="info">';
print $langs->trans("SystemBankAccountInfo");
// Try to show configured bank accounts
require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
$bankAccount = new Account($db);
$sql = "SELECT rowid, label, iban_prefix, bic FROM ".MAIN_DB_PREFIX."bank_account WHERE entity = ".((int) $conf->entity)." AND clos = 0";
$resql = $db->query($sql);
if ($resql && $db->num_rows($resql) > 0) {
print '<br><br><strong>'.$langs->trans("AvailableBankAccounts").':</strong><ul>';
while ($obj = $db->fetch_object($resql)) {
print '<li>'.$obj->label;
if (!empty($obj->iban_prefix)) {
print ' - IBAN: '.substr($obj->iban_prefix, 0, 4).'****'.substr($obj->iban_prefix, -4);
}
print '</li>';
}
print '</ul>';
} else {
print '<br><br><span class="warning">'.$langs->trans("NoBankAccountConfigured").'</span>';
}
print '</div>';
}
// Page end
print dol_get_fiche_end();
llxFooter();
$db->close();