0

I'm working on migrating a D6 site to a nice, shiny, new D7 site, and as part of that migration, I need to split one large vocabulary (approx 12k terms) into two new vocabularies. I have the mapping figured out (done manually, with mappings stored in a custom table), so the only thing left to figure out is how to modify the destination vocabulary as needed. Here's what I have tried so far.

function nb_migrate_register_migrations() {
  // Define arguments used for all migrations.
  $common_arguments = array(
    'source_connection' => 'legacy',
    'source_version' => 6,
  );
  $vocabulary_arguments = array(
    array(
      'class_name' => 'NBPeopleOrganizationsTermMigration',
      'description' => t('Migration of People and Organizations terms from Drupal 6'),
      'machine_name' => 'PeopleOrganizations',
      'source_vocabulary' => '4',  // D6 Vocabulary ID
      'destination_vocabulary' => 'non_journalists',
    ),
  );
  $common_vocabulary_arguments = $common_arguments + array(
    'soft_dependencies' => array('NBUser'),
  );
  foreach ($vocabulary_arguments as $arguments) {
    $arguments += $common_vocabulary_arguments;
    Migration::registerMigration($arguments['class_name'], $arguments['machine_name'],
      $arguments);
  }
}
class NBPeopleOrganizationsTermMigration extends DrupalTerm6Migration {
  /**
   * Implementation of Migration::prepareRow().
   *
   * Need to redirect terms into either Journalists or Non-Journalists vocabularies
   * based on whether term is listed in nb_migrate_journalists table.
   *
   * @param $row
   */
  public function prepareRow($row) {
    if (parent::prepareRow($row) === FALSE) {
      return FALSE;
    }
    static $journalists = array();
    if (!$journalists) {
      $sql = "SELECT * FROM nb_migrate_journalists";
      $result = db_query($sql);
      foreach ($result as $record) {
        $journalists[] = $record->tid;
      }
    }
    // Check to see if term is in $journalists.  If not, leave it as
    // non_journalists (as defined in migration registration), otherwise
    // change it to journalists.
    if (in_array($row->tid, $journalists)) {
      $this->destinationVocabulary = 'journalists';
    }
  }
}

So I've just defined one of the two new vocabs as the default when registering the migration, and then I want to modify the destination vocabulary if the source term is in my custom table.

The problem I'm having is finding what to modify to change the destination. As you can see above, I tried changing $this->destinationVocabulary, but that doesn't have an effect. The only other place I can see to change it is in $this->destination->bundle, but that is a protected property of the MigrateDestinationEntity class, and there is no setter function for that property. Looking at the row, I'm seeing that prepareRow isn't the place to do this, since it just has the source data for the term, not where it's going.

All that being said, what do I need to do to modify the destination vocabulary for a term on the fly like this?

Thanks.

0

After poking around some more, I found my answer in this issue and the Migrate module documentation. Based on what I found there, this is what I came up with:

/**
 * Override of DrupalTerm6Migration. Only for People and Organizations vocabulary
 * since we need to split terms out to two new vocabularies.
 */
class NBPeopleOrganizationsTermMigration extends DrupalTerm6Migration {
  public function __construct(array $arguments) {
    parent::__construct($arguments);

    // Set field mapping for destination vocabulary, since we need to
    // set it on a row by row basis.
    $this->addFieldMapping('vocabulary_machine_name', 'vname');
  }


  /**
   * Implementation of Migration::prepareRow().
   *
   * Need to redirect terms into either Journalists or Non-Journalists vocabularies
   * based on whether term is listed in nb_migrate_journalists table.
   *
   * @param $row
   */
  public function prepareRow($row) {
    if (parent::prepareRow($row) === FALSE) {
      return FALSE;
    }
    // Create journalists array from nb_migrate_journalists table.
    static $journalists = array();
    if (!$journalists) {
      $sql = "SELECT * FROM nb_migrate_journalists";
      $result = db_query($sql);
      foreach ($result as $record) {
        $journalists[] = $record->tid;
      }
    }

    // Set value for name (mapped in constructor above) based on presence in $journalists array.
    $row->vname = in_array($row->tid, $journalists) ? 'journalists' : 'non_journalists';
  }
} 

Basically it just creates a mapping between the destination vocabulary machine name and the vname variable, which is then populated in the prepareRow() method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.