Du « fait à la main » vers WordPress

Passer d’un site dynamique un peu old school fait à la main vers un site WordPress m’est déjà arrivé plusieurs fois.

Il s’agit de prendre intelligemment les données issues d’une structure pour aller à vers une autre, une bonne requête SQL pouvant faire l’affaire.

Cette fois, prenons une précaution supplémentaire: utilisons des fonctions WordPress dédiées.

Contexte: pourquoi utiliser les fonctions WordPress?

Les fidèles le sauront, j’ai déjà narré cela dans mes articles Importer un site existant dans WordPress qui pose la question cruciale des permaliens (et donc de la pérennité du référencement), et surtout Migration vers WordPress. Ce dernier article y glissait même une petite requête SQL pour faire cette migration aisément.

Alors pourquoi passer par une autre méthode?

Tout simplement car, cette migration étant un peu facultative, je ne m’y attelle que tous les 4 ou 5 mois, 10 minutes à la fois environ…

Le site dont il est question est un blog un peu personnel, lancé en 2008 (déjà). Il est un peu complexe, mais a l’avantage de tourner, le passage à WordPress peut donc se considérer comme un caprice (comme à l’époque le fait de ne pas utiliser WordPress d’ailleurs, ironie du sort).

Et donc, à chaque fois que j’essaye de me remettre à cette migration (généralement en période de vacances), mon ami WordPress me signale qu’il y a une mise à jour de version. La dernière, la version 4, a même été assortie d’un message amusant: mise à jour de la base de données.

Et c’est là qu’est l’os. Car si on utilise un accès direct dans notre code aux bases de données, il y a un risque que les structures de la base changent, et donc que notre code devienne obsolète.

Dans l’absolu, ce n’est guère grave: une migration est une opération one shot, c’est à dire qu’on écrit le code, on le teste, et on l’utilise une fois. Face à un nouveau site, il suffit de modifier ce qui change et basta.

C’est juste… sale.

WordPress disposant de fonctions ad hoc, pourquoi ne pas les découvrir?

Algorithme (réfléchir avant de se lancer)

Que le code utilise les fonctions WP ou non ne change rien, réfléchissons aux problèmes qui peuvent se poser.

Connaissance de la structure des tables.

Pour WP c’est simple, on va passer par des fonctions qui nous permettent de ne pas avoir à se poser la question de la structure de WordPress (c’est même le but).

Pour ceux que cela passionne, je parle de la Database Description, consultable sur le site WordPress (pas forcément à jour d’ailleurs).

Par contre, indispensable d’avoir le MCD de nos tables d’origines, pour faire une correspondance de données. Un bon schéma à avoir sous les yeux… A jour, cela va sans dire.

Connaissance de la doc.

Là c’est pour la partie WordPress. Curieusement, ces fonctions sont un peu moins documentées que les autres…

Nous allons utiliser:

Ouf.

Autant de fonctions qui, pour l’heure, m’était plus ou moins inconnues.

Les catégories

Il suffit de les parcourir toutes pour les insérer.

La difficulté provient du fait que dans la structure d’origine, un article ne pouvait être classé que dans une seule catégorie, pas dans WordPress. On passe donc d’une clef étrangère à une table de jointure.

Accessoirement, WordPress dispose d’une catégorie ID=1 qui ne correspond bien sûr pas à la notre…

Il va donc falloir passer par une table de correspondance (un array).

Vu qu’il y en a peu, j’ai hésité à les ressaisir à la main, noter les identifiants, et rajouter un champs de correspondance. Plus rapide dans mon cas, mais plus sale

Les articles

On pourrait penser que c’est le gros du boulot, mais en fait non.

  • quelques chercher/remplacer pour nettoyer la structure html, principalement remettre les sources des images dans wp-content (voir plus loin le chapitre sur les images).
  • supprimer les retours chariots \r et \n que WordPress pourrait comprendre comme des marques de paragraphe.
  • fusionner le contenu et le chapo, avec un <!--more--> entre les deux

Bref, que du classique.

Pour le reste, la fonction wp_insert_post est limpide.

Les commentaires

Pas de grande difficulté à ce niveau non plus. Il faut juste conserver le statut accepté ou non accepté.

Petit soucis dans mon cas, puisque la réponse du bloggeur était stocké dans la même ligne de la table commentaire, et non pas dans une autre ligne; il suffit donc de créer un enfant.

C’est à dire utiliser wp_insert_comment en précisant le bon comment_parent.

Les images

Là, un choix à faire.

La solution feignasse  consiste à laisser les images sans se poser de question.

C’est à dire juste changer le src depuis le dossier /data/image pour le remplacer par /wp-content/upload/data/images.

Ce faisant, c’est simple. Mais tellement triste, car cela n’intègre pas les médias dans la bibliothèque des Médias de WordPress, ce qui nous fait perdre le bénéfice de la chose.

La meilleure solution consiste à scanner l’article, vérifier la présence d’image dedans, déplacer les images sources dans les bons dossiers chronologiques (date de l’image et non du jour de la migration), les insérer une à une dans la bibliothèque (en prenant garde aux doublons), et modifier le code html en conséquence…

Solution retenue, vive le wp_insert_attachment.

L’image à la une

Il se pose un peu la même question que pour les images, mais en y ajoutant un statut particulier, puisque l’image à la une est bien sûr un peu plus qu’une image.

Un bon gros morceau, largement solutionné grâce à l’article Programmatically importing thousands of featured image post thumbnails into WordPress.

Le thème

On est dans un WordPress, il va donc être possible de choisir n’importe quel thème (c’est d’ailleurs une raison de tout ce travail).

Les seuls impératifs à ce niveau vont résider (comme souvent dans le cas d’une migration) à respecter les formats d’images.

Ils sont un peu modeste, il n’était guère question de responsive à l’époque…

La réponse sera sans doute un truc tout fait avec quelques adaptations personnelles. Et peut-être des tests pour que les nouveaux articles disposent d’images plus grandes… A creuser à l’usage.

Le reste

Le blog d’origine disposait également d’autres tables pour gérer des annuaires de sites, et plusieurs autres formats de données non article.

Plusieurs solutions:

  • les supprimer purement et simplement
  • les conserver dans leurs tables d’origine, et faire un plugin pour les récupérer
  • les migrer  en tant qu’article dans une catégorie particulière (quitte à en revoir quelques données dans l’affichage)
  • créer un nouveau format de données (ce qui revient, sauf erreur de ma part à réutiliser wp_insert_post mais en précisant le bon post_type), quitte à ajouter des ACF pour compléter les cases.

Vu que la plupart des données sont obsolètes, la suppression (ou le on verra plus tard) se dessine.

Stratégie de mise en place

Il ne parait pas absurde de jouer en local dans un premier temps, en installant un WordPress vide. Le blog en question existant depuis 2008, il tourne gentiment, hors de question que tout s’arrête avec une erreur 500 ou pire…

J’ai ensuite créé une page import, et placé le code de la migration dans le fichier import.php de mon thème provisoire. Un petit plugin aurait sans doute été préférable à la réflexion…

Ne reste qu’à dupliquer la base de données et les images en local pour pouvoir faire des tests.

Écrire le code ensuite, ce qui n’est pas une mince affaire compte tenu des impératifs chronologiques, mais on touche au but.

Ensuite, viendra la phase mise en oeuvre, donc installation en ligne.

Résultat des courses

Le code marche plutôt pas mal, ne me reste plus qu’à finaliser le thème avant de passer à la mise en production effective.

Mais ceci est une autre histoire

Laisser une réponse