You are here

geocoder_field.module in Geocoder 7.2

File

modules/geocoder_field/geocoder_field.module
View source
<?php

/**
 * Implements hook_field_widget_info().
 */
function geocoder_field_field_widget_info() {
  return array(
    'geocoder' => array(
      'label' => t('Geocode from another field'),
      'field types' => array_keys(field_info_field_types()),
      'behaviors' => array(
        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
        'default value' => FIELD_BEHAVIOR_NONE,
      ),
    ),
  );
}

/**
 * Implements hook_field_widget_settings_form().
 */
function geocoder_field_field_widget_settings_form($this_field, $instance) {
  $valid_fields = array();
  $settings = $instance['widget']['settings'];
  $entity_fields = field_info_instances($instance['entity_type'], $instance['bundle']);
  $all_fields = field_info_fields();
  $entities = entity_get_info();

  // Add the title field to the list of fields on this entity
  $entity_keys = $entities[$instance['entity_type']]['entity keys'];

  // Some entities do not have a "title" field, such as Field Collection or
  // Message entities. If the entity does not have a label key, it will be
  // undefined or FALSE.
  if (isset($entity_keys['label']) && $entity_keys['label'] !== FALSE) {
    $title_field = $entities[$instance['entity_type']]['entity keys']['label'];
    $all_fields[$title_field] = array(
      'field_name' => $title_field,
      'type' => 'text',
    );
    $entity_fields['title']['label'] = t(drupal_ucfirst($title_field));
  }

  // Get a list of all valid fields that we both support and are part of this entity
  foreach ($all_fields as $field) {
    if (array_key_exists($field['field_name'], $entity_fields)) {
      $valid_fields[$field['field_name']] = sprintf('%s (%s)', $entity_fields[$field['field_name']]['label'], $field['field_name']);
    }
  }

  // Extend with virtual fields.
  $info = entity_get_all_property_info($instance['entity_type']);
  foreach ($info as $property_name => $property) {
    if (isset($property['type']) && in_array($property['type'], array(
      'location',
      'text',
    ))) {
      if (!isset($valid_fields[$property_name])) {
        $valid_fields[$property_name] = sprintf('%s (%s)', $property['label'], $property_name);
      }
    }
  }
  natcasesort($valid_fields);
  switch ($instance['widget']['type']) {
    case 'geocoder':
      $form['geocoder_field'] = array(
        '#type' => 'select',
        '#title' => t('Geocode from field'),
        '#default_value' => isset($settings['geocoder_field']) ? $settings['geocoder_field'] : '',
        '#options' => $valid_fields,
        '#description' => t('Select which field you would like to geocode from.'),
        '#required' => TRUE,
      );
      break;
  }
  $geocoder_plugins = (array) $settings['geocoder_handlers'];
  $providers = \Drupal\geocoder\Geocoder::getPlugins('Provider');
  $plugins = array_combine(array_values($providers), array_values($providers));
  $plugins_array = array();
  $i = 0;
  foreach ($plugins as $plugin) {
    $plugins_array[$plugin] = array(
      'name' => $plugin,
      'weight' => $i++,
      'enabled' => 0,
    );
  }
  $i = 0;
  foreach ($geocoder_plugins as $name => $option) {
    if (is_array($option)) {
      if ($option['enabled'] == 1) {
        $plugins_array[$name]['enabled'] = 1;
        $plugins_array[$name]['weight'] = isset($option['weight']) ? $option['weight'] : $i++;
      }
    }
    else {
      if ($plugins[$option]) {
        $plugins_array[$option]['enabled'] = 1;
        $plugins_array[$option]['weight'] = $i++;
      }
    }
  }
  uasort($plugins_array, function ($a, $b) {
    if ($a['enabled'] > $b['enabled']) {
      return -1;
    }
    elseif ($a['enabled'] < $b['enabled']) {
      return 1;
    }
    if ($a['weight'] < $b['weight']) {
      return -1;
    }
    elseif ($a['weight'] > $b['weight']) {
      return 1;
    }
    if ($a['name'] < $b['name']) {
      return -1;
    }
    elseif ($a['name'] > $b['name']) {
      return 1;
    }
    return 0;
  });
  $data = array();
  foreach ($plugins_array as $plugin) {
    $data[$plugin['name']] = array(
      'name' => $plugin['name'],
      'machine_name' => $plugin['name'],
      'weight' => $plugin['weight'],
      'enabled' => $plugin['enabled'],
    );
  }
  $rows = array();
  $row_elements = array();
  foreach ($data as $id => $entry) {
    $rows[$id] = array(
      'data' => array(
        array(
          'class',
          array(
            'entry-cross',
          ),
        ),
        array(
          'data' => array(
            '#type' => 'weight',
            '#title' => t('Weight'),
            '#title_display' => 'invisible',
            '#default_value' => $entry['weight'],
            '#parents' => array(
              'instance',
              'widget',
              'settings',
              'geocoder_handlers',
              $id,
              'weight',
            ),
            '#attributes' => array(
              'class' => array(
                'entry-order-weight',
              ),
            ),
          ),
        ),
        array(
          'data' => array(
            '#type' => 'checkbox',
            '#title' => t('Enable'),
            '#title_display' => 'invisible',
            '#default_value' => (bool) $entry['enabled'],
            '#parents' => array(
              'instance',
              'widget',
              'settings',
              'geocoder_handlers',
              $id,
              'enabled',
            ),
          ),
        ),
        check_plain($entry['name']),
      ),
      'class' => array(
        'draggable',
      ),
    );

    // Build rows of the form elements in the table.
    $row_elements[$id] = array(
      'weight' => &$rows[$id]['data'][1]['data'],
      'enabled' => &$rows[$id]['data'][2]['data'],
    );
  }
  $form['#tree'] = TRUE;

  // Add the table to the form.
  $form['geocoder_handlers'] = array(
    '#theme' => 'table',
    '#caption' => t('Select the geocoder plugin in use, from the top to the bottom.'),
    // The row form elements need to be processed and build,
    // therefore pass them as element children.
    'elements' => $row_elements,
    '#header' => array(
      // We need two empty columns for the weigth field and the cross.
      array(
        'data' => NULL,
        'colspan' => 2,
      ),
      t('Enabled'),
      t('Name'),
    ),
    '#rows' => $rows,
    '#empty' => t('There are no entries available.'),
    '#attributes' => array(
      'id' => 'entry-order-geocoder-handlers',
    ),
  );
  drupal_add_tabledrag('entry-order-geocoder-handlers', 'order', 'sibling', 'entry-order-weight');
  $form['delta_handling'] = array(
    '#type' => 'select',
    '#title' => t('Multi-value input handling'),
    '#description' => t('Should geometries from multiple inputs be: <ul><li>Matched with each input (e.g. One POINT for each address field)</li><li>Aggregated into a single MULTIPOINT geofield (e.g. One MULTIPOINT polygon from multiple address fields)</li><li>Broken up into multiple geometries (e.g. One MULTIPOINT to multiple POINTs.)</li></ul>'),
    '#default_value' => isset($settings['delta_handling']) ? $settings['delta_handling'] : 'default',
    '#options' => array(
      'default' => 'Match Multiples (default)',
      'm_to_s' => 'Multiple to Single',
      's_to_m' => 'Single to Multiple',
      'c_to_s' => 'Concatenate to Single',
      'c_to_m' => 'Concatenate to Multiple',
    ),
    '#required' => TRUE,
  );
  return $form;
}

