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
|
# Ajoute .php si le fichier correspondant existe
|
||||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
|
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
|
||||||
RewriteRule ^(.+?)/?$ /$1.php [L,QSA]
|
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'] ?? '';
|
$uuid = $_GET['uuid'] ?? '';
|
||||||
$slug = $_GET['slug'] ?? '';
|
$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;
|
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
|
||||||
unset($_noindexActions);
|
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 ────────────────────────────────
|
// ─── Extraction de métadonnées depuis une URL ────────────────────────────────
|
||||||
function fetchUrlMeta(string $url): array
|
function fetchUrlMeta(string $url): array
|
||||||
{
|
{
|
||||||
@@ -472,6 +500,7 @@ switch ($action) {
|
|||||||
case 'view':
|
case 'view':
|
||||||
$article = $slug !== '' ? $articles->getBySlug($slug) : null;
|
$article = $slug !== '' ? $articles->getBySlug($slug) : null;
|
||||||
if (!$article) {
|
if (!$article) {
|
||||||
|
searchAndRedirect($slug, $articles);
|
||||||
http_response_code(404);
|
http_response_code(404);
|
||||||
echo 'Article introuvable.';
|
echo 'Article introuvable.';
|
||||||
exit;
|
exit;
|
||||||
@@ -1826,6 +1855,29 @@ switch ($action) {
|
|||||||
include BASE_PATH . '/templates/search.php';
|
include BASE_PATH . '/templates/search.php';
|
||||||
break;
|
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':
|
case 'list':
|
||||||
default:
|
default:
|
||||||
$privateCats = $articles->getPrivateCategories();
|
$privateCats = $articles->getPrivateCategories();
|
||||||
|
|||||||
Reference in New Issue
Block a user