Mapping split taxonomy terms to new vocabs in nodes in migrate_d2d I have a use case in a D6->D7 migration (using migrate_d2d), where I need to split terms from a large vocabulary into two new vocabularies in the D7 site. I achieved the splitting into two new vocabularies just fine in the taxonomy migration (see here for details on how), but the problem is getting the new mapping to work during the blog node migration so that the nodes are attached to the proper vocabulary field in the destination node.

So here's the setup:

D6


People and Organizations (vid 4)


D7


People and Organizations (field_people_organizations, vid 9)
Journalists (field_journalists, vid 5) Non-Journalists
Non-Journalists (field_non_journalists, vid 7)


In my blog node class constructor, I've added this:

$this-&gt;addFieldMapping('field_people_organizations', 4)
  -&gt;sourceMigration('PeopleOrganizations');
$this-&gt;addFieldMapping('field_people_organizations:source_type')-&gt;defaultValue('tid');
$this-&gt;addFieldMapping('field_journalists', 4)
  -&gt;sourceMigration('PeopleOrganizations');
$this-&gt;addFieldMapping('field_journalists:source_type')-&gt;defaultValue('tid');
$this-&gt;addFieldMapping('field_non_journalists', 4)
  -&gt;sourceMigration('PeopleOrganizations');
$this-&gt;addFieldMapping('field_non_journalists:source_type')-&gt;defaultValue('tid');


However, what this does is just populate all three taxonomy reference fields with all terms from the People and Organizations field in the source. For instance, if the D6 People and Organizations field has Term A, Term B, and Term C, and in D7, Term B should be in Journalists and Term C should be in Non_Journalists, I get all three terms in each term reference field instead of Term A in field_people_organizations, Term B in field_journalists, and Term C in field_non_journalists.

I did a query that joined the D6 db with the D7 db using the migrate_map_peopleorganizations table in the D7 site, and the terms themselves are correctly populated in the D7 tables, so I know that's not the issue. I suppose I could do some wrangling in prepare() to move the terms to the appropriate field in the blog node, but it seems there should be an easier way to map to the new vocabulary. I'm guessing I would create a field on the fly and map to it in prepareRow(), but I'm not sure what I would put in that field, since the second parameter in addFieldMapping() for taxonomy terms is the source vocabulary, and there is no source vocabulary for the new ones.

Thanks.
As a possibility I mentioned above, I did some wrangling in the prepare() method to move the terms from field_people_organizations to field_journalists and field_non_journalists.

  function prepare($entity, stdClass $row) {
    // Turn off pathauto generation for the node so we end
    // up with only one alias record.
    $entity-&gt;path['pathauto'] = 0;

    // Need to manually move any items that should be in the Journalists and Non-Journalists
    // vocabularies there from People and Organizations, since migration mapping doesn't
    // seem to be working.

    // First, see if the nb_migrate_users array is already cached.
    $nb_migrate_journalists = &amp; drupal_static(__FUNCTION__);
    if (!isset($nb_migrate_journalists)) {
      if ($cache = cache_get('nb_migrate_journalists')) {
        $nb_migrate_journalists = $cache-&gt;data;
      }
      // Not cached, so we need to generate it this time through.
      else {
        //Get new tids for terms mapped in migrate_map_jounralists.
        $query = db_select('nb_migrate_journalists', 'nmj');
        $query-&gt;fields('nmj', array('journalists', 'non_journalists'));
        $query-&gt;innerJoin('migrate_map_peopleorganizations', 'mmp', 'nmj.tid = mmp.sourceid1');
        $query-&gt;addField('mmp', 'destid1');
        $result = $query-&gt;execute();

        foreach ($result as $record) {
          // Use the target vid for the vocab; 5 = Journalists, 7 = Non-Journalists.
          if ($record-&gt;journalists == 'x') {
            $nb_migrate_journalists[$record-&gt;destid1] = 5;
          }
          elseif ($record-&gt;non_journalists == 'x') {
            $nb_migrate_journalists[$record-&gt;destid1] = 7;
          }
        }
        // Cache the array.
        cache_set('nb_migrate_journalists', $nb_migrate_journalists, 'cache');
      }
    }
    // Move terms in array based on values in field_people_organizations and $nb_migrate_journalists.
    if (isset($entity-&gt;field_people_organizations[LANGUAGE_NONE][0])) {
      foreach ($entity-&gt;field_people_organizations[LANGUAGE_NONE] as $key =&gt; $term) {
        if (in_array((int)$term['tid'], array_keys($nb_migrate_journalists))) {
          if ($nb_migrate_journalists[$term['tid']] == 5) {
            $entity-&gt;field_journalists[LANGUAGE_NONE][] = array('tid' =&gt; $term['tid']);
          }
          elseif ($nb_migrate_journalists[$term['tid']] == 7) {
            $entity-&gt;field_non_journalists[LANGUAGE_NONE][] = array('tid' =&gt; $term['tid']);
          }
          // Remove term from field_people_organizations.
          unset($entity-&gt;field_people_organizations[LANGUAGE_NONE][$key]);
        }
      }
    }
  }


I still think there is probably a better way to do this within the class constructor, so if at some point in the future you read this and know that answer, please add it here.

Thanks.