338 lines
13 KiB
PHP
338 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Admin documentation (doc_mod / doc_page / doc_anchor) — super admin.
|
|
* Lister, creer modules et pages ; edition via /php/doc_edition.php (Trumbowyg).
|
|
* Creation reservee dev/preprod (le contenu est ensuite pousse par la base).
|
|
*/
|
|
|
|
function fxDocAdminEsc($str)
|
|
{
|
|
return htmlspecialchars((string)$str, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
function fxDocAdminIsDevPreprod()
|
|
{
|
|
global $vblnEnvironementDev, $vblnEnvironementPreProd;
|
|
|
|
return !empty($vblnEnvironementDev) || !empty($vblnEnvironementPreProd);
|
|
}
|
|
|
|
function fxDocAdminSchemaReady()
|
|
{
|
|
global $objDatabase;
|
|
|
|
static $blnReady = null;
|
|
|
|
if ($blnReady !== null) {
|
|
return $blnReady;
|
|
}
|
|
|
|
if (!isset($objDatabase)) {
|
|
$blnReady = false;
|
|
return $blnReady;
|
|
}
|
|
|
|
$qry = $objDatabase->fxQuery("SHOW TABLES LIKE 'doc_page'");
|
|
$blnReady = ($qry && mysqli_num_rows($qry) > 0);
|
|
|
|
return $blnReady;
|
|
}
|
|
|
|
function fxDocAdminEditUrl($modClef, $prg)
|
|
{
|
|
global $vDomaine;
|
|
|
|
$prg = ($prg !== '') ? $prg : 'compte.php';
|
|
|
|
return $vDomaine . '/php/doc_edition.php?' . http_build_query(array(
|
|
'mod' => $modClef,
|
|
'anchor' => $modClef,
|
|
'prg' => $prg,
|
|
'bd' => 'client',
|
|
'page' => 'compte.php',
|
|
));
|
|
}
|
|
|
|
function fxDocAdminListModules()
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxDocAdminSchemaReady()) {
|
|
return array();
|
|
}
|
|
|
|
$sql = "SELECT m.pk_doc_mod, m.doc_mod_clef, m.doc_mod_prg, m.doc_mod_titre, m.doc_mod_actif,
|
|
(SELECT COUNT(DISTINCT p.doc_page_clef)
|
|
FROM doc_page p
|
|
WHERE p.doc_mod_clef = m.doc_mod_clef) AS nb_pages
|
|
FROM doc_mod m
|
|
ORDER BY m.doc_mod_tri, m.doc_mod_titre";
|
|
|
|
$rows = $objDatabase->fxGetResults($sql);
|
|
|
|
return is_array($rows) ? $rows : array();
|
|
}
|
|
|
|
function fxDocAdminGetModule($modClef)
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxDocAdminSchemaReady() || trim($modClef) === '') {
|
|
return null;
|
|
}
|
|
|
|
return $objDatabase->fxGetRow(
|
|
"SELECT * FROM doc_mod WHERE doc_mod_clef = '" . $objDatabase->fxEscape($modClef) . "' LIMIT 1"
|
|
);
|
|
}
|
|
|
|
function fxDocAdminListPages($modClef)
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxDocAdminSchemaReady() || trim($modClef) === '') {
|
|
return array();
|
|
}
|
|
|
|
$sql = "SELECT * FROM doc_page
|
|
WHERE doc_mod_clef = '" . $objDatabase->fxEscape($modClef) . "'
|
|
ORDER BY doc_tri, doc_page_clef, doc_langue DESC";
|
|
|
|
$rows = $objDatabase->fxGetResults($sql);
|
|
$grouped = array();
|
|
|
|
if (is_array($rows)) {
|
|
for ($i = 1; $i <= count($rows); $i++) {
|
|
$r = $rows[$i];
|
|
$clef = $r['doc_page_clef'] ?? '';
|
|
if ($clef === '') {
|
|
continue;
|
|
}
|
|
if (!isset($grouped[$clef])) {
|
|
$grouped[$clef] = array(
|
|
'clef' => $clef,
|
|
'tri' => (int)($r['doc_tri'] ?? 0),
|
|
'prg' => $r['doc_prg'] ?? 'compte.php',
|
|
'fr' => null,
|
|
'en' => null,
|
|
);
|
|
}
|
|
$lng = $r['doc_langue'] ?? 'fr';
|
|
if ($lng === 'fr' || $lng === 'en') {
|
|
$grouped[$clef][$lng] = $r;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $grouped;
|
|
}
|
|
|
|
function fxDocAdminCreateModule($clef, $titre, $prg)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$clef = trim($clef);
|
|
$prg = (trim($prg) !== '') ? trim($prg) : 'compte.php';
|
|
|
|
if ($clef === '') {
|
|
return array('state' => 'error', 'message' => 'Clé du module requise.');
|
|
}
|
|
if (!preg_match('/^[a-z0-9_]+$/i', $clef)) {
|
|
return array('state' => 'error', 'message' => 'Clé invalide (lettres, chiffres, underscore seulement).');
|
|
}
|
|
if (!fxDocAdminSchemaReady()) {
|
|
return array('state' => 'error', 'message' => 'Tables de documentation absentes.');
|
|
}
|
|
|
|
$intExists = (int)$objDatabase->fxGetVar(
|
|
"SELECT COUNT(*) FROM doc_mod
|
|
WHERE doc_mod_clef = '" . $objDatabase->fxEscape($clef) . "'
|
|
AND doc_mod_prg = '" . $objDatabase->fxEscape($prg) . "'"
|
|
);
|
|
if ($intExists > 0) {
|
|
return array('state' => 'error', 'message' => 'Ce module existe déjà.');
|
|
}
|
|
|
|
$objDatabase->fxQuery(
|
|
"INSERT INTO doc_mod (doc_mod_clef, doc_mod_prg, doc_mod_titre, doc_mod_actif, doc_mod_tri, doc_mod_creation)
|
|
VALUES ('" . $objDatabase->fxEscape($clef) . "', '" . $objDatabase->fxEscape($prg) . "', '" . $objDatabase->fxEscape($titre) . "', 1, 0, NOW())"
|
|
);
|
|
|
|
$intAnchor = (int)$objDatabase->fxGetVar(
|
|
"SELECT COUNT(*) FROM doc_anchor
|
|
WHERE doc_anchor_clef = '" . $objDatabase->fxEscape($clef) . "'
|
|
AND doc_prg = '" . $objDatabase->fxEscape($prg) . "'"
|
|
);
|
|
if ($intAnchor === 0) {
|
|
$objDatabase->fxQuery(
|
|
"INSERT INTO doc_anchor (doc_anchor_clef, doc_mod_clef, doc_prg, doc_actif, doc_creation)
|
|
VALUES ('" . $objDatabase->fxEscape($clef) . "', '" . $objDatabase->fxEscape($clef) . "', '" . $objDatabase->fxEscape($prg) . "', 1, NOW())"
|
|
);
|
|
}
|
|
|
|
return array('state' => 'ok', 'mod' => $clef, 'prg' => $prg);
|
|
}
|
|
|
|
function fxDocAdminCreatePage($modClef, $pageClef, $prg)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$modClef = trim($modClef);
|
|
$pageClef = trim($pageClef);
|
|
$prg = (trim($prg) !== '') ? trim($prg) : 'compte.php';
|
|
|
|
if ($modClef === '' || $pageClef === '') {
|
|
return array('state' => 'error', 'message' => 'Clé du module et clé de page requises.');
|
|
}
|
|
if (!preg_match('/^[a-z0-9_]+$/i', $pageClef)) {
|
|
return array('state' => 'error', 'message' => 'Clé de page invalide (lettres, chiffres, underscore seulement).');
|
|
}
|
|
if (!fxDocAdminSchemaReady()) {
|
|
return array('state' => 'error', 'message' => 'Tables de documentation absentes.');
|
|
}
|
|
|
|
$intExists = (int)$objDatabase->fxGetVar(
|
|
"SELECT COUNT(*) FROM doc_page
|
|
WHERE doc_page_clef = '" . $objDatabase->fxEscape($pageClef) . "'
|
|
AND doc_prg = '" . $objDatabase->fxEscape($prg) . "'"
|
|
);
|
|
if ($intExists > 0) {
|
|
return array('state' => 'error', 'message' => 'Cette page existe déjà.');
|
|
}
|
|
|
|
$intTri = (int)$objDatabase->fxGetVar(
|
|
"SELECT COALESCE(MAX(doc_tri), 0) + 10 FROM doc_page
|
|
WHERE doc_mod_clef = '" . $objDatabase->fxEscape($modClef) . "'"
|
|
);
|
|
|
|
foreach (array('fr', 'en') as $lng) {
|
|
$objDatabase->fxQuery(
|
|
"INSERT INTO doc_page (doc_mod_clef, doc_page_clef, doc_langue, doc_titre, doc_sous_titre, doc_html, doc_prg, doc_tri, doc_actif, doc_creation)
|
|
VALUES ('" . $objDatabase->fxEscape($modClef) . "', '" . $objDatabase->fxEscape($pageClef) . "', '" . $lng . "', '', '', '', '" . $objDatabase->fxEscape($prg) . "', " . $intTri . ", 1, NOW())"
|
|
);
|
|
}
|
|
|
|
return array('state' => 'ok', 'mod' => $modClef, 'page' => $pageClef, 'prg' => $prg);
|
|
}
|
|
|
|
/** Liste des modules + formulaire de creation. */
|
|
function fxDocAdminRenderModulesList()
|
|
{
|
|
global $vDomaine;
|
|
|
|
$arrModules = fxDocAdminListModules();
|
|
$blnDev = fxDocAdminIsDevPreprod();
|
|
|
|
echo '<div class="d-flex align-items-center justify-content-between mb-3">';
|
|
echo '<h1 class="h3 mb-0">Documentation & Nouveautés</h1>';
|
|
echo '</div>';
|
|
echo '<p class="text-muted">Modules de documentation (pages HTML multipage). Le contenu n\'est pas lié au code : édition directe ici, puis poussé par la base.</p>';
|
|
|
|
if ($blnDev) {
|
|
echo '<div class="card mb-4">';
|
|
echo '<div class="card-header"><i class="fa fa-plus mr-2" aria-hidden="true"></i>Créer un module</div>';
|
|
echo '<div class="card-body">';
|
|
echo '<form method="post" action="documentation.php" class="form-row align-items-end">';
|
|
echo '<input type="hidden" name="action" value="addmodule">';
|
|
echo '<div class="form-group col-md-3"><label>Clé du module</label><input type="text" name="doc_mod_clef" class="form-control" placeholder="ex. promoteur_hub_annonces" required></div>';
|
|
echo '<div class="form-group col-md-4"><label>Titre</label><input type="text" name="doc_mod_titre" class="form-control" placeholder="ex. Nouveautés MS1"></div>';
|
|
echo '<div class="form-group col-md-3"><label>Programme (doc_prg)</label><input type="text" name="doc_mod_prg" class="form-control" value="compte.php"></div>';
|
|
echo '<div class="form-group col-md-2"><button type="submit" class="btn btn-primary btn-block">Créer</button></div>';
|
|
echo '</form>';
|
|
echo '</div></div>';
|
|
} else {
|
|
echo '<div class="alert alert-info">La création de modules/pages est réservée aux environnements dev/préprod.</div>';
|
|
}
|
|
|
|
if (empty($arrModules)) {
|
|
echo '<div class="alert alert-warning">Aucun module de documentation.</div>';
|
|
return;
|
|
}
|
|
|
|
echo '<table class="table table-striped table-hover">';
|
|
echo '<thead><tr><th>Titre</th><th>Clé</th><th>Programme</th><th class="text-center">Pages</th><th class="text-right">Actions</th></tr></thead><tbody>';
|
|
|
|
for ($i = 1; $i <= count($arrModules); $i++) {
|
|
$m = $arrModules[$i];
|
|
$strClef = $m['doc_mod_clef'] ?? '';
|
|
$strPrg = $m['doc_mod_prg'] ?? 'compte.php';
|
|
$intNb = (int)($m['nb_pages'] ?? 0);
|
|
|
|
echo '<tr>';
|
|
echo '<td>' . fxDocAdminEsc($m['doc_mod_titre'] ?? '') . '</td>';
|
|
echo '<td><code>' . fxDocAdminEsc($strClef) . '</code></td>';
|
|
echo '<td>' . fxDocAdminEsc($strPrg) . '</td>';
|
|
echo '<td class="text-center">' . $intNb . '</td>';
|
|
echo '<td class="text-right">';
|
|
echo '<a class="btn btn-sm btn-outline-secondary mr-1" href="documentation.php?p=pages&mod=' . urlencode($strClef) . '"><i class="fa fa-list" aria-hidden="true"></i> Pages</a>';
|
|
echo '<a class="btn btn-sm btn-primary" href="' . fxDocAdminEsc(fxDocAdminEditUrl($strClef, $strPrg)) . '" target="_blank"><i class="fa fa-pencil" aria-hidden="true"></i> Éditer</a>';
|
|
echo '</td>';
|
|
echo '</tr>';
|
|
}
|
|
|
|
echo '</tbody></table>';
|
|
}
|
|
|
|
/** Liste des pages d'un module + formulaire d'ajout de page. */
|
|
function fxDocAdminRenderPages($modClef)
|
|
{
|
|
$modClef = trim($modClef);
|
|
$arrMod = fxDocAdminGetModule($modClef);
|
|
|
|
if ($arrMod === null) {
|
|
echo '<div class="alert alert-danger">Module introuvable.</div>';
|
|
echo '<a class="btn btn-outline-secondary" href="documentation.php"><i class="fa fa-chevron-left" aria-hidden="true"></i> Retour</a>';
|
|
return;
|
|
}
|
|
|
|
$strPrg = $arrMod['doc_mod_prg'] ?? 'compte.php';
|
|
$arrPages = fxDocAdminListPages($modClef);
|
|
$blnDev = fxDocAdminIsDevPreprod();
|
|
|
|
echo '<div class="d-flex align-items-center justify-content-between mb-3">';
|
|
echo '<div><a class="btn btn-sm btn-outline-secondary mb-2" href="documentation.php"><i class="fa fa-chevron-left" aria-hidden="true"></i> Tous les modules</a>';
|
|
echo '<h1 class="h3 mb-0">' . fxDocAdminEsc($arrMod['doc_mod_titre'] ?? $modClef) . '</h1>';
|
|
echo '<div class="text-muted"><code>' . fxDocAdminEsc($modClef) . '</code> · ' . fxDocAdminEsc($strPrg) . '</div></div>';
|
|
echo '<a class="btn btn-primary" href="' . fxDocAdminEsc(fxDocAdminEditUrl($modClef, $strPrg)) . '" target="_blank"><i class="fa fa-pencil" aria-hidden="true"></i> Éditer le module</a>';
|
|
echo '</div>';
|
|
|
|
if ($blnDev) {
|
|
echo '<div class="card mb-4">';
|
|
echo '<div class="card-header"><i class="fa fa-plus mr-2" aria-hidden="true"></i>Ajouter une page</div>';
|
|
echo '<div class="card-body">';
|
|
echo '<form method="post" action="documentation.php" class="form-row align-items-end">';
|
|
echo '<input type="hidden" name="action" value="addpage">';
|
|
echo '<input type="hidden" name="mod" value="' . fxDocAdminEsc($modClef) . '">';
|
|
echo '<input type="hidden" name="doc_prg" value="' . fxDocAdminEsc($strPrg) . '">';
|
|
echo '<div class="form-group col-md-6"><label>Clé de la nouvelle page</label><input type="text" name="doc_page_clef" class="form-control" placeholder="ex. annonce_v4_73" required></div>';
|
|
echo '<div class="form-group col-md-3"><button type="submit" class="btn btn-primary btn-block">Créer et éditer</button></div>';
|
|
echo '</form>';
|
|
echo '<small class="text-muted">La page (FR + EN) est créée vide, puis l\'éditeur s\'ouvre.</small>';
|
|
echo '</div></div>';
|
|
}
|
|
|
|
if (empty($arrPages)) {
|
|
echo '<div class="alert alert-warning">Aucune page dans ce module.</div>';
|
|
return;
|
|
}
|
|
|
|
echo '<table class="table table-striped">';
|
|
echo '<thead><tr><th class="text-center">Tri</th><th>Clé</th><th>Titre FR</th><th>Titre EN</th></tr></thead><tbody>';
|
|
|
|
foreach ($arrPages as $page) {
|
|
$strTitreFr = isset($page['fr']['doc_titre']) ? $page['fr']['doc_titre'] : '';
|
|
$strTitreEn = isset($page['en']['doc_titre']) ? $page['en']['doc_titre'] : '';
|
|
|
|
echo '<tr>';
|
|
echo '<td class="text-center">' . (int)$page['tri'] . '</td>';
|
|
echo '<td><code>' . fxDocAdminEsc($page['clef']) . '</code></td>';
|
|
echo '<td>' . fxDocAdminEsc($strTitreFr) . '</td>';
|
|
echo '<td>' . fxDocAdminEsc($strTitreEn) . '</td>';
|
|
echo '</tr>';
|
|
}
|
|
|
|
echo '</tbody></table>';
|
|
echo '<p class="text-muted"><i class="fa fa-info-circle" aria-hidden="true"></i> Le bouton « Éditer le module » ouvre toutes les pages dans l\'éditeur visuel.</p>';
|
|
}
|