I wonder if anyone is interested in working on a field handler for the Migrate module? I've got a working version - see below. Does anyone have any thoughts or comments?

<?php

/**
 * @file
 * Support for migration into Geofield fields
 *
 * Based on og.inc in Migrate.module/plugins and on the
 * openlayers_cck_migrate.module
 * 
 */

class MigrateGeofieldFieldHandler extends MigrateFieldHandler {

  public function __construct() {
    $this->registerTypes(array('geofield'));
  }

  public function prepare($entity, array $field_info, array $instance, array $values) {
    $migration = Migration::currentMigration();
    if (isset($values['arguments'])) {
      $arguments = $values['arguments'];
      unset($values['arguments']);
    }
    else {
      $arguments = array();
    }
    
    $language = $this->getFieldLanguage($entity, $field_info, $arguments);
    
    $delta = 0;
    $return = array();
    foreach ($values as $value) {
      // Don't save empty references
      if ($value) {
        $return[$language][$delta]['wkt'] = $value['wkt'];
        $return[$language][$delta]['geo_type'] = $value['geo_type'];
        $return[$language][$delta]['lat'] = $value['lat'];
        $return[$language][$delta]['lon'] = $value['lon'];
        $return[$language][$delta]['left'] = $value['left']; 
        $return[$language][$delta]['right'] = $value['right']; 
        $return[$language][$delta]['bottom'] = $value['bottom']; 
        $return[$language][$delta]['top'] = $value['top']; 
        $delta++;
      }
    }
    return $return;
  }
}

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Brandonian’s picture

Definitely interested in the addition. You've caught us at an odd time, b/c we're about ready to push out a release candidate and subsequent full release, so we're in a period of limited new dev, but this sounds like something useful for us.

I'm a little unclear from the code (and limited experience with the Migrate module), in order to migrate data, would one need all of our fields present to port data over? Does the data have to be in WKT format to be ported? We have some pretty useful tools for doing some data conversion that we could take advantage of to make something a little more flexible.

tomwrobel’s picture

Great to hear that you're interested! I haven't contributed code back to a project before, so you'll have to bear with me a little...

1) It doesn't matter if this lies on ice for a while. I have it working for my use case (lat/lon pairs) but haven't properly tested it with any other set of data. I can't really take time to set up a testing platform for other data types yet, but if you're going to be pushing out a full release, it can wait until after that!

2) So far as I can see, it doesn't need to be in WKT format (as I said, everything I have has lat/lon pairs only), but it doesn't do any validation or checking either. Crucially, it doesn't check the submitted data against the data the field instance expects - I'd have to extend it to do that, although it's perfectly feasible. Could you point me at a set of sample data that I can test against?

blue skies

Tom

Brandonian’s picture

Always looking for new contributers. Thanks for showing interest, @tomwrobel.

Ideally, we'd probably want to have some sort of import that does some basic validation so that anything that makes its way into the new database is relevant to Geofield. I can imagine scenarios where we're going to need to consider multiple types of input. We'll likely need to deal with similar issues in #1401630: Refactor WKT input to allow for various types of raw input.

kehan’s picture

Similar functionality has been added to Migrate Extras #1316706: Geofield support but obviously within the geofield module is the best place to add this functionality.

rerooting’s picture

Any plans to roll this into 2.x? I'm having trouble with the migrate_extras destination handler.

rerooting’s picture

My bad! Migrate extras's geofield handler only supports 1.x, I was using 2.x. This issue has a good lead on the problem #1997316: geofield 7.x-2.0-dev migration. See - this is a great reason why geofield's migrate destination handler should be brought into the project, so that 1.x and 2.x can have separate handlers!

gmclelland’s picture

eft’s picture

Here is a patch that works for 7.x-2.x-dev. Field Mapping can be as easy as this:

    $this->addFieldMapping('field_foo_geo', 'wkt');

Or, if you want to add data as lat/longs:

    $this->addFieldMapping('field_foo_geo');
    $this->addFieldMapping('field_foo_geo:input_format', 'input_format');
    $this->addFieldMapping('field_foo_geo:lat', 'lat');
    $this->addFieldMapping('field_foo_geo:lon', 'lon');
eft’s picture

Status: Active » Needs review
FileSize
5.4 KB

Here is a slightly cleaner patch that applies more cleanly.

nedjo’s picture

Nice! I did some basic testing only with the default WKT handling--working fine.

Miguelos’s picture

Great patch!

Did someone tested it for 'lat/lon' input format?

I tried it and had to do a small change:

