How to migrate content from drupal 6 to 7 by using Migrate_d2d - Part 4 - field mappings

This is probably the last post in this series. I will try in this article to bring it all together. This will also be the most code heavy article. If you are new to migrate and Drupal-to-Drupal data migration, make sure you read and understand the first articles before preceding.

Mapping fields (field mappings)

Migrate have no way of knowing your plans for your Drupal 6 CCK fields or to what fields you are planning to store the data in Drupal 7. Perhaps you do not want or need to migrate all your old data. Source and target field have the same field name and type, but sometime you might want to fix a bad decisions made in the past and reorganize your architecture. Migrate call this field mappings. What ever reason you might have, you will need to share these ideas with Mirate. The basic format is like this:

$this->addFieldMapping('drupal7-field_name', 'drupal6-field_name')

More details are found in the official documentation at drupal.org.

An example of this is found in article.inc:

<?php
$this
->addFieldMapping('field_bar', 'field_foo');
?>

This map field_foo (drupal 6) to the cleverly named field field_bar (drupal 7). This is all it take to get a text field like this migrated if you re-run the node migration drush mi Article.

Blog post in this series

Code

Grab the code from github and clone it into your Drupal 7 sites/all/modules/ directory.

git clone --branch example4-1 https://github.com/steinmb/smb_migrate.git

Or if you already have cloned it by following part 1-3, simply switch branch.

git checkout example4-1

Code in this article will only contain the part of the code discussed. Please look at the files for the complete code. The done in hope to make it easier to follow along.

input formats

Before we import anything, lets make sure we have the input formats correctly defined. If any of the imported content ends up in the wrong input formats, and is normally will, try altering the common arguments ($common_arguments array). This is taken from the smb_migrate.migrate.inc:

<?php
$common_arguments
= array(
 
'source_connection' => 'legacy',
 
'source_version' => 6,
 
'group_name' => 'content_migration',
 
'format_mappings' => array(
   
'0' => 'plain_text',
   
'1' => 'filtered_html',
   
'2' => 'full_html',
   
'3' => 'foo',
  ),
);
?>

By using the key format_mappings can you map up all your input formats. Drupal 6 does not have proper machine names but is represented by a numeric value. 0-2 is the default three Drupal 6 ships with but the forth one is custom format I added as an example.

The body field, as you probably have seen, have already been mapped, it is built in. This that also include defining input formats. However, for any custom fields this have to be defined on a field to field basis using a callback function. This is an example taken from article.inc:

<?php
$this
->addFieldMapping('field_bar:format', 'field_foo:format')
     ->
callbacks(array($this, 'mapFormat'));
}
?>

The format field_name: might seems odd at first but you soon get used to this pattern. This pattern is used all over the place to define arguments for mapping.

  • :format - Enable this on a field to field base.
  • mapFormat - this is a method (function) that get called. It try to use the information found in $format_mappings.

Mapping taxonomy terms field

In Part 2 we migrated taxonomy terms, though, references from the nodes to the migrated terms was not migrated and have yet not been created. About time to let migrate know that they exist.

article.inc

The code below migrate all the three populated vocabularies to three separate taxonomy term reference fields.

<?php
/**
 * @file article.inc
 * Article nodes migration from drupal 6 to 7.
 */
class ArticleMigration extends SMBNodeMigration {
  public function
__construct(array $arguments) {
   
parent::__construct($arguments);
   
$this->addFieldMapping('field_tags', 1)
         ->
sourceMigration('Tags');
   
$this->addFieldMapping('field_tags:source_type')
         ->
defaultValue('tid');
   
$this->addFieldMapping('field_tags2', 2)
         ->
sourceMigration('Tags2');
   
$this->addFieldMapping('field_tags2:source_type')
         ->
defaultValue('tid');
   
$this->addFieldMapping('field_tags3', 3)
         ->
sourceMigration('Tags3');
   
$this->addFieldMapping('field_tags3:source_type')
         ->
defaultValue('tid');
  }
}
?>

Let us have a look at the code. This part is repeated three times. Once for each field.

<?php
$this
->addFieldMapping('field_tags', 1)
     ->
sourceMigration('Tags');
$this->addFieldMapping('field_tags:source_type')
     ->
