feat : visiteurs uniques, filtre jours, redirect 404→search, edit_tags (v1.6.16)
- SearchLogParser : visiteurs uniques par terme (IPs distinctes) au lieu de hits bruts (#41) - SearchLogParser : paramètre $days (7/14), cache distinct par période, filtre logFiles par date (#46) - admin/searches : boutons 7 j / 14 j, label dynamique, colonne « Visiteurs » (#41, #46) - URL inconnue / slug absent : redirect 302 /search?q=… au lieu de page 404 (#57) - edit_tags : masquer abbrev/camel si des valeurs connues existent pour le type (#48) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+17
-25
@@ -50,12 +50,17 @@ $metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' :
|
||||
unset($_noindexActions);
|
||||
|
||||
// ─── Recherche de l'article le plus proche et redirection 301 ────────────────
|
||||
function slugToSearchQuery(string $rawPath): string
|
||||
{
|
||||
return trim((string)preg_replace('/\s{2,}/', ' ', (string)preg_replace(
|
||||
'/[^a-zA-ZÀ-ÿ0-9\s]/u', ' ', str_replace(['-', '_', '/'], ' ', $rawPath)
|
||||
)));
|
||||
}
|
||||
|
||||
function searchAndRedirect(string $rawPath, ArticleManager $articles): void
|
||||
{
|
||||
require_once BASE_PATH . '/src/SearchEngine.php';
|
||||
$query = (string)preg_replace('/\s{2,}/', ' ', trim(
|
||||
(string)preg_replace('/[^a-zA-ZÀ-ÿ0-9\s]/u', ' ', str_replace(['-', '_', '/'], ' ', $rawPath))
|
||||
));
|
||||
$query = slugToSearchQuery($rawPath);
|
||||
if ($query === '') {
|
||||
return;
|
||||
}
|
||||
@@ -666,9 +671,8 @@ switch ($action) {
|
||||
case 'view':
|
||||
$article = $slug !== '' ? $articles->getBySlug($slug) : null;
|
||||
if (!$article) {
|
||||
searchAndRedirect($slug, $articles);
|
||||
http_response_code(404);
|
||||
echo 'Article introuvable.';
|
||||
$q = slugToSearchQuery($slug);
|
||||
header('Location: /search' . ($q !== '' ? '?q=' . urlencode($q) : ''), true, 302);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -2577,9 +2581,11 @@ switch ($action) {
|
||||
exit;
|
||||
}
|
||||
require_once BASE_PATH . '/src/SearchLogParser.php';
|
||||
$parser = new SearchLogParser('/var/log/apache2', apacheAccessLog());
|
||||
$adminData['search_terms'] = $parser->topTerms(100);
|
||||
$days = in_array((int)($_GET['days'] ?? 14), [7, 14], true) ? (int)$_GET['days'] : 14;
|
||||
$parser = new SearchLogParser('/var/log/apache2', apacheAccessLog(), '', 600, $days);
|
||||
$adminData['search_terms'] = $parser->topTerms(100);
|
||||
$adminData['search_log_readable'] = $parser->isReadable();
|
||||
$adminData['search_days'] = $days;
|
||||
}
|
||||
|
||||
if ($tab === 'stats') {
|
||||
@@ -3383,23 +3389,9 @@ switch ($action) {
|
||||
(string)(parse_url($_SERVER['REDIRECT_URL'] ?? $_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?? ''),
|
||||
'/'
|
||||
);
|
||||
if ($notFoundPath !== '') {
|
||||
searchAndRedirect(basename($notFoundPath), $articles);
|
||||
}
|
||||
http_response_code(404);
|
||||
ob_start();
|
||||
?>
|
||||
<div class="container py-5 text-center">
|
||||
<h1 class="h2 mb-3">Page introuvable</h1>
|
||||
<p class="text-muted mb-4">Cette adresse ne correspond à aucun article.<br>Vous avez peut-être suivi un ancien lien.</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;
|
||||
$q = slugToSearchQuery($notFoundPath);
|
||||
header('Location: /search' . ($q !== '' ? '?q=' . urlencode($q) : ''), true, 302);
|
||||
exit;
|
||||
|
||||
case 'list':
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user