-            $return[$language][$delta]['lat'] = $arguments['lat'];
-            $return[$language][$delta]['lon'] = $arguments['lon'];
+            $return[$language][$delta]['geom']['lat'] = $arguments['lat'];
+            $return[$language][$delta]['geom']['lon'] = $arguments['lon'];

With this change it works fine.

I'm using subfield notation as proposed by eft (#1411836-8: Field handler for Migrate module).

fonant’s picture

Patched geofield with #9 and disabled the migrate_extras MigrateGeoFieldHandler and I can migrate an old Drupal 6 WKT field with just one line as in #8. Thanks! :)

freelock’s picture

Hi,

I was doing a D7 -> D7 migration, a major overhaul of a data architecture, and migrating Geofield data kept failing. With Miguelos's changes in #11 and the patch in here, got most of the way, but got an error on trim() in Geofield.inc, expected string but got array. This was because the D2D field handler loaded the data in the passed $arguments with each in an array. So the fix in my case was:

-            $return[$language][$delta]['geom']['lat'] = $arguments['lat'];
-            $return[$language][$delta]['geom']['lon'] = $arguments['lon'];
+            $return[$language][$delta]['geom']['lat'] = $arguments['lat'][0];
+            $return[$language][$delta]['geom']['lon'] = $arguments['lon'][0];

Looking at that, 0 might need to be $delta. In any case, to support D7 sources, this needs more work...

thtas’s picture

This works but i get a bunch of errors like this:

Undefined index: input_format File sites/default/modules/contrib/geofield/geofield.migrate.inc, line 92(file: sites/default/modules/contrib/geofield/geofield.migrate.inc, line 92)
iamcarrico’s picture

The patch in #9, plus the change in #11 allowed it to work. One small note though, I had to do this:

<?php
    $this->addFieldMapping('field_foo_geo')
      ->defaultValue('');
    $this->addFieldMapping('field_foo_geo:input_format', 'input_format');
    $this->addFieldMapping('field_foo_geo:lat', 'lat');
    $this->addFieldMapping('field_foo_geo:lon', 'lon');
?>

So that the a value would still be there.

rsbecker’s picture

At some point in the past I was able to migrate D6 openlayers data in to geofield. But today I tried, using a patched version of 7.x-2.x-dev and am getting the following errors on every record that has a openlayers wkt data:

MigrateException: htmlspecialchars() [<a href='function.htmlspecialchars'>function.htmlspecialchars</a>]: Invalid multibyte sequence in argument File /var/www/html/drupaldev2/includes/bootstrap.inc, line 1573 in MigrationBase->errorHandler() (line 701 of /var/www/html/drupaldev2/profiles/openoutreach/modules/contrib/migrate/includes/base.inc).
2858	Error	htmlspecialchars() [function.htmlspecialchars]: Invalid multibyte sequence in argument File /var/www/html/drupaldev2/includes/bootstrap.inc, line 1573

my migration class has:

$addFieldMapping('field_geolocation', 'field_ol_openlayers_wkt');

Any suggestions about why this is happening?
It definitely is related to the geofield, because if I comment out that line the records migrate with no errors, and records that have no data in the field migrate fine.

BillyTom’s picture

This is the patch from #9, plus the change in #11 all in one.

szeidler’s picture

Thanks BillyTom. Patch #17 is working fine with geofield 7.x-2.3 and Migrate 7.x-2.6
Used the following mapping.

$this->addFieldMapping('field_geofield')->defaultValue('Point');
$this->addFieldMapping('field_geofield:input_format')->defaultValue('lat/lon');
$this->addFieldMapping('field_geofield:geo_type')->defaultValue('point');
$this->addFieldMapping('field_geofield:lat', 'srcfield_latitude');
$this->addFieldMapping('field_geofield:lon', 'srcfield_longitude');
timodwhit’s picture

Using Lat/long, I am getting the same issues as #14.

Adding a check for if empty, solved the issues:

$return[$language][$delta]['geom']['lat'] = (!empty($arguments['lat'])) ? $arguments['lat'] : '';
$return[$language][$delta]['geom']['lon'] = (!empty($arguments['lon'])) ? $arguments['lon'] : '';
zxaos’s picture

@timodwhit That still throws an error if input_format is unset, although it works if you set a default value of 'lat/lon' for everything. All of the arrays should probably be wrapped that way, and the input_format switch to boot.

timodwhit’s picture

Ah, good to know, I definitely had the default value set in the migration so didn't run into that issue. Thanks for the heads up

milos.kroulik’s picture

Patch from #17 works fine with WKT source. My mapping looks like:

