fxQuery("SHOW TABLES LIKE 'doc_page'"); $blnReady = ($qry && mysqli_num_rows($qry) > 0); return $blnReady; } /** * Charge en mémoire toutes les pages doc pour une page PHP (comme obtenirTextepage). * Remplit $vdoc_page[doc_page_clef] = row. */ function obtenirDocPage($page = null, $langue = null) { global $objDatabase, $vdoc_page; if ($page === null || $page === '') { $page = fxDocPrg(0); } if ($langue === null || $langue === '') { $langue = fxDocLangue(); } $vdoc_page = array(); if (!isset($objDatabase) || !fxDocSchemaReady()) { return $vdoc_page; } $sql = "SELECT * FROM doc_page WHERE doc_actif = 1 AND doc_langue = '" . $objDatabase->fxEscape($langue) . "' AND doc_prg IN ('" . $objDatabase->fxEscape($page) . "', 'global') ORDER BY doc_tri, pk_doc_page"; $rows = $objDatabase->fxGetResults($sql); if (!is_array($rows)) { return $vdoc_page; } for ($i = 1; $i <= count($rows); $i++) { if (!empty($rows[$i]['doc_page_clef'])) { $vdoc_page[$rows[$i]['doc_page_clef']] = $rows[$i]; } } return $vdoc_page; } /** Ligne doc_anchor par clé d'appel. */ function fxDocGetAnchorRow($clef, $mem_global = 0) { global $objDatabase; static $anchorCache = array(); $strPrg = fxDocPrg($mem_global); $cacheKey = $clef . '|' . $strPrg; if (array_key_exists($cacheKey, $anchorCache)) { return $anchorCache[$cacheKey]; } if (!isset($objDatabase) || $clef === '' || !fxDocSchemaReady()) { $anchorCache[$cacheKey] = array(); return $anchorCache[$cacheKey]; } $sql = "SELECT * FROM doc_anchor WHERE doc_actif = 1 AND doc_anchor_clef = '" . $objDatabase->fxEscape($clef) . "' AND doc_prg IN ('" . $objDatabase->fxEscape($strPrg) . "', 'global') ORDER BY FIELD(doc_prg, '" . $objDatabase->fxEscape($strPrg) . "', 'global') LIMIT 1"; $row = $objDatabase->fxGetRow($sql); $anchorCache[$cacheKey] = is_array($row) ? $row : array(); return $anchorCache[$cacheKey]; } /** Résout doc_mod_clef depuis une clé d'ancre ou un code module direct. */ function fxDocResolveModClef($clef, $mem_global = 0) { $anchor = fxDocGetAnchorRow($clef, $mem_global); if (!empty($anchor['doc_mod_clef'])) { return $anchor['doc_mod_clef']; } return $clef; } /** Pages actives d'un module, triées (pour carrousel overlay). */ function fxDocGetModulePages($modClef, $langue = null, $mem_global = 0) { global $objDatabase, $vdoc_page; if ($langue === null || $langue === '') { $langue = fxDocLangue(); } $strPrg = fxDocPrg($mem_global); $modClef = fxDocResolveModClef($modClef, $mem_global); if (!isset($objDatabase) || $modClef === '' || !fxDocSchemaReady()) { return array(); } $sql = "SELECT * FROM doc_page WHERE doc_actif = 1 AND doc_mod_clef = '" . $objDatabase->fxEscape($modClef) . "' AND doc_langue = '" . $objDatabase->fxEscape($langue) . "' AND doc_prg IN ('" . $objDatabase->fxEscape($strPrg) . "', 'global') ORDER BY doc_tri, pk_doc_page"; $rows = $objDatabase->fxGetResults($sql); $pages = array(); if (!is_array($rows)) { return $pages; } for ($i = 1; $i <= count($rows); $i++) { $pages[] = $rows[$i]; if (!empty($rows[$i]['doc_page_clef'])) { if (!isset($vdoc_page) || !is_array($vdoc_page)) { $vdoc_page = array(); } $vdoc_page[$rows[$i]['doc_page_clef']] = $rows[$i]; } } return $pages; } /** Une page par doc_page_clef (mémoire ou BD). */ function fxDocGetPageRow($clef, $mem_global = 0) { global $vdoc_page, $objDatabase; if (!empty($vdoc_page[$clef])) { return $vdoc_page[$clef]; } if (!isset($objDatabase) || $clef === '' || !fxDocSchemaReady()) { return array(); } $strPrg = fxDocPrg($mem_global); $langue = fxDocLangue(); static $pageCache = array(); $cacheKey = $clef . '|' . $langue . '|' . $strPrg; if (array_key_exists($cacheKey, $pageCache)) { return $pageCache[$cacheKey]; } $sql = "SELECT * FROM doc_page WHERE doc_actif = 1 AND doc_page_clef = '" . $objDatabase->fxEscape($clef) . "' AND doc_langue = '" . $objDatabase->fxEscape($langue) . "' AND doc_prg IN ('" . $objDatabase->fxEscape($strPrg) . "', 'global') ORDER BY FIELD(doc_prg, '" . $objDatabase->fxEscape($strPrg) . "', 'global') LIMIT 1"; $row = $objDatabase->fxGetRow($sql); $pageCache[$cacheKey] = is_array($row) ? $row : array(); return $pageCache[$cacheKey]; } /** Crée une page doc vide si absente (miroir afficheTexte). */ function fxDocEnsurePage($clef, $mem_global = 0, $modClef = '') { global $objDatabase; $row = fxDocGetPageRow($clef, $mem_global); if (!empty($row)) { return $row; } $strPrg = fxDocPrg($mem_global); $langue = fxDocLangue(); if ($modClef === '') { $modClef = $clef; } $tabData = array( 'doc_mod_clef' => $modClef, 'doc_page_clef' => $clef, 'doc_langue' => $langue, 'doc_titre' => $clef, 'doc_sous_titre' => '', 'doc_html' => '', 'doc_prg' => $strPrg, 'doc_tri' => 0, 'doc_actif' => 1, ); fxSetDocPage('add', $tabData); if ($langue === 'fr') { $tabDataEn = $tabData; $tabDataEn['doc_langue'] = 'en'; fxSetDocPage('add', $tabDataEn); } return fxDocGetPageRow($clef, $mem_global); } /** * Titre doc_titre — équivalent afficheTexte pour doc_page. */ function afficheDocTitre($clef, $mem_echo = 1, $mem_global = 0, $modClef = '') { $row = fxDocGetPageRow($clef, $mem_global); if (empty($row)) { fxDocEnsurePage($clef, $mem_global, $modClef); $row = fxDocGetPageRow($clef, $mem_global); } $str = trim($row['doc_titre'] ?? ''); if ($str === '' || $str === $clef) { $str = '*' . $clef . '*'; } if ($mem_echo == 1) { echo fxDocEsc($str); } return $str; } /** * Corps HTML doc_html — équivalent afficheAide (contenu long, HTML admin). */ function afficheDocHtml($clef, $mem_echo = 1, $mem_global = 0, $modClef = '') { $row = fxDocGetPageRow($clef, $mem_global); if (empty($row)) { fxDocEnsurePage($clef, $mem_global, $modClef); $row = fxDocGetPageRow($clef, $mem_global); } $str = $row['doc_html'] ?? ''; if ($mem_echo == 1) { echo $str; } return $str; } /** Sous-titre doc_sous_titre. */ function afficheDocSousTitre($clef, $mem_echo = 1, $mem_global = 0, $modClef = '') { $row = fxDocGetPageRow($clef, $mem_global); if (empty($row)) { fxDocEnsurePage($clef, $mem_global, $modClef); $row = fxDocGetPageRow($clef, $mem_global); } $str = trim($row['doc_sous_titre'] ?? ''); if ($mem_echo == 1) { echo fxDocEsc($str); } return $str; } /** URL pop-up doc_edition.php — module documentation paginé. */ function fxAdminDocUrl($anchorClef, $mem_global = 0) { global $vDomaine, $vPage; $strPrg = fxDocPrg($mem_global); $modClef = fxDocResolveModClef($anchorClef, $mem_global); return $vDomaine . '/php/doc_edition.php?' . http_build_query(array( 'anchor' => $anchorClef, 'mod' => $modClef, 'prg' => $strPrg, 'bd' => 'client', 'page' => !empty($vPage) ? $vPage : 'compte.php', )); } /** Lien crayon doc_edition.php — superadm dev/préprod + switch Textes ON. */ function fxAdminDocButton($anchorClef, $mem_global = 0) { if (!fxAdminTextEditModeActive() || trim($anchorClef) === '') { return ''; } return '' . '' . ''; } /** Bouton ? pour ouvrir le module doc (clé doc_anchor_clef) — même rond que btn-aide-bib. */ function fxDocRenderTrigger($anchorClef, $mem_global = 0, $strAriaLabel = 'Documentation') { $modClef = fxDocResolveModClef($anchorClef, $mem_global); return ''; } /** Panneau overlay paginé pour un module (clé doc_anchor_clef ou doc_mod_clef). */ function fxDocRenderModule($anchorClef, $mem_global = 0) { $modClef = fxDocResolveModClef($anchorClef, $mem_global); $pages = fxDocGetModulePages($modClef, null, $mem_global); if (empty($pages)) { return ''; } $overlayId = 'ms1-doc-overlay-' . preg_replace('/[^a-z0-9_-]/i', '-', $anchorClef); $html = '
'; // Métadonnées titres pour JS (init header sans parser le HTML) $html .= ''; return $html; } /** Trigger + overlay (appel typique à côté d'un titre de bloc). */ function fxDocRenderBlock($anchorClef, $mem_global = 0, $strAriaLabel = 'Documentation') { return fxDocRenderTrigger($anchorClef, $mem_global, $strAriaLabel) . fxDocRenderModule($anchorClef, $mem_global); } function fxSetDocMod($strAction, $tabData, $id = 0) { global $objDatabase; switch ($strAction) { case 'add': $tabFieldsValues = fxListFieldsValues($tabData, 'pk_doc_mod', 'doc_mod', $GLOBALS['arrConDatabaseMain']['db']); $sqlValide = "SELECT COUNT(doc_mod_clef) FROM doc_mod WHERE doc_mod_clef = '" . $objDatabase->fxEscape($tabData['doc_mod_clef']) . "' AND doc_mod_prg = '" . $objDatabase->fxEscape($tabData['doc_mod_prg']) . "'"; if ((int)$objDatabase->fxGetVar($sqlValide) > 0) { break; } $sqlInsert = "INSERT INTO doc_mod " . $tabFieldsValues['set'] . ', doc_mod_creation = NOW()'; $objDatabase->fxQuery($sqlInsert); break; case 'mod': $tabFieldsValues = fxListFieldsValues($tabData, 'pk_doc_mod', 'doc_mod', $GLOBALS['arrConDatabaseMain']['db']); $sqlUpdate = "UPDATE doc_mod " . $tabFieldsValues['set'] . ", doc_mod_maj = NOW() WHERE " . $tabFieldsValues['key']; $objDatabase->fxQuery($sqlUpdate); break; } } function fxSetDocPage($strAction, $tabData, $id = 0) { global $objDatabase; switch ($strAction) { case 'add': $tabFieldsValues = fxListFieldsValues($tabData, 'pk_doc_page', 'doc_page', $GLOBALS['arrConDatabaseMain']['db']); $sqlValide = "SELECT COUNT(doc_page_clef) FROM doc_page WHERE doc_page_clef = '" . $objDatabase->fxEscape($tabData['doc_page_clef']) . "' AND doc_langue = '" . $objDatabase->fxEscape($tabData['doc_langue']) . "' AND doc_prg = '" . $objDatabase->fxEscape($tabData['doc_prg']) . "'"; if ((int)$objDatabase->fxGetVar($sqlValide) > 0) { break; } $sqlInsert = "INSERT INTO doc_page " . $tabFieldsValues['set'] . ', doc_creation = NOW()'; $objDatabase->fxQuery($sqlInsert); break; case 'mod': $tabFieldsValues = fxListFieldsValues($tabData, 'pk_doc_page', 'doc_page', $GLOBALS['arrConDatabaseMain']['db']); $sqlUpdate = "UPDATE doc_page " . $tabFieldsValues['set'] . ", doc_maj = NOW() WHERE " . $tabFieldsValues['key']; $objDatabase->fxQuery($sqlUpdate); break; } } function fxSetDocAnchor($strAction, $tabData, $id = 0) { global $objDatabase; switch ($strAction) { case 'add': $tabFieldsValues = fxListFieldsValues($tabData, 'pk_doc_anchor', 'doc_anchor', $GLOBALS['arrConDatabaseMain']['db']); $sqlValide = "SELECT COUNT(doc_anchor_clef) FROM doc_anchor WHERE doc_anchor_clef = '" . $objDatabase->fxEscape($tabData['doc_anchor_clef']) . "' AND doc_prg = '" . $objDatabase->fxEscape($tabData['doc_prg']) . "'"; if ((int)$objDatabase->fxGetVar($sqlValide) > 0) { break; } $sqlInsert = "INSERT INTO doc_anchor " . $tabFieldsValues['set'] . ', doc_creation = NOW()'; $objDatabase->fxQuery($sqlInsert); break; case 'mod': $tabFieldsValues = fxListFieldsValues($tabData, 'pk_doc_anchor', 'doc_anchor', $GLOBALS['arrConDatabaseMain']['db']); $sqlUpdate = "UPDATE doc_anchor " . $tabFieldsValues['set'] . " WHERE " . $tabFieldsValues['key']; $objDatabase->fxQuery($sqlUpdate); break; } }