Nodes und Taxonomies von Drupal 7 auf Drupal 8 migrieren

Gespeichert von admin am 23.08.2019 - 10:27

Schon lange bauen wir neue Projekte nur noch unter Drupal 8 auf und so langsam migrieren wir auch die eigenen Projekte nach und nach von Drupal 7 auf 8. Die sind ausnahmslos schon lange gewachsen und mit zahlreichen Modulen erweitert.

Die grundsätzlichen Erwägungen sind noch die gleichen, wie bei unserem Blogartikel, der sich vor langer Zeit mit dem Thema Upgrade von Drupal 6 auf 7 beschäftigt hat.

https://www.montviso.de/blog/drupal-upgrade-6-7-teil-1

Hier gehe ich allerdings nur auf das Thema Nodes- und Taxonomien-Migration ein.

Bitte beachtet, dass die Beschreibung über weite Teile sehr kurz gefasst ist und informiert Euch auch noch in der englischen Doku.

Auf den Teil mit CSV-Export bei Drupal 7 und Import auf 8 mit Feeds gehe ich allerdings etwas näher ein, weil es da ein paar Fallstricke gibt.

1. Migration mit drush:
Dazu wird das Modul mit Composer installiert:

composer require drupal/migrate_upgrade:^3

Und danach die Migration durch geführt:
drush migrate-upgrade --legacy-db-url=mysql://user:pass@12.34.56.78/dbname --legacy-root=http://mydrupalsite.com
Bitte User, Passwort, Name, IP-Adresse der Datenbank, sowie URL auf die Drupal Installation anpassen.
Dazu muss sichergestellt sein, dass man die Datenbank via Ip-Adresse ansprechen kann, nicht nur per localhost.

Diese Methode scheiterte bei uns am allowed memory Fehler.
Offensichtlich reicht das memory limit der PHP Version auf der Konsole bei All-inkl nicht aus. Das wundert mich, weil Composer Installationen und Updates immer klappen.
 

2. Migration via Backend
Dazu wird das Migrate Modul verwendet und auch die Migrate Drupal UI aktiviert.
Danach kann man unter /upgrade/credentials folgende Angaben machen:

    

Upgrade Migrate Drupal 7 auf Drupal 8

    

In unserem Fall hat das zahlreiche Fehlermeldungen ergeben und es wurden jede Menge Tabellen in der neuen Installation angelegt nach diesem Muster:

 

Upgrade Migrate Drupal 7 auf Drupal 8

 

Damit hatten wir bereits gerechnet, aber versuchsweise doch mal diesen Migrations-Weg getestet und festgestellt, dass die Inhalsttypen sauber abgeblidet wurden. Das machen wir uns in der Folge zu Nutze, um diese nicht komplett händisch nachbauen zu müssen.

Mehr dazu findet Ihr hier:
https://www.drupal.org/docs/8/upgrade/preparing-a-site-for-upgrade-to-drupal-8

Der Versuch fand auf einer Drupal 8 Version statt, die bereits mit den gewünschten Modulen und Themes ausgestattet war.
Mittels Backup wurde dieser saubere Stand der neuen Installation auf einer neuen Datenbank und mit neuer Subdomain wieder hergestellt.

Nun gibt es also 3 Installationen für das Projekt:

https://meineDomain-d7produktiv.de  (= PRODUKTIV unter D7) 

https://d8-temp-meineDomain.de (= TEMP: mit der Migration via Administrations-Oberfläche)

https://d8-meineDomain.de (= TEST: saubere D8 Installation mit gewünschten Modulen)

Auf der temporären Installation sind durch die Migration alle Inhaltstypen angelegt worden.Das machen wir uns nun zu nutze, um nicht alle Inhaltstypen und Felder auf der sauberen D8 Installation händisch anlegen zu müssen.

3. Import von Taxonomien + Inhalten

Falls die Inhaltstypen Referenzen auf Taxonomien enthalten, dann sollten diese bereits angelegt sein und das Vokabluar exakt gleich benamt sein, wie auf der D7-Installation.

Zum Import der Taxonomy-Einträge kann man auf der TEST-Installation das Modul Taxonomy-Import verwenden.
https://www.drupal.org/project/taxonomy_import

