backdoor/install/sql_dump/{sbuiadmin_create,sbuiadmin_create_7.1_and_more}.sql (12 nouvelles tables), nouveau backdoor/datas/modules/boutique.php + backdoor/datas/modules/tpls/boutique.tpl, backdoor/lang/french.php, backdoor/main.php, backdoor/inc/sbuiadmin-config.php, backdoor/inc/sbuiadmin-rights.php.guyacadeau/ecommerce_recette (architecture générale du tunnel de commande, livraison dématérialisée) et surtout cabaret/web (plus abouti : modèle de TVA multi-taux par produit avec ventilation comptable, classe sbfacturx complète pour la génération de factures Factur-X EN16931/CII avec embed PDF/A-3 et synchronisation Pennylane). Décisions actées avec le client : moyens de paiement, types de produits dématérialisés, calcul de transport, types de remise, format de facture, export comptable et validation Factur-X seront chacun construits en plugins indépendants, un dossier dédié par famille, à leur phase respective (pas en Phase 1 — rien de concret à interfacer avant).sb_shop_* — product (avec ventilation TVA JSON multi-taux + bascule tva_assujetti pour les sociétés en franchise de TVA), category, order/order_detail (avec colonne mode physique/dématérialisé explicite, contrairement à la référence qui le déduit après coup), unique (table unique pour les codes de livraison dématérialisée, génération 100% locale et paramétrable — pas d'API tierce comme la référence), transport, discount, payment, accounting_export/accounting_log (multi-destination comptable simultanée), email, config.boutique.php, calqué sur le module FAQ) : CRUD Catégories, CRUD Produits (référence, titre, catégorie, photo, descriptions, prix HT/TTC, poids, ventilation TVA sur 3 lignes toutes optionnelles avec contrôle de cohérence non bloquant, bascules physique/dématérialisé), et écran Paramètres généraux (TVA globale, devise/affichage, préfixe facture, paramètres de génération des codes uniques : racine/clé/motif/longueur).cc43c24.htaccess, index.php, sbconfig.php, inc/functions.php, backdoor/settings.php, backdoor/core/ (montée de version Smarty complète), backdoor/install/sql_dump/{sbuiadmin_create,sbuiadmin_create_7.1_and_more}.sql.settings.txt (aucun réglage orphelin) — seuls 2 libellés ("Smarty Cache Templates", "Durée du cache Smarty") ne précisaient pas "(FRONT)" contrairement à "Smarty Force Compile (FRONT)", source de confusion potentielle — corrigé.$sbsmarty->display("index.tpl") était appelé sans cache_id — Smarty mettait en cache une seule entrée pour ce template, partagée par erreur par toutes les URLs du site (la première page visitée après activation du cache s'affichait ensuite partout). Corrigé par un cache_id calculé par URL (index.php).smarty_internal_nocache_insert.php) : la compilation d'une balise {insert ... assign=...} (ex : pagination des actualités) générait un antislash littéral invalide dans le PHP produit pour le fichier de cache — erreur fatale (500) sur toute page utilisant cette balise, uniquement quand le cache est actif. Confirmé présent jusque dans la toute dernière version 4.5.x de Smarty (aucun correctif amont) — corrigé directement dans le fichier vendorisé.insert_sbGetContentCms() (dispatcheur de rendu de contenu de page, inc/functions.php) fait un display() Smarty imbriqué dans le display() de la page parente — ce rendu imbriqué héritait à tort du réglage caching=true du parent, passant lui aussi (avec un cache_id vide, partagé par erreur entre pages différentes) par le cache de sortie. Corrigé en désactivant explicitement le cache le temps de cet appel imbriqué.backdoor/core/) : à la demande du client, une fois le bug ci-dessus tracé jusqu'au cœur du moteur. Vérifié fichier par fichier (comparaison avec le 4.5.3 vanilla officiel) qu'aucune personnalisation SBUIADMIN n'existait dans les fichiers remplacés avant d'écraser. Apporte 3 correctifs de sécurité amont (traversée de répertoire via symlinks sur {include}/{fetch}, XSS sur des attributs non échappés de {html_image}, contournement possible de trusted_uri via redirection HTTP) + le support formel des dépréciations PHP 8.4. Les 12 plugins Smarty personnalisés du projet (dont 6 encore utilisés activement : {include_php}, |trim/|ltrim/|rtrim) préservés. function.lang.php (plugin i18n) récupéré du projet de référence guyacadeau (backguya/core/) en prévision du futur module Boutique — importé mais non câblé..htaccess) : RewriteBase / combiné à une cible absolue /index.php dans la règle de réécriture catch-all faisait router toute URL "jolie" (sans index.php littéral dans le chemin) vers la racine du domaine au lieu du sous-répertoire d'installation — 404 systématique. Seules les URLs ciblant déjà index.php littéralement (page d'accueil via DirectoryIndex, ou URLs ?p=...) contournaient le bug par une règle d'exemption antérieure, d'où l'illusion que seul l'accueil fonctionnait. Corrigé en rendant les cibles de réécriture relatives (standard, fonctionne aussi bien en racine qu'en sous-répertoire). En complément, SBSITESUBDIRECTORY (sbconfig.php) était figée en dur à '' (jamais éditée pour ce sous-répertoire d'installation) — désormais auto-détectée depuis l'URL du site configurée dans settings.txt.\r\n littéral (texte, pas un vrai saut de ligne) dans les dumps SQL d'installation — bug d'origine, sans rapport avec les autres points. Nettoyé dans les 2 dumps pour les futures installations fraîches ; le contenu déjà en base sur un site existant doit être corrigé manuellement via l'admin (pas d'accès direct à la base depuis l'environnement de développement).9ef1f5dbackdoor/index-cookie.php (supprimé).var_dump($_SESSION) affiché en clair dès le chargement de la page (reste de débogage jamais retiré), et aucun des correctifs de sécurité du Point 1 — même injection SQL dans le formulaire de connexion, même chiffrement réversible à clé codée en dur, même cookie "Se souvenir de moi" non sécurisé.8d1eb1dbackdoor/inc/plugins/explorer/, backdoor/inc/plugins/bddadmin/), backdoor/inc/sbuiadmin-config.php, backdoor/inc/class/sbuiadmin-sql.php, inc/functions.php.each() (supprimée PHP 8.0) : plantait le bouton "Infos serveur" du plugin File Explorer.get_magic_quotes_gpc() (supprimée PHP 8.0) : plantait tout accès au plugin File Explorer (code en tête de fichier, le @ ne protège pas une erreur fatale d'appel à une fonction inexistante).mysqli qui lève des exceptions non attrapées sur erreur SQL (comportement par défaut depuis PHP 8.1, en plus explicitement forcé dans sql::connect() via MYSQLI_REPORT_ERROR|STRICT) — déjà provoqué un plantage avec trace technique visible (chemins serveur, nom de la base) pendant les tests du Point 1. Tout le reste du code (des centaines de if ($result) {...} else {...}) est écrit pour l'ancien comportement (retour false sur erreur, jamais d'exception) — remis en MYSQLI_REPORT_OFF, corrige la classe de bug entière d'un coup, pour tout le site.explorer/ (File Explorer) et bddadmin/ (même bug get_magic_quotes_gpc(), jamais lié au menu admin, système d'authentification par mot de passe codé en dur indépendant du CMS). Références nettoyées dans $sb_safe_pages/$sb_admin_pages.utf8_encode()/utf8_decode() migrées vers sb_utf8_encode()/sb_utf8_decode() sur les fichiers pas encore couverts. Découverte en cours de route : ces fonctions existaient déjà dans backdoor/inc/sbuiadmin-functions.php (iconv(), un premier effort de compatibilité PHP 8.2 fait en 2024) — le front (inc/functions.php) n'avait pas encore cet équivalent, ajouté à l'identique (même implémentation iconv, pas de doublon).f855ffa.htaccess (racine), upload/.htaccess (nouveau), backdoor/install/inc-auth-guard.php (nouveau) + les 7 fichiers de l'assistant d'installation, backdoor/index.php, backdoor/inc/sbuiadmin-rights.php, backdoor/inc/class/sbuiadmin-form.php, et les 12 classes de backdoor/inc/class/.install/ protégé (gardé, pas supprimé — décision du client pour ses futures mises à niveau) : backdoor/install.php (passerelle) avait été supprimé, mais le dossier install/ et ses scripts individuels (assistant tiers "ApPHP EasyInstaller") restaient accessibles sans aucune authentification, même une fois le site en production — installer.lock n'est écrit qu'en fin d'installation, jamais lu/vérifié pour bloquer un accès ultérieur. Nouveau garde-fou (inc-auth-guard.php) inséré dans les 7 fichiers : accès désormais réservé à un admin déjà connecté au CMS.sbuiadmin-form.php::openForm() dans tous les formulaires admin, vérifié à un point d'étranglement unique dans index.php (toute vraie soumission de formulaire, $_POST['form_submit']) — pas les endpoints AJAX qui ne passent pas par cette convention (ex: messages). Limite connue : les actions de tri/réorganisation (glisser-déposer) n'utilisent pas form_submit et restent hors de cette protection.upload/ durci : nouveau .htaccess empêchant l'exécution de scripts (défense en profondeur si une validation d'extension venait à être contournée).X-Content-Type-Options, X-Frame-Options, Referrer-Policy sur le .htaccess racine.public/private des méthodes de classes : les 12 classes de backdoor/inc/class/ passées en revue une par une — chaque méthode "bare" (implicitement publique en PHP) vérifiée par recherche de tous ses appels dans tout le code avant de choisir public ou private (jamais de private sans preuve d'absence d'usage). sbuiadmin-sql.php (classe de base héritée par user/account/panier) : méthodes partagées (query, assoc, toarray, close...) restent public ; connect/error/getArray/optimize/truncate/blob/showUpdateResult/redirect_error passées en private. sbuiadmin-users.php : rehashPassword, deleteRememberTokenById, checkUser, checkIsAdmin en private. sbuiadmin-sanitize.php : 7 méthodes internes en private. sbuiadmin-account.php/sbuiadmin-cart.php (classes dormantes, jamais instanciées dans le code actuel — scaffolding lié au futur module Boutique) : répartition basée sur le rôle apparent de chaque méthode, à revoir si ces classes sont un jour activées. sbuiadmin-csv.php/sbuiadmin-flood.php/sbuiadmin-upgrade.php : terminées selon la même méthode.75ea77dindex.php (racine), backdoor/index.php, backdoor/inc/class/sbuiadmin-users.php, backdoor/users.php, backdoor/install/sql_dump/{sbuiadmin_create,sbuiadmin_create_7.1_and_more}.sql, nouvelle table sb_users_remember_tokens.session_start() (cookie_secure/cookie_httponly/cookie_samesite). L'audit qui a suivi a mis au jour des problèmes bien plus critiques.login(), checkUserIsActive(), updateAccessUserLogin(), getUserInfo() échappaient le nom d'utilisateur via stopXSS() (protège contre <, >, ", \ mais jamais l'apostrophe) au lieu de escape_string() — n'importe quel visiteur non authentifié pouvait injecter du SQL directement via le champ "Utilisateur" de la page de connexion. Corrigé sur les 4 méthodes.encrypt()/decrypt() utilisaient une clé et un IV par défaut codés en dur dans le code source — repérable par quiconque a déjà vu ce dépôt (public sur GitHub). Migré vers password_hash()/password_verify() (bcrypt) : login() vérifie le nouveau format en priorité, retombe sur l'ancien chiffrement en secours, et migre silencieusement chaque compte vers le nouveau format dès sa prochaine connexion réussie (aucune action requise des utilisateurs). encrypt()/decrypt() conservés uniquement comme filet de compatibilité tant que tous les comptes n'ont pas confirmé leur migration — à retirer plus tard.httponly/secure. Remplacé par un vrai jeton sélecteur/validateur (nouvelle table sb_users_remember_tokens) : cookie unique httponly/secure/samesite, à usage unique (tourne à chaque connexion automatique), révoqué à la déconnexion et si le compte est désactivé.session_regenerate_id(true) n'existait qu'au logout — ajouté après toute connexion réussie (formulaire et cookie), empêche la fixation de session.cookie_secure (calculé selon HTTPS détecté, pas codé en dur pour ne pas casser un accès HTTP local), cookie_httponly, cookie_samesite=Lax sur les 2 session_start() (front et admin).else ne coupait l'accès si elle échouait) — remplacée par une simple vérification de session, le statut "actif" restant lui réévalué à chaque requête.backdoor/index-cookie.php (ancien fichier de connexion en doublon, jamais référencé) ; backdoor/inc/class/sbuiadmin-account.php + datas/modules/user/user.php (scaffolding non câblé pour un système de comptes front, même faiblesse de chiffrement — probablement lié au futur module Boutique, Point 18).mysqli_sql_exception, trace technique visible) a été observée pendant le test, le temps que la nouvelle table soit créée manuellement sur la base live — signale que ce CMS dépend du comportement pré-PHP 8.1 de mysqli (retour false sur erreur plutôt qu'exception). À couvrir par le Point 9 (test PHP 8.4).6968095backdoor/profile.php + backdoor/core/tpls/tpl/system/profile.tpl, backdoor/core/tpls/tpl/navigation.tpl, backdoor/inc/sbuiadmin-config.php, backdoor/inc/sbuiadmin-rights.php, backdoor/index.php.users.php, en lecture seule — pas de formulaire ici. Le bouton "Modifier mon profil" renvoie vers users.php?a=edit&id=<son id>, où le système de droits déjà existant reprend la main sans aucune modification (self-service mot de passe seul si l'utilisateur n'a pas le droit "modifier" sur "users", fiche complète sinon, ou toujours pour un admin).$id toujours pris depuis la session (sbGetCurrentUserId()), jamais un paramètre GET/POST — aucune manipulation d'URL ne permet d'éditer la fiche de quelqu'un d'autre. La page est accessible à tout utilisateur connecté sans dépendre des droits du module "users", et explicitement exclue de la matrice de droits (sbGetRightsGroups()) pour qu'un admin ne puisse jamais accidentellement bloquer un utilisateur sur sa propre page de profil.e1f197dbackdoor/assets/adminator/bridge.css (nouveau composant [data-tooltip]) + 12 templates (menu, users, blocs, sandbox, dashboard, contact, pages, tabbs, slider, table, news, faq).title="..." natifs du navigateur par un vrai tooltip stylé, sur toutes les icônes de tous les tableaux (admin et modules de contenu) — pas les autres usages de title= (vignettes image médias/thèmes, non concernées, ce ne sont pas des icônes).[data-tooltip] en CSS pur (::before/::after), pas de JS — bulle centrée au-dessus de l'icône, apparition au survol et au focus clavier (accessibilité), couleurs via les variables CSS Adminator (compatible mode sombre).title="..." → data-tooltip="..." sur 64 icônes (colonne Actions + icônes de statut) réparties sur les 12 templates.8fee612backdoor/core/tpls/tpl/system/menu.tplindex.php pré-assigne la variable Smarty $all à false (jamais unset) avant l'exécution de tout module, pour l'initialiser proprement. Or en PHP, isset(false) vaut vrai — {if isset($all)} dans menu.tpl était donc toujours vrai, y compris pour a=edit/a=add, où $all n'est jamais repassé à true côté PHP (seule la vraie liste le fait). Le template affichait donc systématiquement le bloc "liste" (jamais {include_php file='form.php'}, qui contient le vrai formulaire), mais avec des données vides ($allmenu/$sb_table_header non peuplés hors de la branche liste) — d'où la liste vide au lieu du formulaire.login.tpl ($sbuiadmin_access_code, voir plus bas dans ce changelog).{if isset($all)} remplacé par {if $all} (test de véracité, pas d'existence) aux 2 endroits concernés. Corrige au passage le même bug sur le bouton "Ajouter", qui partage le même code, bien que non explicitement signalé.d616946backdoor/inc/class/sbuiadmin-form.php, backdoor/inc/plugins/pagebuilder/js/pagebuilder.js, backdoor/inc/plugins/pagebuilder/css/pagebuilder.css, backdoor/assets/adminator/pagebuilder-bridge.css, assets/pagebuilder-front.css, nouveau assets/pagebuilder-front.js, inc/functions.php, backdoor/assets/adminator/{confirm,icon-picker}.js.icon-picker.js/addIconFA(), qui s'ouvrait derrière la modale Bootstrap 3 du Page Builder — 2 systèmes de modale, piles de z-index différentes) — réutilise quand même sa liste de 549 icônes via window.SB_FA_ICON_LIST. Couleur via le colorselector déjà utilisé par le bloc Bouton.colorselector.sbBuildRepeaterEditor(). Une 1ère version en édition HTML brute a été jugée pas user-friendly par le client et entièrement remplacée. Le contenu d'un onglet interprète le HTML saisi (gras, liens...) plutôt que de l'échapper en texte brut.sbTransfert() (sélecteur média partagé par tout le CMS) ne renvoie qu'un nom de fichier nu, jamais une URL exploitable hors admin — le bloc Image s'en sortait via un correctif codé en dur sur son seul champ ; généralisé (MutationObserver délégué sur document) pour couvrir les lignes de la Galerie, dont les ids sont générés dynamiquement. Effet de bord découvert au passage : ce même sélecteur écrase aussi la classe CSS de la miniature à la sélection — isolée dans un <div> interne dédié.sbRenamePageBuilderClasses() + son miroir JS sbRenameClasses()) : comparaison par sous-chaîne (\bbtn\b) au lieu de classe entière — un tiret compte comme limite de mot en PCRE/JS, donc "btn" était détecté à l'intérieur de "sb-tabs-btn" et le corrompait en "sb-tabs-sbbtn" à l'enregistrement, cassant silencieusement le CSS/JS des Onglets sur le front (boutons non stylés, clic sans effet). Corrigé par une comparaison par token entier.<head> via insert_sbGetHeaders(), donc avant que <body> existe — la librairie lie ses clics en délégation sur $('body') dès son exécution, qui résout alors sur un ensemble vide (aucune erreur, mais rien n'est lié). Corrigé avec <script defer>.confirm.js, réutilisé plutôt qu'un confirm() natif) : même souci de z-index sous la modale Bootstrap 3 que le popover d'icônes, corrigé (remonté à 100000, même valeur que le popover pour cohérence) ; libellés des boutons manquants au premier essai (arguments non transmis à l'appel), corrigés avec des valeurs par défaut dans showConfirm().b66d1ebMODIFICATIONS_SBUIADMIN.md, à la racine de informatux_test/) devient la référence unique pour ce projet, désormais fusionné avec le contenu de l'ancienne copie du dépôt.sbuiadmin/markdown/MODIFICATIONS_SBUIADMIN.md (suivie par git) a été supprimée, ainsi que tout le répertoire markdown/ du dépôt (visionneuse Markdown index.php/vendor/ et MODIFICATIONS_CABARET.md, jamais suivis par git — supprimés à la demande explicite de l'utilisateur).427b3f0backdoor/assets/adminator/pagebuilder-bridge.cssaddPageBuilder() charge le vrai bootstrap.css de Bower pour son propre canevas, sans le scoper à son propre widget. Ses règles a:hover, a:focus { text-decoration: underline; } et body { font-family: "Helvetica Neue"... } ont la même spécificité que les règles équivalentes du thème Adminator - c'est donc la dernière chargée (bootstrap.css) qui l'emportait.pagebuilder-bridge.css, déjà chargé en dernier sur ces pages. N'affecte que l'admin, pas le rendu front (feuille séparée).98ed232loadRowSettings()/loadColumnSettings() lisaient la valeur CSS calculée (.css('X'), toujours non-vide) au lieu du style inline réel de l'élément - ouvrir les réglages de n'importe quel bloc (même juste pour configurer une image) figeait silencieusement un fond/padding/marge par défaut qui n'avait jamais été choisi. Corrigé en lisant .style.X (vide si non défini).row clearfix, col-md-X column) et, si l'utilisateur les retirait, cassait l'affichage dans le Page Builder lui-même. Corrigé en traitant ce champ comme des classes en plus uniquement - les classes structurelles sont désormais toujours réappliquées par le code, quel que soit le contenu du champ.ace.edit('code') mort dans news.tpl (jamais réellement relié à un champ Actualités) entrait en collision avec le panneau de réglages du Page Builder (même id #code), empêchant la sauvegarde de ce bloc spécifiquement sur Actualités (fonctionnait sur sandbox.php, qui n'a pas ce script). Retiré.a83c6e1assets/leaflet/ côté front, backdoor/inc/plugins/pagebuilder/js/leaflet/ côté admin), pas de CDN.data-popup sur le conteneur (et non en enfant caché, qui serait détruit par l'initialisation de Leaflet).#class, commun à tous les types de blocs) écrasait la classe sb-pagebuilder-map elle-même à la confirmation des réglages - la 1ère confirmation "réussissait" silencieusement, mais le réglage suivant sur ce même bloc ne le retrouvait plus (part.find() vide) et plantait au clic sur "Confirmer". Corrigé en masquant ce champ (sans objet pour une Carte) au lieu de le laisser écraser la classe.inc/functions.php, front) : portage PHP (DOMDocument/DOMXPath) de cleanRow()/sbRenameClasses() (JS, bouton "Code généré") - sbCleanPageBuilderContent() retire tout le chrome d'édition (poignées, boutons remove/clone/réglages, marqueurs de largeur) et renomme les classes Bootstrap survivantes en .sb*, exactement comme l'aperçu "Code généré" côté admin.pages.php), Tabbs (tabbs/inc/functions.php), Actualités (news_display_article.tpl), FAQ (faq/inc/functions.php), et les Blocs (5 gabarits d'affichage : Pages/Contact/Utilisateur/Actualités/Recherche) - sans ce nettoyage, le HTML brut d'édition (icônes, boutons, inputs de taille) s'affichait tel quel sur le site public.assets/pagebuilder-front.css (racine front, déplacée de backdoor/assets/adminator/) et nouveaux fichiers vendorisés assets/leaflet/ (Leaflet 1.9.4) - injectés dynamiquement via insert_sbGetHeaders() (déjà appelé par les 5 thèmes front) plutôt que par le champ "CSS" de Configuration générale, qui enveloppe systématiquement son contenu dans <style> et ne peut donc pas porter une balise <link>. URL absolues (SB_URL/SB_PATH, jamais SB_ADMIN_URL/SB_ADMIN_DIR) : une page publique ne doit jamais référencer un chemin qui renseigne sur l'emplacement/le nom du répertoire d'administration.box-sizing: border-box manquant sur .sbcol-md-*, ce qui faisait passer deux colonnes de 6 à la ligne au lieu de les afficher côte à côte (le padding s'ajoutait à la largeur au lieu d'être inclus dedans).connectToSortable (jQuery UI 1.11.4) ne déclenchait aucun événement sortover/sortreceive en glissant depuis la barre du haut vers le canevas, sans aucune erreur console, alors que le même mécanisme fonctionnait parfaitement sur sandbox.php. Cause exacte non élucidée malgré investigation poussée (écarté : conflit de version jQuery UI, débordement de conteneur, canevas vide vs rempli). Corrigé par un filet de sécurité manuel dans le stop du glisser-déposer : si les coordonnées réelles de la souris au relâchement sont dans la zone de dépôt mais que jQuery UI n'a rien absorbé, on insère le contenu nous-mêmes.8d58f1esbModuleUsesPageBuilder(), sbuiadmin-functions.php).escape_string() sur ce champ (lacune préexistante). Le re-décodage du contenu (nécessaire pour réafficher du HTML brut au Page Builder après une sauvegarde sans redirection) doit donc se faire après l'exécution de la requête SQL, jamais avant - décoder avant y aurait injecté du HTML brut, donc des apostrophes potentielles, directement dans la requête.addPageBuilder() ne charge plus ses assets (Bootstrap/jQuery UI touch-punch/pagebuilder.js) qu'une seule fois par page (protection statique, défensif).enforceWhitelist) listant les champs éligibles - un seul champ par module, celui qui porte le contenu principal : Pages (Contenu), Actualités (Article - pas Intro), Tabbs (Contenu), FAQ (Réponse), Blocs (Contenu). Sauvegardé position 36 de settings.txt.addTagifyWhitelist() (sbuiadmin-form.php), sans toucher à addTagify() existante (doit rester en saisie libre pour les champs qui en ont besoin, ex: mots-clés SEO).disabled n'est jamais soumis par le navigateur).addTagifyWhitelist() ajoutée dans sandbox.php (non persistée).8d58f1e.sb* pour le frontsbuiadmin-form.php) ouvrant une modale en lecture seule avec le HTML qui serait réellement inséré sur la page front.generatePageBuilderCode() (pagebuilder.js) : travaille sur une copie hors-DOM de .htmlpage (jamais le canevas d'édition réel) - cleanRow() retire tout le chrome d'édition, puis les classes Bootstrap qui survivent dans le contenu exporté (grille .row/.col-md-X/.clearfix, boutons .btn/.btn-*, .img-responsive) sont renommées en équivalents préfixés .sb*, pour ne jamais entrer en conflit avec le Bootstrap du thème front qui affichera ce contenu. Résultat indenté (style_html(), déjà présent mais inutilisé).assets/adminator/pagebuilder-front.css : équivalents .sb* de la grille/boutons/média Bootstrap 3 - à charger uniquement sur les pages front qui afficheront du contenu Page Builder (déplacée ensuite en racine front lors du branchement réel, voir plus haut).?v=filemtime()) ajouté sur pagebuilder-bridge.css et pagebuilder.js - le .htaccess racine impose Cache-Control: proxy-revalidate, max-age=3600, qu'un hard-refresh navigateur ne suffit pas toujours à contourner selon l'hébergement..navbar-header:before/:after { content:" " }) devient 2 items flex à part entière une fois le conteneur passé en display:flex - justify-content:space-between répartissait alors l'espace entre 4 éléments au lieu de 2, poussant titre et bouton vers le centre. Neutralisé (content:none). Modale "Code généré" centrée verticalement, titre recentré (bouton close sorti du flux en position:absolute).d19843fconnectToSortable + helper: 'clone') laissait un style inline résiduel (opacity, position, z-index, largeur forcée à 400px pendant le drag) sur le bloc une fois déposé, jamais nettoyé - visible en permanence, pas seulement pendant le drag..css({...})) dans les gestionnaires stop des 2 draggable() concernés (pagebuilder.js). Les blocs déjà enregistrés avant ce correctif restent opacifiés en base tant qu'ils ne sont pas re-glissés/resauvegardés.sandbox.php n'a aucune redirection HTTP après un Ajouter/Modifier (réussi ou en échec) - le formulaire se réaffiche dans la même requête. Le bloc qui décode le contenu (html_entity_decode(utf8_encode(...))) n'est exécuté que côté GET (!$_POST['form_submit']), donc jamais sur ce réaffichage : addPageBuilder() recevait encore la version encodée en entités destinée au stockage. Rien à voir avec l'URL d'image (fausse piste de timing) - le bug touchait aussi bien Ajouter en échec que Modifier, avec ou sans image.$page_builder_content juste après l'échappement SQL (qui a déjà capturé la version entités pour la requête), avant que le formulaire soit reconstruit.media-popup.php, jamais relié à ce CMS) - branché sur le vrai sélecteur de médias partagé (sbOpenPopup()/sbTransfert(), assets/dist/js/sb-custom.js, le même mécanisme que les champs Photo/Pdf ailleurs dans l'admin). Bouton renommé "Choisir une image ..."._AM_MEDIAS_URL + nom de fichier, exposée en JS via window.sbMediasUrl) plutôt qu'un chemin relatif à la popup de sélection ou le simple nom de fichier que range sbTransfert() par défaut.sbOpenPopup() plantait en JS (invalid escape sequence) - le bloc concerné de addPageBuilderTags() est un HEREDOC PHP, où \' n'a aucune signification spéciale et laissait une vraie barre oblique inverse dans le HTML généré.b83eeb2addPageBuilder() (inc/class/sbuiadmin-form.php) et son plugin tiers (inc/plugins/pagebuilder/) étaient laissés tels quels depuis la Phase 3 de la refonte Adminator — jamais finis ni modernisés. Audit préalable : seul sandbox.php l'utilise réellement à ce stade. Cadré en 2 phases avec le client : phase 1 (cette entrée) = réparer le fonctionnement + moderniser le look sur sandbox.php uniquement ; phase 2 (plus tard, voir entrées ci-dessus) = intégration dans les vrais modules avec réglage par module.
addPageBuilder() n'émettait jusqu'ici aucun champ réellement soumis avec le formulaire (seule la zone d'édition visuelle .htmlpage existait) - ajout d'un <textarea> caché, synchronisé automatiquement à la soumission du formulaire (pagebuilder.js). Plus de bouton "Save"/"Edit" propre au widget (demande explicite du client) : la sauvegarde suit exactement le même comportement que n'importe quel autre champ, via le bouton Ajouter/Modifier standard.<form> imbriquées (onglets Youtube/Carte) qui empêchaient silencieusement toute soumission du formulaire principal dans Firefox - remplacées par de simples <div>.sbsanitize->displayText() à la sauvegarde + html_entity_decode() au rechargement, décalés d'une passe) - puis, une fois l'encodage corrigé, contenu rechargé propre mais plus du tout modifiable : le nettoyage du HTML avant stockage (repris de l'ancien mécanisme d'export, jamais pensé pour un usage "recharger et continuer à éditer") retirait les éléments d'interaction (poignées drag/remove/clone/réglages). Solution : ne plus nettoyer avant stockage - le contenu stocké garde tout son chrome d'édition, qui reste pleinement interactif au rechargement sans réhydratation nécessaire (vérifié).addPageBuilder() (comme addCountry() avant elle) n'enregistrait jamais sa place dans formElementArr - le champ suivant écrasait silencieusement tout son HTML ; aucun échappement SQL sur l'ensemble du formulaire sandbox.php ; sb_sandbox (table de démo) entièrement redéfinie ; $formAction ne portait jamais l'id en édition ; champ "Date de naissance" jamais réaffiché (mauvaise variable) ; Tagify mis à jour vers v4.38.0 suite à un bug connu non protégé (document.getSelection() retournant null, issue #1338) qui plantait sans être intercepté et bloquait toute la file d'initialisation JS de la page.assets/adminator/pagebuilder-bridge.css, palette/rayons/ombres Adminator (clair + sombre) sur navbar/boutons/panneau latéral/canevas/modale, sans toucher au moteur Bootstrap 3/jQuery UI (drag & drop, modales) qui reste inchangé.1dbcad7rss : URL de flux (RSS 2.0 ou Atom, parsé via SimpleXML) + nombre d'articles, liste des N plus récents en carte de contenu, aucune mise en cache.iframe : URL http(s) à intégrer, rendu en <iframe sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-forms"> (surface réduite au strict nécessaire).logs : dernières lignes d'un fichier de log - nouveau dossier backdoor/logs/ (protégé par .htaccess deny from all), nom de fichier systématiquement réduit à basename() avant toute lecture (aucune traversée de chemin possible).logaccess ("Dernières connexions") : les N dernières connexions réussies (sb_logaccess, logaccess_type = 'login' uniquement), avec l'avatar de chaque utilisateur (jointure sur sb_users, repli Gravatar générique si l'utilisateur a été supprimé depuis).<select> à une rangée de boutons cliquables avec icône (composant .tabs.pills du thème Adminator), piloté par un input hidden en JS. Bouton "Retour aux widgets" ajouté dans le bandeau .hero des pages d'ajout/modification.addIconFA() n'émettait pas le </div> fermant .field avant le texte d'aide (espacement cassé) ; les groupes de champs conditionnels par type perdaient le display:flex;gap:14px du <form>, faisant chevaucher l'aide avec le champ au-dessus.17f5db4Remplace l'ancien mécanisme de dashboard (fichier plat inc/admin/dashboard.txt, 4 emplacements fixes codés en dur) par un vrai système de widgets configurables (sb_dashboard_widgets), avec CRUD complet (dashboard.php) et plusieurs types de widgets : table (branché sur n'importe quelle table SQL du cœur, compteur/tendance 7j/graphique SVG maison), system (7 métriques serveur), weather (météo Open-Meteo, géocodage à l'enregistrement), html/text (code brut ou CKEditor), puis en suite : rss, iframe, logs, logaccess (voir entrée suivante).
sb_dashboard_widgets, réordonnancement par flèches ↑/↓ dans la liste.inc/class/sbuiadmin-form.php (addIconFA()) : sélecteur d'icônes Font Awesome (549 icônes du bundle embarqué, recherche incluse) — nouveau composant assets/adminator/icon-picker.js.index.tpl : grille de tuiles KPI et cartes "Récent" entièrement pilotées par $sb_dashboard_widgets - plus aucune tuile ni logique codée en dur.{if isset($all)} toujours vrai, remplacé par {if $all}) ; erreur MySQL stricte Incorrect integer value sur show_chart quand la colonne est désactivée côté JS ; erreur mysqli_real_escape_string(): Argument #1 must be of type mysqli, int given sur sql::escape_string() en connexion paresseuse.6c6329bPremier volet du point 12 (page "Profil" personnelle) : extension de la fiche utilisateur existante (users.php) avec les champs profil et une photo, en préparation de la future page self-service.
sb_users : colonnes prenom/nom/telephone/fonction/profession/centres_interet/infos_complementaires/avatar, fusionnées dans les 2 dumps d'install pour les installs neuves.users.php) étendu avec ces champs. Le libre-service "changer uniquement son mot de passe" (utilisateur sans droit "modifier" sur sa propre fiche) continue d'ignorer tous ces champs, comme il ignorait déjà email/username.addInput('text', ..., icon=>'photo', medias=>'')), avec un sous-dossier dédié upload/avatars/ (subdir=>'avatars') plutôt qu'en vrac avec les autres médias. Repli sur Gravatar si aucune photo n'est choisie (sbGetUserAvatar(), nouvelle fonction dans inc/sbuiadmin-functions.php), désormais utilisé dans la liste des utilisateurs et dans la topbar/sidebar (avatar de l'utilisateur connecté) à la place du Gravatar en dur.inc/class/sbuiadmin-sql.php : escape_string() n'avait pas le lazy-connect déjà présent sur query() — Uncaught TypeError si c'est le tout premier appel BDD d'une requête (rencontré via le nouveau calcul de droits sur Messages dans inc/sbuiadmin-header.php).utf8mb4 (seulement les tables) — corrigé dans sql::connect().transfert.php : le mot-clé global de $sbfiles_medias_dirs_allowed s'exécutait après une ligne qui lisait/modifiait déjà cette variable — le paramètre subdir du picker media n'avait donc jamais d'effet (la popup montrait toujours la racine de la médiathèque, jamais le sous-dossier demandé).$sbfiles_medias_exts_allowed) n'était jamais transmise à Smarty depuis transfert.php — transfert.tpl retombait sur un filet de secours mal formé (une seule chaîne au lieu d'un tableau), qui faisait rejeter systématiquement tout upload par Fine Uploader quel que soit le fichier.92e7efdNouveau module de messagerie entre utilisateurs admin (pas de groupes), annoncé avec une page de référence du thème Adminator (chat.html) et cadré ensuite : 1-à-1, mise à jour temps réel, badge de non-lus dans la topbar, nouvelle table SQL incluse dans l'install de départ.
sb_messages (sender_id/recipient_id/message/created_at/read_at) fusionnée dans les 2 dumps de création (sbuiadmin_create.sql/sbuiadmin_create_7.1_and_more.sql) pour les installs neuves. Pas de table "conversations" séparée : dérivées en PHP à partir des paires expéditeur/destinataire.messages.php/messages.tpl (contrôleur racine "système", même famille que settings.php) : liste des conversations, fil de discussion (markup repris de chat.html), marquage lu à l'ouverture d'un fil.index.php?p=messages&ajax=unread|thread|send) et donc soumis au même contrôle de droits que toute autre page — pas d'endpoint standalone (le module de droits avait justement identifié ce genre d'endpoint comme un trou de sécurité potentiel, cf. sbUploadServer.php). Badge topbar pollé ~15s sur toutes les pages, fil ouvert pollé ~4s (assets/adminator/messages.js).messages ajouté à $sb_safe_pages → apparaît automatiquement dans la matrice de droits (auto-découverte existante, aucun code de rattachement à écrire). Visibilité masquée sur les 3 points d'entrée (icône topbar, menu du compte, entrée "Communications" du menu principal) si l'utilisateur n'a pas le droit "voir", en plus du 403 déjà appliqué par le routeur sur l'accès direct par URL.count info, aperçu des conversations non lues au clic ; badge repris aussi dans le menu principal (nouveau nav-label "Communications") avec la classe native du thème .nav-badge.pro..dd-wrap/.dd-menu du thème pour l'ouverture/fermeture), bouton positionné à gauche du champ de saisie, style "outline primary".sql::escape_string() n'avait jamais eu le lazy-connect déjà présent sur query() — passé inaperçu jusqu'ici car toujours appelé après une première requête ailleurs ; le nouveau code de droits dans inc/sbuiadmin-header.php étant le tout premier accès BDD de la requête, ça remontait une Uncaught TypeError. Corrigé à la source dans la classe.utf8mb4 (jamais réglé auparavant, seulement au niveau des tables) — nécessaire pour que les emojis (4 octets) s'enregistrent sans corruption ; sans danger pour les tables encore en utf8 (sous-ensemble strict).dbe6174index.tpl : les 3 alertes fixes du dashboard (répertoire INSTALL présent, fichier INSTALL.PHP présent, utilisateur ADMIN par défaut existant) surchargeaient l'affichage — remplacées par des toasts déclenchés au chargement de la page (type error, rouge), avec le lien d'action ("Vite") conservé.toast.js : sbToast() accepte un lien d'action optionnel en 3ᵉ/4ᵉ arguments positionnels (href, label) — pas un objet JS {...}, pour éviter le conflit avec les délimiteurs {} de Smarty (rencontré en testant : erreur de compilation du template). Ajoute aussi la pause au survol : le décompte s'arrête à l'entrée de la souris et reprend le temps restant (pas remis à zéro) à la sortie ; le timer en attente est annulé en cas de fermeture manuelle.bb77687contact.php : les boutons d'insertion de champs au-dessus du textarea du formulaire (NAME, EMAIL, TEXT, TXTAREA, SELECT, RECAPTCHA, RECAPTCHA_INVISIBLE, SUBMIT) s'affichaient les uns sous les autres. Cause : addAnything() injecte son contenu sans wrapper, comme enfant direct du <form> (display:flex;flex-direction:column) — chaque <button> devenait donc son propre item flex, empilé au lieu de s'aligner. Regroupés dans un <div style="display:flex;flex-wrap:wrap;gap:8px">. Classes Bootstrap 3 mortes (btn-primary/btn-xs, sans effet dans le thème actuel) remplacées par btn--primary/btn--sm.fd15f58Remplace l'ancien mécanisme (sb_users.menu, liste pipe-délimitée de modules masqués dans le menu, sans aucune vérification côté serveur — connaître l'URL suffisait à tout contourner) par une vraie matrice de droits, appliquée avant l'exécution de chaque contrôleur.
sb_users_rights (une ligne par user_id + module, colonnes can_view/can_add/can_edit/can_delete) : absence de ligne = accès complet par défaut. SQL fourni (install/sql_dump/add_users_rights.sql pour les installs existantes + les 2 dumps de création pour les installs neuves).inc/sbuiadmin-rights.php (nouveau) : auto-découverte de tous les modules (sbGetRightsModules(), inclut automatiquement tout nouveau module ajouté à $sb_safe_pages avec un contrôleur réel), découpage en sous-sections pour les modules à zones distinctes (FAQ/News/Tabbs → Catégories/Onglets, Contact/News → Paramètres, Users → IPs bloquées/Paramètres IPs bloquées, CMS Config → ses 8 sous-pages, Configuration → "Thème sample"), classification de chaque requête en voir/ajouter/modifier/supprimer (sbClassifyAction()), avec cas particuliers pour les contrôleurs qui ne distinguent pas affichage et enregistrement par un paramètre d'action dédié (medias, cache/server, theme, themeinfos/session/dashboard, CMS Config).index.php/index-cookie.php) : sbHasRight() vérifié avant sb_global_include(), donc avant toute écriture BDD éventuelle du contrôleur → page 403.tpl dédiée si refusé.sbGetMenuModule()) : chaque sous-lien d'un groupe est filtré individuellement (sbHasMenuLinkRight()) — un groupe avec sous-menu pointant vers des modules différents (Configuration → session/cache/server/theme..., Pages → blocs) n'est plus masqué en bloc si un seul de ses sous-modules est restreint.server/php/sbUploadServer.php) passait par un endpoint entièrement hors routeur, sans aucune vérification de session — n'importe qui, connecté ou non, pouvait y uploader un fichier. Bootstrap minimal (session + droits) ajouté.users.php/users.tpl) : tableau des droits par utilisateur, groupé comme le menu réel (Configuration/Modules), avec grisage automatique d'ajouter/modifier/supprimer quand "voir" est décoché.index.php/index-cookie.php) ; dropdown de la page "Menu" déplacé dans le hero (cohérence avec les autres modules).index.php?p=menu&a=edit&id=X affiche la liste vide au lieu du formulaire d'édition, malgré un debug confirmant que le bon code PHP s'exécute) — cause non identifiée, reporté à une prochaine session avec accès aux logs serveur.eb81d41settings.php : nouveau champ "Durée d'affichage des toasts (secondes)" (position 35 de settings.txt, section Fonctionnalités, défaut 7s).settings.txt depuis zéro, effaçant systématiquement les réglages anti-flood (positions 32-34, gérés séparément par users.php) — préservés désormais.index.php / index-cookie.php : la durée est exposée globalement (toutes les pages), relue et réassignée juste après l'exécution du module routé (ex: settings.php), pour que la page affichée dans la même réponse reflète une modification qui vient d'être enregistrée. Cause : index.php ne lisait settings.txt qu'une seule fois tout en haut, avant même de savoir quel module allait s'exécuter et potentiellement écrire dedans — nécessitant jusqu'ici un 2e rechargement pour voir l'effet, signalé par le client comme un problème connu depuis la création du CMS.scripts.tpl / toast.js : la durée est lue via window.SB_TOAST_DURATION (repli 7s si absente).install/complete_installation.php : position 35 ajoutée au générateur de settings.txt pour les installs neuves.sb_url_customer, sb_sandbox, sb_cms...) et surtout les constantes PHP comme _AM_SITE_DEBUG (mode Debug) — ces dernières ne peuvent structurellement pas être corrigées de la même façon (une constante PHP ne peut pas être redéfinie dans la même requête). 26 fichiers référencent _AM_SITE_DEBUG ; convertir en variable serait un refactor à part entière, risqué pour un gain faible. Client d'accord pour garder ce comportement (effet visible après rechargement).91ca0c2sandbox.tpl : ancienne barre d'outils (sandbox_bar.tpl, boutons .data-toolbar non chartés) remplacée par une section .hero + dropdown .dd-wrap/btn--outline-primary, cohérent avec le reste du backdoor (Tous les enregistrements / Ajouter / Trier + liens de démo). sandbox_bar.tpl supprimé (dernier appelant).bridge.css — nouvelle série de collisions avec Bootstrap 3, toutes dues au widget Page Builder (addPageBuilder()) qui injecte bootstrap.css en cours de page sur cette page précise (même famille que les collisions .input-group/.help-block/.well déjà rencontrées) :
html body (au lieu de body seul) : le fond du thème était écrasé par le fond blanc fixe de Bootstrap..btn.btn (classe doublée) : padding/border-radius/display du bouton de base écrasés par le .btn de Bootstrap..btn--outline-primary.btn--outline-primary / .btn--ghost.btn--ghost : ces deux modifieurs ne redéfinissent que border-color à la spécificité de base — également emportée par le border du .btn Bootstrap. Corrigés séparément du .btn.btn ci-dessus, qui ne fixe volontairement pas border-color pour ne pas prendre le pas sur ces modifieurs (piège rencontré et corrigé en cours de route : une première version de .btn.btn fixait aussi border-color, cassant l'outline).f3f9fe1tabbs.tpl) : même bug que FAQ — les tableaux "Gestion de vos tabbs" et "Gestion de vos onglets" s'affichaient à tort sur les autres actions (ajout, catégories...). Gardés explicitement sur la valeur réelle du paramètre a de l'URL, comme pour FAQ.shared-slider-4col.tpl / pages.tpl) : le bloc "Entête de la page" (édition/ajout d'une page) s'enveloppait lui-même dans .col-4 et était inclus après la fermeture du .col-4 du formulaire — il ouvrait donc une rangée pleine largeur sous le formulaire au lieu de s'empiler dans la colonne droite sous "Choix du template". Partial dé-enveloppé, appel déplacé dans le bon .col-4, margin-top:20px ajouté.cmsconfig.tpl) : icône ajoutée devant "Aide" (panel colonne droite, partagé par les 8 vues : header/footer, CSS, JS, coming soon, multilangue, plugins, polices, SEO).logaccess.tpl) : les messages (logaccess_event/logaccess_user) affichaient les entités HTML littéralement (ex: ') au lieu de les interpréter — |unescape:"htmlall" ajouté (modificateur déjà utilisé partout ailleurs dans le codebase pour ce type de contenu stocké encodé en BDD).bridge.css) : le séparateur de section (addBreak(), .well.form-break-info) ne redéfinissait que border-top — sur cette page, le .well de Bootstrap 3 (injecté par le widget Page Builder) gardait ses 3 autres côtés + arrondi + ombre, faute d'être explicitement écrasés (même famille de bug que les collisions .input-group/.help-block déjà rencontrées, mais ici par couverture de propriété incomplète plutôt que par ordre de chargement). Reset complet ajouté (border:0, border-radius:0, box-shadow:none avant de redéfinir border-top).5adacd1Découverts en creusant un simple souci d'alignement d'icône sur le champ de démo "Nom (2 icônes)" de sandbox.php. Les correctifs étant au niveau de la classe form partagée (inc/class/sbuiadmin-form.php), ils s'appliquent aussi à d'autres modules déjà en production (Slider, News, Pages, Contact), pas seulement à la page de démo.
addInput() : le 2ᵉ icône/texte (icon2, ex. "500 ms") était rendu en dessous du champ au lieu d'être un suffixe dedans (bug touchant aussi Slider : Pause/Speed/Adaptive Height/Slide Margin, et News : Vue brique Masonry) — déplacé dans .input-icon, nouvelle classe .ico-suffix. Icône de gauche mal centrée verticalement (le span était centré mais pas son contenu) — centrage explicite ajouté. Le style de largeur ('style' => 'width: ...') n'était appliqué qu'à l'input, jamais à son wrapper .input-icon — l'icône/suffixe (positionnés en absolu par rapport au wrapper) ne suivaient donc pas le rétrécissement du champ.'icon' => '0...', ex. "Url du site", utilisé aussi par Pages "URL de votre page" et Contact "Clé publique/secrète" reCAPTCHA) : réutilisait .input-icon/.ico, pensé pour un glyphe de taille fixe (14px) — un texte plus long repassait à la ligne mot par mot. Bascule sur le composant natif Adminator .input-group/.addon (largeur libre), avec des règles flex explicites (flex-basis, min-width) pour neutraliser le width:100% par défaut des champs qui entrait en conflit avec le partage d'espace flex.addDate()/addTagify() : un parasite après l'input devenait, .field étant flex, son propre item flex (avec le gap associé) — décalait le texte d'aide vers le bas. Supprimé.addTagify() (champ "Tags", saisie de mots-clés) : les URLs des assets utilisaient SBUIADMIN_URL (sans le protocole https://) au lieu de _AM_SITE_URL — le script ne se chargeait jamais (Tagify is not defined, le champ ne fonctionnait pas du tout). Le style de largeur n'était appliqué qu'à l'input caché, jamais au widget visible (<tags class="tagify">), qui s'étirait donc sur toute la largeur de la carte. Widget jamais adapté au thème (couleurs par défaut de la librairie, jamais reliées aux tokens Adminator — probablement oublié en Phase 7) : dark-mode ajouté via les variables CSS exposées par la librairie.addCountry() (champ "Pays") : la variable $cpt n'était jamais déclarée dans cette méthode (contrairement aux autres) — la ligne d'assignation finale (de toute façon inutile : openSelect()/addOption()/closeSelect() écrivent chacune directement dans le buffer, aucune ne retourne de HTML) écrivait dans une clé de tableau invalide et perturbait l'assemblage du formulaire juste après : les champs Date, Couleur, Tags, Pdf, Photo (x3), Vidéo, cases à cocher et sélecteurs se retrouvaient hors du <form> dans le DOM final (sandbox.php). Ligne supprimée. Le texte d'aide "Choisissez un pays", jusqu'ici silencieusement perdu (jamais transmis à closeSelect()), s'affiche maintenant..help-block (texte d'aide sous les champs) : couleur passée de var(--t-muted) à var(--t-light) — moins présent visuellement, à la demande du client, aligné sur le niveau de discrétion des placeholders de champ. Sur sandbox.php uniquement : ni la couleur ni cette dernière retouche ne s'appliquaient, à cause du .help-block de Bootstrap 3 (chargé par le widget Page Builder de cette page) qui l'emportait — spécificité renforcée (classe doublée) pour rétablir la priorité quel que soit l'ordre de chargement..input-group (bridge.css) : même cause que .help-block ci-dessus (collision avec le .input-group de Bootstrap 3 sur sandbox.php) — spécificité renforcée (.field .input-group).29c545ccore/tpls/tpl/system/settings.tpl) : les 7 valeurs sensibles (Database Host, Database Name, Database User, Database Password, Database Prefix Table, Google ReCaptcha Clé Publique, Google ReCaptcha Clé Secrète) affichent désormais ************** au lieu de la valeur en clair.settings.php) : ces 7 champs passés en type="password" (masquage natif par défaut).backdoor/assets/adminator/peek.js : composant vanilla JS (même esprit que confirm.js/lightbox.js/modal.js) — ajoute un bouton "œil" sur ces 7 champs ; le contenu ne s'affiche en clair que tant que le bouton est maintenu enfoncé (souris ou tactile), et se remasque dès le relâchement. Chargé dans core/tpls/tpl/scripts.tpl.348783bmain.php + lang/french.php) : ajout des entrées "Questions" (index.php?p=faq) et "Catégories" (index.php?p=faq&a=category), sur le modèle du sous-menu Actualités — jusqu'ici FAQ n'avait qu'une entrée de menu plate.datas/modules/tpls/faq.tpl) : le tableau "Gestion de vos questions" s'affichait à tort sur les pages Catégories, Ajouter une question, Ajouter une catégorie et Trier les questions (a=category/add/categoryadd/sort), en plus de son contenu normal. Cause non trouvée côté contrôleur PHP (faq.php) malgré relecture exhaustive — les sections sont désormais gardées explicitement sur la valeur réelle du paramètre a de l'URL (même principe déjà utilisé par la section formulaire du même template), ce qui élimine le symptôme indépendamment de sa cause.inc/), en plus du shortcode [CS ...] à coller dans un contenu éditable : le modifier Smarty |sbGetShortcode et la fonction {insert name="sbDoShortcode" code="..."} (celle déjà utilisée dans les thèmes, ex. navigation.tpl/index.tpl).a15d401settings.php) : ajout de addBreak() pour regrouper visuellement les champs — Les administrateurs, Base de données, Configuration médias, Modules, Captcha (Google reCAPTCHA), Debug, Fonctionnalités, Performance (Smarty). L'option "Activation du mode CAPTCHA (Login)" déplacée juste après le séparateur Captcha (elle était perdue au milieu des autres cases à cocher).main.php, icône "question-circle"), page autorisée (inc/sbuiadmin-config.php), libellé (lang/french.php).datas/modules/faq.php : bugs corrigés (variable $title jamais définie, $sid orphelin d'un autre module, textes d'aide qui parlaient encore de "témoignages"), gestion des catégories ajoutée (add/edit/suppression) — elle manquait complètement alors que le formulaire de question en dépendait déjà.datas/modules/tpls/faq.tpl repris entièrement au design actuel (l'ancien était du Bootstrap "SB Admin 2") : section hero avec dropdowns Questions/Catégories, bouton "Shortcodes" avec modale d'explication.sb_faq / sb_faq_category créées manuellement sur ce site, et ajoutées aux deux scripts d'installation (sbuiadmin_create.sql et la variante PHP 7.1+) plus un script autonome install/sql_dump/add_faq.sql pour les installations existantes.sbuiadmin/datas/modules/faq/, découvert automatiquement comme Contact/Tabbs/News) : [CS name=sbfaq] (toutes les questions actives) et [CS name=sbfaq id=X] (filtré par catégorie), affichage en accordéon HTML natif (<details>/<summary>, sans JavaScript), CSS auto-injecté indépendant du thème actif.569d41finc/class/sbuiadmin-form.php) : addAnything() écrasait le segment précédent au lieu de l'accumuler quand elle était appelée deux fois de suite sans champ de formulaire entre les deux (clé indexée sur le nombre de champs déjà ajoutés, qui n'avance pas tant qu'aucun champ n'est ajouté). C'est ce qui cassait la structure HTML des blocs .config_blocks sur "CMS Config → Plugins" et la grille de droits par menu d'Utilisateurs (balises <div> perdues ou fusionnées).cmsconfig.php) :
.config_blocks/.config_blocks_active/.config_blocks_desactived jamais porté dans bridge.css lors de la Phase 7 malgré des classes confirmées en usage — blocs sans largeur/flottement, empilés en pleine hauteur. Recréé avec les tokens Adminator (au lieu des couleurs codées en dur d'origine).<label> de la case à cocher (.check est en display:flex : chaque enfant, y compris les <br>, devient son propre item de la ligne flex — le <br> ne produisait donc jamais de vrai retour à la ligne, seul un manque de place par coïncidence le donnait l'impression sur les libellés longs). Modale dupliquée id="Four" (APPEAR et MAGNIFIC POPUP) corrigée.<div class="config_blocks"></div> (vestige de l'ancienne mise en page en tableau à 4 colonnes) supprimées.:has(input:checked) — aucun JavaScript. La classe statique .config_blocks_active (calculée au chargement depuis la BDD) est neutralisée pour que seul l'état réel de la case pilote la couleur, y compris après un décochage sans rechargement.users.php) : même refonte (grille, sous-titre "Module : xxx" sorti du .field-label), avec la logique inversée de ce module (coché = entrée restreinte = rouge, décoché = autorisé = vert).bridge.css (inc/sbuiadmin-header.php + header.tpl) : .htaccess impose max-age=3600 sur les CSS/JS, ce qui pouvait servir une version obsolète via un cache intermédiaire même après un vidage du cache navigateur. L'URL embarque désormais la date de modification du fichier (?v=filemtime(...))..hero ajoutées sur Contact, Pages, Slider, Tabbs, Actualités, Tableaux et Blocs, avec les dropdowns d'actions de chaque ancienne barre d'outils (*_bar.tpl, supprimées) consolidés dans hero-actions (bouton btn--outline-primary, cohérent avec Utilisateurs/CMS Config) ; boutons contextuels dépendant du mode (tri, structure/données, photo…) conservés à côté du dropdown. Bloc de stats "Infos News" réintégré directement dans news.tpl.89c1b8fcore/tpls/tpl/shared/shared-settings-hero.tpl : hero + dropdown "Sections" partagé par les 8 pages de la rubrique Configuration (Générale, Session, Serveur, Cache, Dashboard, Toolbar CKEditor, Thème, Thème infos). Ancienne barre d'onglets settings_bar.tpl supprimée. Entrées "Session" et "Serveur" ajoutées au menu principal (main.php + lang/french.php) — elles n'y figuraient pas du tout jusqu'ici..hero ajouté sur Médias, Menu, Journaux, Utilisateurs (eyebrow + titre dynamique + sous-titre selon la rubrique/vue active). Sur Utilisateurs : dropdown "Actions" consolidant l'ancienne barre d'outils (users_bar.tpl supprimée), avec libellé et surbrillance dynamiques (Tous les utilisateurs / +1 utilisateur / IP(s) bloquée(s) / Paramètres IP bloquées) et titre/sous-titre distincts pour chacune des trois vues.assets/samples/ remplacé par les vraies pages de démo du thème Adminator (à la place des anciennes pages Bootstrap "SB Admin 2").theme.tpl : bouton "Activer ce thème" déplacé sous le texte de description (au lieu de caler sa position sur la hauteur de l'image flottante à gauche) ; dégradé vert clair réintroduit sur le thème actif (bridge.css, construit sur les tokens Adminator/mode sombre au lieu du vert vif opaque d'origine).inc/sbuiadmin-functions.php) :
p=/a=.target d'un lien de sous-menu n'était jamais rendu (affectait aussi le lien Gravatar) — corrigé.bridge.css) sur le groupe parent et sur la sous-rubrique active, pour visualiser la section en cours même repliée.bridge.css) : la classe .fixed n'existait qu'en tant qu'ajout dynamique JS (scripts.tpl), invisible à l'audit statique de la Phase 7 qui avait donc supprimé la règle position:fixed sous-jacente — le panneau ne devenait jamais réellement fixe au scroll, sur toutes les pages utilisant ce composant. Fix connexe : l'animation d'entrée de .grid se terminait sur transform:translateY(0) (pas none) avec fill-mode:both, créant un référentiel de positionnement parasite pour tout position:fixed descendant — passé en fill-mode:backwards. Panneau ajouté sur dashboard.php (Database Dashboard), qui n'en avait pas.floodCheck() jamais appelée nulle part malgré une classe et une UI de gestion des IP bloquées déjà existantes) :
inc/class/sbuiadmin-flood.php rendu configurable (durée de blocage, délai entre tentatives) et défensif (no-op silencieux si Memcache est indisponible, plus de crash possible du login).index.php, avant toute vérification des identifiants.users.php, action blockedipsettings) accessible depuis le dropdown "Actions" d'Utilisateurs.settings.txt de l'installeur (install/complete_installation.php), qui n'avait pas suivi ces ajouts (rattrape aussi un oubli antérieur sur "médias par page").0739a78backdoor/assets/adminator/bridge.cssaddBreak(), ex: "STATUS 1-4" sur dashboard.php, "Coordonnées"/"Réseaux sociaux" sur themeinfos.php) gardait un rendu hérité de l'ancien thème (fond gris + bordure bleue épaisse, texte 1.5em) qui détonnait avec le reste du formulaire (labels discrets, bordures fines).border-left: 3px solid var(--primary)), léger fond grisé (var(--bg-muted)) sur toute la largeur, et une fine ligne de séparation au-dessus du bloc.fa9ff93sb-admin-custom.css sans porter la règle de base p.sbmedia (float/taille/marges) — seuls les boutons de suppression avaient été repris, les vignettes s'empilaient de nouveau en pleine largeur. Restaurée dans bridge.css, bordure passée à #767677.inc/class/sbuiadmin-pagination.php — classe déjà présente dans le code mais jamais instanciée nulle part. Recolorée aux tokens Adminator (mode sombre inclus), bloc centré, texte d'info ("X à Y sur Z résultats") grisé et réduit. Bug latent corrigé au passage : le CSS ciblait .currentpage mais le code générait .active — la page courante ne se surlignait donc jamais.settings.php), stocké en position 31 de settings.txt, défaut 24.medias.php) : si la page demandée dans l'URL dépasse le nombre de pages réel (ex: on vient de réduire le nombre de médias par page), elle est ramenée à la dernière page valide au lieu d'afficher une liste vide.medias.tpl / bridge.css) : image de vignette recentrée (display:block + margin:auto — le text-align:center du parent ne centre pas les <img> en display:block, c'était la vraie cause du décalage) ; croix de suppression repositionnée sur le coin des pointillés (top/right:-8px) au lieu du centre du bloc ; padding-top ajouté sur le conteneur overflow:hidden pour ne plus rogner la croix qui dépasse en haut de la première rangée ; h2.card-title retiré du bloc grille d'images (garde l'eyebrow seul) ; eyebrow retiré des blocs Upload/Informations (garde le h2 seul) ; marge ajoutée entre les deux lignes de blocs.scripts.tpl) : la page se recharge désormais une fois tout le batch d'upload terminé (onAllComplete), plus par fichier individuel (onComplete), qui rechargeait la page en plein milieu d'un upload de plusieurs fichiers.inc/sbuiadmin-functions.php) : sbGetIfIsImg()/sbGetInfoImg() plantaient (array_values(): Argument must be of type array, bool given) sur tout fichier non-image (PDF, vidéo...) — getimagesize() retourne false dans ce cas, un simple warning silencieux avant PHP8 mais une erreur fatale depuis. Corrigé pour retourner proprement false/0.upload_max_filesize=2M, post_max_size=8M), silencieusement vidées par PHP avant même que le script ne s'exécute. .htaccess (mod_php) tenté d'abord, sans effet — confirme un serveur PHP-FPM/CGI — .user.ini ajouté à la place (mécanisme honoré par PHP-FPM pour ces deux réglages précis).sbSyncUploadLimits() (inc/sbuiadmin-functions.php), appelée depuis settings.php après un enregistrement réussi des paramètres — répercute la valeur "Taille max. autorisée" sur .htaccess et .user.ini en une fois, sans étape manuelle serveur à chaque changement.8cc6683backdoor/core/tpls/tpl/navigation.tpl/var/www/html/themes/ADMIN/adminator/2026.js — la sidebar n'a qu'un bloc simple non cliquable (nom + rôle), le menu déroulant (Réglages/Profil/Messages/Déconnexion) est un avatar cliquable tout à droite de la topbar.index.php?p=settings, visible seulement si $sbuiadmin_user_type == 'admin'), "Profil" et "Messages" affichés grisés sans lien (pages pas encore créées, voir backlog points 12/13), "Déconnexion" pour tout le monde.backdoor/core/tpls/tpl/main_menu.tplnav-label "Workspace" au-dessus de l'entrée "Dashboard".backdoor/assets/adminator/bridge.cssui.html (composant .popover-demo/.pop du thème).[data-tip] construit avec le même style visuel mais un vrai comportement au survol, ancré en dessous du déclencheur au lieu d'au-dessus.data-theme, sans JS supplémentaire.e216074sbuiadmin_netinstall.php./administration/index.php, un dossier inexistant.backdoor, déjà entièrement paramétrable via la constante SBADMIN dans sbconfig.php (seul point de config à changer pour renommer ce dossier, tout le reste du CMS en dépend : SB_ADMIN_URL, SB_ADMIN_DIR...)../backdoor/index.php.8caf7d3backdoor/core/tpls/tpl/shared/shared-panel-actions.tplimg,svg{display:block} du thème Adminator rend le SVG de titre bloc, ce qui le fait passer à la ligne au lieu de rester en ligne avec le texte suivant dans le <h2 class="card-title">.display:flex;align-items:center;gap:6px sur le <h2 class="card-title">.backdoor/inc/class/sbuiadmin-form.phpaddInput() consécutifs ; chacun devenait son propre enfant direct du <form> (display:flex;flex-direction:column, Phase 3), donc chacun occupait sa propre ligne.reset qui suit immédiatement un submit rejoint désormais la même ligne, via un wrapper flex détecté automatiquement à l'aide d'un marqueur HTML sur l'élément précédent — sans avoir à modifier les ~50 sites d'appel addInput('submit'/'reset', ...) à travers le code.backdoor/assets/adminator/bridge.css.nav-label : font-size passé à 14px, padding passé à 15px 10px 0px.7fef40astyle="display:none" codé en dur dans leur HTML (5 des 7, dont "Shortcodes" du module News) s'affichaient en permanence dans la page au lieu d'être masqués — le masquage par défaut ne venait que du CSS Bootstrap, supprimé en Phase 7. Ajout d'une règle .modal{display:none} injectée dès le chargement du script, indépendante des styles inline du HTML.order CSS sur .close, sans toucher au HTML..eyebrow : font-size porté à 20px ; .card-title-wrap .eyebrow : margin-bottom porté à 14px.9144e68index.php, core/tpls/tpl/system/login.tplsb_url_customer (l'URL du vrai site, déjà utilisée pour le lien "Aller sur le site" de la topbar) n'était calculée qu'après authentification — jamais disponible sur la page de login, qui retombait donc sur _AM_SITE_URL (l'URL de l'admin).sb_url_customer assignée dès le chargement des réglages (juste après $sb_link_settings), donc disponible dès la page de login ; l'assignation existante après connexion (avec la logique "coming soon") reste inchangée et prend le dessus une fois connecté. login.tpl utilise {$sb_url_customer} avec repli sur _AM_SITE_URL.9144e68Avant toute suppression, audit exhaustif (templates + contrôleurs PHP racine, pas seulement les dossiers habituels) de ce qui dépendait encore réellement de Bootstrap/jQuery/sb-admin-2/sb-admin-custom, pour ne rien casser silencieusement.
header.tpl/scripts.tpl). Seul le Page Builder (sandbox.php, module Pages) en dépendait encore réellement (modals/collapse/buttons-radio jQuery, chrome navbar/grille complet) — rendu autonome : inc/class/sbuiadmin-form.php::addPageBuilder() charge désormais son propre bootstrap.css/bootstrap.min.js, indépendamment du reste de l'admin.backdoor/assets/adminator/modal.js : remplace le plugin modal Bootstrap (même esprit que confirm.js/lightbox.js, vanilla JS, auto-injecte son CSS) pour les 7 dialogues restants : navigation.tpl (mises à jour core/modules, x2), system/users.tpl (IP bloquée), datas/modules/tpls/table.tpl (aides, x3), datas/modules/tpls/news.tpl (shortcodes). L'accordéon Bootstrap de tabbs.tpl ("Que fait TABBS ?") converti en toggle JS inline (cas unique, pas de composant dédié).rel="facebox" du markup reste, réutilisé par lightbox.js), MetisMenu, sb-admin-2.js.sb-admin-2.css / sb-admin-custom.css / sb-admin-custom-login.css. Ces fichiers portaient bien plus que du "pont Bootstrap" : ~90 sélecteurs audités un par un (dont plusieurs qui n'étaient utilisés que dans des contrôleurs PHP à la racine comme cmsconfig.php/users.php/dashboard.php, hors des dossiers explorés au premier passage). Les règles encore réellement actives portées dans bridge.css : aide de champ (.help-block, quasi tous les types de champ), séparateur de section (addBreak() → .well.form-break-info), widget photo (.transfert-media-img*, .icon-transfert), glisser-déposer (#sortable/#sortable-grid, .sb-sort-i), bouton de suppression sur les vignettes médias (.sbmedia-delete), dialogues de mise à jour (.sbupgrade-filelist, .upgrade-now), cartes/prévisualisations de thème (.theme_img, .theme_view...), utilitaires (.red/.green/.center/.margin10).btn-default/btn-danger/btn-info/btn-outline) migrés vers les classes natives Adminator (btn--ghost/btn--danger/btn--warning/btn--sm) dans navigation.tpl, users.tpl, table.tpl, news.tpl, medias.tpl, contact.php, cmsconfig.php. Le bouton de suppression des vignettes médias perd btn btn-info btn-circle (redondant avec les propriétés déjà !important de .sbmedia-delete).bridge.css renommé conceptuellement : ce n'est plus un "pont de compatibilité temporaire" mais l'extension permanente du thème Adminator (gap-fills de grille, skin dark-mode des widgets tiers, classes custom historiques).9144e68.card du thème Adminator est en display:flex;flex-direction:column. Plusieurs blocs de contenu hérités (p.sbmedia, .theme_img, .config_blocks) comptent sur float:left (CSS legacy, sb-admin-custom.css) pour s'aligner côte à côte — mais le float n'a aucun effet sur un enfant flex direct, qui s'empile donc verticalement à la place.<div style="overflow:hidden"> (contexte de blocage de flottants) autour des groupes d'éléments concernés :
system/medias.tpl et system/transfert.tpl (galerie de vignettes médias).system/theme.tpl (image de prévisualisation + description du thème).cmsconfig.php (onglet Plugins) et users.php (grille des droits d'accès menu) : ici le HTML est injecté directement dans le formulaire via $sbform->addAnything(), sans wrapper — même correctif appliqué côté PHP autour des blocs .config_blocks.e61a994backdoor/inc/sbuiadmin-functions.php (sbGetMenuModule())$modules_order liste 9 fichiers dont database.php et explorer.php, qui n'existent pas dans backdoor/. array_intersect($modules_order, $modules_dir) conserve les clés du premier tableau pour les entrées trouvées, ce qui laisse des trous dans les indices (2 et 3 manquants). La boucle for qui suit utilise count() sans réindexer et ne réinitialise pas $module_name quand une clé manque — aux indices manquants elle réutilise la valeur précédente (logaccess) et la traite en double, tout en empêchant les 2 dernières entrées de la liste (menu, blocs) d'être atteintes par la boucle (elles étaient silencieusement absentes du menu).array_values() ajouté autour du résultat de array_intersect() pour réindexer proprement le tableau.e61a994backdoor/inc/admin/version.php3.01, alors que le readme affichait déjà 4.10 — la version bumpée au dernier c/p/m n'était que dans le readme, pas dans le code._AM_START_VERSION (celle réellement utilisée par les templates via {$smarty.const._AM_START_VERSION}) est définie séparément dans backdoor/inc/admin/version.php, indépendante du readme._AM_START_VERSION mise à 4.10.INFORMATUX vers un lien [informatux45](https://github.com/informatux45).be37252backdoor/inc/class/sbuiadmin-form.php.card).openForm() place le <form> en display:flex;flex-direction:column (Phase 3) — sans align-self explicite, les enfants flex s'étirent par défaut (align-items: stretch). Les <div class="field"> en profitaient (comportement voulu), mais les boutons submit/reset (rendus en enfants directs du formulaire, sans wrapper) en subissaient l'effet de bord.style="align-self:flex-start" sur ces boutons — point de levier unique, corrige toutes les pages du backdoor d'un coup.903174aform (sbuiadmin-form.php) signalée par le client comme ne collant pas encore parfaitement partout..grid/.card/.data-toolbar/.dd-wrap : users, menu, medias, settings, cmsconfig, blocs, logaccess, cache, server, session, theme, themeinfos, toolbarck, sandbox, files, transfert, dashboard (page "Database Dashboard").backdoor/assets/adminator/lightbox.js : remplace Facebox (vanilla JS, auto-injecte son propre CSS, event delegation sur [rel*="facebox"] pour compatibilité rétroactive avec le markup existant, sans changement de template nécessaire). Utilisé par users.tpl et medias.tpl (prévisualisation d'images médias). Facebox retiré de scripts.tpl.cmsconfig_bar, menu_bar, sandbox_bar, settings_bar — partagée par settings/session/server/cache/dashboard/toolbarck/theme/themeinfos —, users_bar) migrées de .well.well-sm + dropdowns Bootstrap vers .data-toolbar + .dd-wrap, même principe que les barres de modules en Phase 5.theme.tpl : le sélecteur de thème conserve les classes theme_block/theme_block_active pour le marquage visuel de l'état actif sans JS supplémentaire ; leur ancien style (fond en dégradé vert hérité de sb-admin-custom.css) neutralisé dans bridge.css au profit d'une bordure d'accent cohérente avec .card.</div> surnuméraire dans cmsconfig.tpl (branche SEO, section formulaire) ; shared/shared-slider-4col.tpl utilisait encore .col-lg-4 (classe Bootstrap sans effet dans la grille CSS Adminator, la colonne "Entête de la page" du module Slider ne se positionnait plus correctement) — renommée en .col-4..well/.panel/btn-group/col-lg-* (seule trace restante : du code mort dans un commentaire Smarty non rendu de table.tpl, laissé tel quel).readme.md avec entrée changelog résumant la refonte.d989a45bridge.css, QA complète).contact.tpl, pages.tpl, tabbs.tpl, slider.tpl, table.tpl, news.tpl : grille Bootstrap .row/.col-lg-* migrée vers .grid/.col-N d'Adminator, panneaux .panel panel-default vers .card/.card-head/.card-title. C'était la dernière pièce visuelle de ces pages (formulaires, tableaux, barres d'outils déjà migrés lors des passes précédentes) — panneaux d'aide, panneaux d'information et panneaux conditionnels compris. Les dialogues Bootstrap encore utilisés (aide "Tableau pleine page", shortcodes news) restent fonctionnels tels quels.bridge.css : ajout de .col-8 (pattern formulaire 8/4 colonnes très fréquent dans ces modules).slider.tpl (bug pré-existant, confirmé sur le commit d'avant-session) ; deux fermetures de div orphelines que j'ai moi-même introduites par erreur lors d'une première passe sur table.tpl, repérées et corrigées avant de committer.aa4da8dbackdoor/assets/adminator/confirm.js : dialogue de confirmation vanilla JS (auto-injecte son propre CSS, event delegation sur document via l'attribut data-confirm="message" — fonctionne automatiquement sur tout élément présent ou futur) qui remplace jQuery jConfirm. Ancienne librairie retirée de scripts.tpl ; tous les boutons de suppression (pages système, modules, et medias.tpl bien que non encore migré visuellement — corrigé quand même pour ne pas perdre silencieusement la confirmation) migrés vers data-confirm.contact_bar, pages_bar, tabbs_bar, news_bar, slider_bar, table_bar) : .well.well-sm + dropdowns Bootstrap migrés vers .data-toolbar + dropdowns Adminator (.dd-wrap, pilotés par le JS vanilla déjà en place, plus par Bootstrap JS).news_bar.tpl : petit tableau de statistiques converti en carte avec .stat-cell.shared-panel-actions.tpl (panneau sticky "Actions") et shared-slider-4col.tpl : migrés vers .card..chev du thème n'est stylée que dans des contextes spécifiques (menu latéral, accordéon), utilisée seule dans ces boutons elle ne produisait aucun effet. Remplacée par un positionnement flex explicite sur les 6 boutons concernés.7cbabfbbackdoor/core/tpls/tpl/system/index.tpl : les 4 cartes statistiques admin (utilisateurs, version PHP, DB host, limite d'upload) et les 4 cartes de statuts configurables migrées de .panel/.huge vers .kpi-grid/.kpi-card (icônes SVG dédiées, carte entière cliquable au lieu d'un simple lien en pied de carte, icône Font Awesome dynamique conservée pour les statuts configurables)..list-group vers .card/.card-head/.card-title/.card-action — fusion des deux .row Bootstrap (contrainte 3+1 colonnes) en une seule .grid (CSS Grid gère nativement le retour à la ligne)..col-6/.col-12 pour sa grille 12 colonnes — .col-3/.col-4 ajoutés dans bridge.css, réutilisables pour les phases suivantes.12d9cf0backdoor/core/tpls/tpl/system/index.tpl (le vrai dashboard d'accueil, p=index — distinct de system/dashboard.tpl qui est une page "Database Dashboard") : ajout d'un bandeau .hero avec la date du jour en français (calculée en PHP dans index.php, sans dépendance à la locale système) et un message de bienvenue personnalisé avec le nom de l'utilisateur connecté..alert.danger d'Adminator.system/users.tpl, encart informatif "Anti-Flood"), restylée en .alert.warning. Confirmé qu'aucune autre alerte ancien format ne subsiste nulle part.3c7b212backdoor/inc/class/sbuiadmin-form.php : migration du constructeur de formulaires partagé (utilisé par ~10 pages) vers le markup Adminator — .field/.field-label/.input-icon/.ico pour les champs texte (icônes Font Awesome conservées, ~25 icônes utilisées dans l'app dont des logos de marques), .select/.textarea pour les listes déroulantes et zones de texte, .check pour les cases à cocher et boutons radio, boutons submit/reset restylés en btn btn--primary/btn btn--ghost.open_div/close_div) jamais consommé par le rendu final. Supprimé. Vérifié par un test de rendu autonome que le HTML généré reste bien équilibré.addTextarea(), les attributs required/bname étaient par erreur concaténés à l'intérieur de la valeur de l'attribut class, produisant du HTML invalide sur les champs textarea obligatoires.assets/adminator/bridge.css pour eux ainsi que les widgets jQuery UI (datepicker, colorpicker), afin qu'ils restent lisibles en mode sombre.addPageBuilder(), utilisé par sandbox.php et le module Pages) a son propre chrome Bootstrap complet, plus lourd que CKEditor — laissé tel quel pour l'instant.3c7b212Le client a demandé de restyler tous les tableaux utilisant DataTables selon datatable.html d'Adminator, avant l'exécution dans l'ordre des Phases 4-6. Fait en une passe dédiée.
backdoor/assets/adminator/datatable.js : composant vanilla JS générique (tri au clic sur les colonnes, recherche texte côté client, pagination) qui remplace jQuery DataTables — le thème Adminator ne fournit que le markup statique de démo, aucune logique. Opère directement sur les lignes déjà rendues par PHP/Smarty, aucun changement à la récupération des données..data-table/.data-row/.data-cell-actions/.btn--icon sur 14 fichiers : system/{users,logaccess,menu,sandbox,blocs}.tpl, datas/modules/tpls/{contact,pages,tabbs,news,slider,table}.tpl (câblés au nouveau composant JS), plus system/{settings,dashboard}.tpl (2 tables statiques de récapitulatif de configuration — restylées visuellement seulement, elles n'étaient jamais réellement pilotées par DataTables à l'origine).jquery.dataTables.min.js et dataTables.bootstrap.min.js de scripts.tpl (plus aucune page ne les utilise).data-sort-value (valeur brute avant date_format), au lieu d'un tri alphabétique incorrect sur le texte affiché.dataTables-menu/dataTables-menus dans menu.tpl (le tri ne s'appliquait jamais) ; id HTML dupliqué dataTables-tablestructure utilisé par deux tableaux différents dans table.tpl (renommé en dataTables-tabledata pour le second) ; balise <h5> invalide directement enfant d'un <table> dans table.tpl (déplacée au-dessus).2ac77a2Cette phase impacte toutes les pages connectées d'un coup (sidebar/topbar partagées par l'ensemble du backdoor).
backdoor/core/tpls/tpl/navigation.tpl : reconstruit intégralement — sidebar Adminator (.d-sidebar/.nav-section/.nav-link/.nav-item-group) et topbar (.d-topbar) avec dropdowns notifications/mises à jour, infos, menu compte (déconnexion), bouton mode sombre.backdoor/inc/sbuiadmin-functions.php (sbGetMenuModule()) : seule la sortie HTML est migrée vers le markup Adminator (is-active/is-open) — logique d'autorisation et de calcul d'état actif strictement inchangée.backdoor/core/tpls/tpl/main_menu.tpl : entrées Dashboard/Sandbox portées sur le nouveau markup. Bug latent corrigé au passage : le surlignage actif de ces deux entrées ne fonctionnait jamais (comparaison sur une variable Smarty $active jamais assignée nulle part) — remplacé par un test sur $smarty.get.p, cohérent avec sbGetMenuModule().backdoor/core/tpls/tpl/header_tpl.tpl : réduit aux messages flash + debug (le titre/breadcrumb est déplacé dans la topbar).backdoor/core/tpls/tpl/sb_header.tpl / sb_footer.tpl : #page-wrapper devient <main class="content">.backdoor/core/tpls/tpl/header.tpl / scripts.tpl : Font Awesome repassé en auto-hébergé (fin du CDN), suppression de MetisMenu et sb-admin-2.js (vestiges confirmés, plus aucune référence après la réécriture du chrome), bootstrap.min.js conservé (encore requis par plusieurs pages de contenu pas encore migrées : dropdowns/onglets/modals Bootstrap), bundle JS Adminator chargé globalement.backdoor/assets/adminator/bridge.css : adapte les classes Bootstrap 3 encore utilisées par les pages de contenu pas migrées (Phases 4-6) aux tokens visuels d'Adminator, y compris le mode sombre..sbmenufixed (bouton d'action fixe dans les longs formulaires) passait sous la nouvelle topbar — repositionné à top: 70px avec un z-index sous celui de la topbar, dans bridge.css.d8dc5e6backdoor/core/tpls/tpl/system/login.tpl : reconstruit avec le markup Adminator (.auth-shell/.auth-card), toute la logique Smarty existante conservée (codes d'erreur E1-E4, détection navigateur IE, reCAPTCHA conditionnel, noms de champs de formulaire inchangés côté backend).backdoor/core/tpls/tpl/404.tpl : reconstruit sur le même principe (.error-shell/.error-card).backdoor/500.html) : page statique autonome, indépendante de Smarty (reste affichable même si Smarty est en cause dans l'erreur fatale).backdoor/inc/sbuiadmin-header.php (__fatalHandler()) : sur erreur fatale, affiche désormais la nouvelle page 500 avec le message d'erreur réel intégré (encart rouge, échappé HTML) au lieu du var_dump() brut ; le var_dump() complet reste affiché uniquement en mode debug (_AM_SITE_DEBUG) ; le détail complet (message/fichier/ligne) est dans tous les cas tracé via error_log().c6e0a4bDébut d'un chantier par étapes visant à remplacer entièrement l'ancien thème Bootstrap 3 / jQuery (~2016, "SB Admin 2") du backdoor par le thème moderne Adminator (CSS Grid + variables CSS, mode sombre natif). Plan détaillé en 8 phases conservé dans /home/patrice/.claude-patrice/plans/ethereal-bouncing-volcano.md.
backdoor/assets/adminator/ — assets du thème Adminator (CSS compilé, bundle JS 2026.js/vendors.js/vendor-chartjs.js/vendor-fullcalendar.js/runtime.js, polices, images).assets/adminator/fonts/ — suppression de l'@import externe vers fonts.googleapis.com dans style.css (plus de dépendance CDN à l'exécution).backdoor/core/tpls/tpl/header.tpl : ajout d'un script inline de bootstrap du mode sombre (data-theme, lu depuis localStorage/préférence système) exécuté avant le premier rendu pour éviter le flash de mauvais thème.{if $page == 'login'} pour l'instant), en parallèle de l'ancien stack Bootstrap 3/jQuery/Font Awesome CDN (conservé pour les pages pas encore portées) — migration additive, page par page.assets/dist/css/sb-admin-custom-login.css contenait une règle globale * { margin: 0px auto; } qui cassait la nouvelle mise en page en grille — son chargement est désormais désactivé pour la page de connexion.backdoor/core/tpls/tpl/system/login.tplalert alert-danger alert-danger-custom) s'affichait vide sur la page de connexion, même sans avoir rien saisi ni soumis le formulaire.backdoor/index.php initialise sbuiadmin_access_code à false à chaque chargement de la page (avant toute tentative de connexion). Le template testait {if isset($sbuiadmin_access_code)}, qui est vrai même quand la valeur vaut false (Smarty isset teste l'existence, pas la véracité) — d'où l'affichage du cadre sans texte (aucun des cas E1/E2/E3/E4 ne correspondant à false).{if $sbuiadmin_access_code}, qui n'affiche le bloc que si le code vaut réellement une des valeurs d'erreur.81e05b5backdoor/inc/class/sbuiadmin-users.phpUncaught Error: Call to a member function displayText() on null dans updateAccessLog() (ligne 86), qui bloquait totalement l'accès à la page d'administration (backdoor).$sbsanitize sans le déclarer avec global $sbsanitize;, contrairement aux autres méthodes de la classe (ex: getUserInfo()). PHP 8 lève une erreur fatale sur un appel de méthode sur null (auparavant silencieux/warning en PHP 7).global $sbsanitize; en début de méthode updateAccessLog().81e05b5