View source
<?php
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,
),
),
);
}
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();
$entity_keys = $entities[$instance['entity_type']]['entity keys'];
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));
}
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']);
}
}
$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',
),
);
$row_elements[$id] = array(
'weight' => &$rows[$id]['data'][1]['data'],
'enabled' => &$rows[$id]['data'][2]['data'],
);
}
$form['#tree'] = TRUE;
$form['geocoder_handlers'] = array(
'#theme' => 'table',
'#caption' => t('Select the geocoder plugin in use, from the top to the bottom.'),
'elements' => $row_elements,
'#header' => array(
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;
}
function geocoder_field_field_attach_presave($entity_type, $entity) {
$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;
}
}
}
}
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'];
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;
}
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);
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)) {
unset($value['element_key']);
unset($value['location_settings'], $value['country_name'], $value['latitude'], $value['longitude'], $value['lid']);
return array_filter($value);
}
return array(
'value' => $value,
);
}, $values);
}
else {
return FALSE;
}
}
return $source_field_values;
}
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;
}
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);
if (!$source_field_values) {
$source_field_values = geocoder_field_widget_get_entity_field_value($entity_type, $field_instance, $entity);
}
if (empty($source_field_values)) {
return array();
}
if (empty($field_instance['widget']['settings']['delta_handling'])) {
$delta_handling = 'default';
}
else {
$delta_handling = $field_instance['widget']['settings']['delta_handling'];
}
if ($delta_handling == 'c_to_s' || $delta_handling == 'c_to_m') {
$source_field_values = geocoder_field_widget_get_field_concat($source_field_values);
}
drupal_alter('geocoder_geocode_values', $source_field_values, $field_info, $field_instance);
if (is_array($source_field_values) && count($source_field_values)) {
$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)) {
return array();
}
else {
$values = geocoder_field_widget_resolve_deltas($geometries, $delta_handling, $target_info);
return array(
LANGUAGE_NONE => $values,
);
}
}
}
return array();
}
function geocoder_field_widget_get_field_concat($items) {
$concat = '';
foreach ($items as $item) {
if (!empty($item['value'])) {
$concat .= trim($item['value']) . ', ';
}
}
$concat = trim($concat, ', ');
$items = array(
array(
'value' => $concat,
),
);
return $items;
}
function geocoder_field_widget_resolve_deltas($geometries, $delta_handling = 'default', $target_info) {
$values = array();
if ($delta_handling == 'default') {
foreach ($geometries as $geometry) {
$values[] = geocoder_field_widget_values_from_geometry($geometry, $target_info);
}
}
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);
}
}
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;
}
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();
}
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'])) {
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;
}
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;
}
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;
}
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',
),
);
$row_elements[$id] = array(
'weight' => &$rows[$id]['data'][1]['data'],
'enabled' => &$rows[$id]['data'][2]['data'],
);
}
$form['#tree'] = TRUE;
$form['geocoder_handlers'] = array(
'#theme' => 'table',
'#caption' => t('Select the geocoder plugin in use, from the top to the bottom.'),
'elements' => $row_elements,
'#header' => array(
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;
}
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);
}
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;
}
function _geocoder_field_geocoder_to_addressfield($geocoder, $field, $display, $instance) {
$available_countries = _addressfield_country_options_list($field, $instance);
$default_country = $display['settings']['default_country'];
if ($default_country == 'site_default') {
$default_country = variable_get('site_default_country', '');
}
$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;
}