Von WordPress zu Hugo Teil 2: Export

17. Februar 2023 · Intern · andreas · Kein Kommentar

Der eigentliche Export der Beiträge aus der WordPress-Datenbank wurde mit Hilfe eines Perl-Skripts realisiert, welches speziell für diesen Zweck geschrieben wurde. Das Hauptaugenmerk lag hierbei auf einen möglichst “passenden” Export und nicht auf schönen oder wiederverwendbarem Code.

Zur Ablage der Beiträge wurden im “content”-Ordner zwei Unterordner angelegt: im Ordner “page” landeten die Seiten der Website, im Ordner “post” die Beiträge.

Damit die in WordPress vorhandene Kategoriestruktur und somit auch die Permalinks erhalten blieben, wurde die Kategorie-Struktur unterhalb des “post”-Ordners nachgebildet, d.h. für den Beitrag “https://blog.thul.org/musik/audio/pink-floyd-the-final-cut/” der Ordner “content/post/musik/audio/pink-floyd-the-final-cut/” erzeugt und der Beitragsinhalt in diesem in der Datei “index.html” abgelegt.

Für die wenigen Seiten der WordPress-Instanz wurde eine flache Hierarchie gewählt, d.h. der Beitrag “https://blog.thul.org/impressum/” wurde in den Ordner “content/page/impressum” kopiert.

Die zu exportierenden Beiträge wurden anhand einer Datenbankabfrage ermittelt

SELECT * FROM wp_posts
WHERE post_type = '$type' AND post_status='publish'
ORDER BY post_date DESC;

wobei in der Variable “$type” der jeweils zu exportierende Typ “post” oder “page” gesetzt wurde.

Die Beitragsinhalte (Spalte “post_content”) wurden jeweils in einer “index.html”-Datei gespeichert und um die Metadaten im Front Matter ergänzt, z.B.:

---
title: 'Pink Floyd - The Final Cut'
slug: 'pink-floyd-the-final-cut'
date: 2019-11-21 17:38:42
author: andreas
wordpressID: 4040
category:
- Audio
tag:
- CD
- Lieblingsalben
- Pink Floyd
---
Beitragsinhalt

Die WordPress-ID (Spalte “ID”) und Beitrags-URL (Spalte “post_name”) wurden ebenfalls mit abgespeichert, erstere zu Referenz-Zwecken, letztere um ein paar Unterschiede in der automatischen URL-Generierung zwischen WordPress und Hugo auszugleichen.

Das Auslesen der Kategorien und Tags wurde ebenfalls mittels SQL aus der Datenbank realisiert

SELECT *
FROM wp_term_relationships, wp_term_taxonomy, wp_terms
WHERE wp_term_taxonomy.taxonomy = '$taxonomy'
  AND wp_term_relationships.object_id = $objectID
  AND wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id
  AND wp_term_taxonomy.term_id = wp_terms.term_id
ORDER BY wp_terms.name ASC;

wobei in “$objectID” die jeweilige “ID” des WordPress-Beitrags gesetzt und “$taxonomy” wahlweise auf “category” oder “post_tag” gesetzt wurde.

Nach dem Auslesen aller Inhalte wurden im Bereich des “post_content” mehrere Bearbeitungsschritte durchgeführt:

Bereinigen aller “Weiterlesen”-Markierungen

Da Hugo mittels “<!–more–>” nicht nur Weiterlesen-Links sondern auch die Trennung zwischen “Summary” und vollständigem Beitrag realisiert, wurde der Trenner aus allen Beitragstexten entfernt.

Bilder

Im nächsten Schritt wurden alle “img”-Tags innerhalb der Beitragstexte umgewandelt. Sofern gesetzt, wurden die “src”- und “alt”-Attribute übernommen, die Liste der zugewiesenen Klassen wurde um alle WordPress-spezifischen Klassen (beginnend mit “wp-”) bereinigt. Alle weiteren Attribute wie z.B. “height” und “width” wurden verworfen.

Im Rahmen der Verarbeitung wurden die Bilddateien vom Ursprungsort im “wp-content/uploads/"-Verzeichnis in das Verzeichnis des jeweiligen Beitrags kopiert und dort zusammen mit der “index.html” abgelegt.

In einem letzten Schritt wurde das ursprüngliche “img”-Tag im Beitrag durch einen Hugo-Shortcode zur Bildeinbettung ersetzt.

Galerien

In verschiedenen Beiträgen wurden Standard-WordPress-Galerien verwendet, die im Quellcode wie folgt dargestellt werden

[gallery link="file" ids="4687,4688,4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700"]

Die zu den IDs gehörenden Bilddateien wurden in der Datenbank ermittelt

SELECT *
FROM wp_postmeta
WHERE meta_key = '_wp_attached_file' AND post_id = $imageID;

und anschließend zusammen mit eventuell vorhandenen Thumbnails ins Beitragsverzeichnis kopiert. Ebenso wurden eventuell in der Datenbank vorhandene “alt”-Tags ausgelesen:

SELECT * FROM wp_postmeta
WHERE meta_key = '_wp_attachment_image_alt' AND post_id = $imageID;

Analog zu den Bildern wurde die Galerie-Definition durch einen Hugo-Shortcode ersetzt. Die Bilder selbst wurden zusammen mit den Textinformationen im Front Matter gespeichert:

gallery:
- src: 2006-02-17_deep_purple_img_7147.jpg
  alt: Deep Purple

Textformatierung

Da in WordPress die wpautop()-Funktion aktiv war, wurde diese im Perl-Skript nachgebildet und der Text damit formatiert. Freundlicherweise besteht ein Großteil der WordPress-Funktion aus Perl-kompatiblen Regulären Ausdrücken, was die Umsetzung deutlich beschleunigt hat.

Rückblickend betrachtet wäre trotzdem mit großer Wahrscheinlichkeit ein PHP-Skript zum Export die effektivere Lösung gewesen: in dieses hätte ich die relevanten WordPress-Funktionen direkt einbinden können, statt deren Funktionalität in einer anderen Sprache nachzubauen. Aber hier schlug wohl das bekannte “Law of the Instrument” zu.

Als letzter Schritt wurde die Verlinkung innerhalb der Beiträge modifiziert. Alle FQDN-Links, welche auf die Blog-Domain zeigten, wurden um den Domain-Teil reduziert. Sofern ein Link eine Referenz auf die in WordPress verwendete Lightbox enthielt, wurde diese verworfen.

Sofern der Link auf eine Datei unterhalb von “wp-content/uploads” zeigte, wurde die verlinkte Datei ins Beitragsverzeichnis kopiert und das Linkziel entsprechend angepasst.

Falls im Link weiterhin eine Domain enthalten war, wurde dem Link die CSS-Klasse “extlink” hinzugefügt, eine Funktionalität, die bisher von einem selbstgeschriebenen WordPress-Plugin bereitgestellt wurde.

Zusammenfassung

Nach Ende der Bearbeitungsschritte war eine erste und im Wesentlichen (mit Hugo) funktionsfähige Version des Blogs vorhanden, allerdings stand noch einiges an Detail- und Aufräumarbeiten an.