/**
 * Implements hook_field_attach_presave().
 *
 * Geocoding for the geocoder widget is done here to ensure that only validated
 * and fully processed fields values are accessed.
 */
function geocoder_field_field_attach_presave($entity_type, $entity) {

  // Loop over any geofield using our geocode widget
  $entity_info = entity_get_info($entity_type);
  $bundle_name = empty($entity_info['entity keys']['bundle']) ? $entity_type : $entity->{$entity_info['entity keys']['bundle']};
  foreach (field_info_instances($entity_type, $bundle_name) as $field_instance) {
    if ($field_instance['widget']['type'] === 'geocoder') {
      if (($field_value = geocoder_field_widget_get_field_value($entity_type, $field_instance, $entity)) !== FALSE) {
        $entity->{$field_instance['field_name']} = $field_value;
      }
    }
  }
}

/**
 * Find a field instance's or entity property's relevant meta data.
 */
function geocoder_field_widget_get_field_info($entity_type, $field_instance, $entity) {
  $entity_info = entity_get_info($entity_type);
  $field_name = is_array($field_instance['widget']['settings']['geocoder_field']) ? reset($field_instance['widget']['settings']['geocoder_field']) : $field_instance['widget']['settings']['geocoder_field'];

  // Determine the source type, if it's a entity-key, we mock it as a "text" field
  if (in_array($field_name, $entity_info['entity keys']) && $entity) {
    $field_info = array(
      'type' => 'text',
      'entity_key' => TRUE,
    );
  }
  else {
    $field_info = field_info_field($field_name);
    if (!$field_info) {
      $info = entity_get_all_property_info($entity_type);
      $field_info = $info[$field_name];
    }
    $field_info['entity_key'] = FALSE;
  }
  return $field_info;
}

