View source
<?php
module_load_include('inc', 'geofield', 'geofield.elements');
module_load_include('inc', 'geofield', 'geofield.widgets');
module_load_include('inc', 'geofield', 'geofield.formatters');
module_load_include('inc', 'geofield', 'geofield.openlayers');
module_load_include('inc', 'geofield', 'geofield.feeds');
module_load_include('inc', 'geofield', 'geofield.apachesolr');
module_load_include('inc', 'geofield', 'geofield.schemaorg');
module_load_include('inc', 'geofield', 'geofield.microdata');
define('GEOFIELD_GEOHASH_LENGTH', 16);
$geofield_geom_schema = TRUE;
function geofield_field_info() {
return array(
'geofield' => array(
'label' => 'Geofield',
'description' => t('This field stores geo information.'),
'default_widget' => 'geofield_wkt',
'default_formatter' => 'geofield_wkt',
'settings' => array(
'srid' => '4326',
'backend' => 'default',
),
'property_type' => 'geofield',
'property_callbacks' => array(
'geofield_property_info_callback',
),
'microdata' => TRUE,
),
);
}
function geofield_field_update_field($field, $prior_field, $has_data) {
if ($field['type'] == 'geofield') {
$backend = ctools_get_plugins('geofield', 'geofield_backend', $field['settings']['backend']);
if (!empty($backend['update_field'])) {
$postinstall_callback = $backend['update_field'];
$postinstall_callback($field, $prior_field, $has_data);
}
}
}
function geofield_field_update_instance($instance, $prior_instance) {
if (!empty($instance['widget']['type']) && !empty($prior_instance['widget']['type']) && $instance['widget']['type'] != $prior_instance['widget']['type']) {
$instance['default_value'] = array();
_field_write_instance($instance, TRUE);
field_cache_clear();
}
}
function geofield_field_delete_field($field) {
if ($field['type'] == 'geofield') {
$backend = ctools_get_plugins('geofield', 'geofield_backend', $field['settings']['backend']);
if (!empty($backend['delete_field'])) {
$delete_field_callback = $backend['delete_field'];
$delete_field_callback($field);
}
}
}
function geofield_field_settings_form($field, $instance, $has_data) {
ctools_include('plugins');
$settings = $field['settings'];
$backend_options = array();
$backends = ctools_get_plugins('geofield', 'geofield_backend');
foreach ($backends as $id => $backend) {
if (isset($backend['requirements'])) {
if ($backend['requirements']) {
$callback = $backend['requirements'];
$error = '';
if (!$callback($error)) {
$form['backend_error'][] = array(
'#markup' => '<div class="geofield-backend-error">' . $backend['title'] . ' not usable because ' . $error . '</div>',
);
continue;
}
}
}
$backend_options[$id] = $backend['title'];
}
$form['backend'] = array(
'#type' => 'select',
'#title' => 'Storage Backend',
'#default_value' => $settings['backend'],
'#options' => $backend_options,
'#description' => "Select the Geospatial storage backend you would like to use to store geofield geometry data. If you don't know what this means, select 'Default'.",
'#disabled' => $has_data,
);
$form['settings'] = array(
'#tree' => TRUE,
);
foreach ($backends as $id => $backend) {
if (isset($backend['settings'])) {
if ($backend['settings']) {
$callback = $backend['settings'];
$form[$id] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => $backend['title'] . ' Settings',
'#states' => array(
'visible' => array(
':input[name="field[settings][backend]"]' => array(
'value' => $id,
),
),
),
);
$form[$id] = array_merge($form[$id], $callback($field, $instance, $has_data));
}
}
}
return $form;
}
function geofield_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
ctools_include('plugins');
$backend = ctools_get_plugins('geofield', 'geofield_backend', $field['settings']['backend']);
foreach ($items as $delta => $item) {
$geom_empty = geofield_geom_is_empty($item);
if ($instance['required'] && $geom_empty) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'data_missing',
'message' => t('%name is required and must not be empty.', array(
'%name' => $instance['label'],
)),
);
}
else {
if ($geom_empty) {
return FALSE;
}
else {
$error = geofield_validate_geom($item);
if ($error) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'data_faulty',
'message' => t('%name: Specified location data is invalid.', array(
'%name' => $instance['label'],
)),
);
}
if (!empty($backend['validate'])) {
$validate_callback = $backend['validate'];
$error = $validate_callback($item);
if ($error) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'data_faulty',
'message' => t('%name: Specified location data is invalid.', array(
'%name' => $instance['label'],
)),
);
}
}
}
}
}
}
function geofield_validate_geom($item) {
if (is_string($item)) {
try {
$values = geofield_compute_values($item);
} catch (Exception $e) {
return $e;
}
}
else {
try {
$input_format = !empty($item['input_format']) ? $item['input_format'] : NULL;
$values = geofield_compute_values($item['geom'], $input_format);
} catch (Exception $e) {
return $e;
}
}
return NULL;
}
function geofield_geom_is_empty($item) {
if (!empty($item['input_format'])) {
switch ($item['input_format']) {
case 'wkt':
if (empty($item['geom'])) {
return TRUE;
}
break;
case 'lat/lon':
if (empty($item['geom']['lat']) || empty($item['geom']['lon'])) {
return TRUE;
}
break;
case 'bounds':
if (empty($item['geom']['top']) || empty($item['geom']['right']) || empty($item['geom']['bottom']) || empty($item['geom']['left'])) {
return TRUE;
}
break;
case 'json':
if (empty($item['geom'])) {
return TRUE;
}
break;
}
}
else {
return empty($item['geom']);
}
}
function geofield_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
if ($field['type'] === 'geofield') {
if ($instance['required'] == 0 && empty($items)) {
$entity_ids = entity_extract_ids($entity_type, $entity);
if (empty($entity_ids[0])) {
$items = isset($instance['default_value']) ? array(
$instance['default_value'],
) : array();
}
}
ctools_include('plugins');
$backend = ctools_get_plugins('geofield', 'geofield_backend', $field['settings']['backend']);
$save_callback = $backend['save'];
foreach ($items as $delta => $item) {
$items[$delta] = geofield_compute_values($item);
if (isset($items[$delta]['geom']) && $items[$delta]['geom']) {
$items[$delta]['geom'] = $save_callback($items[$delta]['geom']);
}
}
}
}
function geofield_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
geophp_load();
if (geoPHP::geosInstalled()) {
$reader = new GEOSWKBReader();
$writer = new GEOSWKTWriter();
$writer
->setTrim(TRUE);
foreach ($entities as $id => $entity) {
foreach ($items[$id] as $delta => $item) {
if (!empty($item['geom'])) {
$raw_geom = unpack('H*', $item['geom']);
try {
$geom = $reader
->readHEX($raw_geom[1]);
$items[$id][$delta]['geom'] = $writer
->write($geom);
} catch (Exception $e) {
watchdog(WATCHDOG_ERROR, 'Cannot render poorly formatted WKB value %message', array(
'%message' => $e
->getMessage(),
));
}
}
}
}
}
else {
foreach ($entities as $id => $entity) {
foreach ($items[$id] as $delta => $item) {
if (!empty($item['geom'])) {
$geom = geophp::load($item['geom']);
if ($geom) {
$items[$id][$delta]['geom'] = $geom
->out('wkt');
}
}
}
}
}
}
function geofield_field_is_empty($item, $field) {
if (isset($item['input_format'])) {
switch ($item['input_format']) {
case GEOFIELD_INPUT_LAT_LON:
return trim($item['geom']['lat']) == '' || trim($item['geom']['lon']) == '';
case GEOFIELD_INPUT_BOUNDS:
return trim($item['geom']['top']) == '' || trim($item['geom']['right']) == '' || trim($item['geom']['bottom']) == '' || trim($item['geom']['left']) == '';
}
}
return empty($item['geom']);
}
function geofield_views_api() {
return array(
'api' => '3.0',
'path' => drupal_get_path('module', 'geofield') . '/views',
);
}
function geofield_ctools_plugin_type() {
return array(
'geofield_backend' => array(),
'behaviors' => array(
'use hooks' => TRUE,
),
);
}
function geofield_ctools_plugin_api($module, $api) {
return array(
'version' => 1,
);
}
function geofield_ctools_plugin_directory($module, $plugin) {
if ($plugin == 'geofield_backend') {
return 'includes/' . $plugin;
}
}
function geofield_compute_values($raw_data, $input_format = NULL) {
if (empty($raw_data)) {
return array();
}
$geophp = geophp_load();
if (!$geophp) {
drupal_set_message(t("Unable to load geoPHP library. Not all values will be calculated correctly"), 'error');
return;
}
$geometry = geofield_geometry_from_values($raw_data, $input_format);
if (!empty($geometry)) {
$values = geofield_get_values_from_geometry($geometry);
}
else {
$values = array();
}
return $values;
}
function geofield_geometry_from_values($raw_data, $input_format = NULL) {
$geophp = geophp_load();
if (!$geophp) {
drupal_set_message(t("Unable to load geoPHP library. Not all values will be calculated correctly"), 'error');
return;
}
if (is_array($raw_data)) {
if (!empty($raw_data['input_format'])) {
if ($raw_data['input_format'] == GEOFIELD_INPUT_LAT_LON) {
$geometry = new Point($raw_data['geom']['lon'], $raw_data['geom']['lat']);
}
elseif ($raw_data['input_format'] == GEOFIELD_INPUT_BOUNDS) {
$wkt_bounds_format = 'POLYGON((left bottom,right bottom,right top,left top,left bottom))';
$wkt = strtr($wkt_bounds_format, array(
'top' => $raw_data['geom']['top'],
'right' => $raw_data['geom']['right'],
'bottom' => $raw_data['geom']['bottom'],
'left' => $raw_data['geom']['left'],
));
$geometry = geoPHP::load($wkt);
}
else {
$geometry = geoPHP::load($raw_data['geom'], $raw_data['input_format']);
}
}
else {
if (!empty($raw_data['geom'])) {
$geometry = geoPHP::load($raw_data['geom']);
}
elseif (!empty($raw_data['lat']) && !empty($raw_data['lon'])) {
$geometry = new Point($raw_data['lon'], $raw_data['lat']);
}
}
}
else {
if ($input_format) {
$geometry = geoPHP::load($raw_data, $input_format);
}
else {
$geometry = geoPHP::load($raw_data);
}
}
if (isset($geometry)) {
return $geometry;
}
}
function geofield_get_values_from_geometry($geometry) {
$values = array();
$centroid = $geometry
->getCentroid();
$bounding = $geometry
->getBBox();
$values['geom'] = $geometry
->out('wkb');
$values['geo_type'] = drupal_strtolower($geometry
->getGeomType());
if ($centroid) {
$values['lat'] = $centroid
->y();
$values['lon'] = $centroid
->x();
}
$values['top'] = $bounding['maxy'];
$values['bottom'] = $bounding['miny'];
$values['right'] = $bounding['maxx'];
$values['left'] = $bounding['minx'];
$values['geohash'] = substr($geometry
->out('geohash'), 0, GEOFIELD_GEOHASH_LENGTH);
return $values;
}
function geofield_latlon_DMStoDEC($dms) {
if (is_numeric($dms)) {
return $dms;
}
if (stripos($dms, 'H') !== FALSE && stripos($dms, 'M') !== FALSE) {
$dms = strtr($dms, "'\"HOURSMINTECNDAhoursmintecnda", " ");
$dms = preg_replace('/\\s\\s+/', ' ', $dms);
$dms = explode(" ", $dms);
$deg = $dms[0];
$min = $dms[1];
$sec = $dms[2];
$dec = floatval($deg * 15 + $min / 4 + $sec / 240);
return $dec;
}
if (stripos($dms, 'S') !== FALSE || stripos($dms, 'W') !== FALSE) {
$direction = -1;
}
else {
$direction = 1;
}
$dms = strtr($dms, "�'\"NORTHSEAWnorthseaw'", " ");
$dms = preg_replace('/\\s\\s+/', ' ', $dms);
$dms = explode(" ", $dms);
$deg = $dms[0];
$min = $dms[1];
$sec = $dms[2];
$dec = floatval($deg + ($min * 60 + $sec) / 3600);
if ($dec > 0) {
$dec = $direction * $dec;
}
return $dec;
}
function geofield_latlon_DECtoDMS($dec, $axis) {
if ($axis == 'lat') {
if ($dec < 0) {
$direction = 'S';
}
else {
$direction = 'N';
}
}
if ($axis == 'lon') {
if ($dec < 0) {
$direction = 'W';
}
else {
$direction = 'E';
}
}
$vars = explode(".", $dec);
$deg = abs($vars[0]);
if (isset($vars[1])) {
$tempma = "0." . $vars[1];
}
else {
$tempma = "0";
}
$tempma = $tempma * 3600;
$min = floor($tempma / 60);
$sec = $tempma - $min * 60;
return $deg . "° " . $min . "' " . round($sec, 3) . "\" " . $direction;
}
function geofield_latlon_DECtoCCS($dec, $axis) {
if ($axis == 'lat') {
$vars = explode(".", $dec);
$deg = $vars[0];
if (isset($vars[1])) {
$tempma = "0." . $vars[1];
}
else {
$tempma = "0";
}
$tempma = $tempma * 3600;
$min = floor($tempma / 60);
$sec = $tempma - $min * 60;
return $deg . "° " . $min . "' " . round($sec, 3) . "\"";
}
if ($axis == 'lon') {
$tempma = $dec / 15;
$vars = explode(".", $tempma);
$hrs = $vars[0];
if (isset($vars[1])) {
$tempma = "0." . $vars[1];
}
else {
$tempma = "0";
}
$tempma = $tempma * 60;
$vars = explode(".", $tempma);
$min = $vars[0];
if (isset($vars[1])) {
$tempma = "0." . $vars[1];
}
else {
$tempma = "0";
}
$sec = $tempma * 60;
return $hrs . "h " . $min . "m " . round($sec, 3) . "s";
}
}
function geofield_haversine($options = array()) {
$formula = '( :earth_radius * ACOS( COS( RADIANS(:origin_latitude) ) * COS( RADIANS(:destination_latitude) ) * COS( RADIANS(:destination_longitude) - RADIANS(:origin_longitude) ) + SIN( RADIANS(:origin_latitude) ) * SIN( RADIANS(:destination_latitude) ) ) )';
foreach ($options as $key => $option) {
if (is_numeric($option)) {
$formula = str_replace(':' . $key, $option, $formula);
}
else {
$formula = str_replace(':' . $key, db_escape_field($option), $formula);
}
}
return $formula;
}
function _geofield_get_geofield_fields() {
$geofield_fields = array();
$fields = field_info_fields();
foreach ($fields as $field => $info) {
if ($info['type'] == 'geofield') {
$geofield_fields[$field] = $info;
}
}
return $geofield_fields;
}