| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- <?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)));
- 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');
- }
|