Hi there --
I've been migrating a big, homegrown system over to D7. (I asked about another aspect of this earlier this week, #1536722: "Could not save to map table" for every item.) I'm almost there, but I just need to get files attached to the new nodes I've created. My file migration works fine; my node migration works fine, except that it's not getting its file fields filled. The files definitely exist in the files_managed table, and the migrate_map table exists for the file migration, so I'd expect that the node migration would be able to use those facts to grab the right fids and populate nodes' fields with them... no go. I must be doing something wrong in the code...? Perhaps it's something to do with the fact that I don't have a distinct id for files in the old system, so I was focred to use their filenames as sourceid1?

Anyway, thank you (again!) for any help you can give.

Ben

class ChFileMigration extends Migration {
  public function __construct() {
    parent::__construct(MigrateGroup::getInstance('clearinghouse'));
    
    $this->map = new MigrateSQLMap($this->machineName,
      array(
        'art_binary' => array('type' => 'varchar',
                          'length' => 255,
                          'description' => 'Source record ID',
                        )
      ),
      MigrateDestinationFile::getKeySchema()
    );

    $query = Database::getConnection('default', 'phi_migrate')
      ->select('article', 'a')
      ->distinct()
      ->fields('a', array('art_binary'))
      ->condition('art_binary', '', '!=')
      ->condition('art_binary', ' ', '!=');
    
    $query->addField('a', 'art_binary', 'source_uri');

    // Source
    $this->source = new MigrateSourceSQL($query, array(), NULL, array('map_joinable' => FALSE));
    
    // Destination
    $this->destination = new MigrateDestinationFile(array('preserve_files' => TRUE));
    
    // Mappings
    $this->addFieldMapping('uri', 'source_uri');

  }
  
  public function prepareRow($row) {
    $row->source_uri = file_default_scheme() . '://' . 'clearinghouse/' . $row->art_binary;
    
    return TRUE;
  }
}

class ClearinghouseMigration extends Migration {
  public function __construct() {
    parent::__construct(MigrateGroup::getInstance('clearinghouse'));
    
    // Make sure the 2 term migrations happen first.
    $this->dependencies = array('ChCat', 'ChTag', 'ChFile');
    
    $this->map = new MigrateSQLMap($this->machineName,
      array(
        'res_id' => array('type' => 'int',
                          'length' => 10,
                          'unsigned' => TRUE,
                          'not null' => TRUE,
                          'description' => 'Source record ID',
                        )
      ),
      MigrateDestinationNode::getKeySchema()
    );

    $query = Database::getConnection('default', 'phi_migrate')
      ->select('article', 'a')
      ->fields('a', array('res_id', 'art_author_fname', 'art_pubmonth', 'art_pubyear', 'art_date', 'art_volume', 'art_publisher', 'art_pub', 'art_http', 'art_binary', 'art_fulltext', 'art_order_details', 'art_entrydate', 'art_hardcopy', 'art_softcopy'));
    // Resource table.
    $query->join('resource', 'r', 'a.res_id=r.res_id');
    $query->fields('r', array('res_name', 'res_abstract'));
    
    $source_fields = array('tags', 'categories', 'res_id');
    
    // Source
    $this->source = new MigrateSourceSQL($query, $source_fields, NULL, array('map_joinable' => FALSE));
    
    // Destination
    $this->destination = new MigrateDestinationNode('articles_commentaries');
    
    // Mappings
    $this->addFieldMapping('title', 'res_name');
    $this->addFieldMapping('body', 'res_abstract');
    $this->addFieldMapping('field_author', 'art_author_fname');
    $this->addFieldMapping('field_volume', 'art_volume');
    $this->addFieldMapping('field_publisher', 'art_publisher');
    $this->addFieldMapping('field_pub', 'art_pub');
    $this->addFieldMapping('field_url', 'art_http');
    $this->addFieldMapping('field_full_text_of_article', 'art_fulltext');
    $this->addFieldMapping('field_ordering_info', 'art_order_details');
    $this->addFieldMapping('field_old_ch_tags', 'tags');
    $this->addFieldMapping('field_old_ch_cats', 'categories');
    $this->addFieldMapping('field_file', 'art_binary')
      ->sourceMigration('ChFile');
    
  } // end of constructor.

  public function prepareRow($row) {
    // Tags
    $tag_query = Database::getConnection('default', 'phi_migrate')
      ->select('resource_tag', 'rt')
      ->condition('res_id', $row->res_id);
    $tag_query->join('tag', 't', 'rt.tag_id=t.tag_id');
    $tag_result = $tag_query->fields('t', array('tag_name'))
      ->condition('t.res_type_id', 0)
      ->execute();
    
    foreach($tag_result as $line) {
      $row->tags[] = $line->tag_name;
    }
  
    // Categories
    $category_query = Database::getConnection('default', 'phi_migrate')
      ->select('category', 'c')
      ->fields('c', array('cat_name'));
      
    $category_query->join('resource_category', 'rc', 'c.cat_id=rc.cat_id');
    $category_query->condition('rc.res_id', $row->res_id);
    $category_result = $category_query->execute();
  
    foreach($category_result as $line) {
      $row->categories[] = $line->cat_name;
    }
    
    return TRUE;
    
  }
}

Comments

mikeryan’s picture

Status: Active » Postponed (maintainer needs more info)

Try

$this->addFieldMapping('field_file', 'art_binary')
      ->arguments(array('file_function' => 'file_fid'))
      ->sourceMigration('ChFile');

You need to tell the migration to interpret the incoming value as a fid rather than a URI.

bdimaggio’s picture

Aha! Did not understand that relationships between new entities and existing ones are created by the existing ones' values, rather than IDs. The migration went off without a hitch! Thanks again.

mikeryan’s picture

Status: Postponed (maintainer needs more info) » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

cameron prince’s picture

The example code in the solution should now be as follows for 7.x-2.4:

$this->addFieldMapping('field_file', 'art_binary')
      ->arguments(array('file_class' => 'MigrateFileFid'))
      ->sourceMigration('ChFile');
peteruithoven’s picture

And with 2.4 (and the new argument system) it would be the following, right?

$this->addFieldMapping('field_file', 'art_binary')
$this->addFieldMapping('field_file:file_class')
     ->defaultValue('MigrateFileFid')
     ->sourceMigration('ChFile');
bdone’s picture

@peteruithoven: yes. you're using the right syntax, but your sourceMigration should chain onto the field, vs. the file_class.

$this->addFieldMapping('field_file', 'art_binary')->sourceMigration('ChFile');
$this->addFieldMapping('field_file:file_class')->defaultValue('MigrateFileFid');