array( 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'ID of destination term', ), ); } /** * Return an options array for term destinations. * * @param string $language * Default language for terms created via this destination class. * @param string $text_format * Default text format for terms created via this destination class. */ static public function options($language, $text_format) { return compact('language', 'text_format'); } /** * Basic initialization * * @param array $options * Options applied to terms. */ public function __construct($bundle, array $options = array()) { parent::__construct('taxonomy_term', $bundle, $options); } /** * Returns a list of fields available to be mapped for this vocabulary (bundle) * * @return array * Keys: machine names of the fields (to be passed to addFieldMapping) * Values: Human-friendly descriptions of the fields. */ public function fields() { $fields = array(); // First the core (taxonomy_term_data table) properties $fields['tid'] = t('Term: Existing term ID'); $fields['name'] = t('Term: Name'); $fields['description'] = t('Term: Description'); $fields['format'] = t('Term: Format'); $fields['weight'] = t('Term: Weight'); // TODO: Remove parent_name, implement via arguments $fields['parent_name'] = t('Term: Parent (by name)'); $fields['parent'] = t('Term: Parent (by Drupal term ID)'); // Then add in anything provided by handlers $fields += migrate_handler_invoke_all('Term', 'fields', $this->entityType, $this->bundle); return $fields; } /** * Delete a migrated term * * @param $ids * Array of fields representing the key (in this case, just tid). */ public function rollback(array $key) { $tid = reset($key); migrate_instrument_start('taxonomy_term_delete'); $this->prepareRollback($tid); $result = (bool) taxonomy_del_term($tid); $this->completeRollback($tid); migrate_instrument_stop('taxonomy_term_delete'); return $result == SAVED_DELETED; } /** * Import a single term. * * @param $term * Term object to build. Prefilled with any fields mapped in the Migration. * @param $row * Raw source data object - passed through to prepare/complete handlers. * @return array * Array of key fields (tid only in this case) of the term that was saved if * successful. FALSE on failure. */ public function import(stdClass $term, stdClass $row) { $migration = Migration::currentMigration(); // Updating previously-migrated content? if (isset($row->migrate_map_destid1)) { $term->tid = $row->migrate_map_destid1; if (isset($term->tid)) { if ($term->tid != $row->migrate_map_destid1) { throw new MigrateException(t("Incoming tid !tid and map destination nid !destid1 don't match", array('!tid' => $term->tid, '!destid1' => $row->migrate_map_destid1))); } } else { $term->tid = $row->migrate_map_destid1; } } if ($migration->getSystemOfRecord() == Migration::DESTINATION) { if (!isset($term->tid)) { throw new MigrateException(t('System-of-record is DESTINATION, but no destination tid provided')); } $rawterm = $term; $this->prepare($term, $row); $old_term = taxonomy_term_load($term->tid); foreach ($rawterm as $field => $value) { $old_term->$field = $term->$field; } $parents = taxonomy_get_parents($term->tid); if ($parents) { $parent = array_pop($parents); $old_term->parent = $parent->tid; } else { $old_term->parent = 0; } $term = $old_term; } else { // Default to bundle if no vocabulary machine name provided if (!isset($term->vocabulary_machine_name)) { $term->vocabulary_machine_name = $this->bundle; } // vid is required if (empty($term->vid)) { static $vocab_map = array(); if (!isset($vocab_map[$term->vocabulary_machine_name])) { $vid = db_select('vocabulary', 'v') ->fields('v', array('vid')) ->condition('name', $term->vocabulary_machine_name) ->execute() ->fetchField(); if ($vid) { $vocab_map[$term->vocabulary_machine_name] = $vid; } else { $migration->saveMessage(t('No vocabulary found with machine_name !name', array('!name' => $term->vocabulary_machine_name))); return FALSE; } } $term->vid = $vocab_map[$term->vocabulary_machine_name]; } // Look up parent name if provided if (isset($term->parent_name)) { // Look for the name in the same vocabulary. // Note that hierarchies may have multiples of the same name... $terms = taxonomy_get_term_by_name(trim($term->parent_name)); foreach ($terms as $candidate) { if ($candidate->vid == $term->vid) { $term->parent = $candidate->tid; break; } } unset($term->parent_name); } if (is_array($term->parent['arguments'])) { // Unset arguments here to avoid duplicate entries in the // term_hierarchy table. unset($term->parent['arguments']); } if (empty($term->parent)) { $term->parent = 0; } if (!isset($term->format)) { $term->format = $this->textFormat; } $this->prepare($term, $row); } // Trying to update an existing term if ($migration->getSystemOfRecord() == Migration::DESTINATION) { $existing_term = taxonomy_term_load($term->tid); if ($existing_term) { // Incoming data overrides existing data, so only copy non-existent fields foreach ($existing_term as $field => $value) { if (!isset($term->$field)) { $term->$field = $existing_term->$field; } } } } migrate_instrument_start('taxonomy_term_save'); $term = (array)$term; $status = taxonomy_save_term($term); $term = (object)$term; migrate_instrument_stop('taxonomy_term_save'); $this->complete($term, $row); $return = isset($term->tid) ? array($term->tid) : FALSE; return $return; } } /** * Handler to process term assignments for nodes */ class MigrateTermNodeHandler extends MigrateDestinationHandler { public function __construct() { $this->registerTypes(array('node')); } public function prepare(stdClass $node, stdClass $row) { // Identify vocabularies for this node type $vocabs = taxonomy_get_vocabularies($node->type); foreach ($vocabs as $vid => $vocab) { $vocab_name = $vocab->name; if (isset($node->$vocab_name)) { $vocab_values = $node->$vocab_name; if (!is_array($vocab_values)) { $vocab_values = array($vocab_values); } $by_tid = FALSE; if (isset($vocab_values['arguments']['source_type'])) { if ($vocab_values['arguments']['source_type'] == 'tid') { $by_tid = TRUE; } } unset($vocab_values['arguments']); foreach ($vocab_values as $term_value) { if ($by_tid) { $node->taxonomy[$term_value] = $term_value; } else { foreach (taxonomy_get_term_by_name($term_value) as $term) { if ($term->vid == $vid) { $node->taxonomy[$term->tid] = $term->tid; } } } } } } } /* * @param * Can be 'tid'. Otherwise, 'name' is assumed. */ static function arguments($source_type = NULL) { return get_defined_vars(); } public function fields($entity_type, $bundle) { $fields = array(); $vocabs = taxonomy_get_vocabularies($bundle); foreach ($vocabs as $vid => $vocab) { $vocab_name = $vocab->name; $fields[$vocab_name] = $vocab_name; } return $fields; } }