/**
 * Return the value for the given proxy-field for the given entity.
 */
function geocoder_field_widget_get_entity_field_value($entity_type, $field_instance, $entity) {
  $field_name = is_array($field_instance['widget']['settings']['geocoder_field']) ? reset($field_instance['widget']['settings']['geocoder_field']) : $field_instance['widget']['settings']['geocoder_field'];
  $field_info = geocoder_field_widget_get_field_info($entity_type, $field_instance, $entity);

  // Get the source values
  if ($field_info['entity_key'] && $entity) {
    $source_field_values = array(
      array(
        'value' => $entity->{$field_name},
      ),
    );
  }
  else {
    if ($entity) {
      $wrapper = entity_metadata_wrapper($entity_type, $entity);
      $field_wrapper = $wrapper->{$field_name};
      $value = $field_wrapper
        ->value();
      $values = array_filter(is_array($value) && isset($value[0]) ? $value : array(
        $value,
      ));
      $source_field_values = array_map(function ($value) {
        if (is_array($value)) {

          // Clean up array from Addressfield, for diff.
          unset($value['element_key']);

          // Clean up array from Location, for diff.
          unset($value['location_settings'], $value['country_name'], $value['latitude'], $value['longitude'], $value['lid']);
          return array_filter($value);
        }
        return array(
          'value' => $value,
        );
      }, $values);
    }
    else {

      // We can't find the source values
      return FALSE;
    }
  }
  return $source_field_values;
}

/**
 * Get a field's value based on geocoded data.
 *
 * @param $entity_type
 *   Type of entity
 * @para field_instance
 *   Field instance definition array
 * @param $entity
 *  Optionally, the entity. You must pass either the entity or $source_field_values
 * @param $source_field_values
 *  Array of deltas / source field values. You must pass either this or $entity.
 *
 * @return
 *  Three possibilities could be returned by this function:
 *    - FALSE: do nothing.
 *    - An empty array: use it to unset the existing field value.
 *    - A populated array: assign a new field value.
 */
