Download & Extend

Implementation of Location support for Migrate Extras V2

Project:Location
Version:7.x-3.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:closed (fixed)

Issue Summary

I need to draw from several source fields in order to build a Location. In general, though, I have no idea how I'd go about drawing from several source fields (and mapping it to one destination field).

I could just call a helper method in my Migration's prepare method, I guess, but I'd prefer to be able to code up a nice addition to migrate_extras that will work more generally.

Any pointers would be appreciated!

Comments

#1

Sorry for the late response, I've been paying more attention to the Migrate issue queue than Migrate Extras... I haven't used Location before, but the general idea would be to map the primary field, and specify the source fields for the other components using arguments. From migrate_example:

<?php
    $arguments
= MigrateTextFieldHandler::arguments(array('source_field' => 'excerpt'));
   
$this->addFieldMapping('body', 'body')
         ->
arguments($arguments);
   
// Since the excerpt is mapped via an argument, add a null mapping so it's
    // not flagged as unmapped
   
$this->addFieldMapping(NULL, 'excerpt');
?>

So, if for the location module your primary component is 'gps', and you also have 'title' and 'description' components, you might map the field like:

<?php
  $arguments
= MigrateLocationHandler::arguments(array('title_source' => 'title', 'description_source' => 'descr'));
 
$this->addFieldMapping('field_my_location', 'gps')
         ->
arguments($arguments);
 
$this->addFieldMapping(NULL, 'title');
 
$this->addFieldMapping(NULL, 'descr');
?>

Of course, your primary concern is implementing the field handler that understands those arguments... My best advice (not having much time at the moment) is to look at the MigrateTextFieldHandler implementation in the migrate module's fields.inc and see how it handles the summary argument (the first parameter to MigrateTextFieldHandler::arguments).

Hope this helps.

#2

Title:How should I go about adding Location support?» Implementation Location support for Migrate Extras V2
Category:support request» feature request

Let's make this the central Location request issue, superceding the following:

#459236: Location Integration
#735714: location cck (work around or bounty)
#753048: location_user integration
#788724: Migrate Location Fields from Legacy CMS to Node Location
#942208: Location integration does not take into account location fields added through API
#1118132: Working example of how to map source fields to a Location destination field?

#3

Title:Implementation Location support for Migrate Extras V2» Implementation of Location support for Migrate Extras V2

#4

Status:active» needs review

I made it here and it's working.

#5

Status:needs review» active

The location_cck_migrate module in that sandbox is based on the content_migrate module, not the migrate module.

#6

I put my first try with Migrate and FieldHandlers in LocationMigrate module (sandbox).
Only JSON data is handled, as exampled in module homepage.. patches are (super) welcome! :)

Note: do not use for production-level migrations!

#7

Status:active» needs review

Here is a patch for location field handler, based on geofield.inc and #6, this is for Location 7.x-3.x.

AttachmentSizeStatusTest resultOperations
migrate_extras-location_field_handler-943178-7.patch2.8 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch migrate_extras-location_field_handler-943178-7.patch. Unable to apply patch. See the log in the details link for more information.View details

#8

Project:Migrate Extras» Location
Version:6.x-2.x-dev» 7.x-3.x-dev
Component:Location» Code
Status:needs review» needs work

This would best go into the Location module itself. This patch would need the following changes:

1. Add location_migrate_api().
2. Rename location.inc to location.migrate.inc, so hook_migrate_api() can be found automatically.
3. Add location.migrate.inc to location.info.

To take advantage of Migrate 2.4's subfield approach, it'd be nice to implement fields() to document the components ('street', 'city', etc.). Then in your migration class instead of using the arguments array you'll be able to do

<?php
$this
->addFieldMapping('field_location_dest:latitude', 'source_field_latitude');
$this->addFieldMapping('field_location_dest:longitude', 'source_field_longitude');
?>

#9

Status:needs work» needs review

Here's a patch for the location field handler. I based it on #7, using #8's suggestions. It's for location 7.x-3.x.

AttachmentSizeStatusTest resultOperations
location-migrate_field_handler-943178-9.patch8.41 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch location-migrate_field_handler-943178-9.patch. Unable to apply patch. See the log in the details link for more information.View details

#10

Status:needs review» needs work

Due to the class magic in Migrate (yuk), the test "location_cck.php" needs to be renamed to "location_cck.test" to prevent a fatal class not found error.

I was just trying on a user field (unsuccessfully), before remembering that this is currently broken. However, the MigrateLocationFieldHandler::prepare() was correctly getting all fields and returning a lid.

Mapping used was:

<?php
    $this
->addFieldMapping('field_user_postal_address:street', 'profile_address_1');
   
$this->addFieldMapping('field_user_postal_address:additional', 'profile_address_2');
   
$this->addFieldMapping('field_user_postal_address:city', 'profile_suburb');
   
$this->addFieldMapping('field_user_postal_address:province', 'profile_state');
   
$this->addFieldMapping('field_user_postal_address:postal_code', 'profile_postcode');
   
$this->addFieldMapping('field_user_postal_address:country')->defaultValue('AU');
?>

And the source fields were populated via profile quries in Migration::prepareRow($current_row);

<?php
    $current_row
