1180 lines
30 KiB
Plaintext
1180 lines
30 KiB
Plaintext
<?php
|
|
|
|
/**
|
|
* @defgroup openlayers OpenLayers provides an API and
|
|
* Modules to interface with OpenLayers
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Main OpenLayers API File
|
|
*
|
|
* This file holds the main Drupal hook functions,
|
|
* and the openlayers API functions for the openlayers module.
|
|
*
|
|
* @ingroup openlayers
|
|
*/
|
|
|
|
/**
|
|
* OpenLayers hosted default library.
|
|
*/
|
|
define('OPENLAYERS_DEFAULT_LIBRARY', 'http://openlayers.org/api/2.12/OpenLayers.js');
|
|
|
|
/**
|
|
* OpenLayers library compatible suggestion.
|
|
*/
|
|
define('OPENLAYERS_SUGGESTED_LIBRARY', 2.12);
|
|
|
|
/**
|
|
* OpenLayers hosted API version. What version is used when going to
|
|
* http://openlayers.org/api/OpenLayers.js
|
|
*/
|
|
define('OPENLAYERS_HOSTED_API_LIBRARY', 2.12);
|
|
|
|
/**
|
|
* Implements hook_help().
|
|
*/
|
|
function openlayers_help($path, $arg) {
|
|
switch ($path) {
|
|
case 'admin/help#openlayers':
|
|
return '<p>' . t('The OpenLayers module is the base module for the
|
|
OpenLayers suite of modules, and provides the main API.') . '</p>';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Implements hook_theme().
|
|
*/
|
|
function openlayers_theme($existing, $type, $theme, $path) {
|
|
return array(
|
|
'openlayers_map' => array(
|
|
'arguments' => array(
|
|
'map' => array(),
|
|
),
|
|
'file' => 'includes/openlayers.theme.inc',
|
|
'template' => '/templates/openlayers-map'
|
|
),
|
|
'openlayers_styles' => array(
|
|
'arguments' => array(
|
|
'styles' => array(),
|
|
'map' => array(),
|
|
),
|
|
'file' => 'includes/openlayers.theme.inc',
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Implements hook_ctools_plugin_directory().
|
|
*/
|
|
function openlayers_ctools_plugin_directory($module, $plugin) {
|
|
if ($plugin == 'content_types' && !empty($plugin)) {
|
|
return 'includes/' . $plugin;
|
|
}
|
|
if ($module == 'openlayers' && !empty($plugin)) {
|
|
return 'plugins/' . $plugin;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_ctools_plugin_type().
|
|
*/
|
|
function openlayers_ctools_plugin_type() {
|
|
// For backwards compatability, we allow for the use
|
|
// of hooks to define these plugins.
|
|
//
|
|
// This should be removed in 7.x-3.x
|
|
return array(
|
|
'behaviors' => array(
|
|
'use hooks' => TRUE,
|
|
'classes' => array('behavior'),
|
|
),
|
|
'layer_types' => array(
|
|
'use hooks' => TRUE,
|
|
'classes' => array('layer_types'),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Include necessary CSS and JS for rendering maps
|
|
*
|
|
* @ingroup openlayers_api
|
|
*/
|
|
function openlayers_include() {
|
|
// Use a static variable to prevent running URL check code repeatedly.
|
|
static $once;
|
|
if (!isset($once)) {
|
|
$once = TRUE;
|
|
|
|
$path = check_plain(variable_get('openlayers_source', OPENLAYERS_DEFAULT_LIBRARY));
|
|
|
|
// Correctly handle URLs beginning with a double backslash, see RFC 1808 Section 4
|
|
if (substr($path, 0, 2) == '//') {
|
|
$http_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
|
$path = $http_protocol .':'. $path;
|
|
}
|
|
|
|
// Check for full URL and include it manually if external.
|
|
if (valid_url($path, TRUE)) {
|
|
drupal_add_js($path, 'external');
|
|
}
|
|
else {
|
|
drupal_add_js($path);
|
|
}
|
|
|
|
drupal_add_css(drupal_get_path('module', 'openlayers') .
|
|
'/css/openlayers.css', 'file');
|
|
drupal_add_js(drupal_get_path('module', 'openlayers') .
|
|
'/js/openlayers.js', 'file');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare a map for rendering.
|
|
*
|
|
* Takes a map array and builds up the data given the
|
|
* reference to objects like styles, layers, and behaviors.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $map
|
|
* Array of map settings
|
|
* @return
|
|
* Filled in map array.
|
|
*/
|
|
function openlayers_build_map($map = array()) {
|
|
// Get the necessary parts
|
|
openlayers_include();
|
|
module_load_include('inc', 'openlayers', 'includes/openlayers.render');
|
|
|
|
// If no map is specified, use the default map.
|
|
if (empty($map)) {
|
|
if ($loaded_map = openlayers_map_load(
|
|
variable_get('openlayers_default_map', 'default'))) {
|
|
$map = $loaded_map->data;
|
|
}
|
|
}
|
|
|
|
// Create ID for map as this will help with alters.
|
|
$map['id'] = !isset($map['id']) ?
|
|
_openlayers_create_map_id() : $map['id'];
|
|
|
|
// Hook to alter map before main processing. Styles, behaviors,
|
|
// layers may all be added here.
|
|
// hook_openlayers_map_preprocess_alter($map)
|
|
drupal_alter('openlayers_map_preprocess', $map);
|
|
|
|
// Styles and layer styles are not required parameters
|
|
$map['styles'] = isset($map['styles']) ? $map['styles'] : array();
|
|
$map['layer_styles'] = isset($map['layer_styles']) ? $map['layer_styles'] : array();
|
|
$map['layer_styles_select'] = isset($map['layer_styles_select']) ? $map['layer_styles_select'] : array();
|
|
|
|
// Process map parts.
|
|
$map['layers'] = _openlayers_layers_process($map['layers'], $map);
|
|
$map['behaviors'] = _openlayers_behaviors_render($map['behaviors'], $map);
|
|
$map['styles'] = _openlayers_styles_process($map['styles'], $map['layer_styles'], $map['layer_styles_select'], $map);
|
|
|
|
// Hook to alter map one last time. Final modification to existing
|
|
// styles, behaviors, layers can happen here, but adding new styles,
|
|
// behaviors will not get rendered.
|
|
// hook_openlayers_map_alter($map)
|
|
drupal_alter('openlayers_map', $map);
|
|
|
|
// Check map for errors
|
|
$map['errors'] = openlayers_error_check_map($map);
|
|
return $map;
|
|
}
|
|
|
|
/**
|
|
* Render map array
|
|
*
|
|
* Given a map array, render into HTML to display
|
|
* a map.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $map
|
|
* Associative array of map paramters.
|
|
* @return
|
|
* Map HTML.
|
|
*/
|
|
function openlayers_render_map_data($map = array()) {
|
|
// Run map through build process
|
|
$map = openlayers_build_map($map);
|
|
$output = '';
|
|
|
|
// Given hide_empty_map flag, check if the map has any features
|
|
// defined. If not, assume it is an empty map and shouldn't be displayed.
|
|
if (isset($map['hide_empty_map']) && $map['hide_empty_map'] == TRUE) {
|
|
$empty = TRUE;
|
|
foreach ($map['layers'] as $layer) {
|
|
if (isset($layer['features']) && count($layer['features'])) {
|
|
$empty = FALSE;
|
|
}
|
|
}
|
|
if ($empty) {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
// Return themed map if no errors found
|
|
if (empty($map['errors'])) {
|
|
$js = array('openlayers' => array('maps' => array($map['id'] => $map)));
|
|
drupal_add_js($js, 'setting');
|
|
|
|
// Push map through theme function and return
|
|
$output = theme('openlayers_map', array(
|
|
'map' => $map,
|
|
));
|
|
}
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Render a map by name
|
|
*
|
|
* Given a map name render it into a full map object.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $map
|
|
* Name of the map
|
|
* @return
|
|
* Map HTML.
|
|
*/
|
|
function openlayers_render_map($map = '') {
|
|
|
|
// If it's an array, then we have been passed the map data array
|
|
if (is_array($map)) {
|
|
return openlayers_render_map_data($map);
|
|
}
|
|
|
|
// If it's a string, then we are passing a map name instead of the whole map object
|
|
// so we need to load the object
|
|
if (!$map || is_string($map)) {
|
|
$map_name = $map;
|
|
if (!$map_name) {
|
|
$map_name = variable_get('openlayers_default_map', 'default');
|
|
}
|
|
$map = openlayers_map_load($map_name);
|
|
}
|
|
|
|
return openlayers_render_map_data($map->data);
|
|
}
|
|
|
|
/**
|
|
* Get layer object
|
|
*
|
|
* @ingroup openlayers_api
|
|
* @param $reset
|
|
* Boolean whether to reset cache or not
|
|
* @return array
|
|
* array of layer info
|
|
*/
|
|
function openlayers_get_layer_object($layer, $map = array()) {
|
|
// Static cache because this function will possibly be called in big loops
|
|
static $layer_types;
|
|
if (!isset($layer_types)) {
|
|
$layer_types = openlayers_layer_types();
|
|
}
|
|
|
|
$layer->title = t($layer->title);
|
|
$layer->description = t($layer->description);
|
|
|
|
// Attempt to get ctool class
|
|
if (isset($layer_types[$layer->data['layer_type']]) &&
|
|
$class = ctools_plugin_get_class(
|
|
$layer_types[$layer->data['layer_type']],
|
|
'layer_type')
|
|
) {
|
|
$layer_object = new $class($layer, $map);
|
|
return $layer_object;
|
|
}
|
|
else {
|
|
watchdog('openlayers', 'Layer !layer_name is unavailable because its
|
|
layer type or the module that provides its layer type is missing',
|
|
array('!layer_name' => $layer->title),
|
|
WATCHDOG_ERROR);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Menu loader for layers. (%openlayers_layer)
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $name
|
|
* Layer name
|
|
* @return array
|
|
* Layer export
|
|
*/
|
|
function openlayers_layer_load($name, $reset = FALSE) {
|
|
ctools_include('export');
|
|
if ($reset) ctools_export_load_object_reset('openlayers_layers');
|
|
$layer = ctools_export_load_object('openlayers_layers', 'names', array($name));
|
|
|
|
if (is_array($layer) && isset($layer[$name])) {
|
|
$layer_object = openlayers_get_layer_object($layer[$name]);
|
|
if (openlayers_layer_sanity_check($layer_object)) {
|
|
// Automatic layer load for layers.
|
|
/*
|
|
$definitions = ctools_get_plugins('openlayers', 'layer_types');
|
|
$type = get_class($layer_object);
|
|
$base = basename($definitions[$type]['file'], '.inc');
|
|
$js = $definitions[$type]['path'] . '/' . $base .'.js';
|
|
$css = $definitions[$type]['path'] . '/' . $base .'.css';
|
|
drupal_add_js($js);
|
|
drupal_add_css($css);
|
|
*/
|
|
return $layer_object;
|
|
}
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all openlayers layers as objects.
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $reset
|
|
* Boolean whether to reset cache or not
|
|
* @return array
|
|
* array of layer info
|
|
*/
|
|
function openlayers_layers_load($reset = FALSE) {
|
|
ctools_include('export');
|
|
$layer_objects = array();
|
|
if ($reset) ctools_export_load_object_reset('openlayers_layers');
|
|
$layers = ctools_export_load_object('openlayers_layers', 'all', array());
|
|
foreach ($layers as $layer) {
|
|
$layer_objects[$layer->name] = openlayers_get_layer_object($layer);
|
|
}
|
|
|
|
return array_filter($layer_objects, 'openlayers_layer_sanity_check');
|
|
}
|
|
|
|
/**
|
|
* Check the plugin definition of a layer.
|
|
* Some field *MUST* be there to work correctly with OL.
|
|
*
|
|
* @ingroup openlayers_api
|
|
* @param $definition
|
|
* @return bool
|
|
*/
|
|
function openlayers_layer_definition_check($definition) {
|
|
$mandatory_fields = array(
|
|
array('title'),
|
|
array('description'),
|
|
array('name'),
|
|
array('path'),
|
|
array('layer_type', 'file'),
|
|
array('layer_type', 'class'),
|
|
array('layer_type', 'parent'),
|
|
);
|
|
|
|
foreach ($mandatory_fields as $field) {
|
|
$missing = drupal_array_nested_key_exists($definition, $field);
|
|
if (!$missing) {
|
|
drupal_set_message(t("There's a problem in the plugin definition of the layer type <em>!type</em>. The layer will be disabled.", array('!type' => $definition['name'])), 'warning');
|
|
watchdog('openlayers', 'Layer !layer is unavailable because its
|
|
plugin definition is incomplete.',
|
|
array('!layer' => $definition['name']),
|
|
WATCHDOG_ERROR);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Check the plugin definition of a behavior.
|
|
* Some field *MUST* be there to work correctly with OL.
|
|
*
|
|
* @ingroup openlayers_api
|
|
* @param $definition
|
|
* @return bool
|
|
*/
|
|
function openlayers_behavior_definition_check($definition) {
|
|
$mandatory_fields = array(
|
|
array('title'),
|
|
array('description'),
|
|
array('name'),
|
|
array('path'),
|
|
array('type'),
|
|
array('behavior', 'file'),
|
|
array('behavior', 'class'),
|
|
array('behavior', 'parent'),
|
|
);
|
|
|
|
foreach ($mandatory_fields as $field) {
|
|
$missing = drupal_array_nested_key_exists($definition, $field);
|
|
if (!$missing) {
|
|
drupal_set_message(t("There's a problem in the definition of the behavior <em>!behavior</em>. The behavior will be disabled.", array('!behavior' => $definition['name'])), 'warning');
|
|
watchdog('openlayers', 'Behavior !behavior is unavailable because its
|
|
plugin definition is incomplete.',
|
|
array('!behavior' => $definition['name']),
|
|
WATCHDOG_ERROR);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check layer to determine whether it has all the
|
|
* necessary attributes to be rendered. This is necessary
|
|
* because of API changes, and is a consolidation from other
|
|
* layer-error-checking in this module
|
|
*
|
|
* @param $layer
|
|
* Layer object
|
|
* @param $projection
|
|
* Projection number (EPSG) to check compatibility with
|
|
* @param $strict
|
|
* reject invalid layers
|
|
* @return boolean
|
|
* layer validity if strict is set, otherwise always true
|
|
*/
|
|
function openlayers_layer_sanity_check($layer, $projection = FALSE, $strict = FALSE) {
|
|
// Handle layers after they've been rendered for a map
|
|
$layer = (is_array($layer)) ? (object) $layer : $layer;
|
|
|
|
if (!isset($layer->name)) {
|
|
return !$strict;
|
|
}
|
|
|
|
if (!isset($layer->data['projection']) || !is_array($layer->data['projection'])) {
|
|
watchdog('openlayers', 'Layer %name does not have a projection set.',
|
|
array('%name' => $layer->name));
|
|
drupal_set_message(
|
|
t('OpenLayers layers failed the sanity check. See the
|
|
<a href="@drupallog">Drupal log</a> for details',
|
|
array('@drupallog' => url('admin/reports/dblog')))
|
|
);
|
|
return !$strict;
|
|
}
|
|
|
|
if (!isset($layer->data['layer_type'])) {
|
|
watchdog('openlayers', 'Layer %name does not have its layer_type set.',
|
|
array('%name' => $layer->name));
|
|
drupal_set_message(
|
|
t('OpenLayers layers failed the sanity check. See the
|
|
<a href="@drupallog">Drupal log</a> for details',
|
|
array('@drupallog' => url('admin/reports/dblog')))
|
|
);
|
|
return !$strict;
|
|
}
|
|
|
|
if ($projection && empty($layer->data['vector']) &&
|
|
(!in_array($projection, $layer->data['projection']))) {
|
|
watchdog('openlayers',
|
|
'The layer %layer_name cannot be reprojected to the map projection: EPSG: %map_proj',
|
|
array(
|
|
'%layer_name' => $layer->name,
|
|
// TODO: $map is not defined.
|
|
'%map_proj' => $map['projection'],
|
|
)
|
|
);
|
|
return !$strict;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Delete a layer object from the database.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $layer
|
|
* String identifier of a layer or layer object with name.
|
|
* @return
|
|
* The results of DB delete.
|
|
*/
|
|
function openlayers_layer_delete($layer) {
|
|
return openlayers_object_delete($layer, 'layer');
|
|
}
|
|
|
|
/**
|
|
* Get all layer types.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $reset
|
|
* Boolean whether to reset cache or not.
|
|
* @return
|
|
* Array of layer type info.
|
|
*/
|
|
function openlayers_layer_types($reset = FALSE) {
|
|
ctools_include('plugins');
|
|
$layers = ctools_get_plugins('openlayers', 'layer_types');
|
|
|
|
return array_filter($layers, 'openlayers_layer_definition_check');
|
|
}
|
|
|
|
/**
|
|
* Menu loader for layer types.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $name
|
|
* String identifier of layer type.
|
|
* @param $reset
|
|
* Boolean whether to reset cache or not.
|
|
* @return
|
|
* An instantiated layer type object or FALSE if not found.
|
|
*/
|
|
function openlayers_layer_type_load($name, $reset = FALSE) {
|
|
ctools_include('plugins');
|
|
|
|
if ($layer_type_class = ctools_plugin_load_class(
|
|
'openlayers',
|
|
'layer_types',
|
|
$name,
|
|
'layer_type')) {
|
|
$layer_type = new $layer_type_class();
|
|
return $layer_type;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Get all behaviors.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $reset
|
|
* Boolean whether to reset cache or not.
|
|
* @return
|
|
* Array of behavior info.
|
|
*/
|
|
function openlayers_behaviors($reset = FALSE) {
|
|
ctools_include('plugins');
|
|
$behaviors = ctools_get_plugins('openlayers', 'behaviors');
|
|
return array_filter($behaviors, 'openlayers_behavior_definition_check');
|
|
|
|
}
|
|
|
|
/**
|
|
* Get all openlayers styles.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $reset
|
|
* Boolean whether to reset cache or not.
|
|
* @return
|
|
* Array of all available styles.
|
|
*/
|
|
function openlayers_styles($reset = FALSE) {
|
|
ctools_include('export');
|
|
if ($reset) {
|
|
ctools_export_load_object_reset('openlayers_styles');
|
|
}
|
|
|
|
$styles = ctools_export_load_object('openlayers_styles', 'all', array());
|
|
return $styles;
|
|
}
|
|
|
|
/**
|
|
* Load a style object by name.
|
|
*
|
|
* This function can also be used as a
|
|
* menu loader for a style.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $name
|
|
* The string identifier of the style.
|
|
* @param $reset
|
|
* Boolean whether to reset the cache or not.
|
|
* @return
|
|
* A style object or FALSE if not found.
|
|
*/
|
|
function openlayers_style_load($name, $reset = FALSE) {
|
|
$styles = openlayers_styles($reset);
|
|
return !empty($styles[$name]) ? $styles[$name] : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Save style.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $style
|
|
* The style object to save.
|
|
* @return
|
|
* The results of DB write or FALSE if no name.
|
|
*/
|
|
function openlayers_style_save($style) {
|
|
if (!empty($style->name)) {
|
|
return (db_select('openlayers_styles')
|
|
->fields('openlayers_styles', array('name'))
|
|
->condition('name', $style->name)
|
|
->execute()
|
|
->fetchCol()) ?
|
|
drupal_write_record('openlayers_styles', $style, 'name') :
|
|
drupal_write_record('openlayers_styles', $style);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Delete a style object from the database.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $style
|
|
* String identifier of a style or style object with name.
|
|
* @return
|
|
* The results of DB delete.
|
|
*/
|
|
function openlayers_style_delete($style) {
|
|
return openlayers_object_delete($style, 'style');
|
|
}
|
|
|
|
/**
|
|
* Get maps from DB or code, via cache.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $reset
|
|
* Boolean whether to reset or not.
|
|
* @return
|
|
* Return array of maps.
|
|
*/
|
|
function openlayers_maps($reset = FALSE) {
|
|
ctools_include('export');
|
|
if ($reset) {
|
|
ctools_export_load_object_reset('openlayers_maps');
|
|
}
|
|
|
|
$maps = ctools_export_load_object(
|
|
'openlayers_maps', 'all', array());
|
|
return $maps;
|
|
}
|
|
|
|
/**
|
|
* Given a map name, get full map object.
|
|
*
|
|
* This function can also be used as a
|
|
* menu loader for a style.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $name
|
|
* String identifier of the map.
|
|
* @param $reset
|
|
* Boolean whether to reset cache.
|
|
* @return
|
|
* map object or FALSE if not found.
|
|
*/
|
|
function openlayers_map_load($name = '', $reset = FALSE) {
|
|
ctools_include('export');
|
|
if ($reset) {
|
|
ctools_export_load_object_reset('openlayers_maps');
|
|
}
|
|
|
|
$maps = ctools_export_load_object('openlayers_maps', 'names', array($name));
|
|
|
|
if (empty($maps[$name])) {
|
|
return FALSE;
|
|
} else {
|
|
$map = $maps[$name];
|
|
$map->data['map_name'] = $name;
|
|
return clone $map;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save a map object to the database.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $map
|
|
* map object.
|
|
* @return
|
|
* The results of DB write or FALSE if no name.
|
|
*/
|
|
function openlayers_map_save($map) {
|
|
if (!empty($map->name)) {
|
|
return (db_select('openlayers_maps')
|
|
->fields('openlayers_maps', array('name'))
|
|
->condition('name', $map->name)
|
|
->execute()
|
|
->fetchCol()) ?
|
|
drupal_write_record('openlayers_maps', $map, 'name') :
|
|
drupal_write_record('openlayers_maps', $map);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Delete a map object from the database.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $map
|
|
* String identifier of a map or map object with name.
|
|
* @return
|
|
* The results of DB delete.
|
|
*/
|
|
function openlayers_map_delete($map) {
|
|
return openlayers_object_delete($map, 'map');
|
|
}
|
|
|
|
/**
|
|
* Get map options in an array suitable for a FormAPI element.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $reset
|
|
* Boolean whether to reset or not.
|
|
* @return
|
|
* Return array of formatted data.
|
|
*/
|
|
function openlayers_map_options($reset = FALSE) {
|
|
$maps = openlayers_maps($reset);
|
|
$options = array();
|
|
foreach ($maps as $map) {
|
|
$options[$map->name] = $map->title;
|
|
}
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Delete an object from the database.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $ol_object
|
|
* String identifier of an object or the object with name.
|
|
* @param $type
|
|
* Type of object to delete. The options are the following:
|
|
* - 'layer'
|
|
* - 'style'
|
|
* = 'map'
|
|
* @return
|
|
* The results of the DB delete.
|
|
*/
|
|
function openlayers_object_delete($ol_object, $type) {
|
|
// Check for object or name
|
|
$tables = array(
|
|
'style' => 'openlayers_styles',
|
|
'layer' => 'openlayers_layers',
|
|
'map' => 'openlayers_maps');
|
|
if (is_object($ol_object) && isset($ol_object->name) && isset($tables[$type])) {
|
|
$ol_object = $ol_object->name;
|
|
return db_delete($tables[$type])->condition('name', $ol_object)->execute();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks map array for incompatibilities or errors.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $map
|
|
* Map array
|
|
* @param $log_errors
|
|
* Boolean whether to log errors.
|
|
* @return
|
|
* FALSE if passed. Array of descriptive errors if fail.
|
|
*/
|
|
function openlayers_error_check_map($map, $log_errors = TRUE) {
|
|
$errors = array();
|
|
|
|
// Check for layers
|
|
if (!is_array($map['layers'])) {
|
|
$errors[] = t('Map contains no renderable layers.');
|
|
}
|
|
else {
|
|
// Check layer projections
|
|
foreach ($map['layers'] as $layer) {
|
|
openlayers_layer_sanity_check(
|
|
array('data' => $layer),
|
|
$map['projection'],
|
|
TRUE);
|
|
}
|
|
}
|
|
|
|
// Check if any errors found to log
|
|
if (count($errors) > 0 && $log_errors) {
|
|
// Log the Error(s)
|
|
watchdog('openlayers', implode(', ', $errors), array(), WATCHDOG_ERROR);
|
|
}
|
|
|
|
// Check if errors and return
|
|
return (count($errors) > 0) ? $errors : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Get extent given projection
|
|
*
|
|
* Returns standard world-max-extents for common projections.
|
|
* Layers implementing other projections and subsets of the
|
|
* world should define their maxExtent in the layer array.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $projection
|
|
* String of the projection value. Currently
|
|
* supports 900913, 4326.
|
|
* @return
|
|
* Array of maxExtent in OpenLayers toArray() format.
|
|
*/
|
|
function openlayers_get_extent($projection) {
|
|
switch ($projection) {
|
|
case '900913':
|
|
return array(-20037508, -20037508, 20037508, 20037508);
|
|
case '4326':
|
|
return array(-180, -90, 180, 90);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get resolution given projection
|
|
*
|
|
* Returns a default set of resolutions for standard
|
|
* TMS, WMS, etc servers serving up common projections.
|
|
* Layers supporting less common projections and resolutions
|
|
* can easily define custom resolutions arrays.
|
|
*
|
|
* @ingroup openlayers_api
|
|
*
|
|
* @param $projection
|
|
* String specifying which projection this should take, like 900913.
|
|
* @param $zoom_start
|
|
* Integer of first zoom level, default 0.
|
|
* @param $zoom_end
|
|
* Integer of last zoom level, default FALSE.
|
|
* @return
|
|
* Array of resolutions.
|
|
*/
|
|
function openlayers_get_resolutions($projection, $zoom_start = 0, $zoom_end = FALSE) {
|
|
switch ($projection) {
|
|
case '900913':
|
|
// 16 zoom levels, taken from
|
|
// openlayers.org TMS map
|
|
$res = array(
|
|
156543.0339,
|
|
78271.51695,
|
|
39135.758475,
|
|
19567.8792375,
|
|
9783.93961875,
|
|
4891.969809375,
|
|
2445.9849046875,
|
|
1222.99245234375,
|
|
611.496226171875,
|
|
305.7481130859375,
|
|
152.87405654296876,
|
|
76.43702827148438,
|
|
38.21851413574219,
|
|
19.109257067871095,
|
|
9.554628533935547,
|
|
4.777314266967774,
|
|
2.388657133483887,
|
|
1.1943285667419434,
|
|
0.5971642833709717,
|
|
0.29858214169740677,
|
|
0.14929107084870338,
|
|
0.07464553542435169
|
|
);
|
|
break;
|
|
case '4326':
|
|
// 16 zoom levels, taken from
|
|
// openlayers.org default WMS map
|
|
$res = array(
|
|
0.703125,
|
|
0.3515625,
|
|
0.17578125,
|
|
0.087890625,
|
|
0.0439453125,
|
|
0.02197265625,
|
|
0.010986328125,
|
|
0.0054931640625,
|
|
0.00274658203125,
|
|
0.001373291015625,
|
|
0.0006866455078125,
|
|
0.00034332275390625,
|
|
0.000171661376953125,
|
|
0.0000858306884765625,
|
|
0.00004291534423828125,
|
|
0.000021457672119140625,
|
|
0.000010728836059570312,
|
|
);
|
|
break;
|
|
default:
|
|
$res = array();
|
|
break;
|
|
}
|
|
$length = ($zoom_end == FALSE) ? NULL : $zoom_end - $zoom_start;
|
|
// By default this will not actually clip the array
|
|
$resolutions = array_slice($res, $zoom_start, $length);
|
|
return $resolutions;
|
|
}
|
|
|
|
/**
|
|
* We define base classes in the core module.
|
|
* All other parent classes can be autoloaded through ctools.
|
|
*/
|
|
class openlayers_behavior {
|
|
var $options, $map;
|
|
|
|
function __construct($options = array(), $map = array()) {
|
|
$this->options = $options + $this->options_init();
|
|
$this->map = $map;
|
|
}
|
|
|
|
/*
|
|
* @return array of JavaScript functions required to be defined
|
|
* in order for this function to work
|
|
*/
|
|
function js_dependency() {
|
|
return array();
|
|
}
|
|
|
|
function options_init() {
|
|
return array();
|
|
}
|
|
|
|
/*
|
|
* @param $defaults default values for the form as an array
|
|
* @return a FormAPI form
|
|
*/
|
|
function options_form($defaults = array()) {
|
|
return array();
|
|
}
|
|
|
|
function render(&$map) {}
|
|
}
|
|
|
|
/**
|
|
* We define base classes in the core module.
|
|
* All other parent classes can be autoloaded through ctools.
|
|
*/
|
|
class openlayers_layer_type {
|
|
|
|
/**
|
|
* Stores the options for this layer.
|
|
* @var array
|
|
*/
|
|
public $data = array();
|
|
|
|
/**
|
|
* Stores the current map.
|
|
* @var array
|
|
*/
|
|
public $map;
|
|
|
|
/**
|
|
* Set configuration and store map.
|
|
*
|
|
* @param $layer
|
|
* Configuration object with the options for the layer.
|
|
* @param $map
|
|
* Array with the current map.
|
|
*/
|
|
function __construct($layer = array(), $map = array()) {
|
|
foreach (array('name', 'title', 'description', 'data', 'export_type') as $k) {
|
|
if (isset($layer->{$k})) {
|
|
$this->{$k} = $layer->{$k};
|
|
}
|
|
}
|
|
// Extend options with the defaults.
|
|
$this->data += $this->options_init();
|
|
|
|
$this->map = $map;
|
|
}
|
|
|
|
/**
|
|
* Provides the default options for the layer.
|
|
*
|
|
* @return
|
|
* An associative array with the default options.
|
|
*/
|
|
function options_init() {
|
|
return array(
|
|
'layer_type' => get_class($this),
|
|
'isBaseLayer' => TRUE,
|
|
'projection' => array('900913'),
|
|
'serverResolutions' => openlayers_get_resolutions('900913'),
|
|
'maxExtent' => openlayers_get_extent('900913'),
|
|
'resolutions' => openlayers_get_resolutions('900913'),
|
|
'base_url' => NULL,
|
|
'transitionEffect' => 'resize',
|
|
'weight' => 0
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Options form to configure layer instance options.
|
|
*
|
|
* @return
|
|
* Array with form elements.
|
|
*/
|
|
function options_form($default = array()) {
|
|
return array(
|
|
'projection' => array(
|
|
'#type' => 'select',
|
|
'#title' => t('Projection'),
|
|
'#multiple' => TRUE,
|
|
'#options' => array(
|
|
'900913' => '900913',
|
|
'4326' => '4326'
|
|
),
|
|
'#default_value' => isset($default->data['projection']) ?
|
|
$default->data['projection'] :
|
|
'900913'
|
|
),
|
|
'isBaseLayer' => array(
|
|
'#type' => 'checkbox',
|
|
'#title' => t('Base Layer'),
|
|
'#description' => t('Uncheck to make this map an overlay'),
|
|
'#default_value' => !empty($default->data['isBaseLayer']) ?
|
|
$default->data['isBaseLayer'] : FALSE
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Validate the options_form().
|
|
*
|
|
* @param array $default
|
|
*/
|
|
function options_form_validate($form, &$form_state) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Submit the options_form().
|
|
*
|
|
* @param array $default
|
|
*/
|
|
function options_form_submit($form, &$form_state) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Options form to configure layer-type-wide options.
|
|
*
|
|
* @return
|
|
* Array with form elements.
|
|
*/
|
|
function settings_form() {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Render the layer and return the layer options.
|
|
*
|
|
* Has no return value.
|
|
*
|
|
* @param $map
|
|
*/
|
|
function render(&$map) {}
|
|
|
|
}
|
|
|
|
/**
|
|
* Implements hook_ctools_plugin_api().
|
|
*/
|
|
function openlayers_ctools_plugin_api($module, $api) {
|
|
if ($module == "openlayers") {
|
|
switch ($api) {
|
|
case 'openlayers_maps':
|
|
return array('version' => 1);
|
|
|
|
case 'openlayers_layers':
|
|
return array('version' => 1);
|
|
|
|
case 'openlayers_styles':
|
|
return array('version' => 1);
|
|
|
|
case 'openlayers_layer_types':
|
|
return array('version' => 1);
|
|
|
|
case 'openlayers_behaviors':
|
|
return array('version' => 1);
|
|
|
|
}
|
|
}
|
|
elseif ($module == 'boxes' && $api == 'plugins') {
|
|
return array('version' => 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_openlayers_layers().
|
|
*/
|
|
function openlayers_openlayers_layers() {
|
|
module_load_include('inc', 'openlayers', 'includes/openlayers.layers');
|
|
return _openlayers_openlayers_layers();
|
|
}
|
|
|
|
/**
|
|
* Implements hook_openlayers_styles().
|
|
*/
|
|
function openlayers_openlayers_styles() {
|
|
module_load_include('inc', 'openlayers', 'includes/openlayers.styles');
|
|
return _openlayers_openlayers_styles();
|
|
}
|
|
|
|
/**
|
|
* Implements hook_openlayers_maps().
|
|
*/
|
|
function openlayers_openlayers_maps() {
|
|
module_load_include('inc', 'openlayers', 'includes/openlayers.maps');
|
|
return _openlayers_openlayers_maps();
|
|
}
|
|
|
|
/**
|
|
* Implements hook_boxes_plugins().
|
|
*/
|
|
function openlayers_boxes_plugins() {
|
|
return array(
|
|
'openlayers_simple' => array(
|
|
'title' => 'OpenLayers',
|
|
'handler' => array(
|
|
'parent' => 'boxes_box',
|
|
'class' => 'openlayers_simple',
|
|
'file' => 'openlayers_simple.inc',
|
|
'path' => drupal_get_path('module', 'openlayers') . '/includes/boxes'
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* Alias Functions
|
|
*
|
|
* These functions temporarily map the alias the renamed 'map' functions to their
|
|
* previous 'preset' functions to allow time for contrib modules to catch up.
|
|
* These will eventually be removed
|
|
*
|
|
* These should be removed in 7.x-3.x
|
|
*/
|
|
function openlayers_build_preset($map = array()) { return openlayers_build_map($map); }
|
|
function openlayers_preset_load($name = '', $reset = FALSE) { return openlayers_map_load($name, $reset); }
|
|
function openlayers_render_preset_data($map = array(), $map_name = '') { return openlayers_render_map_data($map, $map_name); }
|
|
function openlayers_presets($reset = FALSE) { return openlayers_maps($reset); }
|
|
function openlayers_preset_save($map) { return openlayers_map_save($map); }
|
|
function openlayers_preset_delete($map) { return openlayers_map_delete($map); }
|
|
function openlayers_preset_options($reset = FALSE) { return openlayers_map_options($reset); }
|
|
function openlayers_error_check_preset($map, $log_errors = TRUE) { return openlayers_error_check_map($map, $log_errors); }
|
|
function openlayers_render_preset($map = '', $map_name = '') {
|
|
if (is_array($map)) {
|
|
return openlayers_render_preset_data($map, $map_name);
|
|
}
|
|
else {
|
|
return openlayers_render_map($map);
|
|
}
|
|
}
|