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
+89 -2
View File
@@ -23,8 +23,10 @@ require_once BASE_PATH . '/src/helpers.php';
require_once BASE_PATH . '/src/auth.php';
require_once BASE_PATH . '/src/SiteSettings.php';
require_once BASE_PATH . '/src/ArticleManager.php';
require_once BASE_PATH . '/src/BookManager.php';
$articles = new ArticleManager(BASE_PATH . '/data');
$books = new BookManager(BASE_PATH . '/data/books');
// ─── Mode maintenance ──────────────────────────────────────────────────────
if (file_exists(BASE_PATH . '/data/.maintenance')) {
@@ -41,7 +43,7 @@ $action = $_GET['action'] ?? 'list';
$uuid = $_GET['uuid'] ?? '';
$slug = $_GET['slug'] ?? '';
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags'];
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete'];
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
unset($_noindexActions);
@@ -825,6 +827,13 @@ switch ($action) {
$comments = $commentMgr->forArticle($article['uuid']);
}
// Contexte livre (navigation précédent/suivant si l'article fait partie d'un livre)
$bookContext = $books->findForArticle($article['slug'] ?? '');
if ($bookContext !== null) {
$bookContext['prev_article'] = $bookContext['prev'] !== null ? $articles->getBySlug($bookContext['prev']) : null;
$bookContext['next_article'] = $bookContext['next'] !== null ? $articles->getBySlug($bookContext['next']) : null;
}
include BASE_PATH . '/templates/post_view.php';
break;
@@ -2528,7 +2537,7 @@ switch ($action) {
exit;
}
require_once BASE_PATH . '/src/SearchLogParser.php';
$parser = new SearchLogParser();
$parser = new SearchLogParser('/var/log/apache2', apacheAccessLog());
$adminData['search_terms'] = $parser->topTerms(100);
$adminData['search_log_readable'] = $parser->isReadable();
}
@@ -2539,6 +2548,21 @@ switch ($action) {
$adminData['tagTypes'] = $articles->getTagTypes();
}
if ($tab === 'books') {
if (!isAdmin()) {
http_response_code(403);
exit;
}
$adminData['books'] = $books->getAll();
$adminData['edit_book'] = null;
$adminData['all_articles'] = $articles->getAll();
usort($adminData['all_articles'], static fn ($a, $b) => strcmp($a['title'] ?? '', $b['title'] ?? ''));
$editBookSlug = trim($_GET['edit'] ?? '');
if ($editBookSlug !== '') {
$adminData['edit_book'] = $books->getBySlug($editBookSlug);
}
}
include BASE_PATH . '/templates/admin.php';
break;
@@ -3120,6 +3144,69 @@ switch ($action) {
include BASE_PATH . '/templates/search.php';
break;
case 'book':
$bookSlug = trim($_GET['book_slug'] ?? '');
$book = $books->getBySlug($bookSlug);
if (!$book) {
http_response_code(404);
ob_start();
?>
<div class="container py-5 text-center">
<h1 class="h2 mb-3">Livre introuvable</h1>
<p class="text-muted mb-4">Ce livre n'existe pas ou a été supprimé.</p>
<a href="/" class="btn btn-primary">← Retour à l'accueil</a>
</div>
<?php
$content = ob_get_clean();
$title = '404 — ' . siteTitle();
$metaRobots = 'noindex, nofollow';
include BASE_PATH . '/templates/layout.php';
break;
}
$bookArticles = [];
foreach ($book['articles'] ?? [] as $aSlug) {
$a = $articles->getBySlug($aSlug);
if (!$a) {
continue;
}
if (!$a['published'] && !canDoOnArticle('view_drafts', $a)) {
continue;
}
$bookArticles[] = $a;
}
$allCats = $articles->getCategories();
include BASE_PATH . '/templates/book.php';
break;
case 'book_save':
requireAuth();
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(403);
exit;
}
$bSlug = trim($_POST['slug'] ?? '');
$bTitle = trim($_POST['title'] ?? '');
$bDesc = trim($_POST['description'] ?? '');
$bArts = array_values(array_filter(array_map('trim', preg_split('/[\r\n]+/', $_POST['articles'] ?? ''))));
if ($bSlug !== '' && $bTitle !== '') {
$books->save(['slug' => $bSlug, 'title' => $bTitle, 'description' => $bDesc, 'articles' => $bArts]);
}
header('Location: /admin/books?saved=1&edit=' . rawurlencode($bSlug));
exit;
case 'book_delete':
requireAuth();
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(403);
exit;
}
$bSlug = trim($_POST['slug'] ?? '');
if ($bSlug !== '') {
$books->delete($bSlug);
}
header('Location: /admin/books?deleted=1');
exit;
case 'not_found':
$notFoundPath = trim(
(string)(parse_url($_SERVER['REDIRECT_URL'] ?? $_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?? ''),