In migrating taxonomy terms, the key is mapping the legacy vocabulary to the destination vocabulary. Note that up till now we've dealt with classes that you will generally instantiate once - this is our first example of classes you would instantiate multiple times, one for each vocabulary to migrate.

  • source_vocabulary: The unique identifier of the legacy vocabulary (a machine name in Drupal 7, or a vid for earlier Drupal versions).
  • destination_vocabulary: The unique machine name of the destination vocabulary.
// In this example, we're consolidating two legacy vocabularies into one
$photo_term_arguments = $common_arguments + array(
  'machine_name' => 'ExamplePhotoTerm',
  'description' => t('Import Drupal 6 photo terms into media terms'),
  'source_vocabulary' => '3',  // "Photo category" vocabulary
  'destination_vocabulary' => 'media_category',
);
Migration::registerMigration('DrupalTerm6Migration', 
  $photo_term_arguments['machine_name'], $photo_term_arguments);

$video_term_arguments = $common_arguments + array(
  'machine_name' => 'ExampleVideoTerm',
  'description' => t('Import Drupal 6 video terms into media terms'),
  'source_vocabulary' => '5',  // "Video category" vocabulary
  'destination_vocabulary' => 'media_category',
);
Migration::registerMigration('DrupalTerm6Migration', 
  $video_term_arguments['machine_name'], $video_term_arguments);

For help with the Migrate UI and taxonomy migration, see also Advanced field mappings.

Comments

tmetzger’s picture

This works great to import the terms themselves (using 6.x-2.0-rc1), but mapping them to nodes seems to be a bit tricky. Here's the pattern I have seen to make this work, assuming that the vocabulary ID on the source Drupal 6 system was 1 (which it was):

class MSIArrangementNodeMigration extends MSINodeMigration {
  public function __construct(array $arguments) {
    parent::__construct($arguments);

    $this->addFieldMapping('field_voices', 1)
         ->sourceMigration('Voices')
         ->arguments(array('source_type' => 'tid'));

  }
  public function sourceFieldList() {
    $fields = parent::sourceFieldList();
    return $fields;
  }
}

Unfortunately it doesn't seem to work. Is this the correct pattern?

Thanks in advance,
Tom

tmetzger’s picture

Oops my mistake - it does work! :) I had a bit of old data hanging around in my database that led me to believe otherwise.

Anonymous’s picture

Any hints or examples for a D6 to D7 migration? I'm having a hard time getting this to work.

Anonymous’s picture

Actually, this does work in D7, except you don't need the sourceFieldList function at all.

johnvsc’s picture

In the code above*:

    $this->addFieldMapping('field_voices', 1)
         ->sourceMigration('Voices')
         ->arguments(array('source_type' => 'tid'));

The sourceMigration method is referring to the machine name of a term mapping that would have been defined in the hook_register_migrations. This took me some time to figure out.

So, my hook is defined as

/**
 * Register all D6->D7 migrations.
 */
function vsc_migrate_627_register_migrations() {
  // Specify the DB connection and the source Drupal version.
  $common_arguments = array(
    'source_connection' => 'legacy',
    'source_version' => 6,
  );

  // Register migrations.
  _vsc_migrate_627_coupon($common_arguments);
  _vsc_migrate_627_coupon_conditions_terms($common_arguments);
}

The _vsc_migrate_627_coupon_conditions_terms is defined as:

/**
 * @param $common_arguments
 */
function _vsc_migrate_627_coupon_conditions_terms($common_arguments) {

  $args = $common_arguments + array(
      'description' => 'Migrate coupon tags',
      'machine_name' => 'CouponConditionsMigration',
      'source_vocabulary' => $vid = 1,
      // The Vocab Id of the tags on the D6 instance.
      'destination_vocabulary' => 'conditions',
    );

  // We can use the same class as the *Node* terms.
  Migration::registerMigration($migration_class = "VSCTerm6Migration", $args['machine_name'], $args);
}

So, you see where the machine name is defined ... right?
Then in my class VSCCoupon6Migration extends DrupalNode6Migration, we map it using:

    /**
     * Taxonomy Terms.
     *
     * This leans on the Classes / mappings for individual terms items: defined
     * by the sourceMigration method
     */
    $this->addFieldMapping('field_medical_conditions', 1)
      ->sourceMigration('CouponConditionsMigration')
      ->arguments(array('source_type' => 'tid'));

Get it?

