geolocation.module in Geolocation Field 7
Same filename and directory in other branches
A geolocation field using the Field API.
File
geolocation.moduleView source
<?php
/**
* @file
* A geolocation field using the Field API.
*/
/**
* Implements hook_field_info().
*/
function geolocation_field_info() {
return array(
'geolocation_latlng' => array(
'label' => t('Geolocation'),
'description' => t('Geolocation input.'),
'default_widget' => 'geolocation_latlng',
'default_formatter' => 'geolocation_text',
'property_type' => 'geolocation',
'property_callbacks' => array(
'geolocation_property_info_callback',
),
),
);
}
/**
* Callback to alter the property info of geolocation fields.
*
* @see geolocation_field_info()
*/
function geolocation_property_info_callback(&$info, $entity_type, $field, $instance, $field_type) {
$name = $field['field_name'];
$property =& $info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
$property['type'] = $field['cardinality'] != 1 ? 'list<geolocation>' : 'geolocation';
$property['getter callback'] = 'entity_metadata_field_verbatim_get';
$property['setter callback'] = 'entity_metadata_field_verbatim_set';
$property['property info'] = geolocation_data_property_info();
unset($property['query callback']);
}
/**
* Defines info for the properties of the geolocation field data structure.
*/
function geolocation_data_property_info() {
// Build an array of basic property information for the geolocation field.
$properties = array(
'lat' => array(
'label' => 'Latitude',
'type' => 'decimal',
'required' => TRUE,
'description' => '',
'getter callback' => 'entity_property_verbatim_get',
),
'lng' => array(
'label' => 'Longitude',
'type' => 'decimal',
'description' => '',
'required' => TRUE,
'getter callback' => 'entity_property_verbatim_get',
),
'lat_sin' => array(
'label' => 'the sine of latitude',
'description' => '',
'type' => 'decimal',
'getter callback' => 'entity_property_verbatim_get',
),
'lat_cos' => array(
'label' => 'the cosine of latitude',
'description' => '',
'type' => 'decimal',
'getter callback' => 'entity_property_verbatim_get',
),
'lng_rad' => array(
'label' => 'the radian longitude',
'description' => '',
'type' => 'decimal',
'getter callback' => 'entity_property_verbatim_get',
),
'latlng' => array(
'label' => 'the latlng of point',
'description' => '',
'type' => 'string',
'getter callback' => 'geolocation_return_latlon',
),
);
return $properties;
}
/**
* Gets the a latlong property.
*/
function geolocation_return_latlon($data, array $options, $name) {
if (is_array($data) || is_object($data) && $data instanceof ArrayAccess) {
return $data['lat'] . ',' . $data['lng'];
}
return NULL;
}
/**
* Implements hook_field_validate().
*/
function geolocation_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
foreach ($items as $delta => $item) {
if (!geolocation_field_is_empty($item, $field)) {
switch (TRUE) {
case !is_numeric($item['lat']):
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'geolocation_invalid_lat',
'message' => t('Invalid Latitude. Value must be numeric.'),
);
break;
case $item['lat'] > 90:
case $item['lat'] < -90:
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'geolocation_invalid_lat',
'message' => t('Invalid Latitude. Value must be between 90 and -90.'),
);
break;
}
switch (TRUE) {
case !is_numeric($item['lng']):
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'geolocation_invalid_lng',
'message' => t('Invalid Longitude. Value must be numeric.'),
);
case $item['lng'] > 180:
case $item['lng'] < -180:
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'geolocation_invalid_lng',
'message' => t('Invalid Longitude. Value must be between 180 and -180'),
);
break;
}
}
}
}
/**
* Implements hook_field_presave().
*/
function geolocation_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
foreach ($items as $delta => $item) {
// Precalculate some goodness.
$items[$delta] = _geolocation_field_precalculate_values($item);
}
}
/**
* Implements hook_field_is_empty().
*/
function geolocation_field_is_empty($item, $field) {
if (empty($item['lat']) && (string) $item['lat'] !== '0' && empty($item['lng']) && (string) $item['lng'] !== '0') {
return TRUE;
}
}
/**
* Implements hook_field_formatter_info().
*/
function geolocation_field_formatter_info() {
return array(
'geolocation_text' => array(
'label' => t('Simple text-based formatter'),
'field types' => array(
'geolocation_latlng',
),
),
'geolocation_latlng' => array(
'label' => t('Simple microdata formatter'),
'field types' => array(
'geolocation_latlng',
),
),
'geolocation_latitude' => array(
'label' => t('Latitude text-based formatter'),
'field types' => array(
'geolocation_latlng',
),
),
'geolocation_longitude' => array(
'label' => t('Longitude text-based formatter'),
'field types' => array(
'geolocation_latlng',
),
),
);
}
/**
* Implements hook_field_formatter_view().
*/
function geolocation_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
case 'geolocation_text':
foreach ($items as $delta => $item) {
$element[$delta]['#markup'] = '<p>' . t('Geolocation is @lat, @lng', array(
'@lat' => $item['lat'],
'@lng' => $item['lng'],
)) . '</p>';
}
break;
case 'geolocation_latlng':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#theme' => 'geolocation_latlng',
'#lat' => $item['lat'],
'#lng' => $item['lng'],
);
}
break;
case 'geolocation_latitude':
foreach ($items as $delta => $item) {
$element[$delta]['#markup'] = $item['lat'];
}
break;
case 'geolocation_longitude':
foreach ($items as $delta => $item) {
$element[$delta]['#markup'] = $item['lng'];
}
break;
}
return $element;
}
/**
* Implements hook_theme().
*/
function geolocation_theme() {
return array(
'geolocation_latlng' => array(
'template' => 'geolocation_latlng',
'variables' => array(
'lat' => NULL,
'lng' => NULL,
),
),
);
}
/**
* Implements hook_field_widget_info().
*/
function geolocation_field_widget_info() {
return array(
'geolocation_text' => array(
'label' => t('Latitude/Longitude'),
'field types' => array(
'geolocation_latlng',
),
),
);
}
/**
* Implements hook_field_widget_form().
*/
function geolocation_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$lat_value = isset($items[$delta]['lat']) ? $items[$delta]['lat'] : '';
$lng_value = isset($items[$delta]['lng']) ? $items[$delta]['lng'] : '';
$element += array(
'#delta' => $delta,
);
// Wrap in a fieldset for single fields.
if ($field['cardinality'] == 1) {
$element['#type'] = 'fieldset';
}
$element['lat'] = array();
$element['lng'] = array();
switch ($instance['widget']['type']) {
case 'geolocation_text':
$element['lat'] += array(
'#title' => t('Latitude'),
'#type' => 'textfield',
'#default_value' => $lat_value,
'#size' => 30,
'#maxlength' => 30,
'#required' => $instance['required'],
);
$element['lng'] += array(
'#title' => t('Longitude'),
'#type' => 'textfield',
'#default_value' => $lng_value,
'#size' => 30,
'#maxlength' => 30,
'#required' => $instance['required'],
);
$element['#attached']['css'][] = drupal_get_path('module', 'geolocation') . '/geolocation.css';
break;
}
return $element;
}
/**
* Implements hook_field_widget_error().
*/
function geolocation_field_widget_error($element, $error, $form, &$form_state) {
switch ($error['error']) {
case 'geolocation_invalid_lat':
form_error($element['lat'], $error['message']);
break;
case 'geolocation_invalid_lng':
form_error($element['lng'], $error['message']);
break;
}
}
/**
* Helper function. Precalculates values for geolocation field item.
*
* @param array $item
* Geolocation field item with the following keys:
* - lat: (required) Latitude
* - lng: (required) Longitude
*
* @return array
* Geolocation field item with added precalculated values:
* - lat_sin: Latitude sine
* - lat_cos: Latitude cosine
* - lng_rad: Radian longitude
*/
function _geolocation_field_precalculate_values(array $item) {
$item['lat_sin'] = sin(deg2rad($item['lat']));
$item['lat_cos'] = cos(deg2rad($item['lat']));
$item['lng_rad'] = deg2rad($item['lng']);
return $item;
}