feat: smart 404 redirige vers article le plus proche via moteur de recherche
This commit is contained in:
@@ -59,3 +59,6 @@ RewriteRule ^sitemap\.xml$ /sitemap.php [L]
|
||||
# Ajoute .php si le fichier correspondant existe
|
||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
|
||||
RewriteRule ^(.+?)/?$ /$1.php [L,QSA]
|
||||
|
||||
# 404 intelligent : redirige vers l'article le plus proche
|
||||
ErrorDocument 404 /index.php?action=not_found
|
||||
|
||||
+53
-1
@@ -22,10 +22,38 @@ $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'];
|
||||
$_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'];
|
||||
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
|
||||
unset($_noindexActions);
|
||||
|
||||
// ─── Recherche de l'article le plus proche et redirection 301 ────────────────
|
||||
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))
|
||||
));
|
||||
if ($query === '') {
|
||||
return;
|
||||
}
|
||||
$privateCats = $articles->getPrivateCategories();
|
||||
$pool = array_values(array_filter(
|
||||
$articles->getAll(true),
|
||||
static function (array $a) use ($privateCats): bool {
|
||||
if (strtotime((string)($a['published_at'] ?? '')) > time()) {
|
||||
return false;
|
||||
}
|
||||
$cat = trim($a['category'] ?? '');
|
||||
return $cat === '' || !in_array($cat, $privateCats, true);
|
||||
}
|
||||
));
|
||||
$results = (new SearchEngine())->search($query, $pool);
|
||||
if (!empty($results)) {
|
||||
header('Location: /post/' . rawurlencode($results[0]['article']['slug'] ?? ''), true, 301);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Extraction de métadonnées depuis une URL ────────────────────────────────
|
||||
function fetchUrlMeta(string $url): array
|
||||
{
|
||||
@@ -472,6 +500,7 @@ switch ($action) {
|
||||
case 'view':
|
||||
$article = $slug !== '' ? $articles->getBySlug($slug) : null;
|
||||
if (!$article) {
|
||||
searchAndRedirect($slug, $articles);
|
||||
http_response_code(404);
|
||||
echo 'Article introuvable.';
|
||||
exit;
|
||||
@@ -1826,6 +1855,29 @@ switch ($action) {
|
||||
include BASE_PATH . '/templates/search.php';
|
||||
break;
|
||||
|
||||
case 'not_found':
|
||||
$notFoundPath = trim(
|
||||
(string)(parse_url($_SERVER['REDIRECT_URL'] ?? $_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?? ''),
|
||||
'/'
|
||||
);
|
||||
if ($notFoundPath !== '') {
|
||||
searchAndRedirect($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;
|
||||
|
||||
case 'list':
|
||||
default:
|
||||
$privateCats = $articles->getPrivateCategories();
|
||||
|
||||
Reference in New Issue
Block a user