* Note, i am doing a 6 to 7 migration leaning on the awesome https://drupal.org/project/migrate_d2d ( not to say that Migrate ain't awesome either!)

SomebodySysop’s picture

The logic of this term mapping is correct

    $this->addFieldMapping('field_voices', 1)
         ->sourceMigration('Voices')
         ->arguments(array('source_type' => 'tid'));

But this format has been deprecated. I just tried it to solve a term matching problem I was having in a D6 to D7 migration.

You can do this in the Migrate d2d UI:

When mapping term for node in UI, map the term AND include it's source migration (important!). Next, right under the term field source destination is Option: Set to 'tid' when the value is a source ID [term_field:source_type] You should put "tid" in the Default Value column.

Here is an example.

lancewig’s picture

If all you are doing is moving a term inside a node in D6 to a term field in a D7 CCK field, then you can use the GUI. SomebodySysop is right. I really banged my head on this for a while. I hope this helps somebody.

This is what worked for me in my case.

texas-bronius’s picture

Note that DrupalTerm6Migration in this example will not create the destination Vocabulary. Instead, you will get something like:

New object was not saved, no error provided     [error]
New object was not saved, no error provided     [error]
... etc

one for each source Term. Also, drush mmsg [yourmigration] shows something like:

 sourceid1   message                                             
 15          No vocabulary found with machine_name document_type 
 15          New object was not saved, no error provided         
 16          No vocabulary found with machine_name document_type 
 16          New object was not saved, no error provided         
... etc

Manually creating empty Vocabulary placeholders at the destination allows the import to succeed as shown in the example.

--
http://drupaltees.com
80s themed Drupal T-Shirts

Summit’s picture

Hi, @Pearlbear,
I need also to migrate a vocabulary with term referenced node fields to convert from a D6 to a D7 site.
Can you may be give me a plan of action how to deal with this please?
I also try this through Migrat D-D but the taxonomy fields (node/term relation) do not get migrated....
Does anyone have reusable code for this? A plain (sub)module in .zip?

Thanks a lot in advance!
Greetings, Martijn

justice4world’s picture

Hi,

I'm new to Drupal and have performed a D5 to D7 migration and everything migrated over just fine except for forum content. I found this code here:

$this->addFieldMapping('taxonomy_forums', 'objectid');
$this->addFieldMapping('taxonomy_forums:source_type')
     ->defaultValue('tid');

on a comment to this post here:

https://www.drupal.org/node/1609160

My question is, where in the migrate module should this code be inserted? Possibly in this include file here:

/modules/migrate/includes/field-mapping.inc

Or, somewhere else?

The errors I am receiving during the migration are:

for Nodeforum:

reset() expects parameter 1 to be array, null given File /forum.module, line 331

This is line 331 in forum.module:

$forum_terms[] = $term->tid;

and for Commentforum:

No node ID provided for comment

Thank you in advance. :)

Summit’s picture

Hi @johnvsc, and others
May be not the right issue for this, but the issue is evolving to node term references as I see.
I would very much like to migrate my referenceD terms on my nodes from D6 to D7.
With the 'standard UI' and method it seems I only get one term reference per node.
Somehow node term references from a vocabulary with multiple values enabled. Like for a Hotel; wifi, 2 beds, bath etc..only one comes true.
Does your module help with this?
Are you willing to share your whole module here?
Thanks in advance for considering this.

EDIT: It works now. I forgot to set my term_reference field to "unlimited".
Greetings, Martijn

steinmb’s picture

Try and read this series of articles - https://smbjorklund.no/how-migrate-content-drupal-6-7-using-migrated2d-p... it might help.

Stein Magne
http://smbjorklund.no

davemybes’s picture

Just in case anyone else is needing this information, if you are migrating taxonomy terms on a node (in D6) that are put there by assign the taxonomy to the node, then the default mapping is used (put in constructor function in your migration code):

    $this->addFieldMapping('D7_field_name', D6_vocab_id)
         ->sourceMigration('term_migration_machine_name');
    $this->addFieldMapping('D7_field_name:source_type')
         ->defaultValue('tid');

However, if the D6 field is a Content Taxonomy field, the D6_vocab_id should be the D6 field name instead. The rest of the code stays as above:

    $this->addFieldMapping('D7_field_name', 'D6_field_name')
         ->sourceMigration('term_migration_machine_name');
    $this->addFieldMapping('D7_field_name:source_type')
         ->defaultValue('tid');

______________________________________________________________________________________________________