defaultValue('tid');
?>
  • field_tags it the Drupal 7 name of the field.
  • 1 is the vocabulary id in Drupal 6.
  • sourceMigration - Name of the migration job that migrated this vocabulary to Drupal 7.
  • source_type - This need to be set to tid for the migration to work. Read more about it migrate documentation.

page.inc - taxonomy term ref. to entity reference

Simplest content types we have. Does not have any custom CCK fields but it does have taxonomy terms added that needs to be mapped. To demonstrate that we easily can alter the target does this code map from a traditionally taxonomy reference to the more general and flexible entity reference. This field type have already been removed in Drupal 8 and it might already be a good idea to migrate away from it.

<?php
/**
 * @file page.inc
 * Page nodes migration from drupal 6 to 7.
 */
class PageMigration extends SMBNodeMigration {
  public function
__construct(array $arguments) {
   
parent::__construct($arguments);
   
$this->addFieldMapping('field_entityref_taxonomy', 3)
         ->
sourceMigration('Tags3');
  }
}
?>

As with regular taxonomy terms do you also there need to tell Migrate what migration job that imported these terms.

Subs

I wrote in part 2 that taxonomy terms have to be migrated before you migrate the nodes. Well I lied you you. I was trying to keep my example simple and easy to understand.

You my have noticed that the node migration have no absolute dependency to the taxonomy migration. This allow us to migrate nodes first, and then attempt to migrate the terms. The good news it that this will also work. If you try to do this (empty vocabularies), you will soon find them populated with terms that all are named stub. These stubs are placeholders used in nodes. Have a look at your migrated nodes. They will stay like this until you also migrate the real taxonomy terms.

Migrating nodes and creating taxonomy term references

Test out this code by rolling back any imported nodes:

drush mr Article
drush mr Page

Import the nodes over again:

drush mi Article
drush mi Page

Mapping file field

article.inc

Content type Story in Drupal 6 is the only one that have a file field.

<?php

/**
 * @file article.inc
 * Article nodes migration from drupal 6 to 7.
 */
class ArticleMigration extends SMBNodeMigration {
  public function
__construct(array $arguments) {
   
parent::__construct($arguments);
   
$this->addFieldMapping('field_file', 'field_file')
         ->
sourceMigration('File');
   
$this->addFieldMapping('field_file:file_class')
         ->
defaultValue('MigrateFileFid');
  }
}
?>
  • field_file - Name of the file field. Here have I used the same field name in Drupal 6 and 7.
  • sourceMigration('File') - Tell migrate what migration task that have migrated all the files to the system. For more details look at - Part 3 - File migration.
  • file_class - This is a new one. This is not a migration class. This is the migration destination class. For a regular migration like this do we use MigrateFileFid.

Troubleshooting

There is multiple tings that might could make your migration fail. Migrate does a great job catching these errors, so please make sure you start out by checking these. You will any logged error in the migrate UI admin/content/migrate, there will be created one log pr. migration task, or, you could use drush:

drush migrate-messages Article
drush migrate-messages Page

Changes not used/detected

Make sure you are not fooled by Migrate not registering your new migration code. It is easily done.

  • Flush your cache drush cc all
  • Register your classes: drush migrate-register
  • Try to unregister your classes and register them again: drush migrate-unregister
  • Try registering the classes with migrate UI if drush is not your thing.

Taxonomy

Make sure that the taxonomy vocabularies exists in Drupal 7 before attempting to migrate the taxonomy terms and/or nodes that contain mapping to them.

Check your field settings in Drupal 7. Make sure you are allowed to reference the vocabulary and that Number of values are correctly set.

Blog post in this series

Comments

Hi, very helpful this series of posts. I think this line $ this-> addFieldMapping ('field_bar: format', 'field_foo: format') It should be written as $ this-> addFieldMapping ('field_bar: format', 'field_foo_format') otherwise field_bar will receive the 'plain text' filter

Thank you, this series was very helpful for me. If somebody needs to study all the migration and migration_d2d classes, I recommend by using http://drupalcontrib.org alongside to official Migrate documentation. This worked for me while I was searching for details on mapFormats class method.

Add new comment