Auf der D7 Installation exportiert man die Einträge pro Vokalbular in eine CSV-Datei die als UTF-8 abgespeichert wird.
In der TEST-Installation importiert man dann diese CSV-Dateien unter //admin/config/content/import_taxonomy

Bei Hierarchien benötigt man ein XML Format. Eine Beispiel-Datei mit der Syntax befindet sich im Ordner des Moduls: XML_Test.xml.

4. Export / Import der Inhaltstypen mit Feature-Modul

Mit Hilfe des feature-Moduls wird auf der Installation TEMP ein Export auf die gewünschten Inhaltstypen gemacht.
Das erzeugt ein tar-Archiv, in dem sich für jeden Inhaltstyp ein Ordner mit den Konfigurations-Dateien befindet.

Diese Ordner speichert man entzippt auf der TEST Installation im Ordner /module/custom und aktiviert sie via drush oder Drupal Admin-Oberfläche, wie bei Modulen üblich.
Durch diese Aktivierung des Moduls mit Namen <meininhaltstyp> wird "meinInhaltstyp" angelegt.

5. CSV-Datei mit Nodes von der D7-Installation

Hierzu braucht man das Modul "Views Data Export. (https://www.drupal.org/project/views_data_export).

Ist dieses installiert, so kann man eine neue View-Ansicht für CSV-Export erzeugen.
Dazu auf "Hinzufügen" klicken und "Data Export" wählen.

Das CSV Format ist dann bereits voreingestellt.

Es wird sofort darauf aufmerksam gemacht, dass diese Ansicht einen Pfad benötigt.
Also geben wir den Pfade "meininhaltstyp.csv" ein.

Unter "Format: Einstellungen" machen wir noch einige Angaben

  • Als Sepeator verwende ich gerne das | Pipe-Zeichen.

  • Anführungszeichen verwendet, um die Felder sauber zu trennen.

  • Newline wird entfernt (replace mit leer)

  • Erste Zeile ist die Überschrift (Haken lassen)

  • Ein "Haken bei Keep HTML tags" wird gesetzt

 

Upgrade Migrate Drupal 7 auf Drupal 8 - CSV Export aus View

 

Der Ansicht fügen wir die gewünschten Felder hinzu.

Dabei ist zu beachten:

  • Links auf Titel, Taxonomie Felder ect. sollten ausgeschaltet sein.

  • Label sollten keine Umlaute und Leerzeichen enthalten, weil das ja die Spaltenbezeichner im CSV werden.
     
     Upgrade Migrate Drupal 7 auf Drupal 8 CSV Export View Felder
     

  • Listen-Felder werden als Schlüssel formatiert, sonst kann später beim Import der Bezug nicht her gestellt werden.

  • Falls Bilder integriert sind, muss die URL exportiert werden.
    Hier ist später Handarbeit angesagt und es muss mit Suchen und ersetzen der vollständige Bildpfad in der Spalte stehen.
    Feeds auf der neuen Installation holt sich dann die Bilder von der alten Installation über das Netz. Das funktioniert natürlich nur bei Bildern, die public zugänglich sind.
    Bei private Dateien muss ein anderer Weg eingeschlagen werden.

Ruft man nun https://meinedomain/meininhaltstyp.csv auf, dann kann man die Datei im Editor betrachten und gegebenenfalls den Replace auf die Bildpfade machen.
Danach speichert man die Datei im UTF-8-Format ab.

6. Feeds-Typ einrichten unter Drupal 8

Das Feeds Modul (https://www.drupal.org/project/feeds) liegt momentan noch in alpha-Version vor, funktioniert aber nach unseren Erfahrungen einwandfrei für den Import der Nodes.

Es wird wie üblich mit Composer oder über das Backend installiert und aktiviert.

Danach kann man unter /admin/structure/feeds/add einen neue Feed-Typ anlegen.

Wir arbeiten mit folgenden Einstellungen:

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds-Typ anlegen

  

"Import period" stellen wir auf Aus, weil wir nur händischen Import machen möchten und nicht regelmäßig automatisch, was auch ginge.

Bei "Fetcher Einstellungen" behalten wir die Voreinstellungen.

Bei "Parser Einstellungen" geben wir als Delimiter das ein, was wir beim CSV Export als Separator gewünscht haben, also das Pipe-zeichen

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Parser Einstellungen

  

Bei "Processor Einstellungen" stellen wir sicher, dass wir den Import so oft, wie gewünscht machen können. Mit diesen Einstellungen wird beim wiederholten Mal ein Update auf vorhandene Datensätze gemacht. Das funktioniert nur, wenn im Mapping – zu dem wir gleich kommen – ein Feld als unique definiert wurde. Das kann der Titel sein, wenn wir sicher gestellt haben, dass Node-Titel nur einmal vorkommen dürfen.
In diesem Fall handelt es sich um ein Produkt mit Artikelnummer, die eignet sich ebenfalls gut als eindeutiger Schlüssel.

Falls gar kein Feld da ist, exportieren wir aus dem alten Feld die Node-ID und führen die im neuen Inhaltstyp als temporäres Hilfsfeld ein, bis wir mit den Ergebnissen zufrieden sind. Dann kann es wieder weg gelöscht werden.

Warum das Ganze?
Weil wir mit großer Sicherheit den Import-Vorgang mit Anpassungen mehrmals durchführen werden, bis wir mit dem Ergebnis zufrieden sind.

Man sieht, dass sich das Prozedere nur rentiert, wenn es ein paar mehr Nodes eines Inhaltstyps sind, bzw. sehr viele Felder, die man nicht händisch bestücken möchte.
Da muss man von Fall zu Fall entscheiden, was effektiver ist.

Dies waren also die Einstellungen unter dem Feeds-Reiter "Bearbeiten".
Der Reiter "Zuordnung" führt uns zum Mapping.
Hier wird angegeben, welches Feld aus der CSV in welches Feld des Inhaltstyps geschrieben werden soll.

Man wählt "Select a target" das Zielfeld.
Hat man das gemacht, steht das Ziel im Klartext da und es erscheint links davon die Aufforderung, die Quelle zu bennen.

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Mapping erstellen

 

Als Quelle wählen wir "New CSV Source".
Danach erscheint ein neues Eingabe-Fenster

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Mapping Source Namen

 

Wie kaum anders zu erwarten, heißt die Spaltenüberschrift der CSV-Datei für das Feld mit dem gewünschten Inhalt für dieses Feld ebenfalls "Fernsteuerung".
Es könnte aber auch ganz anders heißen, wenn wir den Label in der View mit dem CSV-Export anders benamt hätten.

Sobald wir in das leere Feld den Begriff eingetragen haben, erscheint darunter der Maschinen-Namen, den wir ändern können, bzw. auch noch ändern müssen, dazu gleich mehr.

Aber erst mal mappen wir auf diese Art alle Felder aus dem CSV zu den Feldern im neuen Inahaltstyp. Sollten wir uns vertun, dann kann man einfach unter ENTFERNEN (ganz hinten) einen Haken setzen. Dann verschwindet der Eintrag sofort.

Die Reihenfolge, in der wir die Mappings anlegen, ist egal.

Wichtig sind folgende Punkte:
Die Felder mit Langtext und Filter (z.B. Body-Feld) müssen auf den Filter "Vollständiges HTML" gesetzt werden. Das kann man mit Klick auf das Zahnrädchen machen.
Da wir bei der View gewünscht haben, dass HTML-Tags erhalten bleiben, werden diese Felder also mit dem HTML und allen Formatierungen aus der alten Installation übernommen.

Handelt es sich um ein Feld mit Text+Zusammenfassung, wie üblicherweise beim Bodyfeld der Fall ist, dann können wir zwei Sourcen verpflegen.
Haben wir Zusammenfassungen geschrieben, die nicht nur eine Kürzung des Body-Textes darstellen, dann müssen wir diese als extra Spalte im CSV erzeugen, also das Bodyfeld in der View zwei Mal hinzufügen, einmal als Text und einmal als Zusammenfassung.
Und dann müssen auch beide Spaltennamen als Sourcen angegeben werden.

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Mapping Textfeld mit Filter

 

In unserem Fall wurden keine abweichenden Zusammenfassung geschrieben, deshalb müssen wir nur die Source für Text angeben, welche hier den Spalte-Namen "Details" hat.

Ganz wichtig ist die Definition eines Feldes, welches "unique" sein muss, damit wir Updates auf den Datensatz machen können und nicht ein Node bei jedem Import versuch neu angelegt wird.

In unserem Fall ist es die Artikelnummer, bei der wir den Haken setzen:

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Mapping unique Field

 

Wenn wir Felder importieren, die eine Referenz auf eine Taxonomie darstellen, dann ist es unabdingbar, dass diese Taxonomie mit allen Inhalten bereits angelegt wurde, wie weiter oben beschrieben. Die Namen müssen eindeutig sein und in gleicher Schreibweise vorliegen.
Falls also auffällt, dass ein Begriff später anders lauten soll, dann bitte erst später diese Änderung vornehmen, sobald jeglicher automatischer Import abgeschlossen ist.

Die Voreinstellungen lassen wir, wie Feeds sie anbietet:

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Mapping Taxonomy Reference

 

Wenn wir nun alle Felder gemappt haben, können wir auf Speichern klicken und erleben erst mal eine böse Überraschung:

Bei fast allen Feldern steht dieses hier:

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds eindeutigen Systemnamen erzeugen

 

Das passiert, weil bereits ein gleicher Maschinen irgendwo in der Datenbank existiert.
Deshalb hängen wir einfach an den vorgeschlagenen Systemnamen (wir haben das ja nicht so genannt) noch eine Ziffer oder den Begriff "feed" an.
Damit ist der Systemname nun eindeutig und das Mapping kann gespeichert werden und wir können den nächsten Schritt ausführen, um endlich die Datensätze importiert zu können.

7. Feeds einrichten und ausführen:

Wenn ein neuer Feeds-Typ eingerichtet wurde, dann muss die Ausführung noch konfiguriert werden, über einen neuen Inhalt "Feed" von einem bestimmten Typ.
Das geht unter /admin/content/feed

Wir nennen den Feed genauso "Produkt", wie den Typ, könnte aber auch anders heißen.
Hier haben wir eigentlich nichts weiter zu tun, als unsere CSV-Datei hoch zu laden, die wir im Punkt 5 erzeugt haben.

Der Begrenzer wird bereits übernommen, weil dieser Feed ein Inhalt vom Feed-Typ "Produkt" ist und bei dem haben wir das Pipe-Zeichen gewählt, wie schon bei der View zum Erstellen der CSV-Datei.

Hier kann man nun entweder auf "Save and Import" klicken und damit den Import-Vorgang sofort anstoßen.
Oder man kann umschalten auf "Save", dann werden nur evt. Änderungen gespeichert.

Wichtig ist: Wenn Du feststellst, dass am CSV noch etwas verbessert werden muss, dann musst Du dieses hier weg löschen und das neue CSV - anders benamt - lokal speichern und wieder hier hoch laden.

 

Upgrade Migrate Drupal 7 auf Drupal 8 Feeds Import Optionen

Dieser Vorgang muss nun für jeden Inhaltstyp wiederholt werden.
Wie weit man die Prozesse einrichtet, die (teil)-automatisierten Import von Struktur und Inhalten erlauben - oder eben per Hand einrichtet, hängt stark von der Anzahl der Felder und Nodes ab.
Diese Entscheidung kann ich Euch nicht abnehmen.

Meine Beschreibung bezieht sich auf Nodes, die unter D7 weitgehend mit Core-Modulen erstellt und gepflegt wurden.
Sobald Informationen wie z.B. komplexe Node-Permissions, Domain-Acess-Angaben oder Display-Angaben mit Paragraphs oder Display Suite migriert werden müssen, kann das Vorgehen schnell an seine Grenzen stoßen.

D.h. nicht, dass es nicht mit Feeds funktioniert, sondern nur, dass ich es noch nicht probiert habe, und deshalb nicht beschreibe.
Ich weiß, dass es ein Feeds Paragraphs Modul gibt. Wie zuverlässig es arbeitet, weiß ich aber nicht.

Und natürlich bleibt jetzt noch genug zu tun, bis die Migration vollständig gelungen ist.