function geocoder_field_widget_get_field_value($entity_type, $field_instance, $entity = NULL, $source_field_values = NULL) {
  if (!$source_field_values && !$entity) {
    trigger_error('geocoder_field_widget_get_field_value: You must pass either $source_field_values OR $entity', E_USER_ERROR);
    return FALSE;
  }

  // Required settings
  if (isset($field_instance['widget']['settings']['geocoder_handlers']) && isset($field_instance['widget']['settings']['geocoder_field'])) {
    $geocoder_handlers = array_filter($field_instance['widget']['settings']['geocoder_handlers'], function ($v) {
      return (bool) $v['enabled'];
    });
    uasort($geocoder_handlers, function ($a, $b) {
      if ($a['enabled'] > $b['enabled']) {
        return -1;
      }
      elseif ($a['enabled'] < $b['enabled']) {
        return 1;
      }
      if ($a['weight'] < $b['weight']) {
        return -1;
      }
      elseif ($a['weight'] > $b['weight']) {
        return 1;
      }
      return 0;
    });
    $geocoder_handlers = array_keys($geocoder_handlers);
    $target_info = field_info_field($field_instance['field_name']);
    $field_info = geocoder_field_widget_get_field_info($entity_type, $field_instance, $entity);

    // Get the source values
    if (!$source_field_values) {
      $source_field_values = geocoder_field_widget_get_entity_field_value($entity_type, $field_instance, $entity);
    }

    // If no valid source values were passed.
    if (empty($source_field_values)) {
      return array();
    }

    // Determine how we deal with deltas (multi-value fields)
    if (empty($field_instance['widget']['settings']['delta_handling'])) {
      $delta_handling = 'default';
    }
    else {
      $delta_handling = $field_instance['widget']['settings']['delta_handling'];
    }

    // Check to see if we should be concatenating
    if ($delta_handling == 'c_to_s' || $delta_handling == 'c_to_m') {
      $source_field_values = geocoder_field_widget_get_field_concat($source_field_values);
    }

    // Allow other modules to alter values before we geocode them.
    drupal_alter('geocoder_geocode_values', $source_field_values, $field_info, $field_instance);
    if (is_array($source_field_values) && count($source_field_values)) {

      // Geocode geometries.
      $geometries = array();
      foreach ($source_field_values as $delta => $item) {
        if (in_array($field_info['type'], array(
          'file',
          'image',
        ))) {
          $file = file_load($item['fid']);
          $item['value'] = drupal_realpath($file->uri);
        }
        if ($addressCollection = geocoder($geocoder_handlers, $item['value'])) {
          $geometry = \Drupal\geocoder\Geocoder::getPlugin('Dumper', 'geometry')
            ->dump($addressCollection
            ->first());
          if ($geometry instanceof \Geometry) {
            $geometries[] = $geometry;
          }
        }
      }
      if (empty($geometries)) {

        // This field has no data, so set the field to an empty array in
        // order to delete its saved data.
        return array();
      }
      else {

        // Resolve multiple-values - get back values from our delta-resolver
        $values = geocoder_field_widget_resolve_deltas($geometries, $delta_handling, $target_info);

        // Set the values - geofields do not support languages
        return array(
          LANGUAGE_NONE => $values,
        );
      }
    }
  }
  return array();
}

/**
 * Get field items and info
 *
 * We always pass the full field-item array (with all columns) to the handler, but there is some preprocessing
 * that we need to do for the special case of entity-labels and multi-field concatenation
 * For these two special cases we "mock-up" a text-field and pass it back for geocoding
 */
function geocoder_field_widget_get_field_concat($items) {

  // Check if we should concatenate
  $concat = '';
  foreach ($items as $item) {
    if (!empty($item['value'])) {
      $concat .= trim($item['value']) . ', ';
    }
  }
  $concat = trim($concat, ', ');
  $items = array(
    array(
      'value' => $concat,
    ),
  );
  return $items;
}

/**
 * Geocoder Widget - Resolve Deltas
 *
 * Given a list of geometries, and user configuration on how to handle deltas,
 * we created a list of items to be inserted into the fields.
 */
