geocoder.module in Geocoder 7
Same filename and directory in other branches
File
geocoder.moduleView source
<?php
/**
* @file
* Module file for geocoder module.
*/
include_once 'geocoder.widget.inc';
include_once 'geocoder.services.inc';
define('GEOCODER_GOOGLE_AUTH_NONE', 1);
define('GEOCODER_GOOGLE_AUTH_KEY', 2);
define('GEOCODER_GOOGLE_AUTH_WORK', 3);
/**
* The Geocoder API call.
* TODO.
*/
function geocoder_reverse($handler, $lat, $long, $options = array(), $cache_type = 2, $cache_reset = FALSE) {
ctools_include('plugins');
static $static_cache_reverse = array();
if ($cache_reset) {
$static_cache_reverse = array();
}
if ($cache_type) {
$cache_id = $handler . '_' . md5(serialize(array(
$lat,
$long,
$options,
)));
if (!empty($static_cache_reverse[$cache_id])) {
return $static_cache_reverse[$cache_id];
}
}
$processor = ctools_get_plugins('geocoder', 'geocoder_reverse_handler', $handler);
$address = call_user_func($processor['callback'], $lat, $long, $options);
if ($cache_type) {
$static_cache_reverse[$cache_id] = $address;
}
return $address;
}
/**
* The Geocoder API call.
*
* Given a handler and data, geocode the data into a geometry object using the handler.
*
* @param string $handler
* The geocoder handler to use. Call geocoder_handler_info() to get a list.
* @param mixed $data
* Data to be passed into the handler for geocoding. For example a address string.
* @param array $options
* Additional options to pass to the handler. Exact key / values to pass depend on the handler.
* @param int $cache_type
* DEPRECATED. All results are cached persistently.
* @param bool $cache_reset
* (optional) Ignore potentially matched cache record, and live fetch. Defaults to FALSE.
*
* @return Geometry
* Returns a geoPHP geometry object. Generally a Point.
* See http://drupal.org/project/geoPHP and https://github.com/phayes/geoPHP/wiki/API-Reference
*
* @example:
* geocoder('google','4925 Gair Ave, Terrace, BC');
* geocoder('google','New York City',array('geometry_type' => 'bounds'));
*/
function geocoder($handler, $data, $options = array(), $cache_type = 'DEPRECATED', $cache_reset = FALSE) {
ctools_include('plugins');
$processor = ctools_get_plugins('geocoder', 'geocoder_handler', $handler);
if (!$processor) {
return NULL;
}
// Attempt to retrieve from persistent cache.
$geometry = $cache_reset ? NULL : geocoder_cache_get($handler, $data, $options);
// No cache record, so fetch live.
if ($geometry === NULL) {
try {
// Load the file.
geocoder_get_handler($handler);
$geometry = call_user_func($processor['callback'], $data, $options);
} catch (Exception $e) {
watchdog_exception('geocoder', $e);
return NULL;
}
// Always save result into persistent cache.
geocoder_cache_set($geometry, $handler, $data, $options);
}
if (!$geometry && variable_get('geocoder_log_empty_results', FALSE)) {
watchdog('geocoder', t('No results for geocoding @data', array(
'@data' => $data,
)));
}
return $geometry;
}
/**
* Implements hook_menu().
*/
function geocoder_menu() {
// Admin settings for the site.
$items['admin/config/content/geocoder'] = array(
'title' => 'Geocoder settings',
'description' => 'Configuration for API keys and other global settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'geocoder_admin_settings',
),
'file' => 'geocoder.admin.inc',
'access arguments' => array(
'administer site configuration',
),
// Optional.
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['geocoder/service/%'] = array(
'title' => 'AJAX / AJAJ geocoding service',
'description' => 'Provides basic callback for geocoding using JavaScript',
'page callback' => 'geocoder_service_callback',
'page arguments' => array(
2,
),
'type' => MENU_CALLBACK,
'access arguments' => array(
arg(2),
),
'access callback' => 'geocoder_service_check_perms',
);
return $items;
}
/**
* Geocoder Handler Information.
*
* Return a list of all handlers that might geocode something for you.
* Optionally you may pass a field-type and get back a list of
* handlers that are compatible with that field.
*/
function geocoder_handler_info($field_type = NULL) {
ctools_include('plugins');
static $handlers;
if (!$handlers) {
$handlers = ctools_get_plugins('geocoder', 'geocoder_handler');
}
if ($field_type) {
$field_handlers = $handlers;
foreach ($field_handlers as $i => $handler) {
if (!isset($handler['field_types']) || !in_array($field_type, $handler['field_types'], TRUE)) {
unset($field_handlers[$i]);
}
}
return $field_handlers;
}
return $handlers;
}
/**
* Fetch geocoder handler.
*
* Given a name, fetch the full handler definition.
*/
function geocoder_get_handler($handler_name) {
$handlers = geocoder_handler_info();
if (isset($handlers[$handler_name])) {
require_once $handlers[$handler_name]['path'] . '/' . $handlers[$handler_name]['file'];
return $handlers[$handler_name];
}
return FALSE;
}
/**
* Get supported field types.
*
* Get a list of supported field types along with the processors that support them.
*/
function geocoder_supported_field_types() {
$supported = array();
$processors = geocoder_handler_info();
foreach ($processors as $processor) {
if (isset($processor['field_types'])) {
foreach ($processor['field_types'] as $field_type) {
$supported[$field_type][] = $processor['name'];
}
}
}
return $supported;
}
/**
* Implementation of hook_ctools_plugin_api().
*/
function geocoder_ctools_plugin_api() {
return array(
'version' => 1,
);
}
/**
* Implementation of hook_ctools_plugin_directory() to let the system know
* we implement plugins.
*/
function geocoder_ctools_plugin_directory($module, $plugin) {
return 'plugins/' . $plugin;
}
/**
* Implements hook_ctools_plugin_type.
*/
function geocoder_ctools_plugin_type() {
return array(
'geocoder_handler' => array(
'cache' => TRUE,
),
'geocoder_reverse_handler' => array(),
);
}
// These functions have to do with providing AJAX / AHAH
// service functionality so that users can make use of
// geocoder interactively via JavaScript.
/**
* Implements hook_permission().
*
* We define permissions for accessing geocoder over AJAX / services.
* There is one global permission which gives access to everything,
* and one permission per handler. The site-administrator can therefore
* fine tune which handlers are accessible. Note that to use AJAX with
* geocoder these permissions need to be set.
*/
function geocoder_permission() {
$handler_info = geocoder_handler_info();
$perms = array(
'geocoder_service_all_handlers' => array(
'title' => t('Can use all Geocoder handlers through AJAX / service'),
),
);
foreach ($handler_info as $name => $handler) {
$perms['geocoder_service_handler_' . $name] = array(
'title' => t('Can geocode using @handler through AJAX / service', array(
'@handler' => $handler['title'],
)),
);
}
return $perms;
}
/**
* Geocoder service check permissions.
*
* Given a handler, check to see if the user has
* permission to execute it via AJAX / services.
*/
function geocoder_service_check_perms($handler) {
return user_access('geocoder_service_all_handlers') || user_access('geocoder_service_handler_' . $handler);
}
/**
* Page callback for AJAX / Geocoder service.
*
* This service can be accessed at /geocoder/service/<handler>
* and takes the query-parameter "data". Optionally a "output"
* parameter may also be passed. "output" corresponds to
* geoPHP output formats.
*
* Some examples:
* /geocoder/service/google?data=4925 Gair Ave, Terrace, BC
* /geocoder/service/wkt?data=POINT(10 10)
* /geocoder/service/yahoo?data=94112&output=wkt
*/
function geocoder_service_callback($handler) {
if (!isset($_GET['data'])) {
throw new Exception(t('No data parameter found'));
exit;
}
$format = isset($_GET['output']) ? $_GET['output'] : 'json';
geophp_load();
geocoder_service_check_request($handler, $format);
$geom = geocoder($handler, $_GET['data']);
header('Content-Type: ' . geocoder_service_get_content_type($format));
print $geom
->out($format);
exit;
}
/**
* Get Content-Type for an output format.
*
* Given an output format, this helper function passes
* a compatible HTTP content-type to be placed in the
* header.
*/
function geocoder_service_get_content_type($format) {
$types = array(
'json' => 'application/json',
'kml' => 'application/xml',
'georss' => 'application/xml',
'gpx' => 'application/xml',
'wkt' => 'text/plain',
'wkb' => 'text/plain',
'google_geocode' => 'text/plain',
);
return $types[$format];
}
/**
* Geocoder Service Check Request.
*
* Check to make sure the request to the service is valid. This
* checks to make sure the handler and the format exists, and
* also checks permission.
*/
function geocoder_service_check_request($handler, $format, $check_ac = TRUE) {
if (!geocoder_get_handler($handler)) {
drupal_set_message(t('Could not find handler @handler', array(
'@handler' => $handler,
)), 'error');
drupal_not_found();
exit;
}
if ($format && $format !== 'default' && !in_array($format, array_keys(geoPHP::getAdapterMap()), TRUE)) {
throw new Exception(t('Could not find output-format @format', array(
'@format' => $format,
)), 'error');
exit;
}
if (!geocoder_service_check_perms($handler)) {
drupal_access_denied();
exit;
}
}
/**
* Create a unified cache id from relevant cache data.
*/
function _geocoder_cache_cid($data) {
ksort($data);
return sha1(serialize($data));
}
/**
* Retrieve a cached geocoded location.
*
* @param string $handler
* The handler used to geocode this data.
* @param mixed $data
* The data used to fetch live geo data.
* @param array $options
* Handler-specific options that have effect on the result.
*
* @return Geometry
* A Geometry object, FALSE (no result), or NULL (no cache).
*/
function geocoder_cache_get($handler, $data, $options) {
$data = compact('handler', 'data', 'options');
$cid = _geocoder_cache_cid($data);
geophp_load();
if ($cache = cache_get($cid, 'cache_geocoder')) {
return $cache->data['geometry'];
}
}
/**
* Cache a geocoded result.
*
* @param mixed $geometry
* A Geometry object, or FALSE (no result).
* @param string $handler
* The handler used to geocode this data.
* @param mixed $data
* The data used to fetch live geo data.
* @param array $options
* Handler-specific options that have effect on the result.
*/
function geocoder_cache_set($geometry, $handler, $data, $options) {
// Don't cache no-results, to live geocode the same data again next time.
if (!$geometry && !variable_get('geocoder_cache_empty_results', TRUE)) {
return;
}
// Construct the cache id from result-relevant parameters.
$data = compact('handler', 'data', 'options');
$cid = _geocoder_cache_cid($data);
// Cache result-relevant parameters together with the actual result, so cache records can be traced.
$data['geometry'] = $geometry ? $geometry : FALSE;
cache_set($cid, $data, 'cache_geocoder', variable_get('geocoder_cache_ttl', CACHE_PERMANENT));
}
/**
* Implements hook_flush_caches().
*/
function geocoder_flush_caches() {
return array(
'cache_geocoder',
);
}
Functions
Name![]() |
Description |
---|---|
geocoder | The Geocoder API call. |
geocoder_cache_get | Retrieve a cached geocoded location. |
geocoder_cache_set | Cache a geocoded result. |
geocoder_ctools_plugin_api | Implementation of hook_ctools_plugin_api(). |
geocoder_ctools_plugin_directory | Implementation of hook_ctools_plugin_directory() to let the system know we implement plugins. |
geocoder_ctools_plugin_type | Implements hook_ctools_plugin_type. |
geocoder_flush_caches | Implements hook_flush_caches(). |
geocoder_get_handler | Fetch geocoder handler. |
geocoder_handler_info | Geocoder Handler Information. |
geocoder_menu | Implements hook_menu(). |
geocoder_permission | Implements hook_permission(). |
geocoder_reverse | The Geocoder API call. TODO. |
geocoder_service_callback | Page callback for AJAX / Geocoder service. |
geocoder_service_check_perms | Geocoder service check permissions. |
geocoder_service_check_request | Geocoder Service Check Request. |
geocoder_service_get_content_type | Get Content-Type for an output format. |
geocoder_supported_field_types | Get supported field types. |
_geocoder_cache_cid | Create a unified cache id from relevant cache data. |