First of all. I know Migrate support for Address Field was available in Migrate Extras and I know that since Migrate 2.6 we fall back on a default field handler in Migrate. However, this field handler does not support multiple values for fields other that the main value. meaning that we cannot migrate data into a multivalued address field.

I think we should therefore add a Migrate handler for the Address Field and since Migrate Extras is obsolete and the correct place for adding Migrate support is in the module itself, I opened the issue here and not in the Migrate Extras issue queue.

Patch will soon follow.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

xatoo’s picture

Assigned: xatoo » Unassigned
Status: Active » Needs review
FileSize
7.13 KB
xatoo’s picture

I've changed the patch to store additional data as a serialized array in the 'data' column so that it can now be used with extensions to address field, (like Address Field Phone.)

Example:

    $this->addFieldMapping('field_addresses', 'address_country');
    $this->addFieldMapping('field_addresses:name_line', 'address_name');
    $this->addFieldMapping('field_addresses:thoroughfare', 'address_street');
    $this->addFieldMapping('field_addresses:postal_code', 'address_postalcode');
    $this->addFieldMapping('field_addresses:locality', 'address_city');
    $this->addFieldMapping('field_addresses:phone_number', 'address_phone');
    $this->addFieldMapping('field_addresses:fax_number', 'address_fax');
kostajh’s picture

This patch worked great for me. Thanks for contributing it!

Even though you've documented this in the code, it might be worth throwing an exception if someone tries to migrate country names that are longer than two characters (or perhaps better, are not valid ISO country codes). As it stands, you'll get SQL errors when trying to migrate "United States" in place of "US".

bc’s picture

Status: Needs review » Reviewed & tested by the community

Tested and works for me, as well. Thanks for the patch :)

dwkitchen’s picture

Also worked for me

rszrama’s picture

Status: Reviewed & tested by the community » Fixed

Committing as is. I'm not sure where such an exception for invalid country codes would go in the Migrate class, but I'd be happy to patch that in if it's an accepted pattern for Migrate classes.

Status: Fixed » Closed (fixed)

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

ShaunDychko’s picture

Issue summary: View changes

Not sure if this belongs in docs somewhere, but here's a suggested starting point for someone migrating into Address Field with country names in the source. This does Google geocoding since Google can understand typos in the country name, returning DE for "ermany", "Gerany", and other typos. In the migrate constructor use $this->addFieldMapping('my_destination_address_field', 'country_code');
The following takes inspiration from the Geocoder module, and requires it to be enabled with a Google API key entered.

    if (!empty($row->field_country)) {
      // Geocode the country name to the 2 letter country code expected by
      // Address Field.

      // Sleep between Google API requests to avoid being blocked by overuse.
      $delay_trigger = &drupal_static(__METHOD__);
      $delay = variable_get('geocoder_google_delay', 0);
      if ($delay > 0 && $delay_trigger) {
        usleep($delay * 1000);
      }

      // Get Google API key entered in the geocoder module.
      $geocoder_settings = variable_get('geocoder_settings', array());
      $query['key'] = $geocoder_settings['geocoder_apikey_google'];

      // Use "components" rather than an "address" to prevent Google from
      // mistaking an improperly typed country name as a city.
      $query['components'] = 'country:' . $row->field_country[0];
      $base_url = 'https://maps.googleapis.com/maps/api/geocode/json';
      $url = url($base_url, array(
        'query' => $query,
      ));

      // Send the request.
      $result = drupal_http_request($url);
      $delay_trigger = TRUE;

      if (isset($result->error)) {
        $args = array(
          '@code' => $result->code,
          '@error' => $result->error,
          '@uid' => $row->uid,
        );
        $msg = t('HTTP request to google API failed.\nCode: @code\nError: @error for user with source uid: @uid', $args);
        drush_print($msg);
        return FALSE;
      }

      $data = json_decode($result->data);

      if ($data->status == 'ZERO_RESULTS') {
        drush_print('zero results from geocoding country for source uid: ' . $row->uid);
        return FALSE;
      }
      elseif ($data->status != 'OK') {
        $args = array('@status' => $data->status, '@uid' => $row->uid);
        $msg = t('Google API returned bad status.\nStatus: @status for source uid: @uid', $args);
        drush_print($msg);
        return FALSE;
      }

      if (empty($data->results[0]->address_components[0]->short_name)) {
        drush_print('Empty country geocode result for source uid: ' . $row->uid);
        return FALSE;
      }

      $country_code = $data->results[0]->address_components[0]->short_name;
      $row->country_code = $country_code;
    }