You are here

openlayers.module in Openlayers 6

Main OpenLayers API File

This file holds the main Drupal hook functions, and the openlayers API functions for the openlayers module.

File

openlayers.module
View 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',
//  );
// }

Related topics

Functions

Namesort descending Description
openlayers_behaviors_get_info Get Behavior Info
openlayers_domainconf Implementation of hook_domainconf().
openlayers_error_check_map Check Map Errors
openlayers_get_default_map Get Default Map
openlayers_get_map OpenLayers Get Map
openlayers_get_preset OpenLayers Get Preset
openlayers_get_presets Get Formatted Presets
openlayers_help Implementation of hook_help().
openlayers_initialize Intialize OpenLayers
openlayers_layers_get_info Get Layer Info
openlayers_menu Implementation of hook_menu().
openlayers_merge_maps Merge Maps
openlayers_openlayers_layers_handler_info Implementation of hook_openlayers_layers_handler_info().
openlayers_openlayers_layers_info Implementation of hook_openlayers_layers_info().
openlayers_openlayers_presets Implementation of hook_openlayers_presets().
openlayers_openlayers_styles_info Implementation of hook_openlayers_styles_info().
openlayers_perm Implementation of hook_perm().
openlayers_presets Get Presets Array
openlayers_render_map Render Map
openlayers_save_preset OpenLayers Save Preset
openlayers_styles_get_info Get Styles Info
openlayers_theme Implementation of hook_theme().

Constants

Namesort descending 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.