Mein Blog lief bis gestern mit dem eher unbekannten CMS Serendipity, welches nicht nur unnötig kompliziert zu buchstabieren ist, sondern ein funktionell ziemlich rudimentäres, aber dafür stabiles Blog-System bietet. Außerdem ist die Entwicklungsgeschichte richtig spannend!
Durch verschiedene PHP-Versionen und Serverumzüge hat es mich begleitet, dabei aber immer weitere Bugs und Inkompatibilitäten erzeugt. Zum Schluss konnte ich keine Bilder mehr hochladen – Ursache unbekannt, der Image Picker wurde mit einer leeren Seite ausgeliefert. Troubleshooting einer Serendipity-Installation ist furchtbar.
Da WordPress inzwischen ziemlich komfortabel geworden ist und sich zu sowas wie einem Industriestandard (43% aller Webseiten laufen angeblich heute mit WordPress!) entwickelt hat, war es Zeit, zu wechseln. Auch wenn ich mit der Plugin- und Theme-Flut nicht zufrieden bin: Eine WP-Seite, die heute läuft, ist morgen mangels Maintenance schon out-of-date. Oh well… das ist wohl der Preis des Fortschritts.
Doch wie bekommt man die Inhalte von einem unbekannten, nur durch eine Hand voll Developer gepflegten CMS, bei dem links und rechts die Projekte eingestellt werden, und für das nur ein Hauch an Doku existiert in ein super populäres, flashy shiny fancy CMS migriert?
Es wird komplex.
Es gibt ein Migrationsplugin namens s9y-to-wp, welches jedoch seit 2011 brach liegt (was auch einiges über den Status von Serendipity aussagt). Dieses kann als Basis genutzt werden.
Dank eines ebenfalls hilfreichen Blog-Posts von Matthias Düsi können einige Klippen schon direkt umschifft werden: Die dort erwähnten Workarounds kann ich so nur bestätigen.
Die Installationsanleitung des Plugins ist allerdings Lichtjahre out of date, und ich habe zusätzlich zu den Themen im Düsiblog weitere Probleme gehabt, daher beschreibe ich im Vorgehen im Folgenden.
Die Basics
Ihr braucht Zugriff auf die alte Serendipity-Datenbank, sowie ein frisch installiertes WordPress – möglichst sollte die neue Installation von WP im gleichen Pfad sein, wie die alte S9Y-Installation, das macht es später einfacher. Also einfach den alten S9Y-Ordner umbenennen, WP in den Ordner installieren, und den Inhalt des Ordners „/uploads“ aus dem alten Verzeichnis nach „/wp-content/uploads“ schieben.
Dann in der neuen WP-Installation unter „/wp-content/plugins“ einen Ordner „s9y-to-wp“ anlegen und dort die serendipity.php hineinlegen. Die Zeile mit den Magic Quotes wie beim Düsiblog beschrieben ändern/löschen.
In WP kann nun unter „Plugins“ das entsprechende „Serendipity to WordPress Importer“-Plugin aktiviert werden, woraufhin in der Menübar der gleichnamige Punkt auftaucht.
Dann dem ersten Teil der Installationsanleitung des Plugins folgen und folgendes SQL in der frisch installierten WP-Datenbank ausführen:
TRUNCATE wp_posts;
TRUNCATE `wp_postmeta`;
TRUNCATE `wp_term_relationships`;
TRUNCATE `wp_term_taxonomy`;
TRUNCATE `wp_comments`;
TRUNCATE `wp_commentmeta`;
DELETE FROM wp_terms WHERE wp_terms.term_id!=1;
Dann den Assistenten des Plugins im WP-Backend durchklicken.
Anschließend gibt es wieder ein paar SQL-Befehle für die WP-Datenbank, welche theoretisch die Zuordnungen und Indexes intern korrigieren soll. Das hat bei mir überhaupt nicht gut funktioniert und ich denke, dass hier einiges an Inkompatibilität mit dem inzwischen deutlich anders funktionierenden Datenmodell von WP besteht.
Sei’s drum, folgendes SQL:
UPDATE `wp_comments` as a SET a.`comment_post_ID`= (SELECT b.`menu_order` FROM `wp_posts` as b WHERE a.`comment_post_ID`= b.`ID`);
UPDATE `wp_term_relationships` SET `object_id`=`object_id`+9000;
UPDATE `wp_term_relationships` as a SET a.`object_id`= (SELECT b.`menu_order` FROM `wp_posts` as b WHERE a.`object_id`-9000= b.`ID`);
UPDATE `wp_posts` SET `ID`=`ID`+9000;
SELECT `id`+1 FROM `wp_posts` ORDER BY `id` DESC LIMIT 0,1;
ALTER TABLE `wp_posts` AUTO_INCREMENT = XXX; -- Where XXX is the value returned from the select above
Der Block, mit dem die „menu_order“ für „wp_posts“-Einträge gesetzt wird (habe ich oben direkt weg gelassen) funktioniert nicht und scheitert mit einer entsprechenden Fehlermeldung, dass „menu_order“ nicht NULL sein kann. Da dieses Feld auch nur die Anzeigereihenfolge der Posts in einem theoretischen Menü steuert – und wir nur Beiträge, aber keine Seiten importieren und Beiträge keine „menu_order“ haben – kann man das getrost ignorieren.
Schwieriger wird es tatsächlich bei den Post-IDs, die +9000 gezählt werden. Das ist schon wild, zumal wir die „comment_post_ID“ im ersten Befehl bereits gesetzt haben. Die Logik ist mir hier nicht ganz klar, aber mir hat es die Zuordnung der Kommentare zu den Posts damit zerschossen. Die mussten dann wieder korrekt zugeordnet werden… in meinem Fall manuell, da es nicht so viele Kommentare sind.
Nacharbeiten
Außerdem schwierig ist, dass WP inzwischen auch Entwürfe, Teile von Einstellungen usw. in der Tabelle „wp_posts“ speichert. Das sorgt dafür, dass teilweise während des Imports einzelne Einträge „dazwischengeklemmt“ werden und das einfache Hochzählen nicht mehr ganz stimmt. Was da unter der Motorhaube passiert, weiß ich nicht genau. Aber Posts mit der ID „5“ in S9Y waren schlussendlich nicht „9005“, sondern oftmals um ein oder zwei versetzt.
An sich stört das nicht, außer man hat die Post-ID in den Permalinks inkludiert. Das war bei mir kein Problem, daher habe ich das entschieden. Die „comment_post_ID“ musste ich sowieso manuell nachziehen, also war das an der Stelle dann auch egal
Die Posts selbst haben keinerlei Kategoriezuweisung mehr gehabt. Auch das kann nicht automatisch nachgezogen werden, weil die Zuweisung einfach als „0“ gesetzt wird. Die Plugin-Doku sagt dazu:
After the import, you’ll need to edit one of the categories (just open and save it) to fix the hierarchy.
Nö. Funktioniert nicht. Die Kategorien werden aber „flat“ in WP angelegt, sodass man im Backend mit der Massenbearbeitung von Posts das ganz gut in den Griff bekommt. Eine mögliche Hierarchie kann man dann händisch wieder anlegen.
Damit Bilder und andere Medien angezeigt werden, genügt ein einfacher SQL-Search/Replace auf „/uploads“ im besten Fall aus:
UPDATE wp_posts
SET post_content = REPLACE(post_content, ‚/uploads‘, ‚/wp-content/uploads‘);
Dann werden die Bilder und alle anderen Medien wieder angezeigt. Der Vorteil an S9Y ist, dass hier Medien als HTML eingebunden wurden und WP damit auch zurecht kommt. Im Backend werden ggf. nur HTML-Blöcke angezeigt, aber da bestehende Artikel nicht oft noch mal bearbeitet werden, war das für mich in Ordnung und das bleibt jetzt so.
Und damit ist die Migration an sich erstmal abgeschlossen. Ein bisschen Aufräumarbeiten sind dennoch notwendig – „more“-Tags, kleinere Design-Problemchen durch die HTML-Blöcke, etc.
Es ist schon eine etwas hemdsärmelige, rudimentäre Migration.
Aber immerhin: Der Inhalt ist da 🙂