function geocoder_field_widget_resolve_deltas($geometries, $delta_handling = 'default', $target_info) {
  $values = array();

  // Default delta handling: just pass one delta to the next
  if ($delta_handling == 'default') {
    foreach ($geometries as $geometry) {
      $values[] = geocoder_field_widget_values_from_geometry($geometry, $target_info);
    }
  }

  // Single-to-multiple handling - if we can, explode out the component geometries
  if ($delta_handling == 's_to_m' || $delta_handling == 'c_to_m') {
    $type = $geometries[0]
      ->geometryType();
    if (in_array($type, array(
      'MultiPoint',
      'MultiLineString',
      'MultiPolygon',
      'GeometryCollection',
    ))) {
      $components = $geometries[0]
        ->getComponents();
      foreach ($components as $component) {
        $values[] = geocoder_field_widget_values_from_geometry($component, $target_info);
      }
    }
    else {
      $values[] = geocoder_field_widget_values_from_geometry($geometries[0], $target_info);
    }
  }

  // For multiple-to-single handling, run it though geometryReduce
  if ($delta_handling == 'm_to_s' || $delta_handling == 'c_to_s') {
    $reduced_geom = \geoPHP::geometryReduce($geometries);
    $values[] = geocoder_field_widget_values_from_geometry($reduced_geom, $target_info);
  }
  return $values;
}

/**
 * Geocoder Widget - Field values from geometry
 *
 * Given a geometry and the field type, return back a values array for that field.
 * The passed back array represents a single delta.
 */
function geocoder_field_widget_values_from_geometry($geometry, $target_info) {
  if ($target_info['type'] == 'geofield') {
    return geofield_get_values_from_geometry($geometry);
  }
  if ($target_info['type'] == 'geolocation_latlng') {
    $centroid = $geometry
      ->centroid();
    $lat = $centroid
      ->y();
    $lng = $centroid
      ->x();
    return array(
      'lat' => $lat,
      'lng' => $lng,
      'lat_sin' => sin(deg2rad($lat)),
      'lat_cos' => cos(deg2rad($lat)),
      'lng_rad' => deg2rad($lng),
    );
  }
  if ($target_info['type'] == 'location') {
    $centroid = $geometry
      ->centroid();
    return array(
      'latitude' => $centroid
        ->y(),
      'longitude' => $centroid
        ->x(),
      'source' => 2,
    );
  }
  if ($target_info['type'] == 'postgis') {
    $srid = $geometry
      ->getSRID() ? $geometry
      ->getSRID() : '4326';
    $type = $target_info['settings']['type'];
    $postgis_geometry = new PostgisGeometry($type, $srid);
    $postgis_geometry
      ->fromText($geometry
      ->asText());
    $postgis_geometry
      ->transform($target_info['settings']['srid']);
    return array(
      'geometry' => $postgis_geometry
        ->getGeometry(),
    );
  }
  return array();
}

/**
 * Geocoder Widget - Parse an address field.
 */
function geocoder_field_widget_parse_addressfield($field_item) {
  $address = '';
  if (!empty($field_item['premise'])) {
    $address .= $field_item['premise'] . ',';
  }
  if (!empty($field_item['thoroughfare'])) {
    $address .= $field_item['thoroughfare'] . ',';
  }
  if (!empty($field_item['locality'])) {
    $address .= $field_item['locality'] . ',';
  }
  if (!empty($field_item['administrative_area'])) {
    $address .= $field_item['administrative_area'] . ',';
  }
  if (!empty($field_item['sub_administrative_area'])) {
    $address .= $field_item['sub_administrative_area'] . ',';
  }
  if (!empty($field_item['country'])) {

    // Convert country code to country name.
    include_once DRUPAL_ROOT . '/includes/locale.inc';
    $countries = country_get_list();
    if (array_key_exists($field_item['country'], $countries)) {
      $field_item['country'] = $countries[$field_item['country']];
    }
    $address .= $field_item['country'] . ',';
  }
  if (!empty($field_item['postal_code'])) {
    $address .= $field_item['postal_code'] . ',';
  }
  $address = rtrim($address, ', ');
  return $address;
}

