feat: add editable 301 redirects via dedicated panel page
All checks were successful
Deploy Production / Deploy to Production (push) Successful in 21s
All checks were successful
Deploy Production / Deploy to Production (push) Successful in 21s
- New "Redirections" page in panel (blueprint + content) with a structure field: old URL (text) → target page (pages field, auto-resolves URL) - error.php controller intercepts 404s, checks redirect map, fires go() 301 - Cache (file driver) invalidated on redirections page update or slug change - Removed catch-all route that was breaking Kirby multilingual routing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
91ac702f3c
commit
dbeca5e095
5 changed files with 81 additions and 3 deletions
27
site/blueprints/pages/redirections.yml
Normal file
27
site/blueprints/pages/redirections.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
title: Redirections
|
||||||
|
icon: link
|
||||||
|
|
||||||
|
tabs:
|
||||||
|
content:
|
||||||
|
label: Redirections
|
||||||
|
sections:
|
||||||
|
rules:
|
||||||
|
type: fields
|
||||||
|
fields:
|
||||||
|
rules:
|
||||||
|
label: Règles de redirection (301)
|
||||||
|
type: structure
|
||||||
|
fields:
|
||||||
|
from:
|
||||||
|
label: Ancienne URL
|
||||||
|
type: text
|
||||||
|
required: true
|
||||||
|
placeholder: /BLOG/ancien-slug
|
||||||
|
help: "Chemin relatif (la casse est ignorée)"
|
||||||
|
width: 1/2
|
||||||
|
to:
|
||||||
|
label: Page cible
|
||||||
|
type: pages
|
||||||
|
multiple: false
|
||||||
|
required: true
|
||||||
|
width: 1/2
|
||||||
|
|
@ -58,6 +58,5 @@ tabs:
|
||||||
accept: application/pdf
|
accept: application/pdf
|
||||||
translate: false
|
translate: false
|
||||||
help: Fichier téléchargé après soumission du formulaire
|
help: Fichier téléchargé après soumission du formulaire
|
||||||
|
|
||||||
files: tabs/files
|
files: tabs/files
|
||||||
seo: seo/page
|
seo: seo/page
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,23 @@ return [
|
||||||
|
|
||||||
'thumbs' => require __DIR__ . '/thumbs.php',
|
'thumbs' => require __DIR__ . '/thumbs.php',
|
||||||
|
|
||||||
|
'cache' => [
|
||||||
|
'redirects' => ['type' => 'file'],
|
||||||
|
],
|
||||||
|
|
||||||
|
'hooks' => [
|
||||||
|
'page.update:after' => function ($newPage) {
|
||||||
|
if ($newPage->id() === 'redirections') {
|
||||||
|
kirby()->cache('redirects')->remove('map');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'page.changeSlug:after' => function () {
|
||||||
|
kirby()->cache('redirects')->remove('map');
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
'routes' => [
|
'routes' => [
|
||||||
require(__DIR__ . '/routes/download-white-paper.php')
|
require(__DIR__ . '/routes/download-white-paper.php'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'tobimori.seo' => [
|
'tobimori.seo' => [
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ return [
|
||||||
'a-propos' => menuItem('a-propos', 'À propos', 'users', 'pages/a-propos'),
|
'a-propos' => menuItem('a-propos', 'À propos', 'users', 'pages/a-propos'),
|
||||||
'blog' => menuItem('blog', 'Blog', 'text', 'pages/blog'),
|
'blog' => menuItem('blog', 'Blog', 'text', 'pages/blog'),
|
||||||
'white-papers' => menuItem('livres-blancs', 'Livres blancs', 'book', 'pages/livres-blancs'),
|
'white-papers' => menuItem('livres-blancs', 'Livres blancs', 'book', 'pages/livres-blancs'),
|
||||||
'confidentialite' => menuItem('confidentialite', 'Confidentialité', 'lock', 'pages/policy'),
|
'confidentialite' => menuItem('confidentialite', 'Confidentialité', 'lock', 'pages/policy'),
|
||||||
|
'redirections' => menuItem('redirections', 'Redirections', 'url', 'pages/redirections'),
|
||||||
'-',
|
'-',
|
||||||
'users',
|
'users',
|
||||||
'system',
|
'system',
|
||||||
|
|
|
||||||
36
site/controllers/error.php
Normal file
36
site/controllers/error.php
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return function ($kirby, $page, $site) {
|
||||||
|
$path = $kirby->path();
|
||||||
|
|
||||||
|
if (!str_ends_with($path, '.json')) {
|
||||||
|
$normalized = '/' . rtrim(strtolower($path), '/');
|
||||||
|
|
||||||
|
$cache = $kirby->cache('redirects');
|
||||||
|
$map = $cache->get('map');
|
||||||
|
|
||||||
|
if ($map === null) {
|
||||||
|
$map = [];
|
||||||
|
$redirectsPage = $site->find('redirections');
|
||||||
|
if ($redirectsPage) {
|
||||||
|
foreach ($redirectsPage->rules()->toStructure() as $rule) {
|
||||||
|
$from = trim($rule->from()->value());
|
||||||
|
if ($from === '') continue;
|
||||||
|
$key = '/' . trim(strtolower($from), '/');
|
||||||
|
$target = $rule->to()->toPage();
|
||||||
|
if ($target) {
|
||||||
|
$map[$key] = $target->url();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cache->set('map', $map, 1440);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($map[$normalized])) {
|
||||||
|
go($map[$normalized], 301);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$kirby->response()->code(404);
|
||||||
|
return [];
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue