[gelöst] Node & Taxonomie Migration D7 > D7 mit migrate_d2d
am 22.09.2016 - 14:52 Uhr in
Hallo,
ich versuche gerade Content/Nodes und Taxonomie Vokabeln/Begriffe von einer D7 Installation (Drupal 7.44 mit eCommerce Kickstart 2.38) zu einer anderen D7 Installation (reines & frisches Drupal 7.50) zu migrieren.
Prinzipiell geht das, aber es übernimmt beispielsweise bei Blogeinträgen nur die Felder body und title, alle selbst hinzugefügten Felder werden ignoriert (z.B. Tags oder Kategorien). Jetzt gibt es ja scheinbar die Möglichkeit den Migrations-Task zu bearbeiten und nachträglich noch ein Field-Mapping durchzuführen. Sieht ja erstmal richtig cool und intuitiv aus, aber egal was ich da auch ändere und auswähle, es wird nicht abgespeichert wenn ich auf "apply changes" klicke.
Woran kann das liegen? Könnt Ihr mir hier weiterhelfen?
Hier die Software inkl. Versionen die ich hierfür einsetze:
- Drupal 7.50
- migrate 2.8
- migrate_d2d 2.1
- bundle_copy 1.1
Vielen Dank im Voraus für Eure Unterstützung und Hilfe.
LG,
pyretta
EDIT/ERGÄNZUNG:
---------------
Habe eine Class für das Migration Module geschrieben nach Google Suche & gefundener Anleitung/Dokumentation. Jetzt klappts schon besser. Die Kategorie und die Tags der Blogbeiträge werden zumindest Mengenmäßig importiert. D.h. wenn ich bei einem Blogbeitrag 10 Tags vergeben habe, sind jetzt auch 10 Einträge im Beitrag für Tags vorhanden - aber deren Namen werden nicht angezeigt, sondern ein Füllwort "Stub". Außerdem stimmt die ID der Quelle nicht mit der des Ziels überein. Müsste das nicht der Fall sein? Und wie krieg ich das hin, dass er den Namen anzeigt?
Hier jedenfalls mein verwendeter Code (Passwörter, DB-Zugangsdaten etc. natürlich durch Beispieldaten ersetzt).
blog_d2d_migrate.inc:
<?php
/**
* @file blog_d2d.migrate.inc
*/
/**
* Implements hook_migrate_api().
*/
function blog_d2d_migrate_api() {
/**
* Declare the api version and migration group.
*/
$api = array(
'api' => 2,
'groups' => array(
'content_migration' => array(
'title' => t('Blog Migration'),
),
'migrations' => array(),
),
);
$common_arguments = array(
'source_connection' => 'legacy',
'source_version' => 7,
'source_database' => array('driver' => 'mysql','database' => 'dbname','username' => 'benutzer','password' => 'pw12345','host' => 'dbserver','prefix' => '',),
'group_name' => 'content_migration',
);
$vocabulary_arguments = array(
'Tags' => array(
'description' => t('Migration of Tags terms from Drupal 7'),
'source_vocabulary' => '2', // vid 2
'destination_vocabulary' => 'tags',
),
'Categories' => array(
'description' => t('Migration of Categories terms from Drupal 7'),
'source_vocabulary' => '1', // vid 1
'destination_vocabulary' => 'blog_category',
),
);
$common_vocabulary_arguments = $common_arguments + array(
'class_name' => 'TermsD7Migration',
);
foreach ($vocabulary_arguments as $migration_name => $arguments) {
$arguments += $common_vocabulary_arguments;
$api['migrations'][$migration_name] = $arguments;
}
$node_arguments = array(
'blogs' => array(
'class_name' => 'BlogsNodeMigration',
'description' => t('Blog Migration - von einem Inhaltstyp zum anderen'),
'source_type' => 'blog_post',
'destination_type' => 'blog_post',
),
);
foreach ($node_arguments as $migration_name => $arguments) {
$arguments = array_merge_recursive($arguments, $common_arguments);
$api['migrations'][$migration_name] = $arguments;
}
return $api;
}
?>
node.inc
<?php
class BlogsNodeMigration extends DrupalNode7Migration {
public function __construct(array $arguments) {
parent::__construct($arguments);
$this->addFieldMapping('body', 'body');
$this->addFieldMapping('body:summary', 'body:summary');
$this->addFieldMapping('field_blog_category', '1')->sourceMigration('Categories');
$this->addFieldMapping('field_blog_category:source_type')->defaultValue('tid');
$this->addFieldMapping('field_tags', '2')->sourceMigration('Tags');
$this->addFieldMapping('field_tags:source_type')->defaultValue('tid');
}
}
?>
taxonomy.inc
<?php
<?php
/**
* @file
* Implementation of DrupalTermMigration for Drupal 7 sources.
*/
class TermsD7Migration extends DrupalTerm7Migration {
public function __construct(array $arguments) {
parent::__construct($arguments);
$this->addFieldMapping('format', 'format')
->callbacks(array($this, 'mapFormat'));
$this->addFieldMapping('name', 'name');
$this->addFieldMapping('description', 'description');
$this->addFieldMapping('path', 'path');
}
protected function query() {
$query = Database::getConnection('default', $this->sourceConnection)
->select('taxonomy_term_data', 'td')
->fields('td', array('tid', 'name', 'description', 'weight', 'format'))
->orderBy('th.parent')
->distinct();
// Join to the hierarchy so we can sort on parent, but we'll pull the
// actual parent values in separately in case there are multiples.
$query->leftJoin('taxonomy_term_hierarchy', 'th', 'td.tid=th.tid');
$query->innerJoin('taxonomy_vocabulary', 'v', 'td.vid=v.vid');
$query->condition('v.machine_name', array($this->sourceVocabulary), 'IN');
return $query;
}
/**
* Review a data row after fetch, returning FALSE to skip it.
*
* @param $row
* @return bool
*/
public function prepareRow($row) {
if (parent::prepareRow($row) === FALSE) {
return FALSE;
}
// Add the (potentially multiple) parents.
$result = Database::getConnection('default', $this->sourceConnection)
->select('taxonomy_term_hierarchy', 'th')
->fields('th', array('parent'))
->condition('tid', $row->tid)
->execute();
$row->parent = array();
foreach ($result as $parent_row) {
$row->parent[] = $parent_row->parent;
}
$this->version->getSourceValues($row, $row->tid);
return TRUE;
}
}
?>
- Anmelden oder Registrieren um Kommentare zu schreiben
ist es nicht einfacher
am 23.09.2016 - 05:56 Uhr
ist es nicht einfacher atxonomy export/import und nodeimport zu nutzen?
C.A.W. Webdesign
Hallo caw, ja, wäre es
am 23.09.2016 - 08:14 Uhr
Hallo caw,
ja, wäre es sicherlich, wenn es in dem eCommerce System funktionieren würde. Habe es installiert & aktiviert, aber es ist nicht nutzbar in diesem System, es ist fast als wäre es nicht installliert. Es ist nicht einmal über das Admin-Menü erreichbar. Wenn ich über die Modul-Liste auf den Konfigurationslink klicke, gelange ich nur auf die Admin Index-Seite. Dementsprechend kann ich dort keinen Export erstellen. Dieses eCommerce System erscheint mir ohnehin etwas fehlerhaft, was ein Grund ist warum ich es loswerden und die Inhalte in ein normales Drupal überführen will.
Hast du keine Idee, warum die Taxonomie-Begriffe leer übergeben und mit "Stub" gefüllt werden könnten? Bzw. muss ich vllt. in der taxonomy.inc irgendwas bestimmtes angeben oder ändern?
keine idee.... aber
am 23.09.2016 - 09:33 Uhr
keine idee.... aber vielelicht ist ja ein fehler im commerce, wenn du sagst, daß das ja generell fehlerhaft ist.
das das nicht erscheint liegt eher wohl am php memeory limit. mal alle cache geleert nach dem installieren?
C.A.W. Webdesign
ok, das mit dem Cache leeren
am 23.09.2016 - 11:11 Uhr
ok, das mit dem Cache leeren nach der Installation hatte ich zugegebenermaßen versäumt. Danach konnte ich das Modul auch nutzen. Musste nur noch in der View für Inhalte die Funktion "node export" in der Stapelverarbeitung aktivieren (in Drupal eCommerce sind fast alle Backend Seiten als Views organisiert).
Ich habe gerade die Blogbeiträge in der D7.50 Installation (Ziel-System) importiert. Funktioniert im Prinzip, aber es hat scheinbar keine Verbindung zu den Beitragsautoren und gibt zum einen folgende Fehlermeldung in ca. 1000 Wiederholungen aus (so viel wie Blogbeiträge eben) und sowohl das Beitragsdatum als auch der Autor (logischerweise) stimmen nicht und werden als "Gast" mit heutigem Datum ausgegeben. Außerdem fehlen die Tags und die Kategorien völlig und der Titel ist doppelt.
Fehlermeldung:
Notice: Undefined offset: 51 in user_node_load() (Zeile 3696 von /html/drupal_7/drupal/modules/user/user.module).
Notice: Trying to get property of non-object in user_node_load() (Zeile 3696 von /html/drupal_7/drupal/modules/user/user.module).
Die Autoren bzw. User sind allerdings schon 1:1 überführt worden - vor dem Import. Es hätte also so sein müssen, dass es diese auch findet, meiner Meinung nach.
Alles in allem scheint mir diese Methode die schlechtere Option zu sein.
Gibt es denn keine Möglichkeit meine Migration Class zu optimieren, dass diese die richtigen Werte ausgeben kann?
Dort bin ich doch nur ein Quäntchen vom Glück entfernt... (hoffe ich zumindest).
Vielleicht könnt ihr den
am 23.09.2016 - 14:59 Uhr
Vielleicht könnt ihr den Fehler besser nachvollziehen, wenn ich das Migrations Protokoll (nur ein Auszug) mitgebe:
Processed 10 (0 created, 0 updated, 0 failed, 10 ignored) in 0.1 sec (0/min) - done with 'User'
Processed 0 (0 created, 0 updated, 0 failed, 0 ignored) in 0 sec (0/min) - done with 'Tags'
Processed 0 (0 created, 0 updated, 0 failed, 0 ignored) in 0 sec (0/min) - done with 'Categories'
Processed 116 (116 created, 0 updated, 0 failed, 0 ignored) in 218.7 sec (32/min) - continuing with 'blogs'
Tags addFieldMapping: format was previously mapped from format, overridden
Tags addFieldMapping: name was previously mapped from name, overridden
Tags addFieldMapping: description was previously mapped from description, overridden
Tags addFieldMapping: path was previously mapped from path, overridden
Categories addFieldMapping: format was previously mapped from format, overridden
Categories addFieldMapping: name was previously mapped from name, overridden
Categories addFieldMapping: description was previously mapped from description, overridden
Categories addFieldMapping: path was previously mapped from path, overridden
Processed 4 (4 created, 0 updated, 0 failed, 0 ignored) in 29.4 sec (8/min) - continuing with 'blogs'
[.....]
Tags addFieldMapping: format was previously mapped from format, overridden
Tags addFieldMapping: name was previously mapped from name, overridden
Tags addFieldMapping: description was previously mapped from description, overridden
Tags addFieldMapping: path was previously mapped from path, overridden
Categories addFieldMapping: format was previously mapped from format, overridden
Categories addFieldMapping: name was previously mapped from name, overridden
Categories addFieldMapping: description was previously mapped from description, overridden
Categories addFieldMapping: path was previously mapped from path, overridden
Processed 8 (8 created, 0 updated, 0 failed, 0 ignored) in 35.3 sec (16/min) - continuing with 'blogs'
Außerdem habe ich folgendes schon vergeblich versucht
am 23.09.2016 - 15:18 Uhr
Außerdem habe ich folgendes schon vergeblich versucht:
1. Hinweis von Drupal.Stackexchange.com nachgegangen, dass Migrate keine multi-value Felder verarbeiten könnte.
URL: http://drupal.stackexchange.com/questions/112660/how-to-migrate-a-multi-...
Deshalb sowohl nach Anweisung der als "richtig" getaggten Antwort vorgegangen (allerdings kam dann die Fehlermeldung dass die verwendete MEthode veraltet wäre, deshalb wieder verworfen) als auch mit dem sog. Seperator Argument gearbeitet, das vom Fragesteller am Schluss als die Lösung bekannt gab.
<?php
$this->addFieldMapping('blog_category', 'field_blog_category')->separator('|');
$this->addFieldMapping('field_blog_category', 'field_blog_category')->separator('|');
?>
und auch folgende Mappings hinzugefügt:
<?php
$this->addFieldMapping('field_blog_category:create_term')->defaultValue(true);
$this->addFieldMapping('field_blog_category:ignore_case')->defaultValue(true);
?>
=> hat alles nicht funktioniert
2. In der "taxonomy.inc" Datei die Database Connection Anweisung erweitert
<?php
protected function query() {
Database::addConnectionInfo('for_migration', 'default', array(
'driver' => 'mysql',
'database' => 'dbname',
'username' => 'user',
'password' => 'pw1234',
'host' => 'dbserver',
'prefix' => '',
));
$query = Database::getConnection('default', 'for_migration')
->select('taxonomy_term_data', 'td')
->fields('td', array('tid', 'name', 'description', 'weight', 'format'))
->orderBy('th.parent')
->distinct();
// Join to the hierarchy so we can sort on parent, but we'll pull the
// actual parent values in separately in case there are multiples.
$query->leftJoin('taxonomy_term_hierarchy', 'th', 'td.tid=th.tid');
$query->innerJoin('taxonomy_vocabulary', 'v', 'td.vid=v.vid');
$query->condition('v.machine_name', array($this->sourceVocabulary), 'IN');
return $query;
}
?>
=> brachte auch keine Besserung
Außerdem habe ich noch den Code von "blog_d2d.migrate.inc" erweitert, so dass Abhängigkeiten geschaffen werden und die Usertabelle miteinbezogen wird.
Neuer Code von "blog_d2d.migrate.inc":
<?php
/**
* @file blog_d2d.migrate.inc
*/
/**
* Implements hook_migrate_api().
*/
function blog_d2d_migrate_api() {
/**
* Declare the api version and migration group.
*/
$api = array(
'api' => 2,
'groups' => array(
'content_migration' => array(
'title' => t('Blog Migration'),
),
'migrations' => array(),
),
);
$common_arguments = array(
'source_connection' => 'legacy',
'source_version' => 7,
'source_database' => array('driver' => 'mysql','database' => 'dbname','username' => 'user','password' => 'pw1234','host' => 'dbserver','prefix' => '',),
'group_name' => 'content_migration',
);
$api['migrations']['User'] = $common_arguments + array(
'description' => t('Migration of users from Drupal 7'),
'class_name' => 'UserD7Migration',
);
$vocabulary_arguments = array(
'Tags' => array(
'description' => t('Migration of Tags terms from Drupal 7'),
'source_vocabulary' => '2', // vid 2
'destination_vocabulary' => 'tags',
),
'Categories' => array(
'description' => t('Migration of Categories terms from Drupal 7'),
'source_vocabulary' => '1', // vid 1
'destination_vocabulary' => 'blog_category',
),
);
$common_vocabulary_arguments = $common_arguments + array(
'class_name' => 'TermsD7Migration',
'soft_dependencies' => array('User'),
);
foreach ($vocabulary_arguments as $migration_name => $arguments) {
$arguments += $common_vocabulary_arguments;
$api['migrations'][$migration_name] = $arguments;
}
$node_arguments = array(
'blogs' => array(
'class_name' => 'BlogsNodeMigration',
'description' => t('Blog Migration - von einem Inhaltstyp zum anderen'),
'source_type' => 'blog_post',
'destination_type' => 'blog_post',
'dependencies' => array('Tags', 'Categories'),
),
);
$common_node_arguments = $common_arguments + array(
'user_migration' => 'User'
);
foreach ($node_arguments as $migration_name => $arguments) {
$arguments = array_merge_recursive($arguments, $common_node_arguments);
$api['migrations'][$migration_name] = $arguments;
}
return $api;
}
?>
Habe es nun selbst lösen
am 26.09.2016 - 10:09 Uhr
Habe es nun selbst lösen können.
Es war so simpel dass man es wirklich leicht hat übersehen können.
Die variable für "source_vocabulary" darf nicht die VID sein, wie es wäre wenn man von D6 käme, es muss der "machine_name" sein.
Deshalb habe ich es wie folgt geändert:
<?php
$vocabulary_arguments = array(
'Tags' => array(
'description' => t('Migration of Tags terms from Drupal 7'),
'source_vocabulary' => 'tags', // vid 2
'destination_vocabulary' => 'tags',
),
'Categories' => array(
'description' => t('Migration of Categories terms from Drupal 7'),
'source_vocabulary' => 'blog_category', // vid 1
'destination_vocabulary' => 'blog_category',
),
);
?>