/**
 * Geocoder Widget - Parse a location field
 */
function geocoder_field_widget_parse_locationfield($field_item) {
  $address = '';
  if (!empty($field_item['name'])) {
    $address .= $field_item['name'] . ',';
  }
  if (!empty($field_item['street'])) {
    $address .= $field_item['street'] . ',';
  }
  if (!empty($field_item['additional'])) {
    $address .= $field_item['additional'] . ',';
  }
  if (!empty($field_item['city'])) {
    $address .= $field_item['city'] . ',';
  }
  if (!empty($field_item['province']) && function_exists('location_province_name')) {
    $province_fullname = location_province_name($field_item['country'], $field_item['province']);
    $address .= $province_fullname . ',';
  }
  if (!empty($field_item['country'])) {
    $address .= $field_item['country'] . ',';
  }
  if (!empty($field_item['postal_code'])) {
    $address .= $field_item['postal_code'] . ',';
  }
  $address = rtrim($address, ', ');
  return $address;
}

/**
 * Implements hook_field_formatter_info().
 */
function geocoder_field_field_formatter_info() {
  $formatters = array();
  $formatters['geocoder_reverse'] = array(
    'label' => t('Reverse geocoding to address'),
    'field types' => array(
      'geofield',
    ),
    'settings' => array(
      'format_handlers' => array(
        'address',
      ),
      'geocoder_handlers' => array(
        'googlemaps',
      ),
      'default_country' => '',
    ),
  );
  return $formatters;
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function geocoder_field_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $form = array();
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $geocoder_plugins = (array) $settings['geocoder_handlers'];
  $plugins = array_combine(array_values(\Drupal\geocoder\Geocoder::getPlugins('Provider')), array_values(\Drupal\geocoder\Geocoder::getPlugins('Provider')));
  $plugins_array = array();
  $i = 0;
  foreach ($plugins as $plugin) {
    $plugins_array[$plugin] = array(
      'name' => $plugin,
      'weight' => $i++,
      'enabled' => 0,
    );
  }
  $i = 0;
  foreach ($geocoder_plugins as $name => $option) {
    if (is_array($option)) {
      if ($option['enabled'] == 1) {
        $plugins_array[$name]['enabled'] = 1;
        $plugins_array[$name]['weight'] = isset($option['weight']) ? $option['weight'] : $i++;
      }
    }
    else {
      if ($plugins[$option]) {
        $plugins_array[$option]['enabled'] = 1;
        $plugins_array[$option]['weight'] = $i++;
      }
    }
  }
  uasort($plugins_array, function ($a, $b) {
    if ($a['enabled'] > $b['enabled']) {
      return -1;
    }
    elseif ($a['enabled'] < $b['enabled']) {
      return 1;
    }
    if ($a['weight'] < $b['weight']) {
      return -1;
    }
    elseif ($a['weight'] > $b['weight']) {
      return 1;
    }
    if ($a['name'] < $b['name']) {
      return -1;
    }
    elseif ($a['name'] > $b['name']) {
      return 1;
    }
    return 0;
  });
  $data = array();
  foreach ($plugins_array as $plugin) {
    $data[$plugin['name']] = array(
      'name' => $plugin['name'],
      'machine_name' => $plugin['name'],
      'weight' => $plugin['weight'],
      'enabled' => $plugin['enabled'],
    );
  }
  $rows = array();
  $row_elements = array();
  foreach ($data as $id => $entry) {
    $rows[$id] = array(
      'data' => array(
        array(
          'class',
          array(
            'entry-cross',
          ),
        ),
        array(
          'data' => array(
            '#type' => 'weight',
            '#title' => t('Weight'),
            '#title_display' => 'invisible',
            '#default_value' => $entry['weight'],
            '#parents' => array(
              'fields',
              $field['field_name'],
              'settings_edit_form',
              'settings',
              'geocoder_handlers',
              $id,
              'weight',
            ),
            '#attributes' => array(
              'class' => array(
                'entry-order-weight',
              ),
            ),
          ),
        ),
        array(
          'data' => array(
            '#type' => 'checkbox',
            '#title' => t('Enable'),
            '#title_display' => 'invisible',
            '#default_value' => (bool) $entry['enabled'],
            '#parents' => array(
              'fields',
              $field['field_name'],
              'settings_edit_form',
              'settings',
              'geocoder_handlers',
              $id,
              'enabled',
            ),
          ),
        ),
        check_plain($entry['name']),
      ),
      'class' => array(
        'draggable',
      ),
    );

    // Build rows of the form elements in the table.
    $row_elements[$id] = array(
      'weight' => &$rows[$id]['data'][1]['data'],
      'enabled' => &$rows[$id]['data'][2]['data'],
    );
  }
  $form['#tree'] = TRUE;

  // Add the table to the form.
  $form['geocoder_handlers'] = array(
    '#theme' => 'table',
    '#caption' => t('Select the geocoder plugin in use, from the top to the bottom.'),
    // The row form elements need to be processed and build,
    // therefore pass them as element children.
    'elements' => $row_elements,
    '#header' => array(
      // We need two empty columns for the weigth field and the cross.
      array(
        'data' => NULL,
        'colspan' => 2,
      ),
      t('Enabled'),
      t('Name'),
    ),
    '#rows' => $rows,
    '#empty' => t('There are no entries available.'),
    '#attributes' => array(
      'id' => 'entry-order-geocoder-handlers',
    ),
  );
  drupal_add_tabledrag('entry-order-geocoder-handlers', 'order', 'sibling', 'entry-order-weight');
  $form['default_country'] = array(
    '#type' => 'select',
    '#title' => t('Default country'),
    '#options' => array(
      'site_default' => t('- Site default -'),
    ) + _addressfield_country_options_list(),
    '#default_value' => $settings['default_country'],
    '#empty_value' => '',
  );
  $form['format_handlers'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Format handlers'),
    '#options' => addressfield_format_plugins_options(),
    '#process' => array(
      'form_process_checkboxes',
      '_addressfield_field_formatter_settings_form_process_add_state',
    ),
    '#element_validate' => array(
      '_addressfield_field_formatter_settings_form_validate',
    ),
    '#default_value' => $settings['format_handlers'],
  );
  return $form;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function geocoder_field_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $summary = array();
  $geocoder_handlers = array_filter($settings['geocoder_handlers'], function ($v) {
    return (bool) $v['enabled'];
  });
  uasort($geocoder_handlers, function ($a, $b) {
    if ($a['enabled'] > $b['enabled']) {
      return -1;
    }
    elseif ($a['enabled'] < $b['enabled']) {
      return 1;
    }
    if ($a['weight'] < $b['weight']) {
      return -1;
    }
    elseif ($a['weight'] > $b['weight']) {
      return 1;
    }
    return 0;
  });
  $geocoder_handlers = implode(', ', array_keys($geocoder_handlers));
  $summary[] = t('Geocoder plugin: @data', array(
    '@data' => $geocoder_handlers,
  ));
  return implode('<br />', $summary);
}