->profile_address_1 = empty($profile['profile_address_1']) ? NULL : $profile['profile_address_1'];
   
$current_row->profile_address_2 = empty($profile['profile_address_2']) ? NULL : $profile['profile_address_2'];
   
$current_row->profile_suburb = empty($profile['profile_suburb']) ? NULL : $profile['profile_suburb'];
   
$current_row->profile_state = empty($profile['profile_state']) ? NULL : $profile['profile_state'];
   
$current_row->profile_postcode = empty($profile['profile_postcode']) ? NULL : $profile['profile_postcode'];
?>

#11

Status:needs work» needs review

Also, this is not used

<?php
$field_name
= $instance['field_name'];
?>

The import structure was causing my import to fail, it expects something like:

<?php
    $current_row
->profile_address_1[0] = empty($profile['profile_address_1']) ? NULL : mkStdClass($profile['profile_address_1']);
....
function
mkStdClass($value) {
  return (object) array(
'value' => $value);
}
?>

If this is the norm, then all good. I will update my code. However, this doesn't feel right as that suggests the norm is to be importing individual objects that define a singular component value.

So leaving my mapping the same and changing the prepareRow() to this:

<?php
    $current_row
->profile_address_1[0] = empty($profile['profile_address_1']) ? NULL : $profile['profile_address_1'];
?>

And updating the patch with:

  • Treat is_primary as any standard component
  • Accepting either object or scalar properties, but same decoupled structure
  • Minor code clean up
  • Rename the test (no update to flush registry - only developers would be doing this, so I didn't see the need)
AttachmentSizeStatusTest resultOperations
location-943178-11-migrate-support.patch18.03 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch location-943178-11-migrate-support.patch. Unable to apply patch. See the log in the details link for more information.View details

#12

Rewrite based on #9 #11, - prepareRow() mentioned in #11 is not required

  • to handle multiple values
  • simplified code, looping of fields is not needed as location_normalize_settings() will be called by location_save()
AttachmentSizeStatusTest resultOperations
location-migrate-943178-12.patch4.67 KBIdlePASSED: [[SimpleTest]]: [MySQL] 425 pass(es).View details

#13

note the test file renamed from #11 is in #1844462: Class 'DrupalWebTestCase' not found

#14

Fixed Call to undefined method MigrateFieldHandler::fields() in location.migrate.inc

AttachmentSizeStatusTest resultOperations
location-migrate-943178-14.patch4.61 KBIdlePASSED: [[SimpleTest]]: [MySQL] 425 pass(es).View details

#15

I have just run this on a much larger data set and the geoencoding was painfully slow. As such, maybe inhibit_geocode needs to be an option?

#16

Can someone give a full example of how to migrate location data? I currently have

    $this->addFieldMapping('field_location_dest')->defaultValue('TRUE');
    $this->addFieldMapping('field_location_dest:street', 'address_mailing');
    $this->addFieldMapping('field_location_dest:city', 'city_mailing');
    $this->addFieldMapping('field_location_dest:province', 'abbreviation');
    $this->addFieldMapping('field_location_dest:latitude', 'latitude');
    $this->addFieldMapping('field_location_dest:longitude', 'longitude');
    $this->addFieldMapping('field_location_dest:postal_code', 'zip_mailing');
    $this->addFieldMapping('field_location_dest:country')->defaultValue('US');

Inside my "MemberNodeMigration" class, which extends "MasterMemberMigration", which in turn extends "DynamicMigration".

I've tried changing "field_location_dest", to "location" (which is the table in drupal), but I've been unable to get any locations to actually import. I'm new to the migrate module, but I've gotten everything except the locations to import. This is my first time working with extra handlers. I've applied the patch offered in #12 (location-migrate-943178-12.patch)

Any help would be greatly appreciated.

#17

Status:needs review» active

#1931088: [META] Fixing tests tests were broken, so triggering to active

#18

Status:active» needs review

bot

#19

Status:needs review» fixed

#14 commited pushed to 7.x-3.x
thanks!!!!

commit dfdcd1b96794d8406cee24ce60d31c722bf08648
Author: ckng <ckng@16307.no-reply.drupal.org>
Date:   Tue Mar 12 20:13:33 2013 +0200

    Issue #943178 by ckng, fluffy, kziv, Alan D. | adamdicarlo: Added Implementation of Location support for Migrate Extras V2.

#20

Status:fixed» closed (fixed)

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

#21

Where is this? I don't find a location_migrate module, nor anything associated with "migrate" in the location module. And on the project page for migrate_extras, for location it says "requested".

So how to migrate location information from D6 to D7. I'm currently using views to create XML files for import by feed_import. Any help appreciated.

#22

If you get the dev version (should also be in the latest release based on the dates) there is location.migrate.inc in the root directory of the location module.

There is also a brief example of how to implement the migration of locations in the comment block at the top of that file.

Once you have updated to a version of location that has migrate support, make sure you clear the cache and it should work.

#23

Also, if you are migrating from drupal 6 to 7 you should use the migrate_d2d module. it will make things a bit easier for you.

#24

D5 > D7 - I can migrate to a location destination mapping, however the D5 location cck field is not appearing as a source. Using d2d migrate. Should I open a seperate ticket at this point?

nobody click here