Files
xamxam/public/admin/pages-edit.php
Pontoporeia fe1f8629ea rename admin-submit-wrap → admin-form-footer across all templates and CSS
- Updated 6 admin templates: add.php, edit.php, login.php, account.php,
  import.php, pages-edit.php — replaced <div class="admin-submit-wrap">
  with <div class="admin-form-footer">
- Updated 8 CSS selectors in admin.css:
  - .admin-form-footer { margin-top/padding-top } (was .admin-submit-wrap)
  - .admin-form > div:not(.admin-form-footer) grid exclusion guard (×3)
  - .admin-login-box .admin-form > div:not(.admin-form-footer) overrides (×2)
  - .admin-login-box .admin-form-footer compact spacing override
- No visual change; purely a semantic rename to a descriptive class name
- Also marked status-badge.php partial and WCAG 1.3.1 badge tasks as
  already-done in todo/02-php-components.md and todo/04-accessibility.md
  (partial + CSS were fully implemented but todo had not been updated)
2026-04-06 15:33:08 +02:00

107 lines
8.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . "/../../config/bootstrap.php";
require_once __DIR__ . '/../../src/AdminAuth.php';
AdminAuth::requireLogin();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
require_once __DIR__ . '/../../src/Database.php';
$allowedSlugs = ['about', 'licenses', 'charte', 'contact'];
$slug = $_GET['slug'] ?? '';
if (!in_array($slug, $allowedSlugs)) {
header('Location: /admin/pages.php');
exit;
}
try {
$db = new Database();
$page = $db->getPage($slug);
if (!$page) {
die("Page introuvable.");
}
} catch (Exception $e) {
die("Erreur: " . htmlspecialchars($e->getMessage()));
}
$pageTitle = "Éditer : " . htmlspecialchars($page['title']);
$extraCss = ['/assets/css/easymde.min.css'];
$extraJs = ['/assets/js/easymde.min.js'];
// SVG icons for each toolbar button — eliminates the Font Awesome dependency entirely.
// Paths sourced from Tabler Icons (MIT). 20×20 viewBox, stroke-based, no fill.
$extraJsInline = <<<'JS'
var SVG = {
bold: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h8a4 4 0 0 1 0 8H6z"/><path d="M6 12h9a4 4 0 0 1 0 8H6z"/></svg>',
italic: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/></svg>',
heading: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4v16"/><path d="M18 4v16"/><path d="M6 12h12"/></svg>',
quote: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z"/><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z"/></svg>',
"unordered-list": '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="9" y1="6" x2="20" y2="6"/><line x1="9" y1="12" x2="20" y2="12"/><line x1="9" y1="18" x2="20" y2="18"/><circle cx="4" cy="6" r="1" fill="currentColor" stroke="none"/><circle cx="4" cy="12" r="1" fill="currentColor" stroke="none"/><circle cx="4" cy="18" r="1" fill="currentColor" stroke="none"/></svg>',
"ordered-list": '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>',
link: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>',
image: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg>',
preview: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',
"side-by-side": '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="18" rx="1"/><rect x="14" y="3" width="7" height="18" rx="1"/></svg>',
fullscreen: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/></svg>',
guide: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>'
};
var toolbar = [
{ name: 'bold', action: EasyMDE.toggleBold, icon: SVG.bold, title: 'Gras (Ctrl+B)' },
{ name: 'italic', action: EasyMDE.toggleItalic, icon: SVG.italic, title: 'Italique (Ctrl+I)' },
{ name: 'heading', action: EasyMDE.toggleHeadingSmaller, icon: SVG.heading, title: 'Titre' },
'|',
{ name: 'quote', action: EasyMDE.toggleBlockquote, icon: SVG.quote, title: 'Citation' },
{ name: 'unordered-list', action: EasyMDE.toggleUnorderedList, icon: SVG['unordered-list'], title: 'Liste à puces' },
{ name: 'ordered-list', action: EasyMDE.toggleOrderedList, icon: SVG['ordered-list'], title: 'Liste numérotée' },
'|',
{ name: 'link', action: EasyMDE.drawLink, icon: SVG.link, title: 'Insérer un lien (Ctrl+K)'},
{ name: 'image', action: EasyMDE.drawImage, icon: SVG.image, title: 'Insérer une image' },
'|',
{ name: 'preview', action: EasyMDE.togglePreview, icon: SVG.preview, title: 'Aperçu (Ctrl+P)', noDisable: true },
{ name: 'side-by-side', action: EasyMDE.toggleSideBySide, icon: SVG['side-by-side'], title: 'Côte à côte (F9)', noDisable: true, noMobile: true },
{ name: 'fullscreen', action: EasyMDE.toggleFullScreen, icon: SVG.fullscreen, title: 'Plein écran (F11)', noDisable: true, noMobile: true },
'|',
{ name: 'guide', action: 'https://www.markdownguide.org/basic-syntax/', icon: SVG.guide, title: 'Guide Markdown', noDisable: true }
];
var easyMDE = new EasyMDE({
element: document.getElementById('content'),
autoDownloadFontAwesome: false,
toolbar: toolbar,
spellChecker: false,
status: ['lines', 'words'],
minHeight: '400px',
toolbarTips: true
});
JS;
?>
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?>
<main id="main-content">
<h1>Éditer : <?= htmlspecialchars($page['title']) ?></h1>
<form action="/admin/actions/page.php" method="post" class="admin-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="hidden" name="slug" value="<?= htmlspecialchars($slug) ?>">
<div>
<label for="content">Contenu (Markdown) :</label>
<div>
<textarea id="content" name="content"
rows="20"><?= htmlspecialchars($page['content'] ?? '') ?></textarea>
<small>Appuyez sur <kbd>Échap</kbd> pour quitter l'éditeur au clavier.</small>
</div>
</div>
<div class="admin-form-footer">
<button type="submit" class="admin-btn">Enregistrer</button>
<a href="/admin/pages.php" class="admin-btn-secondary admin-cancel-link">Annuler</a>
</div>
</form>
</main>
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>