/**
 * Implements hook_field_formatter_view().
 */
function geocoder_field_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];
  $geocoder_handlers = array_filter($settings['geocoder_handlers'], function ($v) {
    return (bool) $v['enabled'];
  });
  uasort($geocoder_handlers, function ($a, $b) {
    if ($a['enabled'] > $b['enabled']) {
      return -1;
    }
    elseif ($a['enabled'] < $b['enabled']) {
      return 1;
    }
    if ($a['weight'] < $b['weight']) {
      return -1;
    }
    elseif ($a['weight'] > $b['weight']) {
      return 1;
    }
    return 0;
  });
  $geocoder_handlers = array_keys($geocoder_handlers);
  switch ($display['type']) {
    case 'geocoder_reverse':
      foreach ($items as $delta => $item) {
        if ($geocoder = reverse($geocoder_handlers, $item['lat'], $item['lon'])) {
          $geocoder = _geocoder_field_geocoder_to_addressfield($geocoder, $field, $display, $instance);
          $context = array(
            'mode' => 'render',
            'field' => $field,
            'instance' => $instance,
            'langcode' => $langcode,
            'delta' => $delta,
          );
          $element[$delta] = addressfield_generate($geocoder, array_values($settings['format_handlers']), $context);
        }
      }
      break;
  }
  return $element;
}

