openlayers.module in Openlayers 6
Same filename and directory in other branches
Main OpenLayers API File
This file holds the main Drupal hook functions, and the openlayers API functions for the openlayers module.
File
openlayers.moduleView source
<?php
/**
* @defgroup openlayers OpenLayers: Provides an API and Modules to interface with OpenLayers
*
* Provides an API and Modules to interface with OpenLayers. Needs work...
*/
/**
* @defgroup openlayers_api OpenLayers API: Specific functions that are part of the OpenLayers API
*
* Provides an API and Modules to interface with OpenLayers. Needs work...
*/
/**
* @file
* Main OpenLayers API File
*
* This file holds the main Drupal hook functions,
* and the openlayers API functions for the openlayers module.
*
* @ingroup openlayers
*/
/**
* Map ID Prefix
*/
define('OPENLAYERS_MAP_ID_PREFIX', 'openlayers-map-auto-id');
/**
* OpenLayers preset storage constant for user-defined presets in the DB.
*/
define('OPENLAYERS_STORAGE_NORMAL', 0);
/**
* OpenLayers preset storage constant for module-defined presets in code.
*/
define('OPENLAYERS_STORAGE_DEFAULT', 1);
/**
* OpenLayers preset storage constant for user-defined presets that override
* module-defined presets.
*/
define('OPENLAYERS_STORAGE_OVERRIDE', 2);
/**
* Implementation of hook_help().
*/
function openlayers_help($path, $arg) {
$output = '';
switch ($path) {
case 'admin/help#openlayers':
$output = '<p>' . t('The OpenLayers module is the base module for the OpenLayer suite of modules, and provides the main API.') . '</p>';
return $output;
}
}
/**
* Implementation of hook_perm().
*/
function openlayers_perm() {
return array(
'administer openlayers',
);
}
/**
* Implementation of hook_theme().
*/
function openlayers_theme($existing, $type, $theme, $path) {
return array(
'openlayers_map' => array(
'arguments' => array(
'map' => array(),
),
'file' => 'includes/openlayers.theme.inc',
),
'openlayers_vector_styles' => array(
'arguments' => array(
'styles' => array(),
'map' => array(),
),
'file' => 'includes/openlayers.theme.inc',
),
);
}
/**
* Implementation of hook_menu().
*/
function openlayers_menu() {
$items = array();
$items['admin/settings/openlayers'] = array(
'title' => 'OpenLayers',
'description' => 'Main settings for OpenLayers.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'openlayers_admin_settings',
),
'access arguments' => array(
'administer openlayers',
),
'file' => 'includes/openlayers.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/settings/openlayers/settings'] = array(
'title' => 'Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -20,
);
return $items;
}
/**
* Intialize OpenLayers
*
* Make sure that we have everything we need for OpenLayers
*
* @ingroup openlayers_api
* @param $params
* Associative array of pamaters
* (none at the moment)
* @return
* Boolean if intialization was succesful
*/
function openlayers_initialize() {
$success = TRUE;
// Include the OpenLayers JS
// We need to check if it a local path or URL, but really only need to do it once.
static $included = FALSE;
if ($included == FALSE) {
$path = check_plain(variable_get('openlayers_source', 'http://openlayers.org/api/OpenLayers.js'));
// Check for full URL
if (valid_url($path, TRUE)) {
// If URL, we have to manually include it in Drupal
drupal_set_html_head('<script src="' . check_url($path) . '" type="text/javascript"></script>');
}
else {
// Ensure that the JS file is not aggregated with the rest
drupal_add_js($path, 'module', 'header', FALSE, TRUE, FALSE);
}
// Add CSS
drupal_add_css(drupal_get_path('module', 'openlayers') . '/openlayers.css', 'module');
// Add base JS file
drupal_add_js(drupal_get_path('module', 'openlayers') . '/js/openlayers.js', 'module');
$included = TRUE;
}
return $success;
}
/**
* Render Map
*
* Given perimeters, render an OpenLayers map
*
* @ingroup openlayers_api
* @param $map
* Associative array of map paramters
* @param $render
* Boolean whether to fully render (include theme and JS)
*
* @return
* Boolean if successful
*/
function openlayers_render_map($map = array(), $render = TRUE) {
static $map_ids = array();
// Check array
if (!is_array($map) && !is_string($map)) {
return FALSE;
}
// If the map is an empty array or string, then load the default preset.
if (empty($map)) {
$map = openlayers_get_default_map();
}
elseif (is_string($map)) {
$preset = openlayers_get_preset($map);
$map = $preset['preset_data'];
}
// Intialize
if (openlayers_initialize() == FALSE) {
return FALSE;
}
// Include extra rendering functions
module_load_include('inc', 'openlayers', 'includes/openlayers.render');
// Check if any ID
if (!$map['id']) {
$map['id'] = _openlayers_create_map_id();
}
// Check if already used
if (!empty($map_ids[$map['id']])) {
$map['id'] .= '-' . (count($map_ids) + 1);
}
// Track map IDs
$map_ids[$map['id']] = $map['id'];
// Hook for map alteration
drupal_alter('openlayers_map_preprocess', $map);
// Debug pre-render
_openlayers_render_debug_map('pre-render', $map);
// Process layers
$map['layers'] = _openlayers_layers_process($map['layers'], $map);
// Process behaviors
$map['behaviors'] = _openlayers_behaviors_process($map['behaviors'], $map);
// Process styles
$map['styles'] = _openlayers_styles_process($map['styles'], $map);
// A little proxy convienence
if (module_exists('proxy') && !isset($map['proxy_path'])) {
$map['proxy_path'] = base_path() . PROXY_ROUTER_PATH . '?' . PROXY_ROUTER_QUERY_VAR . '=';
}
// Hook for one last alter (this should be changed to _postprocess for 2.x)
drupal_alter('openlayers_map', $map);
// Check our map for errors. If we are rendering it, then log errors.
$errors = openlayers_error_check_map($map, $render);
// Add JS and theme if no errors found
if (!$errors && $render) {
// Add map container to drupal JS settings
$openlayers = array(
'openlayers' => array(
'maps' => array(
$map['id'] => $map,
),
),
);
drupal_add_js($openlayers, 'setting');
// Add themed HTML (no need for it to go to JS)
$map['themed'] = theme('openlayers_map', $map);
// Debug post-render
_openlayers_render_debug_map('post-render', $map);
}
// Return map with or without errors
return $map;
}
/**
* Get Layer Info
*
* Wrapper around layer info hook
*
* @ingroup openlayers_api
* @param $reset
* Boolean whether to reset cache or not
* @return
* array of layer info
*/
function openlayers_layers_get_info($reset = FALSE) {
static $info = NULL;
// If empty or reset, get info
if ($info === NULL || $reset == TRUE) {
$info = module_invoke_all('openlayers_layers_info');
}
return $info;
}
/**
* Get Behavior Info
*
* Wrapper around behavior info hook
*
* @ingroup openlayers_api
* @param $reset
* Boolean whether to reset cache or not
* @return
* array of behavior info
*/
function openlayers_behaviors_get_info($reset = FALSE) {
static $info = NULL;
// If empty or reset, get info
if ($info === NULL || $reset == TRUE) {
$info = module_invoke_all('openlayers_behaviors_info');
}
return $info;
}
/**
* Get Styles Info
*
* Wrapper around styles info hook
*
* @ingroup openlayers_api
* @param $reset
* Boolean whether to reset cache or not
* @return
* array of styles info
*/
function openlayers_styles_get_info($reset = FALSE) {
static $info = NULL;
// If empty or reset, get info
if ($info === NULL || $reset == TRUE) {
$info = module_invoke_all('openlayers_styles_info');
}
return $info;
}
/**
* OpenLayers Save Preset
*
* Given an array of data, save the preset
*
* @ingroup openlayers_api
* @param $preset
* Array of data for preset
* @return
* Boolean of whether successful
*/
function openlayers_save_preset($preset = array()) {
$successful = FALSE;
// Check for name
if (empty($preset['preset_name'])) {
return $successful;
}
// Check the map array for errors
$map_processed = openlayers_render_map($preset['preset_data'], FALSE);
if (isset($map_processed['errors']) && count($map_processed['errors'])) {
foreach ($map_processed['errors'] as $error) {
drupal_set_message($error, 'error');
}
return $successful;
}
// Serialize
$preset['preset_data'] = is_array($preset['preset_data']) ? serialize($preset['preset_data']) : '';
// Check for existing preset
$query = "SELECT preset_id FROM {openlayers_map_presets} WHERE preset_name = '%s'";
$preset_id = db_result(db_query($query, $preset['preset_name']));
// Check id
if (!empty($preset_id)) {
$preset['preset_id'] = $preset_id;
$successful = drupal_write_record('openlayers_map_presets', $preset, 'preset_id');
}
else {
$successful = drupal_write_record('openlayers_map_presets', $preset);
}
return $successful;
}
/**
* OpenLayers Get Preset
*
* Given an a string or integer, get full preset array
*
* @ingroup openlayers_api
* @param $name
* Name of preset
* @param $reset
* Boolean whether to reset cache
* @return
* Array of preset data
*/
function openlayers_get_preset($name = '', $reset = FALSE) {
$preset = array();
// Check for value
if (empty($name)) {
return $preset;
}
// Get presets
$presets = openlayers_get_presets('full', $reset);
$preset = $presets[$name];
if (empty($preset)) {
return array();
}
// Manipulate map
if (!is_array($preset['preset_data'])) {
$preset['preset_data'] = unserialize($preset['preset_data']);
}
// Put preset name into map array for safe keeping
$preset['preset_data']['preset_name'] = $preset['preset_name'];
// Remove any map id or errors
unset($preset['preset_data']['id']);
unset($preset['preset_data']['errors']);
return $preset;
}
/**
* OpenLayers Get Map
*
* Given an a string or integer, get just map array
*
* @ingroup openlayers_api
* @param $name
* The preset name
* @return
* Array of preset data
*/
function openlayers_get_map($name = '') {
// Get preset
$preset = openlayers_get_preset($name);
// Check for data
if (is_array($preset['preset_data'])) {
return $preset['preset_data'];
}
else {
return array();
}
}
/**
* Get Presets Array
*
* Get Presets from DB or code, via cache
*
* @ingroup openlayers_api
* @param $reset
* Boolean whether to reset or not
* @return
* Return formatted data
*/
function openlayers_presets($reset = FALSE) {
static $presets = array();
// If reset, reset cache
if ($reset) {
$presets = array();
cache_clear_all('openlayers:presets', 'cache');
// Clear the content.module cache
// (refreshes the list of formatters)
if (module_exists('content')) {
content_clear_type_cache();
}
}
// Return presets if already exists (page request cache)
if (!empty($presets)) {
return $presets;
}
// Attempt to get presets from cache
if ($cache = cache_get('openlayers:presets', 'cache')) {
$presets = $cache->data;
}
else {
// Get data from hooks
$defaults = module_invoke_all('openlayers_presets');
// Since data from hooks cannot be edited or deleted, we mark now
foreach ($defaults as $name => $preset) {
$preset['type'] = OPENLAYERS_STORAGE_DEFAULT;
$presets[$name] = $preset;
}
// Get data from DB
$db_data = array();
$query = "SELECT * FROM {openlayers_map_presets} ORDER BY preset_title";
$results = db_query($query);
while ($row = db_fetch_array($results)) {
$db_data[$row['preset_name']] = $row;
}
// Check for conflicting preset names, use DB over hook
foreach ($db_data as $name => $preset) {
if (!empty($presets[$name])) {
$preset['type'] = OPENLAYERS_STORAGE_OVERRIDE;
$presets[$name] = $preset;
}
else {
$preset['type'] = OPENLAYERS_STORAGE_NORMAL;
$presets[$name] = $preset;
}
}
// Cache data
cache_set('openlayers:presets', $presets);
}
return $presets;
}
/**
* Get Formatted Presets
*
* Get Presets and formats accordingly
*
* @ingroup openlayers_api
* @param $format
* String to determine format of results
* - simple: 'preset_name' => 'Preset Title'
* - full: 'preset_name' => array( full preset data )
* @param $reset
* Boolean whether to reset or not
* @return
* Return formatted data
*/
function openlayers_get_presets($format = 'simple', $reset = FALSE) {
static $data = array();
static $simple = array();
static $full = array();
// Check if data has already been pulled
// (there should at least be the default)
if (empty($data) || $reset == TRUE) {
$data = openlayers_presets($reset);
}
// Check if format variable has data
if (empty(${$format}) || $reset == TRUE) {
$return = array();
// Go through results
foreach ($data as $name => $preset) {
// Determine how to format data
switch ($format) {
case 'simple':
$return[$preset['preset_name']] = $preset['preset_title'];
break;
case 'full':
$return[$preset['preset_name']] = $preset;
break;
}
}
return $return;
}
else {
return ${$format};
}
}
/**
* Get Default Map
*
* Gets default map as determined by admin setting
*
* @ingroup openlayers_api
* @param $reset
* Boolean whether get cached version or not
* @return
* Map array
*/
function openlayers_get_default_map($reset = FALSE) {
static $preset = array();
static $searched = FALSE;
if (!$searched || $reset) {
// Get preset
$preset = openlayers_get_preset(variable_get('openlayers_default_preset', 'default'));
// If for some reason, we still dont have a map
// try to get just default
if (empty($preset)) {
$preset = openlayers_get_preset('default');
}
$searched = TRUE;
}
// Return map data
return $preset['preset_data'];
}
/**
* Merge Maps
*
* Recursive function to merge maps. PHP's array_merge_recursive
* creates unnecesary arrays to values if keys are the same. This
* function simply overwrites a value, even if the key is numeric.
*
* @ingroup openlayers_api
* @param $map1
* Map array that holds values that are not preferred
* @param $map2
* Map array that holds values that are preferred
* @return
* map array
*/
function openlayers_merge_maps($map1 = array(), $map2 = array()) {
// Check maps
if (is_array($map1) && is_array($map2)) {
foreach ($map2 as $k => $v) {
if (isset($map1[$k]) && is_array($v) && is_array($map1[$k])) {
$map1[$k] = openlayers_merge_maps($map1[$k], $v);
}
else {
$map1[$k] = $v;
}
}
}
return $map1;
}
/**
* Check Map Errors
*
* Checks map array for incompatibilities or errors.
*
* @ingroup openlayers_api
* @param $map
* Map array
* @param $log_errors
* Boolean whether to log erros
* @return
* FALSE if passed. Array of descriptive errors if fail
*/
function openlayers_error_check_map(&$map, $log_errors = TRUE) {
// @TODO: Instead of manually specifying projections, we should do a lookup on the projections in a big table to get variables that it should be checked against.
// @TODO: For next release, make hook
$errors = array();
// Check layer projections
foreach ($map['layers'] as $layer) {
if ($layer['projection']) {
if (!in_array($map['projection'], $layer['projection'])) {
watchdog('openlayers', 'Map Error for %mapid: The layer %layer_name cannot work with the map projection: EPSG: %map_proj', array(
'%mapid' => $map['id'],
'%layer_name' => $layer['name'],
'%map_proj' => $map['projection'],
), WATCHDOG_ERROR);
$errors[] = t('The layer %layer_name cannot work with the map projection: EPSG: %map_proj', array(
'%layer_name' => $layer['name'],
'%map_proj' => $map['projection'],
));
}
}
}
// If we are using a web spherical mercator projection and maxResolution
// and maxExtent are not set the map will not function.
if ($map['projection'] == '900913' || $map['projection'] == '3785') {
if (!$map['options']['maxExtent'] || !$map['options']['maxResolution']) {
watchdog('openlayers', 'Map Error for %mapid: You are using a web spherical mercator projection. However maxExtent or maxResolution are not set.', array(
'%mapid' => $map['id'],
), WATCHDOG_ERROR);
$errors[] = t('You are using a web spherical mercator projection. However maxExtent or maxResolution are not set.');
}
}
// If we are using a degree based projection, then check to make sure
// our bounds are not over 180/90 degrees
if ($map['projection'] == '4326' || $map['projection'] == '4269') {
if ($map['options']['maxExtent']['top'] && $map['options']['maxExtent']['top'] > 90 || $map['options']['maxExtent']['bottom'] && $map['options']['maxExtent']['bottom'] < -90 || $map['options']['maxExtent']['left'] && $map['options']['maxExtent']['left'] < -180 || $map['options']['maxExtent']['right'] && $map['options']['maxExtent']['right'] > 180 || $map['options']['maxResoluton'] && $map['options']['maxResoluton'] > 180) {
watchdog('openlayers', 'Map Error for %mapid: Your Maximum Extents are set greater than 180/90 degrees. Try Maximum Extent of: -180,180,-90,90 and a Maximum Resolution of 1.40625', array(
'%mapid' => $map['id'],
), WATCHDOG_ERROR);
$errors[] = t("Your Maximum Extents are set greater than 180/90 degrees. Try Maximum Extent of: -180,180,-90,90 and a Maximum Resolution of 1.40625");
}
}
// Store the errors in our map array
if (count($errors) > 0) {
// Store the errors in our map array
$map['errors'] = $errors;
}
// Check if errors and return
return count($errors) > 0 ? $errors : FALSE;
}
/**
* Implementation of hook_openlayers_layers_handler_info().
*/
function openlayers_openlayers_layers_handler_info($map = array()) {
return array(
'WMS' => array(
'layer_handler' => 'WMS',
'js_file' => drupal_get_path('module', 'openlayers') . '/js/openlayers.layers.js',
),
'Vector' => array(
'layer_handler' => 'Vector',
'js_file' => drupal_get_path('module', 'openlayers') . '/js/openlayers.layers.js',
),
);
}
/**
* Implementation of hook_openlayers_layers_info().
*/
function openlayers_openlayers_layers_info() {
// Define info array
$info['openlayers_default_wms'] = array(
'name' => t('Default OpenLayers WMS'),
'description' => t('A simple basemap to get you started'),
'file' => drupal_get_path('module', 'openlayers') . '/includes/openlayers.layers.inc',
'callback' => 'openlayers_process_layers',
'projection' => array(
'4326',
'900913',
'4269',
),
'baselayer' => TRUE,
);
return $info;
}
/**
* Implementation of hook_openlayers_styles_info().
*/
function openlayers_openlayers_styles_info() {
// Define info array
$info['default'] = array(
'name' => t('Default Style'),
'description' => t('Basic default style.'),
'file' => drupal_get_path('module', 'openlayers') . '/includes/openlayers.styles.inc',
'callback' => 'openlayers_process_styles',
);
$info['default_select'] = array(
'name' => t('Default Select Style'),
'description' => t('Default style for selected geometries'),
'file' => drupal_get_path('module', 'openlayers') . '/includes/openlayers.styles.inc',
'callback' => 'openlayers_process_styles',
);
return $info;
}
/**
* Implementation of hook_openlayers_presets().
*/
function openlayers_openlayers_presets() {
$presets = array();
// Create map array
$default_map = array(
'projection' => '4326',
'width' => 'auto',
'default_layer' => 'openlayers_default_wms',
'height' => '300px',
'center' => array(
'lat' => '0',
'lon' => '0',
'zoom' => '2',
),
'options' => array(
'displayProjection' => '4326',
),
'controls' => array(
'LayerSwitcher' => TRUE,
'Navigation' => TRUE,
'PanZoomBar' => TRUE,
'MousePosition' => TRUE,
),
);
// Create full preset array
$presets['default'] = array(
'preset_name' => 'default',
'preset_title' => t('Default Map'),
'preset_description' => t('This is the default map preset that comes with the OpenLayers module.'),
'preset_data' => $default_map,
);
return $presets;
}
/**
* Implementation of hook_domainconf().
*
* See http://therickards.com/api/function/hook_domainconf/Domain
* Adds support for per-domain map keys
*/
function openlayers_domainconf() {
module_load_include('inc', 'openlayers', 'includes/openlayers.admin');
// Get form items and return
return _openlayers_settings_form();
}
/**
* Implementation of hook_features_api().
*
* For features integration: provides map presets
* to the features module for programmatic export.
*/
// function openlayers_features_api() {
// return array(
// 'file' => drupal_get_path('module', 'openlayers') . '/includes/openlayers.features.inc',
// 'default_hook' => 'openlayers_get_presets',
// );
// }
Functions
Constants
Name | Description |
---|---|
OPENLAYERS_MAP_ID_PREFIX | Map ID Prefix |
OPENLAYERS_STORAGE_DEFAULT | OpenLayers preset storage constant for module-defined presets in code. |
OPENLAYERS_STORAGE_NORMAL | OpenLayers preset storage constant for user-defined presets in the DB. |
OPENLAYERS_STORAGE_OVERRIDE | OpenLayers preset storage constant for user-defined presets that override module-defined presets. |