mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 11:39:18 +02:00
233 lines
9.5 KiB
PHP
233 lines
9.5 KiB
PHP
<?php
|
|
require_once __DIR__ . "/../../bootstrap.php";
|
|
require_once __DIR__ . '/../../src/AdminAuth.php';
|
|
AdminAuth::requireLogin();
|
|
|
|
require_once __DIR__ . '/../../src/Database.php';
|
|
|
|
if (empty($_SESSION["csrf_token"])) {
|
|
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
|
|
}
|
|
|
|
$allowedPageSlugs = ["about", "licenses", "charte"];
|
|
$allowedApropos = ["contacts", "credits"];
|
|
|
|
$pageSlug = $_GET["slug"] ?? "";
|
|
$aproposKey = $_GET["apropos"] ?? "";
|
|
|
|
// Exactly one target must be specified
|
|
if ($pageSlug && !in_array($pageSlug, $allowedPageSlugs)) {
|
|
$pageSlug = "";
|
|
}
|
|
if ($aproposKey && !in_array($aproposKey, $allowedApropos)) {
|
|
$aproposKey = "";
|
|
}
|
|
|
|
if (!$pageSlug && !$aproposKey) {
|
|
header("Location: /admin/contenus.php");
|
|
exit();
|
|
}
|
|
|
|
try {
|
|
$db = new Database();
|
|
|
|
if ($pageSlug) {
|
|
$page = $db->getPage($pageSlug);
|
|
if (!$page) {
|
|
die("Page introuvable.");
|
|
}
|
|
$editTitle = $page["title"];
|
|
$editType = "page";
|
|
} else {
|
|
$editType = "apropos";
|
|
$value = $db->getAproposContent($aproposKey);
|
|
$editTitle = match($aproposKey) {
|
|
'contacts' => 'Contacts',
|
|
'credits' => 'Crédits',
|
|
};
|
|
}
|
|
} catch (Exception $e) {
|
|
die("Erreur: " . htmlspecialchars($e->getMessage()));
|
|
}
|
|
|
|
$pageTitle = "Éditer : " . $editTitle;
|
|
$extraJs = ["/assets/js/overtype.min.js"];
|
|
$extraJsInline = <<<'JS'
|
|
var OT = window.OverType.default || window.OverType;
|
|
var hidden = document.getElementById('content');
|
|
var editor = new OT(document.getElementById('editor'), {
|
|
value: hidden.value,
|
|
minHeight: '400px',
|
|
spellcheck: false,
|
|
onChange: function(value) { hidden.value = value; }
|
|
});
|
|
JS;
|
|
$aproposEditorJs = null;
|
|
if ($editType === 'apropos' && in_array($aproposKey, ['contacts', 'credits'])) {
|
|
// Rich textarea for JSON arrays rendered as structured form
|
|
$aproposEditorJs = <<<'JS'
|
|
// Auto-format JSON in the hidden field for display purposes
|
|
JS;
|
|
}
|
|
|
|
$initialContent = '';
|
|
if ($editType === 'page') {
|
|
$initialContent = $page["content"] ?? "";
|
|
} else {
|
|
// For apropos, show structured form
|
|
}
|
|
?>
|
|
<?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($editTitle) ?></h1>
|
|
|
|
<?php if ($editType === 'page'): ?>
|
|
<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($pageSlug) ?>">
|
|
|
|
<label for="editor">Contenu (Markdown) :</label>
|
|
<input type="hidden" id="content" name="content"
|
|
value="<?= htmlspecialchars($initialContent) ?>">
|
|
<div id="editor"></div>
|
|
|
|
<div class="admin-form-footer">
|
|
<button type="submit" class="admin-btn">Enregistrer</button>
|
|
<a href="/admin/contenus.php" class="admin-btn-secondary admin-cancel-link">Annuler</a>
|
|
</div>
|
|
</form>
|
|
|
|
<?php else: ?>
|
|
<?php
|
|
$groups = is_array($value) ? $value : [];
|
|
?>
|
|
<form action="/admin/actions/apropos.php" method="post" class="admin-form" id="apropos-form">
|
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION["csrf_token"]) ?>">
|
|
<input type="hidden" name="apropos_key" value="<?= htmlspecialchars($aproposKey) ?>">
|
|
|
|
<?php foreach ($groups as $gi => $group): ?>
|
|
<fieldset class="apropos-group">
|
|
<legend><?= htmlspecialchars($aproposKey === 'contacts' ? 'Contact' : 'Crédit') ?> <?= $gi + 1 ?></legend>
|
|
<?php if ($aproposKey === 'contacts'): ?>
|
|
<label for="group_<?= $gi ?>_role">Rôle :</label>
|
|
<input type="text" id="group_<?= $gi ?>_role"
|
|
name="groups[<?= $gi ?>][role]"
|
|
value="<?= htmlspecialchars($group['role'] ?? '') ?>">
|
|
<?php else: ?>
|
|
<label for="group_<?= $gi ?>_label">Label :</label>
|
|
<input type="text" id="group_<?= $gi ?>_label"
|
|
name="groups[<?= $gi ?>][label]"
|
|
value="<?= htmlspecialchars($group['label'] ?? '') ?>">
|
|
<?php endif; ?>
|
|
|
|
<?php $entries = is_array($group['entries'] ?? null) ? $group['entries'] : []; ?>
|
|
<?php foreach ($entries as $ei => $entry): ?>
|
|
<div class="apropos-entry">
|
|
<label for="entry_<?= $gi ?>_<?= $ei ?>_text"><?= $aproposKey === 'contacts' ? 'Nom' : 'Texte' ?> :</label>
|
|
<input type="text" id="entry_<?= $gi ?>_<?= $ei ?>_text"
|
|
name="groups[<?= $gi ?>][entries][<?= $ei ?>][text]"
|
|
value="<?= htmlspecialchars($entry['text'] ?? '') ?>">
|
|
<?php if ($aproposKey === 'contacts'): ?>
|
|
<label for="entry_<?= $gi ?>_<?= $ei ?>_email">Email :</label>
|
|
<input type="email" id="entry_<?= $gi ?>_<?= $ei ?>_email"
|
|
name="groups[<?= $gi ?>][entries][<?= $ei ?>][email]"
|
|
value="<?= htmlspecialchars($entry['email'] ?? '') ?>">
|
|
<?php endif; ?>
|
|
<label for="entry_<?= $gi ?>_<?= $ei ?>_url">Lien (optionnel) :</label>
|
|
<input type="url" id="entry_<?= $gi ?>_<?= $ei ?>_url"
|
|
name="groups[<?= $gi ?>][entries][<?= $ei ?>][url]"
|
|
value="<?= htmlspecialchars($entry['url'] ?? '') ?>">
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
<button type="button" class="admin-btn admin-btn--sm add-entry-btn" data-group="<?= $gi ?>">+ Ajouter une entrée</button>
|
|
</fieldset>
|
|
<?php endforeach; ?>
|
|
|
|
<button type="button" class="admin-btn" id="add-group-btn">+ Ajouter un <?= $aproposKey === 'contacts' ? 'contact' : 'groupe de crédit' ?></button>
|
|
|
|
<div class="admin-form-footer">
|
|
<button type="submit" class="admin-btn">Enregistrer</button>
|
|
<a href="/admin/contenus.php" class="admin-btn-secondary admin-cancel-link">Annuler</a>
|
|
</div>
|
|
|
|
<template id="entry-template-<?= $aproposKey ?>">
|
|
<div class="apropos-entry">
|
|
<label>Entrée :</label>
|
|
<input type="text" name="groups[{{gi}}][entries][{{ei}}][text]">
|
|
<?php if ($aproposKey === 'contacts'): ?>
|
|
<label>Email :</label>
|
|
<input type="email" name="groups[{{gi}}][entries][{{ei}}][email]">
|
|
<?php endif; ?>
|
|
<label>Lien (optionnel) :</label>
|
|
<input type="url" name="groups[{{gi}}][entries][{{ei}}][url]">
|
|
</div>
|
|
</template>
|
|
|
|
<template id="group-template-<?= $aproposKey ?>">
|
|
<fieldset class="apropos-group">
|
|
<legend><?= htmlspecialchars($aproposKey === 'contacts' ? 'Contact' : 'Crédit') ?> {{gi}}</legend>
|
|
<?php if ($aproposKey === 'contacts'): ?>
|
|
<label>Rôle :</label>
|
|
<input type="text" name="groups[{{gi}}][role]">
|
|
<?php else: ?>
|
|
<label>Label :</label>
|
|
<input type="text" name="groups[{{gi}}][label]">
|
|
<?php endif; ?>
|
|
<button type="button" class="admin-btn admin-btn--sm add-entry-btn" data-group="{{gi}}">+ Ajouter une entrée</button>
|
|
</fieldset>
|
|
</template>
|
|
</form>
|
|
|
|
<script>
|
|
(function() {
|
|
const aproposKey = '<?= $aproposKey ?>';
|
|
let groupCount = <?= count($groups) ?>;
|
|
const entryTpl = document.getElementById('entry-template-' + aproposKey).innerHTML;
|
|
const groupTpl = document.getElementById('group-template-' + aproposKey).innerHTML;
|
|
|
|
// Add entry to a group
|
|
document.querySelectorAll('.add-entry-btn').forEach(btn => {
|
|
btn.addEventListener('click', function() {
|
|
const gi = parseInt(this.dataset.group);
|
|
const fieldset = this.closest('fieldset');
|
|
const entryCount = fieldset.querySelectorAll('.apropos-entry').length;
|
|
const html = entryTpl.replaceAll('{{gi}}', gi).replaceAll('{{ei}}', entryCount);
|
|
this.insertAdjacentHTML('beforebegin', html);
|
|
});
|
|
});
|
|
|
|
// Add new group
|
|
document.getElementById('add-group-btn').addEventListener('click', function() {
|
|
groupCount++;
|
|
const html = groupTpl.replaceAll('{{gi}}', groupCount);
|
|
this.insertAdjacentHTML('beforebegin', html);
|
|
|
|
// Re-bind add-entry buttons for the new group
|
|
const newGroup = this.previousElementSibling;
|
|
if (newGroup && newGroup.classList.contains('apropos-group')) {
|
|
const btn = newGroup.querySelector('.add-entry-btn');
|
|
if (btn) {
|
|
btn.dataset.group = groupCount;
|
|
btn.addEventListener('click', function() {
|
|
const gi = parseInt(this.dataset.group);
|
|
const fieldset = this.closest('fieldset');
|
|
const entryCount = fieldset.querySelectorAll('.apropos-entry').length;
|
|
const html = entryTpl.replaceAll('{{gi}}', gi).replaceAll('{{ei}}', entryCount);
|
|
this.insertAdjacentHTML('beforebegin', html);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
<?php endif; ?>
|
|
</main>
|
|
<?php require_once APP_ROOT . "/templates/admin/footer.php"; ?>
|