/**
 * Helper function. Transform an array from Geocoder PHP library into an
 * array for AddressField module.
 */
function _geocoder_field_geocoder_to_addressfield($geocoder, $field, $display, $instance) {
  $available_countries = _addressfield_country_options_list($field, $instance);
  $default_country = $display['settings']['default_country'];

  // Resolve the special site_default option.
  if ($default_country == 'site_default') {
    $default_country = variable_get('site_default_country', '');
  }

  // Fallback to the first country in the list if the default country is not
  // available, or is empty even though the field is required.
  $not_available = $default_country && !isset($available_countries[$default_country]);
  $empty_but_required = empty($default_country) && !empty($instance['required']);
  if ($not_available || $empty_but_required) {
    $default_country = key($available_countries);
  }
  $geocoder += array(
    'country' => $default_country,
    'name_line' => '',
    'first_name' => '',
    'last_name' => '',
    'organisation_name' => '',
    'administrative_area' => '',
    'sub_administrative_area' => '',
    'locality' => '',
    'dependent_locality' => '',
    'postal_code' => '',
    'thoroughfare' => '',
    'premise' => '',
    'sub_premise' => '',
    'data' => '',
  );
  $thoroughfare = array();
  if (isset($geocoder['streetNumber'])) {
    $thoroughfare[] = $geocoder['streetNumber'];
  }
  if (isset($geocoder['streetName'])) {
    $thoroughfare[] = $geocoder['streetName'];
  }
  $geocoder['thoroughfare'] = implode(', ', $thoroughfare);
  if (isset($geocoder['postalCode'])) {
    $geocoder['postal_code'] = $geocoder['postalCode'];
  }
  if (isset($geocoder['countryCode'])) {
    $geocoder['country'] = $geocoder['countryCode'];
  }
  return $geocoder;
}

Functions

Namesort descending Description
geocoder_field_field_attach_presave Implements hook_field_attach_presave().
geocoder_field_field_formatter_info Implements hook_field_formatter_info().
geocoder_field_field_formatter_settings_form Implements hook_field_formatter_settings_form().
geocoder_field_field_formatter_settings_summary Implements hook_field_formatter_settings_summary().
geocoder_field_field_formatter_view Implements hook_field_formatter_view().
geocoder_field_field_widget_info Implements hook_field_widget_info().
geocoder_field_field_widget_settings_form Implements hook_field_widget_settings_form().
geocoder_field_widget_get_entity_field_value Return the value for the given proxy-field for the given entity.
geocoder_field_widget_get_field_concat Get field items and info
geocoder_field_widget_get_field_info Find a field instance's or entity property's relevant meta data.
geocoder_field_widget_get_field_value Get a field's value based on geocoded data.
geocoder_field_widget_parse_addressfield Geocoder Widget - Parse an address field.
geocoder_field_widget_parse_locationfield Geocoder Widget - Parse a location field
geocoder_field_widget_resolve_deltas Geocoder Widget - Resolve Deltas
geocoder_field_widget_values_from_geometry Geocoder Widget - Field values from geometry
_geocoder_field_geocoder_to_addressfield Helper function. Transform an array from Geocoder PHP library into an array for AddressField module.