Nettoyage des chemins stales

Quand vous changez le slug d'un post ou le déplacez dans une autre catégorie, son URL change. La nouvelle URL reçoit un nouveau fichier HTML uploadé ; l'ancienne URL doit être supprimée — sinon les

Quand vous changez le slug d'un post ou le déplacez dans une autre catégorie, son URL change. La nouvelle URL reçoit un nouveau fichier HTML uploadé ; l'ancienne URL doit être supprimée — sinon les visiteurs trouvent encore l'ancienne version en ligne, les moteurs de recherche voient deux pages avec le même contenu, et votre sitemap référence les deux.

Le publisher gère ça automatiquement via un mécanisme appelé nettoyage des chemins stales.

Cycle de vie d'un chemin publié

Chaque post a trois champs en base pertinents :

TS
{
  lastPublishedPath: "actualites/lancement.html",     // URL actuellement en ligne
  lastPublishedHash: "a1b2c3...",                      // hash du HTML actuel
  previousPublishedPaths: [                            // chemins dont la suppression a échoué
    "anciennes-actualites/lancement.html"              // (rare — voir "Retry on failure")
  ]
}

À chaque publication, le pass de cleanup itère sur [lastPublishedPath, ...previousPublishedPaths], tente deleteFile sur chaque chemin qui n'est pas le nouveau, et persiste les échecs non-404 dans previousPublishedPaths pour que la prochaine publication retente.

Quand le cleanup tourne

À chaque appel à publishPost. Pas seulement quand vous cliquez Publier — aussi pour :

  • Regenerate toutes les pages HTML → re-publie chaque post, donc cleanup chaque post
  • Bulk Publish depuis la liste des posts → cleanup chaque post sélectionné
  • Repair URLs dans le menu Regenerate → cleanup spécifiquement les posts dont lastPublishedPath ne matche pas l'URL recalculée

Le cleanup ne tourne PAS pendant unpublishPost (qui supprime explicitement lastPublishedPath puis nettoie tout) ni pendant deletePost.

Cas d'usage typique : renommer un slug

Scénario : vous avez publié recipes/spaghetti.html, vous renommez le slug en pasta-carbonara. Le pipeline :

  1. Calcule le nouveau chemin : recipes/pasta-carbonara.html
  2. Compare au lastPublishedPath : différent → cleanup
  3. deleteFile("recipes/spaghetti.html") — succès
  4. Upload recipes/pasta-carbonara.html
  5. Patch Post.lastPublishedPath = "recipes/pasta-carbonara.html"

Du point de vue visiteur : l'URL recipes/spaghetti.html devient un 404, recipes/pasta-carbonara.html est en ligne avec le contenu mis à jour.

Cas d'usage : changer de catégorie

Scénario : un post à recipes/spaghetti.html est déplacé vers la catégorie pasta. Le pipeline :

  1. Calcule le nouveau chemin : pasta/spaghetti.html
  2. Compare au lastPublishedPath : différent → cleanup
  3. deleteFile("recipes/spaghetti.html") — succès
  4. Upload pasta/spaghetti.html
  5. Patch Post.lastPublishedPath

Notez : le cleanup supprime UNIQUEMENT l'ancien fichier de post. Les archives de catégorie (recipes/index.html et pasta/index.html) sont régénérées par le pass de cascade après le upload — donc la liste du post dans recipes/ disparaît automatiquement, et apparaît dans pasta/.

Cas d'usage : retry sur échec

Scénario : un cleanup échoue (l'API Flexweg renvoie un 500 transitoire au lieu de 200).

  1. deleteFile("recipes/spaghetti.html") → 500
  2. Le pipeline ajoute "recipes/spaghetti.html" à Post.previousPublishedPaths
  3. Upload du nouveau fichier réussit
  4. Post patché avec le nouveau path

À la prochaine publication de CE post (même si vous re-publiez sans rien changer) :

  1. Le cleanup itère sur [lastPublishedPath, ...previousPublishedPaths]
  2. deleteFile("recipes/spaghetti.html") → cette fois 200, ou 404 (déjà supprimé manuellement)
  3. Le chemin est retiré de previousPublishedPaths

C'est pour ça que vous pouvez avoir un site dont l'historique de migrations est sale — la prochaine publication nettoie ce qui restait.

Cas d'usage : unpublishPost

Quand vous cliquez Dépublier :

  1. deleteFile(Post.lastPublishedPath) — supprime le fichier en ligne
  2. Pour chaque chemin dans previousPublishedPaths : tente delete aussi
  3. Patch Post.lastPublishedPath = "", status = "draft"
  4. Ne touche pas au contenu en base — c'est juste le fichier public qui disparaît

Le post est en brouillon, peut être ré-édité, puis re-publié à un nouveau chemin si vous changez le slug.

Cas d'usage : deletePost

deletePost appelle d'abord unpublishPost (qui fait le cleanup), puis supprime le document / la ligne en base. Le contenu est définitivement perdu.

Limitations

  • Le cleanup ne sait pas que vous avez manuellement uploadé un fichier à une URL via l'API Files de Flexweg. Si vous avez bidouillé en dehors du CMS, vous devez nettoyer à la main.
  • Le cleanup ne couvre que les chemins du post lui-même, pas les chemins liés (sitemaps, RSS). Ceux-là sont gérés par les plugins respectifs, chacun avec son propre mécanisme de cleanup.
  • En mode multilang, chaque variante de langue a son propre cleanup via Post.lastPublishedPathsByLocale (un dict { "fr": "fr/recettes/spaghetti.html", "de": "de/rezepte/spaghetti.html" }).