I used the following code to migrate node location info from nodes in D6 to D7. This is how I set my extension to the DrupalNode6Migration class -

abstract class ExampleNodeMigration extends DrupalNode6Migration {
  public function __construct(array $arguments) {
    parent::__construct($arguments);

    $this->addFieldMapping('legacy_nid', 'nid')
         ->description('We have a common field to save the D6 nid');
  }
  
  public function complete(stdClass $account, stdClass $row) {

/**
 * 
 * Fetch location from old node
 * 
 * 
 **/

    $fetched_lid = Database::getConnection('default', $this->sourceConnection)
                 ->select('location_instance', 'i')
                 ->fields('i', array('lid'))
                 ->condition('vid', $row->vid)
                 ->execute()
                 ->fetchObject();
    if ($fetched_lid) {
        $loc = Database::getConnection('default', $this->sourceConnection)
                 ->select('location', 'i')
                 ->fields('i', array('name', 'street', 'additional', 'city', 'province', 'country'))
                 ->condition('lid', $fetched_lid->lid)
                 ->execute()
                 ->fetchObject();  
        if($loc){    

    		$location = array(
    			'name' 		=> $loc->name,
    			'street'	=> $loc->street,
    			'additional' => $loc->additional,
    			'city'		=> $loc->city,
    			'province'	=> $loc->province,
    			'country'	=> $loc->country,
    		);
		$lid = location_save($location);
    		if($lid !== FALSE){
    			$instance = array(
          			'nid' => $account->nid,
          			'vid' => $account->vid,
          			'uid' => $account->uid,
          			'genid' => '',
          			'lid' => $lid,
        		);
        		db_insert('location_instance')
          			->fields($instance)
          			->execute();
    		}
        }
        
    }

  } // /public function
}

I'm relatively new to Drupal module development - how can I commit this to the module so others who want to do something similar don't have to re-invent the wheel?

Comments

tangent’s picture

Category: feature » support

This solution seems very inefficient. I was able to migrate legacy location content (not CCK location) by extending the query method of my class.

  protected function query() {
    $query = parent::query();

    // Join location table, which is not CCK
    $query->join('location_instance', 'i', 'i.nid = n.nid AND i.vid = n.vid');
    $query->join('location', 'l', 'l.lid = i.lid');
    $query->fields('l', array('street', 'additional', 'city', 'province', 'postal_code', 'country', 'latitude', 'longitude'));

    return $query;
  }

You then simply map the fields above to your destination fields (addressfield, or whatever).

    // Map location field
    $arguments = array(
      'administrative_area' => array('source_field' => 'province'),
      'locality' => array('source_field' => 'city'),
      'thoroughfare' => array('source_field' => 'street'),
      'premise' => array('source_field' => 'additional'),
      'postal_code' => array('source_field' => 'postal_code'),
    );
    $this->addFieldMapping('field_address', 'country')
         ->arguments($arguments);
    // Prevent location field elements from showing as unmapped
    $this->addFieldMapping(NULL, 'province');
    $this->addFieldMapping(NULL, 'city');
    $this->addFieldMapping(NULL, 'street');
    $this->addFieldMapping(NULL, 'additional');
    $this->addFieldMapping(NULL, 'postal_code');
    $this->addFieldMapping(NULL, 'latitude');
    $this->addFieldMapping(NULL, 'longitude');

Changing the status of this issue to support so that others can find help here. This requirement is custom so would likely not be committed to the module.

mikeryan’s picture

Component: Code » Documentation
Category: support » task

I prefer the approach @tangent suggests. I'm not sure of what threshold we want to set for what contrib modules should be supported directly in migrate_d2d - cck obviously, and I felt that content_profile was worthwhile, but I'm not so sure about location. I think the best thing would be to document how to migrate location module data in a child page under http://drupal.org/node/1931396.

mikeryan’s picture

I should note that tangent's example is using the obsolete arguments() method, in the modern Migrate world we use subfields:

$this->addFieldMapping('field_address', 'country');
$this->addFieldMapping('field_address:administrative_area', 'province');
...
tangent’s picture

Does the "modern Migrate world" include migrate_d2d 7.x-2.x because those destination subfields do not seem to exist. That's why I used the arguments() method.

tangent’s picture

I've added my solution as a page under the Cookbook page, per @mikeryan's suggestion.

https://drupal.org/node/2018113

mikeryan’s picture

Status: Active » Postponed (maintainer needs more info)

@tangent: If you're still on Migrate 2.5, to expose the address field subfields you need migrate_extras which adds that support. With Migrate 2.6-beta1 (or 2.x-dev) you don't need migrate_extras, the subfields are automatically handled. arguments() is obsolete and deprecated, and will be removed from the documentation.

tangent’s picture

I actually do have migrate_extras enabled as well but subfields for "addressfield" fields are not added as destinations. In any case, I documented the module versions that the solution addresses.

mikeryan’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)
flamingvan’s picture

When I used Tangent's solution with migrate_d2d I couldn't import nodes without a location. I switched the joins to left joins and that did the trick. I don't know if it's going to cause other problems.

    // Join location table, which is not CCK
    $query->leftJoin('location_instance', 'i', 'i.nid = n.nid AND i.vid = n.vid');
    $query->leftJoin('location', 'l', 'l.lid = i.lid');
    $query->fields('l', array('name', 'street', 'additional', 'city', 'province', 'postal_code', 'country', 'latitude', 'longitude', 'source', 'is_primary'));