$this->addFieldMapping('field_point', 'wkt');
$this->addFieldMapping('field_point:input_format')->defaultValue('wkt');
$this->addFieldMapping('field_point:geo_type')->defaultValue('point');
$this->addFieldMapping('field_point:wkt', 'wkt');
$this->addFieldMapping('field_point:lon', NULL);
$this->addFieldMapping('field_point:lat', NULL);
$this->addFieldMapping('field_point:json', NULL);
$this->addFieldMapping('field_point:left', NULL);
$this->addFieldMapping('field_point:top', NULL);
$this->addFieldMapping('field_point:right', NULL);
$this->addFieldMapping('field_point:bottom', NULL);
Summit’s picture

Hi,
Anyone have a working version with Migrate d2d latest dev?
Please add it here. Would love to be able to use Geofield with Migrate_d2d. Thanks!
Greetings, Martijn

Summit’s picture

FileSize
5.05 KB

Hi,
I tried working out for myself...but got PHP Fatal error: Call to undefined method MigrateGeofieldFieldHandler::addFieldMapping() in modules/geofield/geofield.migrate.inc on line 43

Could somebody say what I am doing wrong, it would be great to have a working example with for example the code from https://www.drupal.org/node/1411836#comment-9518633

See attached my file.
greetings, Martijn

szeidler’s picture

I have no experience with the MigrateFieldHandler class. MigrateFieldHandler and it's parent classes don't have any addFieldMapping method. I normally extend the Migration Class.

For example:

class GeofieldNodeMigration extends Migration {
}
Summit’s picture

Hi,
I have the handler working, but empty geofields in my nodes..
See attached my geofield.migrate.inc and my weblinks.migrate.inc (Thanks to Gerhard Stegemann); where the mapping takes place within weblinks nodes with geofield in D7 and location field in D6, and screenshot of mapping with migrate_d2d for Geofield.
What is wrong please?

greetings, Martijn

Summit’s picture

Hi,
Tried setting "point" and "lat/lon" on migrate_d2d screen (see attachment)...but still no values...
what do I forget please?
Greetings, Martijn

Summit’s picture

Hi,
I thought may be geo_type add on was necessary with also default value of 'lat/lon' ...but still no go...
greetings, Martijn

Summit’s picture

Hi,
Yes working! With the adding of Comment #13, thanks for reporting!!
And in the migrate_d2d no '' around the values like Point, lat/lon
See attached my improved geofield.migrate.inc and the migrate_d2d mapping!

Greetings, Martijn

tauno’s picture

A patch to add migrate field handler support. Not tested with d2d, but assuming lat and lon are arrays seems like a bad assumption.

tauno’s picture

FileSize
5.47 KB

Actually adding the geofield.migrate.inc file to the patch would be helpful.

fonant’s picture

Patch in #31 works nicely here.

UPDATE: actually, there's a typo which means multiple-value fields end up with just a single value, the last on imported.

The line with just "$delta;" should read "$delta++;".

fonant’s picture

New patch, fixed so multiple-value fields work.

eneko1907’s picture

Seems like recent versions of geofield 7.x-2.x do not include subfield 'wkt', instead, 'geom' and 'geohash'. This will make these patches not functional for the recent versions (2.3 at least).

ckng’s picture

Patch #33 tested working for lat/lon mapping

    $this->addFieldMapping('field_geofield')->defaultValue('Point');
    $this->addFieldMapping('field_geofield')->defaultValue('lat/lon');
    $this->addFieldMapping('field_geofield')->defaultValue('point');
    $this->addFieldMapping('field_geofield', 'lat');
    $this->addFieldMapping('field_geofield', 'lon');

But getting notice from patch

Stripping trailing CRs from patch; use --binary to disable.)
patching file geofield.info
(Stripping trailing CRs from patch; use --binary to disable.)
patching file geofield.migrate.inc
FMB’s picture

Fixed problems with newlines, and made code compliant with coding standards.

FMB’s picture

I believe we really should work on this, as the (unsupported) implementation in Migrate Extras uses the arguments() method, and does not seem to work any longer with the latest version of Migrate.

ZeiP’s picture

Status: Needs review » Reviewed & tested by the community

The lat/lon migration works nicely with the patch in #36 as confirmed by my tests and a few previous commenters.

As a reply to #34, if I read the code correctly it seems that wkt is actually migrated to the geom field, so it might work?

I suggest committing this version to have a working Migrate support, marking RTBC.

zaporylie’s picture

Just want to confirm Geofield 2.x-dev with applied #36 works very well. Would be nice to see it committed and released in new stable version.

hargobind’s picture

Also confirming that #36 works perfectly. My migration was a success. RTBC++

  • itamair committed 9d2d229 on 7.x-2.x authored by FMB
    Issue #1411836 by tauno, eft, FMB, fonant, BillyTom, Summit: Field...
itamair’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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