feat : log Apache configurable via Administration → Site (apache_access_log)

Ajoute apacheAccessLog() dans SiteSettings — priorité au réglage admin,
fallback sur APACHE_ACCESS_LOG dans .env. Champ ajouté dans le formulaire
Site de l'administration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 00:16:49 +02:00
parent d488bcd00c
commit d18f9abd16
4 changed files with 274 additions and 3 deletions
+171
View File
@@ -65,6 +65,10 @@ function adminStatusBadge(array $a, int $now): string
<a class="nav-link <?= $tab === 'searches' ? 'active' : '' ?>"
href="/admin/searches">Recherches</a>
</li>
<li class="nav-item">
<a class="nav-link <?= $tab === 'books' ? 'active' : '' ?>"
href="/admin/books">Livres</a>
</li>
<?php endif; ?>
</ul>
@@ -503,6 +507,14 @@ function adminStatusBadge(array $a, int $now): string
value="<?= postsPerPage() ?>"
min="1" max="100">
</div>
<div class="mb-3">
<label for="apache-access-log" class="form-label small fw-semibold">Log d'accès Apache</label>
<input type="text" id="apache-access-log" name="apache_access_log"
class="form-control form-control-sm font-monospace"
value="<?= htmlspecialchars(apacheAccessLog()) ?>"
maxlength="200" placeholder="ex : lan.acegrp.monsite-access.log">
<div class="form-text">Nom du fichier dans <code>/var/log/apache2/</code>, utilisé par l'onglet Recherches.</div>
</div>
<div class="mb-3">
<label for="site-license-label" class="form-label small fw-semibold">Licence (libellé)</label>
<input type="text" id="site-license-label" name="site_license_label"
@@ -1114,6 +1126,165 @@ foreach (COLOR_PALETTE_16 as $_i => $_rgb):
<?php endif; ?>
<!-- ─────────────────────────── LIVRES ─────────────────────────── -->
<?php if ($tab === 'books' && isAdmin()): ?>
<?php if (($_GET['deleted'] ?? '') === '1'): ?>
<div class="alert alert-success py-2 small mb-3">Livre supprimé.</div>
<?php endif; ?>
<div class="row g-4">
<!-- Liste des livres -->
<div class="col-md-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0">
Livres
<span class="badge bg-secondary ms-1"><?= count($adminData['books']) ?></span>
</h5>
<a href="/admin/books?new=1" class="btn btn-sm btn-primary">+ Nouveau</a>
</div>
<?php if (empty($adminData['books'])): ?>
<p class="text-muted small">Aucun livre pour l'instant.</p>
<?php else: ?>
<div class="list-group">
<?php foreach ($adminData['books'] as $bk):
$isEdited = ($adminData['edit_book']['slug'] ?? '') === $bk['slug'];
?>
<a href="/admin/books?edit=<?= rawurlencode($bk['slug']) ?>"
class="list-group-item list-group-item-action<?= $isEdited ? ' active' : '' ?>">
<div class="fw-medium"><?= htmlspecialchars($bk['title']) ?></div>
<div class="small <?= $isEdited ? 'text-white-50' : 'text-muted' ?>">
<?= count($bk['articles'] ?? []) ?> page<?= count($bk['articles'] ?? []) > 1 ? 's' : '' ?>
· <a href="/book/<?= rawurlencode($bk['slug']) ?>" target="_blank"
class="<?= $isEdited ? 'text-white-50' : 'text-muted' ?>">Voir ↗</a>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<!-- Formulaire édition / création -->
<div class="col-md-8">
<?php if (($adminData['edit_book'] ?? null) !== null): ?>
<?php $eb = $adminData['edit_book']; ?>
<h5>Modifier le livre</h5>
<?php if (($_GET['saved'] ?? '') === '1'): ?>
<div class="alert alert-success py-2 small">Livre sauvegardé.</div>
<?php endif; ?>
<form method="POST" action="/?action=book_save">
<input type="hidden" name="slug" value="<?= htmlspecialchars($eb['slug']) ?>">
<div class="mb-3">
<label class="form-label small fw-medium">Slug (identifiant URL)</label>
<input type="text" class="form-control bg-light" value="<?= htmlspecialchars($eb['slug']) ?>" readonly>
<div class="form-text">Le slug ne peut pas être modifié après création.</div>
</div>
<div class="mb-3">
<label class="form-label small fw-medium">Titre</label>
<input type="text" name="title" class="form-control" required
value="<?= htmlspecialchars($eb['title'] ?? '') ?>">
</div>
<div class="mb-3">
<label class="form-label small fw-medium">Description</label>
<textarea name="description" class="form-control" rows="2"><?= htmlspecialchars($eb['description'] ?? '') ?></textarea>
</div>
<div class="mb-3">
<label class="form-label small fw-medium">Pages (slugs dans l'ordre, un par ligne)</label>
<textarea name="articles" class="form-control font-monospace"
id="book-articles-ta"
rows="<?= max(6, count($eb['articles'] ?? []) + 2) ?>"><?= htmlspecialchars(implode("\n", $eb['articles'] ?? [])) ?></textarea>
<div class="form-text">Un slug par ligne. L'ordre définit la navigation précédent/suivant.</div>
</div>
<div class="mb-3">
<label class="form-label small fw-medium">Ajouter une page existante</label>
<select class="form-select" onchange="bookAddArticle(this)">
<option value="">— Choisir un article —</option>
<?php
$alreadyIn = $eb['articles'] ?? [];
foreach ($adminData['all_articles'] as $aa):
if (in_array($aa['slug'] ?? '', $alreadyIn, true)) {
continue;
}
?>
<option value="<?= htmlspecialchars($aa['slug'] ?? '') ?>">
<?= htmlspecialchars($aa['title']) ?>
<?= !$aa['published'] ? ' (brouillon)' : '' ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Sauvegarder</button>
<a href="/book/<?= rawurlencode($eb['slug']) ?>" target="_blank"
class="btn btn-outline-secondary">Voir le livre ↗</a>
</div>
</form>
<hr class="my-4">
<form method="POST" action="/?action=book_delete"
data-confirm="Supprimer le livre « <?= htmlspecialchars($eb['title']) ?> » ? Les pages resteront intactes.">
<input type="hidden" name="slug" value="<?= htmlspecialchars($eb['slug']) ?>">
<button type="submit" class="btn btn-outline-danger btn-sm">🗑 Supprimer ce livre</button>
</form>
<script>
function bookAddArticle(sel) {
var slug = sel.value;
if (!slug) return;
var ta = document.getElementById('book-articles-ta');
var lines = ta.value.split('\n').map(function(s) { return s.trim(); }).filter(Boolean);
if (lines.indexOf(slug) === -1) {
lines.push(slug);
ta.value = lines.join('\n');
}
sel.value = '';
}
</script>
<?php elseif (isset($_GET['new'])): ?>
<h5>Nouveau livre</h5>
<form method="POST" action="/?action=book_save">
<div class="mb-3">
<label class="form-label small fw-medium">Slug (identifiant URL)</label>
<input type="text" name="slug" class="form-control" required
placeholder="mon-livre" pattern="[a-z0-9][a-z0-9-]*">
<div class="form-text">Minuscules, chiffres, tirets. Exemple : <code>esp8266</code></div>
</div>
<div class="mb-3">
<label class="form-label small fw-medium">Titre</label>
<input type="text" name="title" class="form-control" required placeholder="Titre du livre">
</div>
<div class="mb-3">
<label class="form-label small fw-medium">Description (optionnelle)</label>
<textarea name="description" class="form-control" rows="2" placeholder="Courte description…"></textarea>
</div>
<input type="hidden" name="articles" value="">
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Créer le livre</button>
<a href="/admin/books" class="btn btn-outline-secondary">Annuler</a>
</div>
</form>
<?php else: ?>
<p class="text-muted mt-2">
<?php if (!empty($adminData['books'])): ?>
Sélectionnez un livre à gauche pour le modifier, ou créez-en un nouveau.
<?php else: ?>
Cliquez sur <strong>+ Nouveau</strong> pour créer votre premier livre.
<?php endif; ?>
</p>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php
$content = ob_get_clean();
$title = 'Administration — ' . siteTitle();