Files
ms1inscription-v5/php/doc_edition.php
stephan c7482016ce Implement superadmin login redirection and session handling improvements
This commit introduces a new function, `fxSuperadmRedirectToLoginIfNeeded`, to streamline the login redirection process for superadmin users. It enhances session management by checking for user authentication and allowing legacy account access under specific conditions. Additionally, the login flow is updated to ensure users are redirected appropriately after login, improving the overall security and user experience in the superadmin interface. These changes aim to enhance maintainability and clarity in session handling across various superadmin pages.
2026-07-07 14:15:48 -04:00

467 lines
17 KiB
PHP

<?php
/**
* Éditeur documentation MS1 (pop-up) — module doc_page FR/EN, toutes les pages d'un module.
*/
require_once('inc_start_time.php');
require_once('inc_fonctions.php');
require_once('inc_fx_messages.php');
if (empty($_SESSION['usa_id'])) {
fxAdminRequireSuperadmLogin();
}
if (!fxAdminCanUseTextEditTools()) {
header('HTTP/1.1 403 Forbidden');
echo 'Accès refusé.';
exit;
}
function docEdEsc($str) {
return htmlspecialchars((string)$str, ENT_QUOTES, 'UTF-8');
}
function docEdFieldAttrs($strChamp, $strRowKey, $strLang) {
$id = 'doc_' . preg_replace('/[^a-z0-9_]/i', '_', $strRowKey) . '_' . $strLang . '_' . $strChamp;
return 'id="' . docEdEsc($id) . '" name="pages[' . docEdEsc($strRowKey) . '][' . docEdEsc($strLang) . '][' . docEdEsc($strChamp) . ']"';
}
function docEdLoadModulePages($modClef, $prg) {
global $objDatabase;
$sql = "SELECT *
FROM doc_page
WHERE doc_mod_clef = '" . $objDatabase->fxEscape($modClef) . "'
AND doc_prg IN ('" . $objDatabase->fxEscape($prg) . "', 'global')
ORDER BY doc_tri, doc_page_clef, doc_langue DESC";
$rows = $objDatabase->fxGetResults($sql);
$grouped = array();
if (!is_array($rows)) {
return $grouped;
}
for ($i = 1; $i <= count($rows); $i++) {
$row = $rows[$i];
$pageClef = $row['doc_page_clef'] ?? '';
if ($pageClef === '') {
continue;
}
if (!isset($grouped[$pageClef])) {
$grouped[$pageClef] = array(
'doc_page_clef' => $pageClef,
'doc_tri' => (int)($row['doc_tri'] ?? 0),
'fr' => null,
'en' => null,
);
}
$lang = $row['doc_langue'] ?? 'fr';
if ($lang === 'fr' || $lang === 'en') {
$grouped[$pageClef][$lang] = $row;
}
}
uasort($grouped, function ($a, $b) {
if ($a['doc_tri'] === $b['doc_tri']) {
return strcmp($a['doc_page_clef'], $b['doc_page_clef']);
}
return $a['doc_tri'] <=> $b['doc_tri'];
});
return $grouped;
}
$anchor = trim($_GET['anchor'] ?? $_POST['anchor'] ?? '');
$modClef = trim($_GET['mod'] ?? $_POST['mod'] ?? '');
$prg = trim($_GET['prg'] ?? $_POST['prg'] ?? 'compte.php');
$page = trim($_GET['page'] ?? $_POST['page'] ?? '');
$bd = trim(strtolower($_GET['bd'] ?? $_POST['bd'] ?? 'client'));
$blnSaved = false;
if ($modClef === '' && $anchor !== '') {
$modClef = fxDocResolveModClef($anchor, 0);
}
if ($anchor === '' && $modClef !== '') {
$anchor = $modClef;
}
if (isset($_POST['btn_mod']) && !empty($_POST['pages']) && is_array($_POST['pages'])) {
foreach ($_POST['pages'] as $pageClef => $langs) {
if (!is_array($langs)) {
continue;
}
foreach ($langs as $lang => $tabPosted) {
if (!is_array($tabPosted) || empty($tabPosted['doc_langue'])) {
continue;
}
$tabPosted['doc_page_clef'] = $pageClef;
$tabPosted['doc_mod_clef'] = $modClef;
$tabPosted['doc_prg'] = $prg;
if (!empty($tabPosted['pk_doc_page'])) {
fxSetDocPage('mod', $tabPosted, $tabPosted['pk_doc_page']);
} else {
fxSetDocPage('add', $tabPosted);
}
}
}
if (!empty($_POST['doc_mod']) && is_array($_POST['doc_mod']) && !empty($_POST['doc_mod']['pk_doc_mod'])) {
fxSetDocMod('mod', $_POST['doc_mod'], $_POST['doc_mod']['pk_doc_mod']);
}
$blnSaved = true;
}
$sqlMod = "SELECT * FROM doc_mod
WHERE doc_mod_clef = '" . $objDatabase->fxEscape($modClef) . "'
AND doc_mod_prg IN ('" . $objDatabase->fxEscape($prg) . "', 'global')
ORDER BY FIELD(doc_mod_prg, '" . $objDatabase->fxEscape($prg) . "', 'global')
LIMIT 1";
$tabMod = $objDatabase->fxGetRow($sqlMod);
$tabPages = docEdLoadModulePages($modClef, $prg);
$tabLangMeta = array(
'fr' => 'Français',
'en' => 'English',
);
?><!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Documentation — <?php echo docEdEsc($modClef); ?></title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
font-size: 14px;
line-height: 1.45;
color: #212529;
background: #f1f3f5;
}
.doced-page {
max-width: 1080px;
margin: 0 auto;
padding: 20px 16px 32px;
}
.doced-card {
background: #fff;
border: 1px solid #dee2e6;
border-radius: 8px;
overflow: hidden;
}
.doced-card-header {
padding: 14px 18px;
background: #2f5fd0;
color: #fff;
}
.doced-card-header h1 {
margin: 0 0 4px;
font-size: 18px;
font-weight: 700;
}
.doced-card-header .doced-key {
font-size: 12px;
opacity: .9;
word-break: break-all;
}
.doced-meta {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
padding: 12px 18px;
background: #f8f9fa;
border-bottom: 1px solid #e9ecef;
}
.doced-meta dt {
margin: 0;
font-size: 11px;
text-transform: uppercase;
letter-spacing: .04em;
color: #6c757d;
}
.doced-meta dd {
margin: 2px 0 0;
font-weight: 600;
word-break: break-all;
}
.doced-alert {
margin: 14px 18px 0;
padding: 10px 12px;
border-radius: 6px;
background: #d1e7dd;
color: #0f5132;
border: 1px solid #badbcc;
}
.doced-mod-field {
padding: 14px 18px;
border-bottom: 1px solid #e9ecef;
}
.doced-mod-field label {
display: block;
margin-bottom: 4px;
font-size: 12px;
font-weight: 600;
}
.doced-mod-field input {
width: 100%;
max-width: 480px;
padding: 8px 10px;
border: 1px solid #ced4da;
border-radius: 4px;
font: inherit;
}
.doced-page-block {
border-bottom: 1px solid #e9ecef;
padding: 16px 18px;
}
.doced-page-block:last-of-type {
border-bottom: none;
}
.doced-page-head {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.doced-page-head h2 {
margin: 0;
font-size: 15px;
font-weight: 700;
color: #2f5fd0;
}
.doced-page-head .doced-page-clef {
font-size: 12px;
color: #6c757d;
}
.doced-page-head input[type="number"] {
width: 72px;
padding: 4px 8px;
border: 1px solid #ced4da;
border-radius: 4px;
}
.doced-lang-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
@media (max-width: 900px) {
.doced-lang-grid { grid-template-columns: 1fr; }
.doced-meta { grid-template-columns: 1fr 1fr; }
}
.doced-lang-panel {
border: 1px solid #dee2e6;
border-radius: 6px;
padding: 12px;
}
.doced-lang-panel h3 {
margin: 0 0 10px;
font-size: 13px;
font-weight: 700;
}
.doced-field {
margin-bottom: 10px;
}
.doced-field:last-child {
margin-bottom: 0;
}
.doced-field label {
display: block;
margin-bottom: 4px;
font-size: 12px;
font-weight: 600;
color: #495057;
}
.doced-field .doced-hint {
font-weight: 400;
color: #868e96;
}
.doced-field input[type="text"],
.doced-field textarea {
width: 100%;
padding: 8px 10px;
border: 1px solid #ced4da;
border-radius: 4px;
font: inherit;
color: #212529;
}
.doced-field textarea.doced-html {
min-height: 200px;
font-family: Consolas, "Courier New", monospace;
font-size: 12px;
line-height: 1.45;
}
.doced-actions {
padding: 16px 18px;
}
.doced-btn-save {
padding: 10px 24px;
border: none;
border-radius: 4px;
background: #28a745;
color: #fff;
font: inherit;
font-weight: 600;
cursor: pointer;
}
.doced-btn-save:hover {
background: #218838;
}
</style>
</head>
<body>
<div class="doced-page">
<form action="<?php echo docEdEsc($vDomaine); ?>/php/doc_edition.php" method="post" id="frm_doc_edition">
<input type="hidden" name="anchor" value="<?php echo docEdEsc($anchor); ?>">
<input type="hidden" name="mod" value="<?php echo docEdEsc($modClef); ?>">
<input type="hidden" name="prg" value="<?php echo docEdEsc($prg); ?>">
<input type="hidden" name="page" value="<?php echo docEdEsc($page); ?>">
<input type="hidden" name="bd" value="<?php echo docEdEsc($bd); ?>">
<div class="doced-card">
<div class="doced-card-header">
<h1>Guide documentation</h1>
<div class="doced-key">Module <?php echo docEdEsc($modClef); ?> · ancre <?php echo docEdEsc($anchor); ?></div>
</div>
<dl class="doced-meta">
<div>
<dt>Programme</dt>
<dd><?php echo docEdEsc($prg); ?></dd>
</div>
<div>
<dt>Ancre UI</dt>
<dd><?php echo docEdEsc($anchor); ?></dd>
</div>
<div>
<dt>Pages</dt>
<dd><?php echo count($tabPages); ?></dd>
</div>
<div>
<dt>Base</dt>
<dd><?php echo docEdEsc($bd); ?></dd>
</div>
</dl>
<?php if ($blnSaved) { ?>
<div class="doced-alert">Enregistré. Fermez cette fenêtre pour recharger l'écran principal.</div>
<?php } ?>
<?php if (is_array($tabMod) && !empty($tabMod['pk_doc_mod'])) { ?>
<div class="doced-mod-field">
<label for="doc_mod_titre">Titre du module (doc_mod)</label>
<input type="hidden" name="doc_mod[pk_doc_mod]" value="<?php echo (int)$tabMod['pk_doc_mod']; ?>">
<input type="hidden" name="doc_mod[doc_mod_clef]" value="<?php echo docEdEsc($tabMod['doc_mod_clef']); ?>">
<input type="hidden" name="doc_mod[doc_mod_prg]" value="<?php echo docEdEsc($tabMod['doc_mod_prg']); ?>">
<input type="text" id="doc_mod_titre" name="doc_mod[doc_mod_titre]"
value="<?php echo docEdEsc($tabMod['doc_mod_titre'] ?? ''); ?>" maxlength="255">
</div>
<?php } ?>
<?php
$intPageNum = 0;
foreach ($tabPages as $pageClef => $tabPageGroup) {
$intPageNum++;
$tri = (int)$tabPageGroup['doc_tri'];
?>
<section class="doced-page-block">
<div class="doced-page-head">
<h2>Page <?php echo (int)$intPageNum; ?></h2>
<span class="doced-page-clef"><?php echo docEdEsc($pageClef); ?></span>
</div>
<div class="doced-lang-grid">
<?php foreach ($tabLangMeta as $strLang => $strLangLabel) {
$tabRow = $tabPageGroup[$strLang];
$isMod = is_array($tabRow) && !empty($tabRow['pk_doc_page']);
?>
<div class="doced-lang-panel">
<h3><?php echo docEdEsc($strLangLabel); ?></h3>
<input type="hidden" <?php echo docEdFieldAttrs('pk_doc_page', $pageClef, $strLang); ?>
value="<?php echo $isMod ? (int)$tabRow['pk_doc_page'] : ''; ?>">
<input type="hidden" <?php echo docEdFieldAttrs('doc_langue', $pageClef, $strLang); ?>
value="<?php echo docEdEsc($strLang); ?>">
<input type="hidden" <?php echo docEdFieldAttrs('doc_tri', $pageClef, $strLang); ?>
value="<?php echo $isMod ? (int)$tabRow['doc_tri'] : $tri; ?>">
<input type="hidden" <?php echo docEdFieldAttrs('doc_actif', $pageClef, $strLang); ?>
value="1">
<div class="doced-field">
<label>Titre overlay</label>
<input type="text" maxlength="255"
<?php echo docEdFieldAttrs('doc_titre', $pageClef, $strLang); ?>
value="<?php echo docEdEsc($isMod ? ($tabRow['doc_titre'] ?? '') : ''); ?>">
</div>
<div class="doced-field">
<label>Sous-titre</label>
<input type="text" maxlength="255"
<?php echo docEdFieldAttrs('doc_sous_titre', $pageClef, $strLang); ?>
value="<?php echo docEdEsc($isMod ? ($tabRow['doc_sous_titre'] ?? '') : ''); ?>">
</div>
<div class="doced-field">
<label>Contenu HTML <span class="doced-hint">(doc_html)</span></label>
<textarea class="doced-html" <?php echo docEdFieldAttrs('doc_html', $pageClef, $strLang); ?>><?php
echo docEdEsc($isMod ? ($tabRow['doc_html'] ?? '') : '');
?></textarea>
</div>
</div>
<?php } ?>
</div>
</section>
<?php } ?>
<?php if (empty($tabPages)) { ?>
<div class="doced-page-block">
<p>Aucune page pour ce module. Vérifiez que <code>doc_page</code> est peuplé pour
<strong><?php echo docEdEsc($modClef); ?></strong>.</p>
</div>
<?php } ?>
<div class="doced-actions">
<button type="submit" name="btn_mod" value="save" class="doced-btn-save">Enregistrer tout le guide</button>
</div>
</div>
</form>
</div>
<!--
Editeur WYSIWYG Trumbowyg — UNIQUEMENT cette page (doc_edition.php).
N'affecte pas le TinyMCE/CKEditor utilises ailleurs sur le site.
-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/trumbowyg@2.27.3/dist/ui/trumbowyg.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/trumbowyg@2.27.3/dist/plugins/table/ui/trumbowyg.table.min.css">
<style>
.trumbowyg-box { margin: 0; border-radius: 4px; }
.trumbowyg-editor { min-height: 220px; font-family: inherit; font-size: 14px; }
</style>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/trumbowyg@2.27.3/dist/trumbowyg.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/trumbowyg@2.27.3/dist/plugins/table/trumbowyg.table.min.js"></script>
<script>
jQuery(function ($) {
$('textarea.doced-html').trumbowyg({
semantic: true,
autogrow: true,
resetCss: true,
removeformatPasted: true,
btns: [
['viewHTML'],
['formatting'],
['strong', 'em'],
['link'],
['unorderedList', 'orderedList'],
['table'],
['horizontalRule'],
['removeformat']
]
});
});
</script>
</body>
</html>