You are here

getlocations.module in Get Locations 7

Same filename and directory in other branches
  1. 6.2 getlocations.module
  2. 6 getlocations.module
  3. 7.2 getlocations.module

getlocations.module @author Bob Hutchinson http://drupal.org/user/52366 @copyright GNU GPL

Displays locations on a map. for Drupal 7 using version 3 googlemaps API

File

getlocations.module
View source
<?php

/**
 * @file
 * getlocations.module
 * @author Bob Hutchinson http://drupal.org/user/52366
 * @copyright GNU GPL
 *
 * Displays locations on a map.
 * for Drupal 7
 * using version 3 googlemaps API
 */
define('GETLOCATIONS_PATH', drupal_get_path('module', 'getlocations'));
define('GETLOCATIONS_ADMIN_PATH', 'admin/config/services/getlocations');
define('GETLOCATIONS_VERSION', '7.x-1.x');

/**
 * Implements hook_help().
 */
function getlocations_help($path, $arg) {
  switch ($path) {
    case 'admin/help#getlocations':
      $output = '<p>' . t('Displays locations on a map.') . '</p>';
      return $output;
  }
}

/**
 * Implements hook_init().
 */
function getlocations_init() {
  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['enable']) {
      $settings = array(
        'getlocations_colorbox' => $getlocations_colorbox,
      );
      drupal_add_js($settings, 'setting');
      $getlocations_paths = getlocations_paths_get();
      drupal_add_js($getlocations_paths['getlocations_colorbox_path']);
    }
  }
}

/**
 * Implements hook_permission().
 */
function getlocations_permission() {
  $perms = array();
  $perms['access getlocations'] = array(
    'title' => t('Access Getlocations'),
    'description' => t('View and use the Getlocations module.'),
  );
  $perms['access user getlocations'] = array(
    'title' => t('Access User locations'),
    'description' => t('View User locations with Getlocation maps.'),
  );
  return $perms;
}

/**
 * Implements hook_flush_caches().
 */
function getlocations_flush_caches() {
  if (variable_get('getlocations_flush', 1)) {
    getlocations_regenerate_markers();
  }
}

/**
 * Implements hook_views_api().
 */
function getlocations_views_api() {
  return array(
    'api' => 3,
    'path' => GETLOCATIONS_PATH . '/views',
  );
}

/**
 * Implements hook_menu().
 */
function getlocations_menu() {
  $items = array();
  $items[GETLOCATIONS_ADMIN_PATH] = array(
    'title' => 'Getlocations',
    'description' => 'Configure Getlocations',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'getlocations_settings_form',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'getlocations.admin.inc',
  );
  $items[GETLOCATIONS_ADMIN_PATH . '/base'] = array(
    'title' => 'Base',
    'description' => 'Getlocations base configuration',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'getlocations_settings_form',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'getlocations.admin.inc',
    'weight' => 1,
  );

  // getlocations/node/$nid    # show all location on one node
  $items['getlocations/node/%getlocations_id'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_nodemap',
    'page arguments' => array(
      2,
    ),
    'type' => MENU_CALLBACK,
  );
  if (getlocations_check_entity_type('user') || getlocations_check_entity_type('profile2')) {

    // getlocations/user/$uid    # show all locations for a user
    $items['getlocations/user/%getlocations_id'] = array(
      'title' => 'Get user locations',
      'access callback' => 'getlocations_access_user_location',
      'page callback' => 'getlocations_usermap',
      'page arguments' => array(
        2,
      ),
      'type' => MENU_CALLBACK,
    );

    // getlocations/users    # show all locations for all users
    $items['getlocations/users'] = array(
      'title' => 'View all user locations',
      'access callback' => 'getlocations_access_user_location',
      'page callback' => 'getlocations_usersmap',
      'type' => MENU_CALLBACK,
    );
  }
  if (module_exists('taxonomy')) {

    // getlocations/term/$tid    # show all locations for a term
    $items['getlocations/term/%getlocations_id'] = array(
      'title' => 'Get term locations',
      'access callback' => 'getlocations_access_location',
      'page callback' => 'getlocations_termmap',
      'page arguments' => array(
        2,
      ),
      'type' => MENU_CALLBACK,
    );
  }
  if (module_exists('comment')) {
    if (getlocations_check_entity_type('comment')) {

      // getlocations/comment/$cid    # show all locations for a comment
      $items['getlocations/comment/%getlocations_id'] = array(
        'title' => 'Get comment locations',
        'access callback' => 'getlocations_access_location',
        'page callback' => 'getlocations_commentmap',
        'page arguments' => array(
          2,
        ),
        'type' => MENU_CALLBACK,
      );
    }
  }

  // getlocations/type/$type     # show all locations of nodes of content-type machine name
  $items['getlocations/type/%getlocations_type'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_typemap',
    'page arguments' => array(
      2,
      3,
      4,
    ),
    'type' => MENU_CALLBACK,
  );

  // getlocations/lids/1,2,3,4    # show lids
  $items['getlocations/lids/%getlocations_cdints'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_lids',
    'page arguments' => array(
      2,
    ),
    'type' => MENU_CALLBACK,
  );

  // getlocations/nids/1,2,3,4    # show nids locations
  $items['getlocations/nids/%getlocations_cdints'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_nids',
    'page arguments' => array(
      2,
    ),
    'type' => MENU_CALLBACK,
  );

  // ajax callbacks
  // getlocations/info?lid     # ajax callback to fetch an address
  $items['getlocations_cb/info'] = array(
    'page callback' => 'getlocations_adinfo',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );

  // getlocations/lidinfo?lid    # ajax callback to fetch a link to the 'owner'
  $items['getlocations_cb/lidinfo'] = array(
    'page callback' => 'getlocations_lidinfo',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['getlocations_box'] = array(
    'title' => 'Get locations',
    'access arguments' => array(
      'access getlocations',
    ),
    'page callback' => 'getlocations_box',
    'type' => MENU_CALLBACK,
  );
  $items['getlocations/markerinfo'] = array(
    'access callback' => TRUE,
    'page callback' => 'getlocations_markerinfo',
    'type' => MENU_CALLBACK,
  );
  $items['getlocations/cb_w3w'] = array(
    'access callback' => TRUE,
    'page callback' => 'getlocations_cb_w3w',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * check that the argument is numeric
 *
 * @param int $arg
 *
 * @return argument or FALSE
 */
function getlocations_id_load($arg) {
  return is_numeric($arg) && $arg > 0 ? $arg : FALSE;
}

/**
 * Check that the node type exists
 *
 * @param string $arg Node type.
 *
 * @return argument or FALSE
 */
function getlocations_type_load($arg) {
  $query = db_select('node_type', 'n')
    ->fields('n', array(
    'type',
  ))
    ->condition('n.type', $arg);
  $row = $query
    ->execute()
    ->fetchAssoc();
  return isset($row['type']) && $row['type'] ? $arg : FALSE;
}

/**
 * sanity check on list of nids
 *
 * @param int $arg
 *
 * @return argument or FALSE
 *
 */
function getlocations_cdints_load($arg) {
  $arr = explode(',', $arg);
  foreach ($arr as $a) {
    if (!is_numeric($a) || $a < 1) {
      return FALSE;
    }
  }
  return $arg;
}

/**
 * sanity check on entity type
 *
 * @param string $arg Entity type.
 *
 * @return argument or FALSE
 *
 */
function getlocations_entity_type_load($arg) {
  if (getlocations_check_entity_type($arg)) {
    return $arg;
  }
  return FALSE;
}

/**
 * Access callback: Checks for access permission and if there is a supported locative module installed
 *
 * @return bool
 *
 */
function getlocations_access_location() {
  if (user_access('access getlocations')) {
    $modules = getlocations_supported_modules();
    foreach ($modules as $module) {
      if (module_exists($module)) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Access callback: Checks for access permission and if there is a supported locative module installed
 *
 * @return bool
 *
 */
function getlocations_access_user_location() {
  if (user_access('access user getlocations') && user_access('access user profiles')) {
    $modules = getlocations_supported_modules();
    foreach ($modules as $module) {
      if (module_exists($module)) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Page callback: displays a map.
 *
 * @param int $nid
 *
 * @return
 *   Returns a map of locations of a node
 *
 */
function getlocations_nodemap($nid) {
  $vid = getlocations_get_vid($nid);
  $locations = getlocations_load_locations($vid);
  $node = node_load($nid);
  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['node_map_marker'];
  $typemarkers = getlocations_get_markertypes('node');
  if (isset($typemarkers[$node->type]) && $typemarkers[$node->type]) {
    $marker = $typemarkers[$node->type];
  }
  $latlons = array();
  $minmaxes = array(
    'minlat' => 0,
    'minlon' => 0,
    'maxlat' => 0,
    'maxlon' => 0,
  );
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();
  if (count($locations)) {

    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations as $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        if (!isset($location['key'])) {
          $location['key'] = '';
        }
        else {
          if ($location['key'] == 'nid') {
            $location['lid'] = $nid;
          }
          elseif ($location['key'] == 'vid') {
            $location['lid'] = $nid;
          }
        }

        // term markers
        $marker = getlocations_get_term_marker($nid, $marker);

        // per location marker
        if (isset($location['marker']) && !empty($location['marker'])) {
          $marker = $location['marker'];
        }
        $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($node->title), ENT_QUOTES);
        $latlons[$ct] = array(
          $location['latitude'],
          $location['longitude'],
          $location['lid'],
          $name,
          $marker,
          $location['key'],
          '',
          '',
        );
        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }
        $ct++;
      }
    }
  }
  if ($ct < 2) {
    unset($minmaxes);
    $minmaxes = '';
  }
  drupal_set_title(t('View !t locations', array(
    '!t' => $node->title,
  )));
  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }
  return getlocations_setlocations($latlons, $minmaxes, 'node', $node, $extra_info);
}

/**
 * Page callback: Displays a map.
 *
 * @param int $uid
 *
 * @return
 *   Returns a map of locations of a user
 *
 */
function getlocations_usermap($uid) {
  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['user_map_marker'];
  $locations = getlocations_load_locations($uid, 'uid');
  $account = user_load($uid);
  $latlons = array();
  $minmaxes = array(
    'minlat' => 0,
    'minlon' => 0,
    'maxlat' => 0,
    'maxlon' => 0,
  );
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();
  if (count($locations)) {

    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations as $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        if (!isset($location['key'])) {
          $location['key'] = '';
        }
        else {
          $location['lid'] = $uid;
        }

        // per location marker
        if (isset($location['marker']) && !empty($location['marker'])) {
          $marker = $location['marker'];
        }
        $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($account->name), ENT_QUOTES);
        $latlons[$ct] = array(
          $location['latitude'],
          $location['longitude'],
          $location['lid'],
          $name,
          $marker,
          $location['key'],
          '',
          '',
        );
        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }
        $ct++;
      }
    }
  }
  if ($ct < 2) {
    unset($minmaxes);
    $minmaxes = '';
  }
  drupal_set_title(t('View user !t locations', array(
    '!t' => $account->name,
  )));
  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }
  return getlocations_setlocations($latlons, $minmaxes, 'user', $account, $extra_info);
}

/**
 * Page callback: Displays a map.
 *
 * @return
 *   Returns a map of locations of all the users
 *
 */
function getlocations_usersmap() {
  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['user_map_marker'];
  $latlons = array();
  $minmaxes = array(
    'minlat' => 0,
    'minlon' => 0,
    'maxlat' => 0,
    'maxlon' => 0,
  );
  $query = db_select('users', 'u')
    ->fields('u', array(
    'uid',
    'name',
  ))
    ->condition('u.status', 1);
  $rows = $query
    ->execute();
  $ct = 0;
  foreach ($rows as $row) {
    $uid = $row->uid;
    $locations = getlocations_load_locations($uid, 'uid');
    if (count($locations)) {

      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations as $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (!isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            $location['lid'] = $uid;
          }

          // per location marker
          if (isset($location['marker']) && !empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($row->name), ENT_QUOTES);
          $latlons[$ct] = array(
            $location['latitude'],
            $location['longitude'],
            $location['lid'],
            $name,
            $marker,
            $location['key'],
            '',
            '',
          );
          $ct++;
        }
      }
    }
  }
  if ($ct < 2) {
    unset($minmaxes);
    $minmaxes = '';
  }
  return getlocations_setlocations($latlons, $minmaxes, 'users');
}

/**
 * Page callback: Displays a map.
 *
 * @param int $tid
 *
 * @return
 *   Returns a map of locations of a term
 *
 */
function getlocations_termmap($tid) {
  if (module_exists('taxonomy')) {
    $locations = getlocations_load_locations($tid, 'tid');
    $term = taxonomy_term_load($tid);
    $getlocations_defaults = getlocations_defaults();
    $marker = $getlocations_defaults['vocabulary_map_marker'];
    $typemarkers = getlocations_get_markertypes('vocabulary');
    if (isset($typemarkers[$term->vid]) && $typemarkers[$term->vid]) {
      $marker = $typemarkers[$term->vid];
    }
    $latlons = array();
    $minmaxes = array(
      'minlat' => 0,
      'minlon' => 0,
      'maxlat' => 0,
      'maxlon' => 0,
    );
    $ct = 0;
    $extra_info = array();
    $sv_info = FALSE;
    $map_info = FALSE;
    $module = getlocations_get_current_supported_module();
    if (count($locations)) {

      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations as $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (!isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            $location['lid'] = $tid;
          }

          // per location marker
          if (isset($location['marker']) && !empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($term->name), ENT_QUOTES);
          $latlons[$ct] = array(
            $location['latitude'],
            $location['longitude'],
            $location['lid'],
            $name,
            $marker,
            $location['key'],
            '',
            '',
          );
          $sv_info = FALSE;
          if ($module == 'getlocations_fields' && count($locations) == 1) {
            if (getlocations_fields_streetview_settings_allow()) {
              $sv_info = getlocations_fields_svinfo($location);
            }
            if (getlocations_fields_map_settings_allow()) {
              $map_info = getlocations_fields_mapinfo($location);
            }
          }
          $ct++;
        }
      }
    }
    if ($ct < 2) {
      unset($minmaxes);
      $minmaxes = '';
    }
    drupal_set_title(t('View term !t locations', array(
      '!t' => $term->name,
    )));
    if ($sv_info) {
      $extra_info = array_merge($extra_info, $sv_info);
    }
    if ($map_info) {
      $extra_info = array_merge($extra_info, $map_info);
    }
    return getlocations_setlocations($latlons, $minmaxes, 'term', $term, $extra_info);
  }
}

/**
 * Page callback: Displays a map.
 *
 * @param int $cid
 *
 * @return
 *   Returns a map of locations of a comment
 *
 */
function getlocations_commentmap($cid) {
  if (module_exists('comment')) {
    $locations = getlocations_load_locations($cid, 'cid');
    $comment = comment_load($cid);
    $getlocations_defaults = getlocations_defaults();
    $marker = $getlocations_defaults['comment_map_marker'];
    $latlons = array();
    $minmaxes = array(
      'minlat' => 0,
      'minlon' => 0,
      'maxlat' => 0,
      'maxlon' => 0,
    );
    $ct = 0;
    $extra_info = array();
    $sv_info = FALSE;
    $map_info = FALSE;
    $module = getlocations_get_current_supported_module();
    if (count($locations)) {

      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations as $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (!isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            $location['lid'] = $cid;
          }

          // per location marker
          if (isset($location['marker']) && !empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($comment->subject), ENT_QUOTES);
          $latlons[$ct] = array(
            $location['latitude'],
            $location['longitude'],
            $location['lid'],
            $name,
            $marker,
            $location['key'],
            '',
            '',
          );
          $sv_info = FALSE;
          if ($module == 'getlocations_fields' && count($locations) == 1) {
            if (getlocations_fields_streetview_settings_allow()) {
              $sv_info = getlocations_fields_svinfo($location);
            }
            if (getlocations_fields_map_settings_allow()) {
              $map_info = getlocations_fields_mapinfo($location);
            }
          }
          $ct++;
        }
      }
    }
    if ($ct < 2) {
      unset($minmaxes);
      $minmaxes = '';
    }
    drupal_set_title(t('View comment !t locations', array(
      '!t' => $comment->subject,
    )));
    if ($sv_info) {
      $extra_info = array_merge($extra_info, $sv_info);
    }
    if ($map_info) {
      $extra_info = array_merge($extra_info, $map_info);
    }
    return getlocations_setlocations($latlons, $minmaxes, 'comment', $comment, $extra_info);
  }
}

/**
 * Page callback: Displays a map.
 *
 * @param string $type
 * A location enabled content type
 *
 * @return
 *   Returns a map of locations of all nodes of content-type $type
 *
 */
function getlocations_typemap($type, $loc_key = '', $loc_val = '') {
  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['node_map_marker'];
  $typemarkers = getlocations_get_markertypes('node');
  if (isset($typemarkers[$type]) && $typemarkers[$type]) {
    $marker = $typemarkers[$type];
  }
  $latlons = array();
  $minmaxes = array(
    'minlat' => 0,
    'minlon' => 0,
    'maxlat' => 0,
    'maxlon' => 0,
  );
  $query = db_select('node', 'n')
    ->fields('n', array(
    'nid',
    'title',
  ))
    ->condition('n.type', $type);
  $rows = $query
    ->execute();
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();
  foreach ($rows as $row) {
    $nid = $row->nid;
    $vid = getlocations_get_vid($nid);
    $locations = getlocations_load_locations($vid);
    if (count($locations)) {

      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations as $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          if ($loc_key && isset($location[$loc_key])) {
            if (drupal_strtolower($location[$loc_key]) != drupal_strtolower($loc_val)) {
              continue;
            }
          }
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (!isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            if ($location['key'] == 'nid') {
              $location['lid'] = $nid;
            }
            elseif ($location['key'] == 'vid') {
              $location['lid'] = $vid;
            }
          }

          // term markers
          $marker = getlocations_get_term_marker($nid, $marker);

          // per location marker
          if (isset($location['marker']) && !empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($row->title), ENT_QUOTES);
          $latlons[$ct] = array(
            $location['latitude'],
            $location['longitude'],
            $location['lid'],
            $name,
            $marker,
            $location['key'],
            '',
            '',
          );
          $sv_info = FALSE;
          if ($module == 'getlocations_fields' && count($locations) == 1) {
            if (getlocations_fields_streetview_settings_allow()) {
              $sv_info = getlocations_fields_svinfo($location);
            }
            if (getlocations_fields_map_settings_allow()) {
              $map_info = getlocations_fields_mapinfo($location);
            }
          }
          $ct++;
        }
      }
    }
  }
  if ($ct < 2) {
    unset($minmaxes);
    $minmaxes = '';
  }
  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }
  return getlocations_setlocations($latlons, $minmaxes, $type, '', $extra_info);
}

/**
 * Page callback: Displays a map.
 *
 * @param string $lidlist
 * A comma-delimited list of location ids
 *
 * @return
 *   Returns a map of locations.
 *
 */
function getlocations_lids($lidlist) {
  $lidarr = explode(',', $lidlist);
  $locations = array();
  $latlons = array();
  $minmaxes = array(
    'minlat' => 0,
    'minlon' => 0,
    'maxlat' => 0,
    'maxlon' => 0,
  );
  $marker = '';
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();
  foreach ($lidarr as $lid) {
    $locations[] = getlocations_load_location($lid);
  }
  if (count($locations)) {

    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations as $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        $location['key'] = '';
        $name = htmlspecialchars_decode(strip_tags($location['name']), ENT_QUOTES);
        $latlons[$ct] = array(
          $location['latitude'],
          $location['longitude'],
          $location['lid'],
          $name,
          $location['marker'],
          $location['key'],
          '',
          '',
        );
        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }
        $ct++;
      }
    }
  }
  if ($ct < 2) {
    unset($minmaxes);
    $minmaxes = '';
  }
  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }
  return getlocations_setlocations($latlons, $minmaxes, 'lids', '', $extra_info);
}

/**
 * Page callback: Displays a map.
 *
 * @param string $nidlist
 * A comma-delimited list of node ids
 *
 * @return
 *   Returns a map of locations.
 *
 */
function getlocations_nids($nidlist) {
  $nidarr = explode(',', $nidlist);
  $locations = array();
  $latlons = array();
  $minmaxes = array(
    'minlat' => 0,
    'minlon' => 0,
    'maxlat' => 0,
    'maxlon' => 0,
  );
  $typemarkers = getlocations_get_markertypes('node');
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();
  foreach ($nidarr as $nid) {
    $vid = getlocations_get_vid($nid);
    $locs = getlocations_load_locations($vid);
    if (count($locs)) {
      foreach ($locs as $key => $loc) {
        $type = getlocations_get_nodetype($nid);
        if (isset($typemarkers[$type])) {
          $loc['marker'] = $typemarkers[$type];
        }
        $locations[] = $loc;
      }
    }
  }
  if (count($locations)) {

    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations as $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        if (!isset($location['key'])) {
          $location['key'] = '';
        }
        else {
          if ($location['key'] == 'nid') {
            $location['lid'] = $nid;
          }
          elseif ($location['key'] == 'vid') {
            $location['lid'] = $vid;
          }
        }
        $name = htmlspecialchars_decode(strip_tags($location['name']), ENT_QUOTES);
        $latlons[$ct] = array(
          $location['latitude'],
          $location['longitude'],
          $location['lid'],
          $name,
          $location['marker'],
          $location['key'],
          '',
          '',
        );
        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }
        $ct++;
      }
    }
  }
  if ($ct < 2) {
    unset($minmaxes);
    $minmaxes = '';
  }
  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }
  return getlocations_setlocations($latlons, $minmaxes, 'nids', '', $extra_info);
}

/**
 * Set up javascript settings and map
 *
 * @param array $latlons
 * @param array $minmaxes
 * @param string $type
 * @param object $node
 * @param string $width
 * @param string $height
 *
 * @return string themed map html
 */
function getlocations_setlocations($latlons, $minmaxes = '', $type = 'node', $node = '', $extras = '', $width = '', $height = '') {
  if (!getlocations_defaults_check()) {
    return t('You need to !c first.', array(
      '!c' => l('Configure Getlocations', 'admin/config/services/getlocations'),
    ));
  }
  $getlocations_defaults = getlocations_defaults();
  $module = getlocations_get_current_supported_module();

  // sv
  if ($extras) {
    if ($module == 'getlocations_fields') {
      if (getlocations_fields_streetview_settings_allow()) {
        $getlocations_defaults['sv_heading'] = $extras['sv_heading'];
        $getlocations_defaults['sv_zoom'] = $extras['sv_zoom'];
        $getlocations_defaults['sv_pitch'] = $extras['sv_pitch'];
        $getlocations_defaults['sv_showfirst'] = $extras['sv_showfirst'];
        $getlocations_defaults['sv_addresscontrol'] = $extras['sv_addresscontrol'];
        $getlocations_defaults['sv_addresscontrolposition'] = $extras['sv_addresscontrolposition'];
        $getlocations_defaults['sv_pancontrol'] = $extras['sv_pancontrol'];
        $getlocations_defaults['sv_pancontrolposition'] = $extras['sv_pancontrolposition'];
        $getlocations_defaults['sv_zoomcontrol'] = $extras['sv_zoomcontrol'];
        $getlocations_defaults['sv_zoomcontrolposition'] = $extras['sv_zoomcontrolposition'];
        $getlocations_defaults['sv_linkscontrol'] = $extras['sv_linkscontrol'];
        $getlocations_defaults['sv_imagedatecontrol'] = $extras['sv_imagedatecontrol'];
        $getlocations_defaults['sv_scrollwheel'] = $extras['sv_scrollwheel'];
        $getlocations_defaults['sv_clicktogo'] = $extras['sv_clicktogo'];
      }
      if (getlocations_fields_map_settings_allow()) {
        $getlocations_defaults['nodezoom'] = $extras['mapzoom'];
        $getlocations_defaults['maptype'] = $extras['map_maptype'];

        // update baselayers
        $getlocations_defaults['baselayers'][$extras['map_maptype']] = 1;
      }
    }
  }
  $mapid = getlocations_setup_map($getlocations_defaults);
  getlocations_js_settings_do($getlocations_defaults, $latlons, $minmaxes, $mapid);
  if (empty($width)) {
    $width = $getlocations_defaults['width'];
  }
  if (empty($height)) {
    $height = $getlocations_defaults['height'];
  }
  return theme('getlocations_show', array(
    'width' => $width,
    'height' => $height,
    'defaults' => $getlocations_defaults,
    'mapid' => $mapid,
    'latlons' => $latlons,
    'minmaxes' => $minmaxes,
    'type' => $type,
    'node' => $node,
  ));
}

/**
 * Function to setup the map scripts
 *
 * @param array $defaults
 *   Required. the current settings.
 * Sets up the call to googlemaps, css and the relevant getlocations js in html head
 */
function getlocations_setup_map($defaults, $googleonly = FALSE, $sv = FALSE, $keyonly = FALSE) {
  static $getlocations_mapid = 0;

  // Generate unique Map ID.
  $getlocations_mapid++;
  $mapid = 'key_' . $getlocations_mapid;
  if (!$keyonly) {
    getlocations_setup_js($defaults, $googleonly, $sv);
  }
  return $mapid;
}

/**
 * Function to setup the map scripts
 *
 * @param array $defaults
 *   Required. the current settings.
 * Sets up the call to googlemaps, css and the relevant getlocations js in html head
 */
function getlocations_setup_js($defaults, $googleonly = FALSE, $sv = FALSE) {
  global $language;
  $current_js = drupal_get_js();
  $current_css = drupal_get_css();
  static $getlocations_js_weight = 0;
  $getlocations_js_weight++;
  if (is_numeric($defaults['getlocations_js_weight']) && $defaults['getlocations_js_weight'] != 0) {
    $getlocations_js_weight += $defaults['getlocations_js_weight'];
  }
  $key = variable_get('getlocations_api3_key', '');
  $clientID = variable_get('getlocations_api3_clientID', '');
  $signature = variable_get('getlocations_api3_signature', '');
  $channel = variable_get('getlocations_api3_channel', '');
  $signed_in = variable_get('getlocations_api3_signed_in', 0);
  $aggr = getlocations_aggr_get() ? TRUE : FALSE;

  // v3 googlemaps API
  $query = array();
  if (!empty($key)) {
    $query['key'] = $key;
    if ($signed_in) {
      $query['signed_in'] = 'true';
    }
  }
  if (!empty($clientID)) {
    $query['client'] = $clientID;
  }
  if (!empty($signature)) {
    $query['signature'] = $signature;
  }
  if (!empty($channel)) {
    $query['channel'] = $channel;
  }
  $query['sensor'] = getlocations_is_mobile() ? 'true' : 'false';
  $map_version = variable_get('getlocations_map_version', '');
  if ($map_version) {
    $query['v'] = $map_version;
  }
  if (isset($language->language)) {
    $query['language'] = $language->language;
  }
  if ($defaults['region_bias']) {
    $query['region'] = $defaults['region_bias'];
  }
  $libraries = array();
  if ($defaults['places'] || module_exists('getlocations_search')) {
    $libraries['places'] = 'places';
  }

  // not active but can be used by other modules
  if ($defaults['geometry']) {
    $libraries['geometry'] = 'geometry';
  }
  if ($defaults['visualization']) {
    $libraries['visualization'] = 'visualization';
  }
  if ($defaults['drawing']) {
    $libraries['drawing'] = 'drawing';
  }
  if ($defaults['adsense']) {
    $libraries['adsense'] = 'adsense';
  }

  // more libraries here
  // check for places library
  if (getlocations_places_check()) {
    $libraries['places'] = 'places';
  }

  // load libraries if any
  if (count($libraries)) {
    $query['libraries'] = implode(',', $libraries);
  }
  if (!isset($defaults['is_https']) || !$defaults['is_https']) {
    global $is_https;
    $defaults['is_https'] = $is_https;
  }
  $scheme = $defaults['is_https'] ? 'https' : 'http';
  $gmapdomain = "maps.googleapis.com/maps/api/js";
  $gmaplink = url($scheme . '://' . $gmapdomain, array(
    'query' => $query,
  ));
  if (!stristr($current_js, $scheme . '://' . $gmapdomain)) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'external';
    drupal_add_js($gmaplink, $js_opts);
    $getlocations_js_weight++;
  }
  if ($defaults['use_jsapi']) {
    $jsapilink = url($scheme . '://' . 'www.google.com/jsapi');
    if (!stristr($current_js, $jsapilink)) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'external';
      drupal_add_js($jsapilink, $js_opts);
      $getlocations_js_weight++;
    }
  }

  // geocoder-js
  if ($defaults['geocoder_enable'] && ($geocoder_path = getlocations_get_geocoder_path())) {
    if (!stristr($current_js, $geocoder_path)) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($geocoder_path, $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($googleonly) {
    return;
  }
  $getlocations_paths = getlocations_paths_get();
  if (!stristr($current_css, GETLOCATIONS_PATH . '/getlocations.css')) {
    drupal_add_css(GETLOCATIONS_PATH . '/getlocations.css');
  }

  // streetview only
  if ($sv && module_exists('getlocations_fields')) {
    $getlocations_fields_paths = getlocations_fields_paths_get();
    if (!stristr($current_js, $getlocations_fields_paths['getlocations_fields_streetview_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_fields_paths['getlocations_fields_streetview_path'], $js_opts);
      $getlocations_js_weight++;
    }
    return;
  }
  if (!stristr($current_js, $getlocations_paths['getlocations_icons_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_icons_path'], $js_opts);
    $getlocations_js_weight++;
  }
  $markerfile = getlocations_get_markerfile();
  if ($markerfile && !stristr($current_js, $markerfile)) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($markerfile, $js_opts);
    $getlocations_js_weight++;
  }
  if ($defaults['markermanagertype'] == 1 && !stristr($current_js, $getlocations_paths['markermanager_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['markermanager_path'], $js_opts);
    $getlocations_js_weight++;
  }
  elseif ($defaults['markermanagertype'] == 2 && !stristr($current_js, $getlocations_paths['markerclusterer_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['markerclusterer_path'], $js_opts);
    $getlocations_js_weight++;
    if (file_exists(GETLOCATIONS_PATH . '/getlocations.markercluster_override.inc')) {
      module_load_include('inc', 'getlocations', 'getlocations.markercluster_override');
    }
    else {
      module_load_include('inc', 'getlocations', 'getlocations.markercluster');
    }
    $markerclusterer_styles = getlocations_get_markerclusterer_styles();
    $js_opts = array();
    $js_opts['type'] = 'setting';
    drupal_add_js(array(
      'getlocations_markerclusterer' => $markerclusterer_styles,
    ), $js_opts);
  }
  if ($defaults['markeraction'] == 2 && !stristr($current_js, $getlocations_paths['infobubble_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['infobubble_path'], $js_opts);
    $getlocations_js_weight++;
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['infobubble_extended_path'], $js_opts);
    $getlocations_js_weight++;
    if (file_exists($getlocations_paths['infobubble_options_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['infobubble_options_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  elseif ($defaults['markeraction'] == 1 && file_exists($getlocations_paths['infowindow_options_path']) && !stristr($current_js, $getlocations_paths['infowindow_options_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['infowindow_options_path'], $js_opts);
    $getlocations_js_weight++;
  }

  // load main getlocations.js
  if (!stristr($current_js, $getlocations_paths['getlocations_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_path'], $js_opts);
    $getlocations_js_weight++;
  }
  if ($defaults['polygons_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_polygons_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_polygons_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($defaults['rectangles_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_rectangles_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_rectangles_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($defaults['circles_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_circles_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_circles_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($defaults['polylines_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_polylines_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_polylines_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // search_places
  if ($defaults['search_places']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_search_places_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_search_places_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // categories
  if ($defaults['category_method'] && $defaults['category_showhide_buttons']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_categories_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_categories_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // preview map
  if ($defaults['extcontrol'] == 'preview_map') {
    if (!stristr($current_js, $getlocations_paths['getlocations_preview_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_preview_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // geojson
  if ($defaults['geojson_enable'] && ($geojson_path = getlocations_get_geojson_path())) {
    if (!stristr($current_js, $geojson_path)) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($geojson_path, $js_opts);
      $getlocations_js_weight++;
    }
    if ($defaults['geojson_data']) {
      if (!stristr($current_js, $getlocations_paths['getlocations_geojson_path'])) {
        $js_opts = array();
        $js_opts['weight'] = $getlocations_js_weight;
        $js_opts['type'] = 'file';
        $js_opts['preprocess'] = $aggr;
        drupal_add_js($getlocations_paths['getlocations_geojson_path'], $js_opts);
        $getlocations_js_weight++;
      }
    }
  }
  if ($defaults['geo_enable'] && !stristr($current_js, $getlocations_paths['getlocations_geo_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight + 10;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_geo_path'], $js_opts);
    $getlocations_js_weight++;
  }
  if (module_exists('field_group') && !stristr($current_js, $getlocations_paths['getlocations_field_group_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight + 10;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_field_group_path'], $js_opts);
    $getlocations_js_weight++;
  }

  // What3Words
  if ($defaults['what3words_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_what3words_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_what3words_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
}

/**
 * Some defaults.
 *
 * @return
 *   Returns the current settings
 */
function getlocations_defaults($reset = FALSE) {
  global $is_https;
  $module = getlocations_get_current_supported_module();
  $defaults = array(
    'api_version' => 3,
    'map_version' => '',
    'width' => '300px',
    'height' => '200px',
    'zoom' => 3,
    'minzoom_map' => -1,
    'maxzoom_map' => -1,
    'controltype' => 'small',
    'zoomcontrolposition' => '',
    'pancontrol' => 1,
    'pancontrolposition' => '',
    'mapcontrolposition' => '',
    'latlong' => '40,0',
    'maptype' => 'Map',
    'mtc' => 'standard',
    'scale' => 0,
    'overview' => 0,
    'overview_opened' => 0,
    'scrollwheel' => 0,
    'scalecontrolposition' => '',
    'sv_show' => 0,
    // Pegman
    'svcontrolposition' => '',
    'sv_showfirst' => 0,
    // Overlay
    'sv_heading' => 0,
    'sv_zoom' => 1,
    'sv_pitch' => 0,
    'sv_enable' => 0,
    // switch set in getlocations_fields, applies to Views
    'sv_addresscontrol' => 1,
    // sv overlay controls
    'sv_addresscontrolposition' => '',
    'sv_pancontrol' => 1,
    'sv_pancontrolposition' => '',
    'sv_zoomcontrol' => 'default',
    'sv_zoomcontrolposition' => '',
    'sv_linkscontrol' => 1,
    'sv_imagedatecontrol' => 0,
    'sv_scrollwheel' => 1,
    'sv_clicktogo' => 1,
    'trafficinfo' => 0,
    'trafficinfo_state' => 0,
    'bicycleinfo' => 0,
    'bicycleinfo_state' => 0,
    'transitinfo' => 0,
    'transitinfo_state' => 0,
    'places' => 0,
    'poi_show' => 1,
    'transit_show' => 1,
    'node_map_marker' => 'drupal',
    'user_map_marker' => 'drupal',
    'vocabulary_map_marker' => 'drupal',
    'term_map_marker' => 'drupal',
    'comment_map_marker' => 'drupal',
    'input_map_marker' => 'drupal',
    'markeraction' => 0,
    'markeractiontype' => 1,
    'markeraction_click_zoom' => -1,
    'markeraction_click_center' => 0,
    'minzoom' => 6,
    'maxzoom' => 16,
    'nodezoom' => 12,
    'markermanagertype' => 0,
    'usemarkermanager' => 0,
    'useclustermanager' => 0,
    'markerclusterer_style' => -1,
    'markerclusterer_zoom' => -1,
    'markerclusterer_size' => -1,
    'markerclusterer_minsize' => -1,
    'markerclusterer_title' => t('Click here to see more'),
    'markerclusterer_imgpath' => base_path() . GETLOCATIONS_PATH . '/js/images',
    'pansetting' => 2,
    'draggable' => 1,
    'styles' => '',
    'returnlink_page_enable' => 0,
    'returnlink_page_link' => t('Return to Page'),
    'returnlink_user_enable' => 0,
    'returnlink_user_link' => t('Return to User'),
    'returnlink_term_enable' => 0,
    'returnlink_term_link' => t('Return to Term'),
    'returnlink_comment_enable' => 0,
    'returnlink_comment_link' => t('Return to Comment'),
    'getlocations_js_weight' => 0,
    'custom_content_enable' => 0,
    'custom_content_source' => '',
    'use_jsapi' => 0,
    'preload_data' => 0,
    'is_mobile' => getlocations_is_mobile() ? 1 : 0,
    'geometry' => 0,
    'visualization' => 0,
    'drawing' => 0,
    'adsense' => 0,
    'map_backgroundcolor' => '',
    'show_maplinks' => 0,
    'show_maplinks_viewport' => 0,
    'fullscreen' => 0,
    'show_bubble_on_one_marker' => 0,
    'polygons_enable' => 0,
    'polygons_strokecolor' => "#FF0000",
    'polygons_strokeopacity' => "0.8",
    'polygons_strokeweight' => "3",
    'polygons_fillcolor' => "#FF0000",
    'polygons_fillopacity' => "0.35",
    'polygons_coords' => "",
    'polygons_clickable' => 0,
    'polygons_message' => "",
    'rectangles_enable' => 0,
    'rectangles_strokecolor' => "#FF0000",
    'rectangles_strokeopacity' => "0.8",
    'rectangles_strokeweight' => "3",
    'rectangles_fillcolor' => "#FF0000",
    'rectangles_fillopacity' => "0.35",
    'rectangles_coords' => "",
    'rectangles_clickable' => 0,
    'rectangles_message' => "",
    'rectangles_apply' => 0,
    'rectangles_dist' => 0,
    'circles_enable' => 0,
    'circles_strokecolor' => "#FF0000",
    'circles_strokeopacity' => "0.8",
    'circles_strokeweight' => "3",
    'circles_fillcolor' => "#FF0000",
    'circles_fillopacity' => "0.35",
    'circles_coords' => "",
    'circles_clickable' => 0,
    'circles_message' => "",
    'circles_radius' => 0,
    'circles_apply' => 0,
    'polylines_enable' => 0,
    'polylines_strokecolor' => "#FF0000",
    'polylines_strokeopacity' => "0.8",
    'polylines_strokeweight' => "3",
    'polylines_coords' => "",
    'polylines_clickable' => 0,
    'polylines_message' => "",
    'category_method' => 0,
    'category_term_reference_field' => '',
    'category_showhide_buttons' => 0,
    'categories' => '',
    'kml_group' => array(
      'kml_url' => '',
      'kml_url_click' => 1,
      'kml_url_infowindow' => 0,
      'kml_url_viewport' => 1,
      'kml_url_button' => 0,
      'kml_url_button_label' => 'Kml Layer',
      'kml_url_button_state' => 0,
    ),
    'map_resize' => 0,
    'region_bias' => variable_get('site_default_country', ''),
    'fullscreen_disable' => 0,
    'fullscreen_controlposition' => '',
    'search_places' => 0,
    'search_places_size' => 40,
    'search_places_position' => 'outside_above',
    'search_places_label' => t('Google Places Search'),
    'search_places_placeholder' => '',
    'search_places_dd' => 0,
    'search_places_list' => 0,
    'getdirections_enabled' => module_exists('getdirections') ? 1 : 0,
    'jquery_colorpicker_enabled' => module_exists('jquery_colorpicker') ? 1 : 0,
    'geo_enable' => 0,
    'extcontrol' => '',
    'geojson_enable' => 0,
    'geojson_data' => '',
    'geojson_options' => '',
    'nokeyboard' => 0,
    'nodoubleclickzoom' => 0,
    'input_map_show' => 1,
    'highlight_enable' => 0,
    'highlight_strokecolor' => "#FF0000",
    'highlight_strokeopacity' => "0.8",
    'highlight_strokeweight' => "3",
    'highlight_fillcolor' => "#FF0000",
    'highlight_fillopacity' => "0.35",
    'highlight_radius' => 10,
    'getdirections_link' => 0,
    'gps_button' => 0,
    'gps_button_label' => '',
    'gps_marker_title' => '',
    'gps_marker' => '',
    'gps_bubble' => 0,
    'gps_geocode' => 0,
    'gps_center' => 0,
    'gps_type' => 0,
    'gps_zoom' => -1,
    'smartip_button' => 0,
    'smartip_button_label' => '',
    'smartip_marker_title' => '',
    'smartip_marker' => '',
    'smartip_bubble' => 0,
    'smartip_center' => 0,
    'smartip_zoom' => -1,
    'smartip_callback' => 'getlocations_smartip/callback',
    'geolocation_mobile_check' => 1,
    'is_https' => $is_https ? 1 : 0,
    'show_search_distance' => 0,
    'views_search_marker_enable' => 0,
    'views_search_marker' => 'drupal',
    'views_search_marker_toggle' => 0,
    'views_search_marker_toggle_active' => 0,
    'views_search_radshape_enable' => 0,
    'views_search_radshape_strokecolor' => '#FF0000',
    'views_search_radshape_strokeopacity' => '0.8',
    'views_search_radshape_strokeweight' => '3',
    'views_search_radshape_fillcolor' => '#FF0000',
    'views_search_radshape_fillopacity' => '0.35',
    'views_search_radshape_toggle' => 0,
    'views_search_radshape_toggle_active' => 0,
    'views_search_center' => 0,
    'geocoder_enable' => 0,
    'what3words_enable' => 0,
    'what3words_search' => 1,
    'what3words_size' => '40',
    'what3words_map_marker' => 'drupal',
    'what3words_marker_show' => 0,
    'what3words_center' => 1,
    'what3words_zoom' => 12,
    'what3words_show' => 1,
    'what3words_click' => 1,
    'what3words_path' => 'getlocations/cb_w3w',
  );
  $providers = getlocations_get_map_providers();
  $baselayers = array();
  foreach ($providers as $k => $v) {
    $baselayers[$k] = $v['default'];
  }
  $defaults['baselayers'] = $baselayers;
  if ($reset) {
    return $defaults;
  }

  // ease over to new settings. Wed Sep 25 01:09:23 BST 2013
  $getlocations_defaults = variable_get('getlocations_default', $defaults);
  if (isset($getlocations_defaults['behavior'])) {
    foreach ($getlocations_defaults['behavior'] as $key => $val) {
      $getlocations_defaults[$key] = $val;
    }
    unset($getlocations_defaults['behavior']);
  }
  $newdefaults = getlocations_adjust_vars($defaults, $getlocations_defaults);
  return $newdefaults;
}

/**
 * Function to check if the configuration has been done yet
 *
 * @return
 *   Returns true or false
 */
function getlocations_defaults_check() {
  $check = variable_get('getlocations_default', 'xxx');
  if ($check == 'xxx') {
    return FALSE;
  }
  return TRUE;
}

/**
 * Function to check a lat,lon string
 *
 * @param string $latlon
 *
 * @return
 *   Returns normalized string or false
 */
function getlocations_latlon_check($latlon) {
  if (!empty($latlon)) {
    $ll = explode(',', $latlon);
    $lat = isset($ll[0]) ? $ll[0] : FALSE;
    $lon = isset($ll[1]) ? $ll[1] : FALSE;
    $lat = trim($lat);
    $lon = trim($lon);
    if ((abs($lat) || abs($lon)) && is_numeric($lat) && is_numeric($lon)) {
      $latregex = "/[-+]{0,1}[0-9]{1,}\\.{1}[0-9]{1,}/";
      if (!strpos($lat, '.')) {
        $latregex = "/[-+]{0,1}[0-9]{1,}/";
      }
      $lonregex = "/[-+]{0,1}[0-9]{1,}\\.{1}[0-9]{1,}/";
      if (!strpos($lon, '.')) {
        $lonregex = "/[-+]{0,1}[0-9]{1,}/";
      }
      if (preg_match($latregex, $lat) && preg_match($lonregex, $lon)) {

        // Normalize coordinates.
        $lat = getlocations_normalizelat($lat);
        $lon = getlocations_normalizelng($lon);
        return $lat . "," . $lon;
      }
    }
  }
  return FALSE;
}

/**
 * Function to check wether the google places library should be enabled.
 *
 * @return bool
 *
 *
 */
function getlocations_places_check() {
  $found = FALSE;
  if (module_exists('getlocations_fields')) {
    $getlocations_fields_defaults = getlocations_fields_defaults();
    if (isset($getlocations_fields_defaults['use_address']) && $getlocations_fields_defaults['use_address']) {
      $found = TRUE;
    }
  }
  $getlocations_defaults = getlocations_defaults();
  if ($getlocations_defaults['getdirections_enabled']) {
    $getdirections_defaults = getdirections_defaults();
    if (isset($getdirections_defaults['advanced_autocomplete']) && $getdirections_defaults['advanced_autocomplete']) {
      $found = TRUE;
    }
  }
  if (module_exists('getlocations_search')) {
    $getlocations_search_defaults = getlocations_search_defaults();
    if (isset($getlocations_search_defaults['method']) && $getlocations_search_defaults['method'] == 'google_ac') {
      $found = TRUE;
    }
  }
  return $found;
}

/**
 * Function to get the vid from node table.
 *
 * @param int $nid
 *
 * @return
 *   Returns vid.
 */
function getlocations_get_vid($nid) {
  if (is_numeric($nid) && $nid) {
    $query = db_select('node', 'n')
      ->fields('n', array(
      'vid',
    ))
      ->condition('n.nid', $nid);
    $row = $query
      ->execute()
      ->fetchAssoc();
    return isset($row['vid']) && $row['vid'] ? $row['vid'] : FALSE;
  }
  return FALSE;
}

/**
 * Function to get the nid from node table.
 *
 * @param int $vid
 *
 * @return
 *   Returns nid.
 */
function getlocations_get_nid($vid) {
  if (is_numeric($vid) && $vid) {
    $query = db_select('node', 'n')
      ->fields('n', array(
      'nid',
    ))
      ->condition('n.vid', $vid);
    $row = $query
      ->execute()
      ->fetchAssoc();
    return isset($row['nid']) && $row['nid'] ? $row['nid'] : FALSE;
  }
  return FALSE;
}

/**
 * Function to get nid from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns nid.
 */
function getlocations_get_nid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')
        ->fields('i', array(
        'nid',
      ))
        ->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && (module_exists('location_cck') || module_exists('location_node'))) {
      $query = db_select('location_instance', 'i')
        ->fields('i', array(
        'nid',
      ))
        ->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query
        ->execute()
        ->fetchAssoc();
      return isset($row['nid']) && $row['nid'] ? $row['nid'] : FALSE;
    }
  }
  return FALSE;
}

/**
 * Function to get uid from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns uid.
 */
function getlocations_get_uid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')
        ->fields('i', array(
        'uid',
      ))
        ->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && module_exists('location_user')) {
      $query = db_select('location_instance', 'i')
        ->fields('i', array(
        'uid',
      ))
        ->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query
        ->execute()
        ->fetchAssoc();
      return isset($row['uid']) && $row['uid'] ? $row['uid'] : FALSE;
    }
  }
  return FALSE;
}

/**
 * Function to get tid from getlocations_fields_entities table.
 *
 * @param int $lid
 *
 * @return
 *   Returns tid.
 */
function getlocations_get_tid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')
        ->fields('i', array(
        'tid',
      ))
        ->condition('i.glid', $lid);
    }
    if ($query) {
      $row = $query
        ->execute()
        ->fetchAssoc();
      return isset($row['tid']) && $row['tid'] ? $row['tid'] : FALSE;
    }
  }
  return FALSE;
}

/**
 * Function to get cid from getlocations_fields_entities table.
 *
 * @param int $lid
 *
 * @return
 *   Returns cid.
 */
function getlocations_get_cid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')
        ->fields('i', array(
        'cid',
      ))
        ->condition('i.glid', $lid);
    }
    if ($query) {
      $row = $query
        ->execute()
        ->fetchAssoc();
      return isset($row['cid']) && $row['cid'] ? $row['cid'] : FALSE;
    }
  }
  return FALSE;
}

/**
 * Function to get entity type from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns entity type.
 */
function getlocations_get_type_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')
        ->fields('i', array(
        'nid',
        'uid',
        'tid',
        'cid',
      ))
        ->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && (module_exists('location_cck') || module_exists('location_node') || module_exists('location_user'))) {
      $query = db_select('location_instance', 'i')
        ->fields('i', array(
        'nid',
        'uid',
      ))
        ->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query
        ->execute()
        ->fetchAssoc();
      $type = '';
      if (isset($row['nid']) && $row['nid'] > 0) {
        $type = 'node';
      }
      elseif (isset($row['uid']) && $row['uid'] > 0) {
        $type = 'user';
      }
      elseif (isset($row['tid']) && $row['tid'] > 0 && module_exists('taxonomy')) {
        $type = 'vocabulary';
      }
      elseif (isset($row['cid']) && $row['cid'] > 0 && module_exists('comment')) {
        $type = 'comment';
      }
      return $type;
    }
  }
  return FALSE;
}

/**
 * Function to get entity path from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns entity path as url.
 */
function getlocations_get_path_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')
        ->fields('i', array(
        'nid',
        'uid',
        'tid',
        'cid',
      ))
        ->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && (module_exists('location_cck') || module_exists('location_node') || module_exists('location_user'))) {
      $query = db_select('location_instance', 'i')
        ->fields('i', array(
        'nid',
        'uid',
      ))
        ->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query
        ->execute()
        ->fetchAssoc();
      $path = '';
      if (isset($row['nid']) && $row['nid'] > 0) {
        $path = url('node/' . $row['nid']);
      }
      elseif (isset($row['uid']) && $row['uid'] > 0) {
        $path = url('user/' . $row['uid']);
      }
      elseif (isset($row['tid']) && $row['tid'] > 0 && module_exists('taxonomy')) {
        $path = url('taxonomy/term/' . $row['tid']);
      }
      elseif (isset($row['cid']) && $row['cid'] > 0 && module_exists('comment')) {
        $path = url('comment/' . $row['cid']);
      }
      return $path;
    }
  }
  return FALSE;
}

/**
 * Ajax callback
 * Fetches bubble content
 *
 * @see theme_getlocations_adinfo()
 */
function getlocations_adinfo() {
  $lid = $_GET['lid'];
  $lidkey = $_GET['key'];
  $extra = FALSE;
  if (isset($_GET['sdist'])) {
    $extra['sdist'] = $_GET['sdist'];
  }
  if (isset($_GET['gdlink'])) {
    $extra['gdlink'] = $_GET['gdlink'];
  }
  $content = getlocations_getinfo($lid, $lidkey, $extra);
  drupal_json_output(array(
    'content' => $content,
  ));
}

/**
 * @param int $lid location id
 * @param string entity id
 * @return string formatted address
 */
function getlocations_getinfo($lid, $lidkey, $extra = FALSE) {
  $content = FALSE;
  if ($lid > 0) {
    if (module_exists('getlocations_fields') || module_exists('location')) {
      $location = getlocations_load_location($lid);
      $location['nid'] = 0;
      $location['uid'] = 0;
      $location['tid'] = 0;
      $location['cid'] = 0;
      $type = getlocations_get_type_from_lid($lid);
      if ($type == 'node') {
        if ($nid = getlocations_get_nid_from_lid($lid)) {
          $location['nid'] = $nid;
        }
      }
      elseif ($type == 'user') {
        if ($uid = getlocations_get_uid_from_lid($lid)) {
          $location['uid'] = $uid;
        }
      }
      elseif ($type == 'vocabulary' && module_exists('taxonomy')) {
        if ($tid = getlocations_get_tid_from_lid($lid)) {
          $location['tid'] = $tid;
        }
      }
      elseif ($type == 'comment' && module_exists('comment')) {
        if ($cid = getlocations_get_cid_from_lid($lid)) {
          $location['cid'] = $cid;
        }
      }
    }
    elseif (module_exists('geofield') || module_exists('geolocation')) {
      $locations = getlocations_load_locations($lid, $lidkey);
      $location = $locations[0];
    }
    if ($extra) {
      if (is_array($extra) && isset($extra['sdist'])) {
        $sdist = $extra['sdist'];
        $arr = explode('|', $sdist);
        $sunit = $arr[0];
        $slat = $arr[1];
        $slon = $arr[2];
        $lat = $location['latitude'];
        $lon = $location['longitude'];
        $latlon_a = array(
          'lat' => $slat,
          'lon' => $slon,
        );
        $latlon_b = array(
          'lat' => $lat,
          'lon' => $lon,
        );
        $dist = getlocations_distance_between($latlon_a, $latlon_b, $sunit);
        $location['sdist'] = $dist['scalar'];
        $location['sunit'] = $dist['distance_unit'];
      }
      if (is_array($extra) && isset($extra['gdlink'])) {
        $location['getdirections_link'] = $extra['gdlink'];
      }
    }
    $content = theme('getlocations_adinfo', array(
      'location' => $location,
    ));
  }
  return $content;
}

/**
 * Ajax callback
 * Provides a link
 *
 * @see theme_getlocations_lidinfo()
 *
 */
function getlocations_lidinfo() {
  $lid = $_GET['lid'];
  $lidkey = $_GET['key'];
  $content = getlocations_getlidinfo($lid, $lidkey);
  drupal_json_output(array(
    'content' => $content,
  ));
}

/**
 * @param int $lid location id
 * @param string entity id
 * @return string path
 */
function getlocations_getlidinfo($lid, $lidkey) {
  $content = theme('getlocations_lidinfo', array(
    'lid' => $lid,
    'lidkey' => $lidkey,
  ));
  return $content;
}

/**
 * Ajax callback
 * provides data for marker colorbox
 *
 * @see template_preprocess_getlocations_marker_box()
 * @see getlocations_marker_box.tpl.php
 */
function getlocations_markerinfo() {
  $linktype = $_GET['lt'];
  $cat = $_GET['cat'];
  $content = "";
  $icons = getlocations_get_icondata();
  $data = array();
  $files = array();
  $machine_names = array();
  $display_names = array();
  $positions = array();
  $iconct = 0;
  foreach (array_keys($icons) as $path) {
    if (preg_match("~^/.*/\$~", $path)) {
      continue;
    }
    $files = $icons[$path]['f'];
    $machine_names = $icons[$path]['i'][0][0][0];
    $display_names = $icons[$path]['i'][0][0][1];
    $positions = $icons[$path]['i'][0][0][2];
    $newpositions = array();
    foreach ($positions as $pos) {
      if (isset($pos[0])) {
        $newpositions[] = $pos[0];
      }
    }
    $adj = 0;
    foreach ($newpositions as $pos) {

      // no shadow
      if ($pos < 1) {
        $adj = 1;
      }

      // skip this
      if ($files[$pos] == 'shadow.png') {
        continue;
      }
      $data[$iconct]['path'] = $path . $files[$pos];
      $data[$iconct]['machine_name'] = $machine_names[$pos + $adj];
      $data[$iconct]['display_name'] = $display_names[$pos + $adj];
      $iconct++;
    }
  }
  $content['data'] = $data;
  $content['linktype'] = $linktype;
  $content['cat'] = $cat;
  $output = theme('getlocations_marker_box', array(
    'content' => $content,
  ));
  print $output;
  exit;
}
function getlocations_cb_w3w() {
  $data = FALSE;
  $content = FALSE;
  if (isset($_REQUEST['data'])) {
    $data = $_REQUEST['data'];
  }
  if ($data) {
    if ($latlon = getlocations_latlon_check($data)) {

      # we have a latlon
      $type = 'position';
    }
    else {

      # must be a w3w
      $type = 'w3w';
    }
    $content = getlocations_cb_w3w_get($data, $type);
  }
  print $content;
  exit;
}
function getlocations_cb_w3w_get($data, $type) {
  $types = array(
    'w3w',
    'position',
  );
  if (in_array($type, $types)) {
    $what3words_lic = variable_get('getlocations_what3words_lic', array(
      'key' => '',
      'url' => 'http://api.what3words.com',
    ));
    $key = $what3words_lic['key'];
    if ($key) {
      $url = $what3words_lic['url'] . '/' . $type;
      $opts = array(
        'method' => 'POST',
        'headers' => array(
          'Content-Type' => 'application/x-www-form-urlencoded',
        ),
      );
      $datastr = 'key=' . $key;
      if ($type == 'position') {
        $datastr .= '&position=' . $data;
      }
      else {
        $datastr .= '&string=' . $data;
      }
      $opts['data'] = $datastr;
      $response = drupal_http_request($url, $opts);
      if ($response->code == '200') {
        return $response->data;
      }
    }
  }
  return FALSE;
}

/**
 * Get the list of marker titles.
 * adapted from gmap
 */
function getlocations_get_marker_titles($reset = FALSE) {
  static $titles;
  if (!$reset) {
    if (is_array($titles)) {
      return $titles;
    }
    $cached = cache_get('getlocations_marker_titles', 'cache');
    if (!empty($cached)) {
      $titles = $cached->data;
      if (is_array($titles)) {
        return $titles;
      }
    }
  }
  module_load_include('inc', 'getlocations', 'getlocations.markerinfo');
  $titles = _getlocations_get_marker_titles();
  cache_set('getlocations_marker_titles', $titles, 'cache');
  return $titles;
}

/**
 * Get the JSON icon data for all the default markers.
 * adapted from gmap
 */
function getlocations_get_icondata($reset = FALSE) {
  static $icons;
  if (is_array($icons) && !$reset) {
    return $icons;
  }
  $icons = cache_get('getlocations_icondata');
  if ($icons) {
    $icons = $icons->data;
  }
  if ($reset || !$icons) {
    module_load_include('inc', 'getlocations', 'getlocations.markerinfo');
    $icons = _getlocations_get_icondata();
  }
  if ($icons) {
    cache_set('getlocations_icondata', $icons, 'cache');
  }
  return $icons;
}

/**
 * Regenerate the markerdata file.
 * adapted from gmap
 */
function getlocations_regenerate_markers() {

  // This often fails in cli mode, so bail.
  if (drupal_is_cli()) {
    return;
  }
  $icons = getlocations_get_icondata(TRUE);
  if ($icons) {
    $contents = '';
    $contents .= "// Getlocations marker image data.\n";
    $contents .= "Drupal.getlocations.iconpath = " . drupal_json_encode(base_path()) . ";\n";
    $contents .= "Drupal.getlocations.icondata = " . drupal_json_encode($icons) . ";\n";

    // Create the js/ within the files folder.
    $jspath = getlocations_get_markerfile(TRUE, FALSE);
    $jsfile = getlocations_get_markerfile(FALSE, FALSE);
    if ($jspath && $jsfile && file_prepare_directory($jspath, FILE_CREATE_DIRECTORY) && file_unmanaged_save_data($contents, $jsfile, FILE_EXISTS_REPLACE)) {

      // Also regenerate the cached marker titles array
      getlocations_get_marker_titles(TRUE);
    }
    else {

      // failed
      drupal_set_message(t('Getlocations is unable to save the marker configuration, so the markers will not work. Please check file system permissions of %filepath!', array(
        '%filepath' => $jsfile,
      )), 'error');
      watchdog('getlocations', 'Getlocations write error when saving the marker configuration to %filepath.', array(
        '%filepath' => $jsfile,
      ), WATCHDOG_ERROR);
      return FALSE;
    }
  }
  else {

    // no markers found
    drupal_set_message(t('No markers found, you need to install some markers, please see the project page for details.'), 'error');
    watchdog('getlocations', 'No markers found.', array(), WATCHDOG_ERROR);
    return FALSE;
  }
  return TRUE;
}

/**
 * Function to find and return the filesystem path and filename of the markers definition javascript file
 *
 */
function getlocations_get_markerfile($dir = FALSE, $check = TRUE) {
  if (file_default_scheme() != 'public') {

    // private
    $markerpath = '';
    $markerfile = variable_get('getlocations_private_markerfile', '');
    if ($markerfile && preg_match("~^(.*)/getlocations_markers.js~", $markerfile, $matches)) {
      $markerpath = $matches[1];
    }
  }
  else {
    $markerpath = file_stream_wrapper_get_instance_by_scheme(file_default_scheme())
      ->getDirectoryPath() . '/getlocations';
    $markerfile = '';
    if ($markerpath) {
      $markerfile = $markerpath . '/getlocations_markers.js';
    }
  }
  if ($dir && $markerpath) {
    if ($check) {
      if (file_exists($markerpath)) {
        return $markerpath;
      }
    }
    else {
      return $markerpath;
    }
  }
  elseif ($markerfile) {
    if ($check) {
      if (file_exists($markerfile)) {
        return $markerfile;
      }
    }
    else {
      return $markerfile;
    }
  }
  return FALSE;
}

/**
 * hook_getlocations_markerdir()
 * from jhm http://drupal.org/user/15946
 *
 * This hook allows modules or themes to add their own markers
 */
function getlocations_getlocations_markerdir() {
  $markerdir = libraries_get_path('getlocations') . '/markers';
  return $markerdir;
}

/**
 * @param int $ct $location $minmaxes
 *
 * @return
 *   Returns $minmaxes
 *
 */
function getlocations_do_minmaxes($ct, $location, $minmaxes) {
  if ($minmaxes == '') {
    $minmaxes = array(
      'minlat' => 0,
      'minlon' => 0,
      'maxlat' => 0,
      'maxlon' => 0,
    );
  }
  if ($ct) {

    // latitudes
    if ($location['latitude'] > $minmaxes['maxlat']) {
      $minmaxes['maxlat'] = $location['latitude'];
    }
    if ($location['latitude'] < $minmaxes['minlat']) {
      $minmaxes['minlat'] = $location['latitude'];
    }

    // longitudes
    if ($location['longitude'] > $minmaxes['maxlon']) {
      $minmaxes['maxlon'] = $location['longitude'];
    }
    if ($location['longitude'] < $minmaxes['minlon']) {
      $minmaxes['minlon'] = $location['longitude'];
    }
  }
  else {
    $minmaxes['minlat'] = $location['latitude'];
    $minmaxes['minlon'] = $location['longitude'];
    $minmaxes['maxlat'] = $location['latitude'];
    $minmaxes['maxlon'] = $location['longitude'];
  }
  return $minmaxes;
}

/**
 * Function for colorbox and suchlike
 *
 * @return
 *   Returns themed content
 *
 */
function getlocations_box() {
  $a1 = FALSE;
  $a2 = FALSE;
  $a3 = FALSE;
  $a4 = FALSE;
  if (arg(1)) {
    $a1 = arg(1);
  }
  if (arg(2)) {
    $a2 = arg(2);
  }
  if (arg(3)) {
    $a3 = arg(3);
  }
  if (arg(4)) {
    $a4 = arg(4);
  }
  $content = '';

  // $a1 can be node, user, users, type, lids, nids
  if ($a1 == 'node' && $a2) {
    $content .= getlocations_nodemap($a2);
  }
  elseif ($a1 == 'user' && $a2) {
    $content .= getlocations_usermap($a2);
  }
  elseif ($a1 == 'term' && $a2) {
    $content .= getlocations_termmap($a2);
  }
  elseif ($a1 == 'comment' && $a2) {
    $content .= getlocations_commentmap($a2);
  }
  elseif ($a1 == 'users') {
    $content .= getlocations_usersmap();
  }
  elseif ($a1 == 'type' && $a2) {
    $content .= getlocations_typemap($a2, $a3, $a4);
  }
  elseif ($a1 == 'lids' && $a2) {
    $content .= getlocations_lids($a2);
  }
  elseif ($a1 == 'nids' && $a2) {
    $content .= getlocations_nids($a2);
  }
  $output = theme('getlocations_box', array(
    'content' => $content,
  ));
  print $output;
  exit;
}

/**
 * Function to fetch node types
 *
 *
 * @return
 *   Returns array of node types supported by the current supported locative module
 *
 */
function getlocations_get_types() {
  $options = array();
  foreach (node_type_get_types() as $type => $object) {
    if (getlocations_check_node($type)) {
      $options[$type] = $object->name;
    }
  }
  return $options;
}

/**
 * Function to check if bundle has a locative field
 *
 * @param string $bundle
 *
 * @return
 *   Returns boolean
 *
 */
function getlocations_check_node($bundle) {
  $module = getlocations_get_current_supported_module();
  if ($module) {
    $query = db_select('field_config', 'f');
    $query
      ->fields('f', array(
      'id',
    ));
    $query
      ->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query
      ->condition('i.bundle', $bundle)
      ->condition('f.module', $module)
      ->condition('i.entity_type', 'node')
      ->condition('f.active', 1);
    $rows = $query
      ->execute();
    $ct = 0;
    foreach ($rows as $row) {
      $ct++;
    }
    if ($ct) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Function to collect field name
 *
 * @param string $bundle
 * @param string $entity_type
 *
 * @return
 *   Returns field name or FALSE
 *
 */
function getlocations_get_fieldname($bundle, $entity_type = 'node') {
  $module = getlocations_get_current_supported_module();
  if ($module) {
    $query = db_select('field_config', 'f');
    $query
      ->fields('f', array(
      'field_name',
    ));
    $query
      ->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query
      ->condition('i.bundle', $bundle)
      ->condition('f.module', $module)
      ->condition('i.entity_type', $entity_type)
      ->condition('f.active', 1);
    $rows = $query
      ->execute();
    $ct = 0;
    foreach ($rows as $row) {
      $data = $row->field_name;
      $ct++;
    }
    if ($ct) {
      return $data;
    }
  }
  return FALSE;
}

/**
 * Function to collect field names
 *
 * @param string $bundle
 * @param string $entity_type
 *
 * @return
 *   Returns field names or FALSE
 *
 */
function getlocations_get_fieldname2($bundle, $entity_type = 'node') {
  $module = getlocations_get_current_supported_module();
  if ($module) {
    $query = db_select('field_config', 'f');
    $query
      ->fields('f', array(
      'field_name',
    ));
    $query
      ->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query
      ->condition('i.bundle', $bundle)
      ->condition('f.module', $module)
      ->condition('i.entity_type', $entity_type)
      ->condition('f.active', 1);
    $rows = $query
      ->execute();
    $ct = 0;
    foreach ($rows as $row) {
      $data[$ct] = $row->field_name;
      $ct++;
    }
    if ($ct) {
      return $data;
    }
  }
  return FALSE;
}

/**
 * Function to collect entities being used by the given module
 *
 * @param string $module
 *
 * @return
 *   Returns array of entity names or FALSE
 *
 */
function getlocations_get_supported_entities($module = FALSE) {
  if (!$module) {
    $module = getlocations_get_current_supported_module();
  }
  if ($module) {
    $query = db_select('field_config', 'f');
    $query
      ->fields('i', array(
      'entity_type',
    ));
    $query
      ->join('field_config_instance', 'i', 'f.id = i.field_id');
    $query
      ->condition('f.module', $module)
      ->condition('f.active', 1);
    $rows = $query
      ->execute();
    $data = array();
    foreach ($rows as $row) {
      $data[$row->entity_type] = $row->entity_type;
    }
    return count($data) ? array_keys($data) : FALSE;
  }
  return FALSE;
}

/**
 * Function is an entity_type location enabled?
 *
 * @param string $entity_type
 * @param string $bundle
 *
 * @return
 *   Returns boolean
 *
 */
function getlocations_check_entity_type($entity_type = '', $bundle = '') {
  if ($entity_type == 'term') {
    $entity_type = 'taxonomy_term';
  }
  if ($module = getlocations_get_current_supported_module()) {
    $query = db_select('field_config', 'f');
    $query
      ->fields('f', array(
      'id',
    ));
    $query
      ->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query
      ->condition('f.module', $module);
    if ($entity_type) {
      $query
        ->condition('i.entity_type', $entity_type);
    }
    if ($bundle) {
      $query
        ->condition('i.bundle', $bundle);
    }
    $query
      ->condition('f.active', 1);
    $number_of_rows = $query
      ->countQuery()
      ->execute()
      ->fetchField();
    if ($number_of_rows) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Function gets list of vocabularies
 *
 * @return
 *   Returns array
 *
 */
function getlocations_get_vocabularies() {
  if (module_exists('taxonomy')) {
    $vocabularies = taxonomy_get_vocabularies();
    $options = array();
    if (count($vocabularies)) {
      foreach ($vocabularies as $vid => $vocabulary) {
        if (getlocations_check_vocabulary($vocabulary->machine_name)) {
          $options[$vid] = $vocabulary->name;
        }
      }
      return $options;
    }
  }
  return FALSE;
}

/**
 * Function gets list of vocabulary machine names
 *
 * @return
 *   Returns array
 *
 */
function getlocations_get_machine_vocabularies() {
  if (module_exists('taxonomy')) {
    $vocabularies = taxonomy_get_vocabularies();
    $options = array();
    if (count($vocabularies)) {
      foreach ($vocabularies as $vid => $vocabulary) {
        if (getlocations_check_vocabulary($vocabulary->machine_name)) {
          $options[$vid] = $vocabulary->machine_name;
        }
      }
      return $options;
    }
  }
  return FALSE;
}

/**
 * Function to check a vocabulary
 *
 * @return
 *   Returns bool
 *
 */
function getlocations_check_vocabulary($machine_name) {
  if (module_exists('taxonomy')) {
    return getlocations_check_entity_type('taxonomy_term', $machine_name);
  }
  return FALSE;
}

/**
 * Function list of term reference fields
 *
 * @return
 *   Returns array
 *
 */
function getlocations_get_term_reference_fields() {
  $module = 'taxonomy';
  $type = 'taxonomy_term_reference';
  $query = db_select('field_config', 'f');
  $query
    ->fields('f', array(
    'field_name',
  ));
  $query
    ->condition('f.module', $module)
    ->condition('f.type', $type)
    ->condition('f.active', 1);
  $rows = $query
    ->execute();
  $data = array();
  foreach ($rows as $row) {
    $data[$row->field_name] = $row->field_name;
  }
  return $data;
}

/**
 * Function to fetch list of markers
 *
 * @param string $type
 *
 * @return
 *   Returns list of markers
 *
 */
function getlocations_get_markertypes($type) {
  $getlocations_defaults = getlocations_defaults();
  $markertypes = array();
  if ($type == 'node') {
    $default_marker = $getlocations_defaults['node_map_marker'];
    $getlocations_node_marker = variable_get('getlocations_node_marker', array(
      'enable' => 0,
    ));
    if ($getlocations_node_marker['enable']) {
      if ($content_types = getlocations_get_types()) {
        foreach ($content_types as $content_type => $name) {
          $field_names = getlocations_get_fieldname2($content_type, 'node');
          foreach ($field_names as $field_name) {
            if (isset($getlocations_node_marker['content_type'][$content_type]['field_name'][$field_name]['map_marker'])) {
              $markertypes[$content_type] = $getlocations_node_marker['content_type'][$content_type]['field_name'][$field_name]['map_marker'];
            }
            else {
              $markertypes[$content_type] = $default_marker;
            }
          }
        }
      }
    }
    return $markertypes;
  }
  elseif ($type == 'vocabulary' && module_exists('taxonomy')) {
    $default_marker = $getlocations_defaults['vocabulary_map_marker'];
    $vocabularies = getlocations_get_vocabularies();
    $getlocations_vocabulary_marker = variable_get('getlocations_vocabulary_marker', array(
      'enable' => 0,
    ));
    foreach ($vocabularies as $vid => $vocabulary) {
      if ($getlocations_vocabulary_marker['enable'] && isset($getlocations_vocabulary_marker['vocabulary'][$vid]['map_marker'])) {
        $markertypes[$vid] = $getlocations_vocabulary_marker['vocabulary'][$vid]['map_marker'];
      }
      else {
        $markertypes[$vid] = $default_marker;
      }
    }
    return $markertypes;
  }
  elseif ($type == 'term' && module_exists('taxonomy')) {
    $default_marker = $getlocations_defaults['term_map_marker'];
    $getlocations_term_marker = variable_get('getlocations_term_marker', array(
      'enable' => 0,
      'vids' => 0,
      'max_depth' => '',
    ));
    if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
      $depth = is_numeric($getlocations_term_marker['max_depth']) && $getlocations_term_marker['max_depth'] > 0 ? $getlocations_term_marker['max_depth'] : NULL;
      $vids = $getlocations_term_marker['vids'];
      foreach ($vids as $vid) {
        $terms = taxonomy_get_tree($vid, 0, $depth);
        foreach ($terms as $term) {
          if (isset($getlocations_term_marker['vid'][$vid]['term'][$term->tid]['map_marker'])) {
            $markertypes[$term->tid] = $getlocations_term_marker['vid'][$vid]['term'][$term->tid]['map_marker'];
          }
          else {
            $markertypes[$term->tid] = $default_marker;
          }
        }
      }
    }
    return $markertypes;
  }
  else {
    return FALSE;
  }
}

/**
 * Function to fetch a node type or bundle
 *
 * @param int $nid The node Identifier
 *
 * @return
 *   Returns the bundle name or false
 *
 */
function getlocations_get_nodetype($nid) {
  $query = db_select('node', 'n')
    ->fields('n', array(
    'type',
  ))
    ->condition('n.nid', $nid);
  $row = $query
    ->execute()
    ->fetchAssoc();
  return isset($row['type']) && $row['type'] ? $row['type'] : FALSE;
}

/**
 * Function sets up javascript settings
 *
 * @param array $defaults
 * @param array $latlons
 * @param array $minmaxes
 * @param string $mapid
 * @param bool $inputmap
 * @param string $extcontrol
 *
 */
function getlocations_js_settings_do($defaults, $latlons, $minmaxes, $mapid, $inputmap = FALSE, $extcontrol = '') {
  global $language;
  $lla = explode(',', $defaults['latlong']);
  $lat = $lla[0];
  $lng = $lla[1];
  $settings = array(
    $mapid => array(
      'lat' => trim($lat),
      'lng' => trim($lng),
      'locale_prefix' => $language->prefix,
      'zoom' => $defaults['zoom'],
      'minzoom_map' => $defaults['minzoom_map'],
      'maxzoom_map' => $defaults['maxzoom_map'],
      'maptype' => $defaults['maptype'],
      'controltype' => $defaults['controltype'],
      'mtc' => $defaults['mtc'],
      'baselayers' => $defaults['baselayers'],
      'scale' => $defaults['scale'],
      'overview' => $defaults['overview'],
      'overview_opened' => $defaults['overview_opened'],
      'scrollwheel' => $defaults['scrollwheel'],
      'trafficinfo' => $defaults['trafficinfo'],
      'trafficinfo_state' => $defaults['trafficinfo_state'],
      'bicycleinfo' => $defaults['bicycleinfo'],
      'bicycleinfo_state' => $defaults['bicycleinfo_state'],
      'transitinfo' => $defaults['transitinfo'],
      'transitinfo_state' => $defaults['transitinfo_state'],
      'sv_show' => $defaults['sv_show'],
      'sv_showfirst' => $defaults['sv_showfirst'],
      'sv_heading' => $defaults['sv_heading'],
      'sv_zoom' => $defaults['sv_zoom'],
      'sv_pitch' => $defaults['sv_pitch'],
      'pancontrol' => $defaults['pancontrol'],
      'poi_show' => $defaults['poi_show'],
      'transit_show' => $defaults['transit_show'],
      'map_marker' => $defaults['node_map_marker'],
      'markeraction' => $defaults['markeraction'],
      'markeractiontype' => $defaults['markeractiontype'],
      'markeraction_click_zoom' => $defaults['markeraction_click_zoom'],
      'markeraction_click_center' => $defaults['markeraction_click_center'],
      'minzoom' => $defaults['minzoom'],
      'maxzoom' => $defaults['maxzoom'],
      'nodezoom' => $defaults['nodezoom'],
      'markermanagertype' => $defaults['markermanagertype'],
      'usemarkermanager' => $defaults['usemarkermanager'],
      'useclustermanager' => $defaults['useclustermanager'],
      'markerclusterer_style' => $defaults['markerclusterer_style'],
      'markerclusterer_zoom' => $defaults['markerclusterer_zoom'],
      'markerclusterer_size' => $defaults['markerclusterer_size'],
      'markerclusterer_minsize' => $defaults['markerclusterer_minsize'],
      'markerclusterer_title' => $defaults['markerclusterer_title'],
      'markerclusterer_imgpath' => $defaults['markerclusterer_imgpath'],
      'pansetting' => $defaults['pansetting'],
      'draggable' => $defaults['draggable'],
      'styles' => $defaults['styles'],
      'inputmap' => $inputmap ? 1 : 0,
      'extcontrol' => $extcontrol,
      'custom_content_enable' => $defaults['custom_content_enable'],
      'preload_data' => $defaults['preload_data'],
      'is_mobile' => getlocations_is_mobile() ? 1 : 0,
      'map_backgroundcolor' => $defaults['map_backgroundcolor'],
      'show_maplinks' => $defaults['show_maplinks'],
      'show_maplinks_viewport' => $defaults['show_maplinks_viewport'],
      'js_path' => base_path() . GETLOCATIONS_PATH . '/js/',
      'images_path' => base_path() . GETLOCATIONS_PATH . '/images/',
      'info_path' => url("getlocations_cb/info"),
      'lidinfo_path' => url("getlocations_cb/lidinfo"),
      'fullscreen' => $defaults['fullscreen'],
      'show_bubble_on_one_marker' => $defaults['show_bubble_on_one_marker'],
      'kml_url' => $defaults['kml_group']['kml_url'],
      'fullscreen_disable' => $defaults['fullscreen_disable'],
      'fullscreen_controlposition' => $defaults['fullscreen_controlposition'],
      'places' => $defaults['places'],
      'search_places' => $defaults['search_places'],
      'getdirections_enabled' => $defaults['getdirections_enabled'],
      'is_https' => $defaults['is_https'],
      'geojson_enable' => $defaults['geojson_enable'],
      'nokeyboard' => $defaults['nokeyboard'],
      'nodoubleclickzoom' => $defaults['nodoubleclickzoom'],
      'zoomcontrolposition' => $defaults['zoomcontrolposition'],
      'mapcontrolposition' => $defaults['mapcontrolposition'],
      'pancontrolposition' => $defaults['pancontrolposition'],
      'scalecontrolposition' => $defaults['scalecontrolposition'],
      'svcontrolposition' => $defaults['svcontrolposition'],
      'sv_addresscontrol' => $defaults['sv_addresscontrol'],
      // sv overlay controls
      'sv_addresscontrolposition' => $defaults['sv_addresscontrolposition'],
      'sv_pancontrol' => $defaults['sv_pancontrol'],
      'sv_pancontrolposition' => $defaults['sv_pancontrolposition'],
      'sv_zoomcontrol' => $defaults['sv_zoomcontrol'],
      'sv_zoomcontrolposition' => $defaults['sv_zoomcontrolposition'],
      'sv_linkscontrol' => $defaults['sv_linkscontrol'],
      'sv_imagedatecontrol' => $defaults['sv_imagedatecontrol'],
      'sv_scrollwheel' => $defaults['sv_scrollwheel'],
      'sv_clicktogo' => $defaults['sv_clicktogo'],
      'input_map_show' => $defaults['input_map_show'],
    ),
  );

  // only set these if wanted
  if ($defaults['kml_group']['kml_url']) {
    $settings[$mapid]['kml_url_click'] = $defaults['kml_group']['kml_url_click'];
    $settings[$mapid]['kml_url_infowindow'] = $defaults['kml_group']['kml_url_infowindow'];
    $settings[$mapid]['kml_url_viewport'] = $defaults['kml_group']['kml_url_viewport'];
    $settings[$mapid]['kml_url_button'] = $defaults['kml_group']['kml_url_button'];
    $settings[$mapid]['kml_url_button_label'] = $defaults['kml_group']['kml_url_button_label'];
    $settings[$mapid]['kml_url_button_state'] = $defaults['kml_group']['kml_url_button_state'];
  }
  if ($defaults['search_places']) {
    $settings[$mapid]['search_places_size'] = $defaults['search_places_size'];
    $settings[$mapid]['search_places_position'] = $defaults['search_places_position'];
    $settings[$mapid]['search_places_label'] = $defaults['search_places_label'];
    $settings[$mapid]['search_places_placeholder'] = $defaults['search_places_placeholder'];
    $settings[$mapid]['search_places_dd'] = $defaults['search_places_dd'];
    $settings[$mapid]['search_places_list'] = $defaults['search_places_list'];
  }
  if ($defaults['geojson_enable']) {
    $settings[$mapid]['geojson_data'] = $defaults['geojson_data'];
    $settings[$mapid]['geojson_options'] = $defaults['geojson_options'];
  }

  // categories
  if (isset($defaults['categories'])) {
    $settings[$mapid]['categories'] = $defaults['categories'];
  }
  else {
    $settings[$mapid]['categories'] = array();
  }

  // highlighting
  $settings[$mapid]['highlight_enable'] = $defaults['highlight_enable'];
  if ($defaults['highlight_enable']) {
    if (!preg_match("/^#/", $defaults['highlight_strokecolor'])) {
      $defaults['highlight_strokecolor'] = '#' . $defaults['highlight_strokecolor'];
    }
    if (!preg_match("/^#/", $defaults['highlight_fillcolor'])) {
      $defaults['highlight_fillcolor'] = '#' . $defaults['highlight_fillcolor'];
    }
    $settings[$mapid]['highlight_strokecolor'] = $defaults['highlight_strokecolor'];
    $settings[$mapid]['highlight_strokeopacity'] = $defaults['highlight_strokeopacity'];
    $settings[$mapid]['highlight_strokeweight'] = $defaults['highlight_strokeweight'];
    $settings[$mapid]['highlight_fillcolor'] = $defaults['highlight_fillcolor'];
    $settings[$mapid]['highlight_fillopacity'] = $defaults['highlight_fillopacity'];
    $settings[$mapid]['highlight_radius'] = $defaults['highlight_radius'];
  }
  $settings[$mapid]['getdirections_link'] = $defaults['getdirections_link'];
  $settings[$mapid]['show_search_distance'] = $defaults['show_search_distance'];
  $settings[$mapid]['views_search_marker_enable'] = $defaults['views_search_marker_enable'];
  $settings[$mapid]['views_search_radshape_enable'] = $defaults['views_search_radshape_enable'];
  $settings[$mapid]['views_search_center'] = $defaults['views_search_center'];
  if ($defaults['views_search_marker_enable'] || $defaults['views_search_radshape_enable']) {
    $settings[$mapid]['views_search_marker'] = $defaults['views_search_marker'];
    $settings[$mapid]['views_search_marker_toggle'] = $defaults['views_search_marker_toggle'];
    $settings[$mapid]['views_search_marker_toggle_active'] = $defaults['views_search_marker_toggle_active'];
    $settings[$mapid]['views_search_radshape_strokecolor'] = $defaults['views_search_radshape_strokecolor'];
    $settings[$mapid]['views_search_radshape_strokeopacity'] = $defaults['views_search_radshape_strokeopacity'];
    $settings[$mapid]['views_search_radshape_strokeweight'] = $defaults['views_search_radshape_strokeweight'];
    $settings[$mapid]['views_search_radshape_fillcolor'] = $defaults['views_search_radshape_fillcolor'];
    $settings[$mapid]['views_search_radshape_fillopacity'] = $defaults['views_search_radshape_fillopacity'];
    $settings[$mapid]['views_search_radshape_toggle'] = $defaults['views_search_radshape_toggle'];
    $settings[$mapid]['views_search_radshape_toggle_active'] = $defaults['views_search_radshape_toggle_active'];
  }

  // geocoder-js
  $settings[$mapid]['geocoder_enable'] = $defaults['geocoder_enable'];

  // What3Words
  $what3words_lic = variable_get('getlocations_what3words_lic', array(
    'key' => '',
    'url' => 'http://api.what3words.com',
  ));
  if ($what3words_lic['key'] && $defaults['what3words_enable']) {

    #$settings[$mapid]['what3words_key'] = $what3words_lic['key'];
    $settings[$mapid]['what3words_enable'] = $defaults['what3words_enable'];
    $settings[$mapid]['what3words_search'] = $defaults['what3words_search'];
    $settings[$mapid]['what3words_map_marker'] = $defaults['what3words_map_marker'];
    $settings[$mapid]['what3words_center'] = $defaults['what3words_center'];
    $settings[$mapid]['what3words_zoom'] = $defaults['what3words_zoom'];
    $settings[$mapid]['what3words_show'] = $defaults['what3words_show'];
    $settings[$mapid]['what3words_marker_show'] = $defaults['what3words_marker_show'];
    $settings[$mapid]['what3words_click'] = $defaults['what3words_click'];
    $settings[$mapid]['what3words_path'] = url($defaults['what3words_path']);
  }

  // baselayer settings
  $providers = getlocations_get_map_providers();
  $baselayers = $defaults['baselayers'];
  foreach ($providers as $k => $v) {
    if (isset($baselayers[$k]) && $baselayers[$k]) {
      $settings[$mapid]['baselayer_settings'][$k] = $v;
    }
  }

  // field group support;
  $settings[$mapid]['field_group_enable'] = module_exists('field_group') ? 1 : 0;
  drupal_add_js(array(
    'getlocations' => $settings,
  ), 'setting');
  if ($defaults['preload_data']) {
    $info = array();
    if (count($latlons)) {
      $ct = 0;
      foreach ($latlons as $latlon) {
        $info[$ct]['lid'] = 0;
        $info[$ct]['lidkey'] = '';
        $info[$ct]['content'] = '';
        if (isset($latlon[2]) && isset($latlon[5])) {
          $info[$ct]['lid'] = $latlon[2];
          $info[$ct]['lidkey'] = $latlon[5];
          $info[$ct]['content'] = '';
          if ($defaults['markeraction'] == 1 || $defaults['markeraction'] == 2) {
            $extra = FALSE;
            if (isset($defaults['getdirections_link'])) {
              $extra['gdlink'] = $defaults['getdirections_link'];
            }
            $info[$ct]['content'] = getlocations_getinfo($latlon[2], $latlon[5], $extra);
          }
          elseif ($defaults['markeraction'] == 3) {
            $info[$ct]['content'] = getlocations_getlidinfo($latlon[2], $latlon[5]);
          }
        }
        $ct++;
      }
    }
    $info_settings = array(
      $mapid => $info,
    );
    drupal_add_js(array(
      'getlocations_info' => $info_settings,
    ), 'setting');
  }

  // polygons
  if ($defaults['polygons_enable'] && !empty($defaults['polygons_coords'])) {
    $polygons = getlocations_get_polygon_settings($defaults);
    if ($polygons) {
      $polygon_settings = array(
        $mapid => $polygons,
      );
      drupal_add_js(array(
        'getlocations_polygons' => $polygon_settings,
      ), 'setting');
    }
  }

  // rectangles
  if ($defaults['rectangles_enable'] && (!empty($defaults['rectangles_coords']) || $defaults['rectangles_apply'] && $defaults['rectangles_dist'])) {
    if ($defaults['rectangles_apply'] && $defaults['rectangles_dist']) {

      // get latlons and set coords
      $tmp = '';
      foreach ($latlons as $ll) {
        $lats = getlocations_earth_latitude_range($ll[0], $ll[1], $defaults['rectangles_dist']);
        $lngs = getlocations_earth_longitude_range($ll[0], $ll[1], $defaults['rectangles_dist']);
        $tmp .= $lats[0] . ',' . $lngs[0] . '|' . $lats[1] . ',' . $lngs[1] . "\n";
      }
      if ($tmp) {
        $defaults['rectangles_coords'] = $tmp;
      }
    }
    $rectangles = getlocations_get_rectangle_settings($defaults);
    if ($rectangles) {
      $rectangle_settings = array(
        $mapid => $rectangles,
      );
      drupal_add_js(array(
        'getlocations_rectangles' => $rectangle_settings,
      ), 'setting');
    }
  }

  // circles
  if ($defaults['circles_enable'] && $defaults['circles_radius'] > 0 && (!empty($defaults['circles_coords']) || $defaults['circles_apply'])) {
    if ($defaults['circles_apply'] && count($latlons)) {

      // get latlons and set coords
      $tmp = '';
      foreach ($latlons as $ll) {
        $tmp .= $ll[0] . ',' . $ll[1] . "\n";
      }
      if ($tmp) {
        $defaults['circles_coords'] = $tmp;
      }
    }
    $circles = getlocations_get_circle_settings($defaults);
    if ($circles) {
      $circle_settings = array(
        $mapid => $circles,
      );
      drupal_add_js(array(
        'getlocations_circles' => $circle_settings,
      ), 'setting');
    }
  }

  // polylines
  if ($defaults['polylines_enable'] && !empty($defaults['polylines_coords'])) {
    $polylines = getlocations_get_polyline_settings($defaults);
    if ($polylines) {
      $polyline_settings = array(
        $mapid => $polylines,
      );
      drupal_add_js(array(
        'getlocations_polylines' => $polyline_settings,
      ), 'setting');
    }
  }

  // getlocations_gps
  if (module_exists('getlocations_gps') && isset($defaults['gps_button']) && $defaults['gps_button']) {
    $getlocations_gps_defaults = getlocations_gps_defaults($defaults);
    getlocations_gps_js_settings_do($getlocations_gps_defaults, $mapid);
  }

  // getlocations_smartip
  if (module_exists('getlocations_smartip') && isset($defaults['smartip_button']) && $defaults['smartip_button']) {
    $getlocations_smartip_defaults = getlocations_smartip_defaults($defaults);
    getlocations_smartip_js_settings_do($getlocations_smartip_defaults, $mapid);
  }
}

/**
 * Function to fetch locations
 *
 * @param int $id The entity identifier
 *
 * @return array $locations
 *
 */
function getlocations_load_locations($id, $key = 'vid') {
  $locations = '';
  if (module_exists('getlocations_fields')) {
    $locations = getlocations_fields_load_locations($id, $key);
  }
  elseif (module_exists('location_cck')) {
    $locations = location_load_locations($id, $key);
  }
  elseif (module_exists('geofield')) {
    $locations = getlocations_other_load_locations($id, $key, 'geofield');
  }
  elseif (module_exists('geolocation')) {
    $locations = getlocations_other_load_locations($id, $key, 'geolocation');
  }
  return $locations;
}

/**
 * Function to fetch a location
 *
 * @param int $lid Location Identifier
 *
 * @return array $location
 *
 */
function getlocations_load_location($lid) {
  $getlocations_defaults = getlocations_defaults();
  $location = '';
  if (module_exists('getlocations_fields')) {
    $location = getlocations_fields_load_location($lid);
    $type = getlocations_get_type_from_lid($lid);
    if (!isset($location['marker']) || empty($location['marker'])) {
      $location['marker'] = $getlocations_defaults[$type . '_map_marker'];
    }
  }
  elseif (module_exists('location_cck')) {
    $location = location_load_location($lid);
    $location['marker'] = $getlocations_defaults['node_map_marker'];
  }
  return $location;
}

/**
 * Function to fetch locations. Supports Geofield and Geolocation modules
 *
 * @param int $id Entity identifier
 * @param string $key Entity key
 * @param string $module Module name
 *
 * @return array $locations
 *
 */
function getlocations_other_load_locations($id, $key = 'vid', $module = '') {
  global $language;
  $locations = array();
  if (empty($module)) {
    return $locations;
  }
  if ($key == 'nid') {
    $entity_type = 'node';
    $obj = node_load($id);
    $location_name = $obj->title;
  }
  elseif ($key == 'vid') {
    $entity_type = 'node';
    $obj = node_load(NULL, $id);
    $location_name = $obj->title;
  }
  elseif ($key == 'uid') {
    $entity_type = 'user';
    $obj = user_load($id);
    $location_name = $obj->name;
  }
  elseif ($key == 'tid') {
    $entity_type = 'taxonomy_term';
    $obj = taxonomy_term_load($id);
    $location_name = $obj->name;
  }
  elseif ($key == 'cid') {
    $entity_type = 'comment';
    $obj = comment_load($id);
    $location_name = $obj->subject;
  }

  // get the field_xxx names
  $objfields = array();
  foreach ($obj as $k => $therest) {
    if (preg_match("/^field_/", $k)) {
      $objfields[] = $k;
    }
  }
  if (empty($objfields)) {
    return $locations;
  }

  // find a geofield
  if ($module == 'geofield') {
    $type = 'geofield';
    $geofields = getlocations_other_get_fieldname($type, $module, $entity_type);
    if (!empty($geofields)) {
      $geofield = '';
      foreach ($objfields as $field) {
        if (in_array($field, $geofields)) {
          $geofield = $field;
        }
      }
      if (empty($geofield)) {
        return $locations;
      }

      // got one
      $geo = $obj->{$geofield};
      $geo_keys = array_keys($geo);
      foreach ($geo_keys as $lang) {
        if ($lang == $language->language || isset($obj->language) && $lang == $obj->language || $lang == 'und') {
          $ct = 0;
          foreach ($geo[$lang] as $g) {
            if (isset($g['lat']) && isset($g['lon'])) {
              if ($latlon = getlocations_latlon_check($g['lat'] . ',' . $g['lon'])) {
                $ll = explode(',', $latlon);
                $locations[$ct]['latitude'] = $ll[0];
                $locations[$ct]['longitude'] = $ll[1];
                $locations[$ct][$key] = $id;
                if ($key == 'vid') {
                  $locations[$ct]['nid'] = getlocations_get_nid($id);
                }
                $locations[$ct]['key'] = $key;
                $ct++;
              }
            }
          }
        }
      }
    }
  }
  elseif ($module == 'geolocation') {
    $type = 'geolocation_latlng';
    $geolocationfields = getlocations_other_get_fieldname($type, $module, $entity_type);
    if (!empty($geolocationfields)) {
      $geolocationfield = '';
      foreach ($objfields as $field) {

        // test for geolocationfields
        if (in_array($field, $geolocationfields)) {
          $geolocationfield = $field;
        }
      }
      if (empty($geolocationfield)) {
        return $locations;
      }

      // got one
      $geo = $obj->{$geolocationfield};
      $geo_keys = array_keys($geo);
      foreach ($geo_keys as $lang) {
        if ($lang == $language->language || isset($obj->language) && $lang == $obj->language || $lang == 'und') {
          $ct = 0;
          foreach ($geo[$lang] as $g) {
            if (isset($g['lat']) && isset($g['lng'])) {
              if ($latlon = getlocations_latlon_check($g['lat'] . ',' . $g['lng'])) {
                $ll = explode(',', $latlon);
                $locations[$ct]['latitude'] = $ll[0];
                $locations[$ct]['longitude'] = $ll[1];
                $locations[$ct][$key] = $id;
                if ($key == 'vid') {
                  $locations[$ct]['nid'] = getlocations_get_nid($id);
                }
                $locations[$ct]['key'] = $key;
                $locations[$ct]['name'] = $location_name;
                $ct++;
              }
            }
          }
        }
      }
    }
  }

  // addressfield
  if (module_exists('addressfield')) {

    // find an addressfield
    $type = 'addressfield';
    $addressfields = getlocations_other_get_fieldname($type, 'addressfield', $entity_type);
    if (!empty($addressfields)) {
      foreach ($objfields as $field) {
        if (in_array($field, $addressfields)) {
          $addressfield = $field;
        }
      }
      if (empty($addressfield)) {
        return $locations;
      }

      // got one
      $addr = $obj->{$addressfield};
      $addr_keys = array_keys($addr);
      foreach ($addr_keys as $lang) {
        if ($lang == $language->language || isset($obj->language) && $lang == $obj->language || $lang == 'und') {
          $ct = 0;
          foreach ($addr[$lang] as $a) {
            $locations[$ct] += getlocations_addressfield_convert($a);
            $ct++;
          }
        }
      }
    }
  }
  return $locations;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_other_get_fieldname($type, $module, $entity_type = '') {
  $query = db_select('field_config', 'fc');
  $query
    ->fields('fc', array(
    'field_name',
  ))
    ->distinct();
  $query
    ->join('field_config_instance', 'i', 'fc.id = i.field_id');
  $query
    ->condition('fc.module', $module);
  $query
    ->condition('fc.type', $type);
  $query
    ->condition('fc.active', 1);
  $query
    ->condition('fc.storage_active', 1);
  if (!empty($entity_type)) {
    $query
      ->condition('i.entity_type', $entity_type);
  }
  $rows = $query
    ->execute();
  $field_names = array();
  foreach ($rows as $row) {
    $field_names[$row->field_name] = $row->field_name;
  }
  return $field_names;
}

/**
 * Some form helper functions
 * for admin and views plugin style
 */

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_marker($title, $options, $default, $description = '') {
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#options' => $options,
    '#default_value' => $default,
  );
  if ($description) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_tf($title, $default, $description = '', $size = 60, $maxlength = 255, $required = FALSE, $weight = '') {
  $element = array(
    '#type' => 'textfield',
    '#title' => $title,
    '#default_value' => $default,
    '#size' => $size,
    '#maxlength' => $maxlength,
  );
  if ($required) {
    $element['#required'] = TRUE;
  }
  if ($description) {
    $element['#description'] = $description;
  }
  if (is_numeric($weight)) {
    $element['#weight'] = $weight;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_zoom($title, $default, $description = '') {
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#default_value' => $default,
    '#options' => drupal_map_assoc(range(0, 21)),
  );
  if (!empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_zoom_map($title, $default, $description = '') {
  $opts = array(
    '-1' => t('Use map type settings'),
  ) + drupal_map_assoc(range(0, 21));
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#default_value' => $default,
    '#options' => $opts,
  );
  if (!empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_zoom_controltype($default, $title = '') {
  if (empty($title)) {
    $title = t('Zoom Control type');
  }
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#options' => array(
      'none' => t('None'),
      'default' => t('Default'),
      'small' => t('Small'),
      'large' => t('Large'),
    ),
    '#default_value' => $default,
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_checkbox($title, $default, $description = '') {
  $element = array(
    '#type' => 'checkbox',
    '#title' => $title,
    '#default_value' => $default,
    '#return_value' => 1,
  );
  if (!empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_mtc($default) {
  $element = array(
    '#type' => 'select',
    '#title' => t('Map Control Type'),
    '#options' => array(
      'none' => t('None'),
      'standard' => t('Horizontal bar'),
      'menu' => t('Dropdown'),
    ),
    '#default_value' => $default,
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_maptype($default, $baselayers) {
  $options = array();
  $providers = getlocations_get_map_providers();
  $layers = array();
  foreach ($providers as $k => $v) {
    $layers[$k] = $v['title'];
  }
  foreach ($layers as $key => $layer) {
    if (isset($baselayers[$key]) && $baselayers[$key]) {
      $options[$key] = $layer;
    }
  }
  $element = array(
    '#type' => 'select',
    '#title' => t('Default map type'),
    '#options' => $options,
    '#default_value' => $default,
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_baselayers($view, $default) {

  // Map Satellite Hybrid Physical
  $title = FALSE;
  $providers = getlocations_get_map_providers();
  if (isset($providers[$view])) {
    $title = $providers[$view]['title'];
    $description = $providers[$view]['description'];
  }
  if ($title) {
    $element = getlocations_element_map_checkbox($title, $default, $description);
    return $element;
  }
  return FALSE;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_pansetting($default) {
  $element = array(
    '#type' => 'select',
    '#title' => t('Automatic Panning'),
    '#default_value' => $default,
    '#options' => array(
      0 => t('None'),
      1 => t('Pan'),
      2 => t('Pan and zoom'),
      3 => t('Set Center'),
    ),
    '#description' => t("'None' is No panning,") . '<br />' . t("'Pan' keeps the markers in the Viewport,") . '<br />' . t("'Pan and zoom' fits the markers to the Viewport,") . '<br />' . t("'Set Center' places the markers in the middle of the map."),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_markeraction($default) {
  $element = array(
    '#type' => 'select',
    '#title' => t('Marker action'),
    '#default_value' => $default,
    '#options' => array(
      0 => t('None'),
      1 => t('InfoWindow'),
      2 => t('InfoBubble'),
      3 => t('Link'),
    ),
    '#description' => t("'None' is No action,") . '<br />' . t("'InfoWindow' show information in a Google InfoWindow,") . '<br />' . t("'InfoBubble' use InfoBubble instead,") . '<br />' . t("'Link' go to a page."),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_markeractiontype($default) {
  $element = array(
    '#type' => 'select',
    '#title' => t('Marker action type'),
    '#default_value' => $default,
    '#options' => array(
      1 => t('Click'),
      2 => t('Mouse over'),
    ),
    '#description' => t("'Click' is clicking on the marker,") . '<br />' . t("'Mouse over' is holding the mouse over a marker."),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_markermanagertype($default) {
  $element = array(
    '#type' => 'select',
    '#title' => t('Marker Manager type'),
    '#default_value' => $default,
    '#options' => array(
      0 => t('None'),
      2 => t('Marker Clusterer'),
      1 => t('Marker Manager'),
    ),
    '#description' => t('The type of marker management software to load, if any.'),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_path($title, $default, $size, $maxlength, $description) {
  $element = getlocations_element_map_tf($title, $default, $description, $size, $maxlength, TRUE);
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_limits($default, $title = '', $description = '') {
  if (empty($title)) {
    $title = t('Locations to show');
  }
  if (empty($description)) {
    $description = t('The maximum number of locations to show, sorted by distance');
  }
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#description' => $description,
    '#options' => array(
      0 => t('All'),
      10 => '10',
      20 => '20',
      30 => '30',
      40 => '40',
      50 => '50',
      75 => '75',
      100 => '100',
      150 => '150',
      175 => '175',
      200 => '200',
      250 => '250',
      300 => '300',
      400 => '400',
      500 => '500',
    ),
    '#default_value' => $default,
  );
  return $element;
}

/**
 * @param string $default
 * @param string $title
 * @param array $options
 * @param string $description
 * @param bool $multiple
 * @param int $weight
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_dd($title, $default, $options, $description = '', $multiple = FALSE, $weight = '') {
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#default_value' => $default,
    '#options' => $options,
  );
  if ($description) {
    $element['#description'] = $description;
  }
  if ($multiple) {
    $element['#multiple'] = TRUE;
    $element['#size'] = min(12, count($options));
  }
  if (is_numeric($weight)) {
    $element['#weight'] = $weight;
  }
  return $element;
}
function getlocations_get_map_providers() {

  // support hook_getlocations_map_providers
  $providers = module_invoke_all('getlocations_map_providers');
  return $providers;
}
function getlocations_getlocations_map_providers() {
  $osm_attrib = '&copy; <a target="_blank" href="http://www.openstreetmap.org">OpenStreetMap</a> contributors, <a target="_blank" href="http://www.openstreetmap.org/copyright">ODBL</a>';
  $stamen_attrib = 'Tiles &copy; <a target="_blank" href="http://stamen.com">Stamen Design</a>, <a target="_blank" href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> &mdash; ' . $osm_attrib;
  $esri_attrib = 'Tiles &copy; <a target="_blank" href="http://www.esri.com/">Esri</a>';
  $providers = array(
    'Map' => array(
      'title' => t('Standard street map'),
      'short_title' => t('Map'),
      'description' => t('The standard default street map.'),
      'default' => 1,
      'minzoom' => 0,
      'maxzoom' => 20,
      'url' => '',
      'attribution' => '',
      'tilesize' => 256,
    ),
    'Satellite' => array(
      'title' => t('Standard satellite map'),
      'short_title' => t('Satellite'),
      'description' => t('Satellite view without street overlay.'),
      'default' => 1,
      'minzoom' => 0,
      'maxzoom' => 20,
      'url' => '',
      'attribution' => '',
      'tilesize' => 256,
    ),
    'Hybrid' => array(
      'title' => t('Hybrid satellite map'),
      'short_title' => t('Hybrid'),
      'description' => t('Satellite view with street overlay.'),
      'default' => 1,
      'minzoom' => 0,
      'maxzoom' => 20,
      'url' => '',
      'attribution' => '',
      'tilesize' => 256,
    ),
    'Physical' => array(
      'title' => t('Terrain map'),
      'short_title' => t('Terrain'),
      'description' => t('Map with physical data (terrain, vegetation.)'),
      'default' => 1,
      'minzoom' => 0,
      'maxzoom' => 20,
      'url' => '',
      'attribution' => '',
      'tilesize' => 256,
    ),
    'OSM' => array(
      'title' => t('OpenStreet map'),
      'short_title' => t('OSM map'),
      'description' => t('Map from the OpenStreetMap Foundation.'),
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.openstreetmap.org/__Z__/__X__/__Y__.png",
      'attribution' => $osm_attrib,
      'tilesize' => 256,
    ),
    'OSMBW' => array(
      'title' => t('OpenStreetMap Black and White'),
      'short_title' => t('OSM BW'),
      'description' => t('Map from the OpenStreetMap Foundation, black and white version.'),
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://www.toolserver.org/tiles/bw-mapnik/__Z__/__X__/__Y__.png",
      'attribution' => $osm_attrib,
      'tilesize' => 256,
    ),
    'OSMDE' => array(
      'title' => t('OpenStreetMap DE'),
      'short_title' => t('OSM DE'),
      'description' => t('German OpenStreet map'),
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.openstreetmap.de/tiles/osmde/__Z__/__X__/__Y__.png",
      'attribution' => $osm_attrib,
      'tilesize' => 256,
    ),
    'OCM' => array(
      'title' => t('OpenCycleMap'),
      'short_title' => t('OCM'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.opencyclemap.org/cycle/__Z__/__X__/__Y__.png",
      'attribution' => '&copy; <a target="_blank" href="http://www.opencyclemap.org" >OpenCycleMap</a>, ' . $osm_attrib,
      'tilesize' => 256,
    ),
    'OCMT' => array(
      'title' => t('OpenCycleMap Transport'),
      'short_title' => t('OCM Transport'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.opencyclemap.org/transport/__Z__/__X__/__Y__.png",
      'attribution' => '&copy; <a target="_blank" href="http://www.opencyclemap.org" >OpenCycleMap</a>, ' . $osm_attrib,
      'tilesize' => 256,
    ),
    'OCML' => array(
      'title' => t('OpenCycleMap Landscape'),
      'short_title' => t('OCM Landscape'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.opencyclemap.org/landscape/__Z__/__X__/__Y__.png",
      'attribution' => '&copy; <a target="_blank" href="http://www.opencyclemap.org" >OpenCycleMap</a>, ' . $osm_attrib,
      'tilesize' => 256,
    ),
    'OCMO' => array(
      'title' => t('OpenCycleMap Outdoors'),
      'short_title' => t('OCM Outdoors'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.thunderforest.com/outdoors/__Z__/__X__/__Y__.png",
      'attribution' => '&copy; <a target="_blank" href="http://www.opencyclemap.org" >OpenCycleMap</a>, ' . $osm_attrib,
      'tilesize' => 256,
    ),
    'Stamen' => array(
      'title' => t('Stamen Toner'),
      'short_title' => t('ST'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/toner/__Z__/__X__/__Y__.png",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'StamenBG' => array(
      'title' => t('Stamen Toner-background'),
      'short_title' => t('STBG'),
      'description' => '',
      'default' => 0,
      'minzoom' => 0,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/toner-background/__Z__/__X__/__Y__.png",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'StamenHY' => array(
      'title' => t('Stamen Toner-hybrid'),
      'short_title' => t('STHY'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/toner-hybrid/__Z__/__X__/__Y__.png",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'StamenLI' => array(
      'title' => t('Stamen Toner-lines'),
      'short_title' => t('STLI'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/toner-lines/__Z__/__X__/__Y__.png",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'StamenLA' => array(
      'title' => t('Stamen Toner-labels'),
      'short_title' => t('STLA'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/toner-labels/__Z__/__X__/__Y__.png",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'StamenLT' => array(
      'title' => t('Stamen Toner-lite'),
      'short_title' => t('STLT'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/toner-lite/__Z__/__X__/__Y__.png",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'Watercolor' => array(
      'title' => t('Watercolor'),
      'short_title' => t('STWC'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://tile.stamen.com/watercolor/__Z__/__X__/__Y__.jpg",
      'attribution' => $stamen_attrib,
      'tilesize' => 256,
    ),
    'ESRI' => array(
      'title' => t('Esri'),
      'short_title' => t('Esri'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 17,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib,
      'tilesize' => 256,
    ),
    'DeLorme' => array(
      'title' => t('Esri DeLorme'),
      'short_title' => t('DeLorme'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 11,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; &copy;2012 DeLorme',
      'tilesize' => 256,
    ),
    'WorldTopoMap' => array(
      'title' => t('Esri Topo'),
      'short_title' => t('Topo'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community',
      'tilesize' => 256,
    ),
    'WorldImagery' => array(
      'title' => t('Esri Imagery'),
      'short_title' => t('Imagery'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 18,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',
      'tilesize' => 256,
    ),
    'WorldTerrain' => array(
      'title' => t('Esri Terrain'),
      'short_title' => t('Terrain'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 9,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; Source: USGS, Esri, TANA, DeLorme, and NPS',
      'tilesize' => 256,
    ),
    'WorldShadedRelief' => array(
      'title' => t('Esri Shaded'),
      'short_title' => t('Shaded'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 13,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . '',
      'tilesize' => 256,
    ),
    'WorldPhysical' => array(
      'title' => t('Esri Physical'),
      'short_title' => t('Physical'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 8,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; US National Park Service',
      'tilesize' => 256,
    ),
    'OceanBasemap' => array(
      'title' => t('Esri Ocean'),
      'short_title' => t('Ocean'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 13,
      'url' => "http://services.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ',
      'tilesize' => 256,
    ),
    'NatGeoWorldMap' => array(
      'title' => t('Esri Geo'),
      'short_title' => t('Esri Geo'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 12,
      'url' => "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC',
      'tilesize' => 256,
    ),
    'WorldGrayCanvas' => array(
      'title' => t('Esri Canvas'),
      'short_title' => t('Esri Canvas'),
      'description' => '',
      'default' => 0,
      'minzoom' => 1,
      'maxzoom' => 16,
      'url' => "http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/__Z__/__Y__/__X__",
      'attribution' => $esri_attrib . ' &mdash; Esri, DeLorme, NAVTEQ',
      'tilesize' => 256,
    ),
  );
  return $providers;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form
 *
 */
function getlocations_map_display_basics_form($defaults, $labels = array()) {
  $label = array(
    'width' => t('Default width'),
    'height' => t('Default height'),
    'styles' => t('Default styles'),
    'latlong' => t('Map center'),
    'zoom' => t('Zoom'),
    'minzoom_map' => t('Minimum Zoom'),
    'maxzoom_map' => t('Maximum Zoom'),
  );
  if (isset($labels['width'])) {
    $label['width'] = $labels['width'];
  }
  if (isset($labels['height'])) {
    $label['height'] = $labels['height'];
  }
  if (isset($labels['styles'])) {
    $label['styles'] = $labels['styles'];
  }
  if (isset($labels['latlong'])) {
    $label['latlong'] = $labels['latlong'];
  }
  if (isset($labels['zoom'])) {
    $label['zoom'] = $labels['zoom'];
  }
  if (isset($labels['minzoom_map'])) {
    $label['minzoom_map'] = $labels['minzoom_map'];
  }
  if (isset($labels['maxzoom_map'])) {
    $label['maxzoom_map'] = $labels['maxzoom_map'];
  }
  $form = array();
  $form['width'] = getlocations_element_map_tf($label['width'], $defaults['width'], t('The default width of a map, as a CSS length or percentage. Examples: <em>50px</em>, <em>5em</em>, <em>2.5in</em>, <em>95%</em>'), 10, 10, TRUE);
  $form['height'] = getlocations_element_map_tf($label['height'], $defaults['height'], t('The default height of a map, as a CSS length or percentage. Examples: <em>50px</em>, <em>5em</em>, <em>2.5in</em>, <em>95%</em>'), 10, 10, TRUE);

  // map_resize
  $form['map_resize'] = getlocations_element_map_checkbox(t('Automatic map resize'), $defaults['map_resize'], t('Set the map dimensions to 100% if the browser is on a mobile device.'));

  // fullscreen_disable
  $form['fullscreen_disable'] = getlocations_element_map_checkbox(t('Disable Fullscreen'), $defaults['fullscreen_disable'], t('Disable the Fullscreen button if the browser is on a mobile device.'));
  $form['styles'] = array(
    '#type' => 'textarea',
    '#title' => $label['styles'],
    '#default_value' => $defaults['styles'],
    '#description' => t('The default styles of a Google map. Use !link for generating your styles', array(
      '!link' => l(t('this wizard'), 'http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html', array(
        'external' => TRUE,
      )),
    )),
  );
  $form['latlong'] = getlocations_element_map_tf($label['latlong'], $defaults['latlong'], t('The default center coordinates of a map, expressed as a decimal latitude and longitude, separated by a comma. This must not be 0,0'), 40, 50, TRUE);
  $form['zoom'] = getlocations_element_map_zoom($label['zoom'], $defaults['zoom'], t('The default zoom level of a map.'));
  $form['minzoom_map'] = getlocations_element_map_zoom_map($label['minzoom_map'], $defaults['minzoom_map'], t('The default Minimum zoom level of a map.'));
  $form['maxzoom_map'] = getlocations_element_map_zoom_map($label['maxzoom_map'], $defaults['maxzoom_map'], t('The default Maximum zoom level of a map.'));
  return $form;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form
 *
 */
function getlocations_map_display_options_form($defaults, $config = TRUE, $extras = TRUE, $source = '') {
  $controlpositions = getlocations_controlpositions();
  $form = array();
  $form['controltype'] = getlocations_element_map_zoom_controltype($defaults['controltype']);
  $form['controltype']['#suffix'] = '<div id="wrap-getlocations-zoomcontrol">';
  $form['zoomcontrolposition'] = getlocations_element_dd(t('Position of Zoom Control'), $defaults['zoomcontrolposition'], $controlpositions);
  $form['zoomcontrolposition']['#suffix'] = '</div>';
  $form['pancontrol'] = getlocations_element_map_checkbox(t('Show Pan control'), $defaults['pancontrol']);
  $form['pancontrol']['#suffix'] = '<div id="wrap-getlocations-pancontrol">';
  $form['pancontrolposition'] = getlocations_element_dd(t('Position of Pan Control'), $defaults['pancontrolposition'], $controlpositions);
  $form['pancontrolposition']['#suffix'] = '</div>';
  $form['mtc'] = getlocations_element_map_mtc($defaults['mtc']);
  $form['mtc']['#suffix'] = '<div id="wrap-getlocations-mapcontrol">';
  $form['mapcontrolposition'] = getlocations_element_dd(t('Position of Map Control'), $defaults['mapcontrolposition'], $controlpositions);
  $form['mapcontrolposition']['#suffix'] = '</div>';
  $getlocations_defaults = getlocations_defaults();

  // get baselayers in
  $baselayers = $getlocations_defaults['baselayers'];
  foreach ($baselayers as $k => $v) {
    if (!isset($defaults['baselayers'][$k])) {
      $defaults['baselayers'][$k] = $v;
    }
  }

  // make sure at least one layer is set
  $found = FALSE;
  foreach ($defaults['baselayers'] as $key => $value) {
    if ($value) {
      $found = TRUE;
    }
  }
  if (!$found) {
    $defaults['baselayers']['Map'] = 1;
    $defaults['maptype'] = 'Map';
  }

  // backward compat
  if (isset($defaults['baselayers']['OpenStreetMap'])) {
    $defaults['baselayers']['OSM'] = $defaults['baselayers']['OpenStreetMap'];
    unset($defaults['baselayers']['OpenStreetMap']);
  }
  $form['maptype'] = getlocations_element_map_maptype($defaults['maptype'], $defaults['baselayers']);
  $form['baselayers'] = array(
    '#type' => 'fieldset',
    '#title' => t('Enable map types'),
    '#description' => t('Select which maps you want to be available.'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );
  foreach ($defaults['baselayers'] as $key => $value) {
    $layer = getlocations_element_map_baselayers($key, $value);
    if ($layer) {
      $form['baselayers'][$key] = $layer;
    }
  }
  $form['scale'] = getlocations_element_map_checkbox(t('Scale'), $defaults['scale'], t('Show scale.'));
  $form['scale']['#suffix'] = '<div id="wrap-getlocations-scale">';
  $form['scalecontrolposition'] = getlocations_element_dd(t('Position of Scale Control'), $defaults['scalecontrolposition'], $controlpositions);
  $form['scalecontrolposition']['#suffix'] = '</div>';
  $form['overview'] = getlocations_element_map_checkbox(t('Overview map'), $defaults['overview'], t('Show overview map.'));
  $form['overview']['#suffix'] = '<div id="wrap-getlocations-overview">';
  $form['overview_opened'] = getlocations_element_map_checkbox(t('Overview map state'), $defaults['overview_opened'], t('Show overview map as open by default.'));
  $form['overview_opened']['#suffix'] = '</div>';
  $form['scrollwheel'] = getlocations_element_map_checkbox(t('Scrollwheel'), $defaults['scrollwheel'], t('Enable scrollwheel zooming.'));
  $form['draggable'] = getlocations_element_map_checkbox(t('Draggable'), $defaults['draggable'], t('Enable dragging the map.'));
  $form['nokeyboard'] = getlocations_element_map_checkbox(t('Disable keyboard shortcuts'), $defaults['nokeyboard'], t('Enabling this will disable keyboard shortcuts on the map.'));
  $form['nodoubleclickzoom'] = getlocations_element_map_checkbox(t('Disable Doubleclick zoom'), $defaults['nodoubleclickzoom'], t('Enabling this will disable doubleclick zooming on the map.'));
  $form['map_backgroundcolor'] = getlocations_element_map_tf(t('Map background color'), $defaults['map_backgroundcolor'], t('Can be a color name or HTML hex, eg #FF0000. Leave empty for the default color.'), 10);
  if ($config) {
    $form['region_bias'] = getlocations_element_dd(t('Regional bias'), $defaults['region_bias'], array(
      '' => t('None'),
    ) + getlocations_get_countries_list(), t('Bias the maps to a particular country'));

    // jquery_colorpicker
    if (module_exists('jquery_colorpicker')) {
      $form['jquery_colorpicker_enabled'] = getlocations_element_map_checkbox(t('Use jQuery Colorpicker'), $defaults['jquery_colorpicker_enabled'], t('Use the jQuery Colorpicker for selecting colors.'));
    }
    else {
      $form['jquery_colorpicker_enabled'] = array(
        '#type' => 'value',
        '#value' => 0,
      );
    }
    $form['is_https'] = getlocations_element_map_checkbox(t('Force https maps'), $defaults['is_https']);
  }
  if ($extras) {

    // getlocations_gps
    if (module_exists('getlocations_gps')) {
      $form += getlocations_gps_map_display_options_form($defaults);
      $form['geolocation_mobile_check'] = array(
        '#type' => 'checkbox',
        '#title' => t('Enable check for mobiles'),
        '#default_value' => $defaults['geolocation_mobile_check'],
        '#return_value' => 1,
        '#description' => t('Enable geolocation for mobile devices only.'),
      );
    }
    else {
      $form['geolocation_mobile_check'] = array(
        '#type' => 'value',
        '#value' => 0,
      );
    }

    // getlocations_smartip
    if (module_exists('getlocations_smartip')) {
      $form += getlocations_smartip_map_display_options_form($defaults);
    }
    $form['sv_show'] = getlocations_element_map_checkbox(t('Show streetview Pegman'), $defaults['sv_show']);
    $form['sv_show']['#suffix'] = '<div id="wrap-getlocations-sv-show">';
    $form['svcontrolposition'] = getlocations_element_dd(t('Position of Pegman'), $defaults['svcontrolposition'], $controlpositions);
    $form['svcontrolposition']['#suffix'] = '</div>';

    // show_maplinks
    $form['show_maplinks'] = getlocations_element_map_checkbox(t('Show map links'), $defaults['show_maplinks'], t('Show a list of links to popup InfoWindow/InfoBubble/Link on the map.'));
    $form['show_maplinks']['#suffix'] = '<div id="wrap-getlocations-maplinks">';
    $form['show_maplinks_viewport'] = getlocations_element_map_checkbox(t('Only Show map links in Viewport'), $defaults['show_maplinks_viewport']);
    $form['show_maplinks_viewport']['#suffix'] = '</div>';
    $form['show_bubble_on_one_marker'] = getlocations_element_map_checkbox(t('Show bubble automatically'), $defaults['show_bubble_on_one_marker'], t('Have the InfoWindow/InfoBubble popup automatically if there is only one marker on the map.'));
    $form['fullscreen'] = getlocations_element_map_checkbox(t('Show Fullscreen button'), $defaults['fullscreen']);
    $form['fullscreen']['#suffix'] = '<div id="wrap-getlocations-fs-show">';
    $form['fullscreen_controlposition'] = getlocations_element_dd(t('Position of Fullscreen button'), $defaults['fullscreen_controlposition'], $controlpositions);
    $form['fullscreen_controlposition']['#suffix'] = '</div>';
    $form['trafficinfo'] = getlocations_element_map_checkbox(t('Enable Traffic information'), $defaults['trafficinfo'], t('Google Traffic layer, limited availability.'));
    $form['trafficinfo']['#suffix'] = '<div id="wrap-getlocations-trafficinfo">';
    $form['trafficinfo_state'] = getlocations_element_map_checkbox(t('Activate Traffic information'), $defaults['trafficinfo_state'], t('Activate Traffic layer when map is first displayed.'));
    $form['trafficinfo_state']['#suffix'] = '</div>';
    $form['bicycleinfo'] = getlocations_element_map_checkbox(t('Enable Bicycling information'), $defaults['bicycleinfo'], t('Google Bicycling layer, limited availability.'));
    $form['bicycleinfo']['#suffix'] = '<div id="wrap-getlocations-bicycleinfo">';
    $form['bicycleinfo_state'] = getlocations_element_map_checkbox(t('Activate Bicycle information'), $defaults['bicycleinfo_state'], t('Activate Bicycling layer when map is first displayed.'));
    $form['bicycleinfo_state']['#suffix'] = '</div>';
    $form['transitinfo'] = getlocations_element_map_checkbox(t('Enable Public transport information'), $defaults['transitinfo'], t('Google Transit layer, limited availability.'));
    $form['transitinfo']['#suffix'] = '<div id="wrap-getlocations-transitinfo">';
    $form['transitinfo_state'] = getlocations_element_map_checkbox(t('Activate Public transport information'), $defaults['transitinfo_state'], t('Activate Transit layer when map is first displayed.'));
    $form['transitinfo_state']['#suffix'] = '</div>';
    $form['poi_show'] = getlocations_element_map_checkbox(t('Show Points of Interest'), $defaults['poi_show'], t('Show Google points of interest icons.'));
    $form['transit_show'] = getlocations_element_map_checkbox(t('Show Transit Points'), $defaults['transit_show'], t('Show Google transit points icons.'));
    $form += getlocations_shapes_form($defaults, $source);
    $form += getlocations_kml_form($defaults);
    $form += getlocations_geojson_form($defaults);
    $form += getlocations_highlight_form($defaults);
    $form += getlocations_geocoder_form($defaults);
    $form += getlocations_google_places_form($defaults, $config);
    $form += getlocations_what3words_form($defaults);
    if ($config) {
      $form['places'] = array(
        '#type' => 'value',
        '#value' => $defaults['places'],
      );
    }
  }
  return $form;
}
function getlocations_shapes_form($defaults, $source) {
  $form = array();
  $form['polygons_enable'] = getlocations_element_map_checkbox(t('Enable polygons'), $defaults['polygons_enable'], t('Show polygons if defined.'));
  $form['polygons_enable']['#suffix'] = '<div id="wrap-getlocations-polygons">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['polygons_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Polygon line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['polygons_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['polygons_strokecolor'] = getlocations_element_map_tf(t('Polygon line color'), $defaults['polygons_strokecolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['polygons_strokeopacity'] = getlocations_element_map_tf(t('Polygon line opacity'), $defaults['polygons_strokeopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['polygons_strokeweight'] = getlocations_element_map_tf(t('Polygon line thickness'), $defaults['polygons_strokeweight'], t('Must be an integer.'), 10, 10, TRUE);

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['polygons_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Polygon fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['polygons_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['polygons_fillcolor'] = getlocations_element_map_tf(t('Polygon fill color'), $defaults['polygons_fillcolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['polygons_fillopacity'] = getlocations_element_map_tf(t('Polygon fill opacity'), $defaults['polygons_fillopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['polygons_clickable'] = getlocations_element_map_checkbox(t('Clickable'), $defaults['polygons_clickable'], t('Show Popup on clicking on the polygon.'));
  $form['polygons_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['polygons_message'],
    '#description' => t('The content of the popup.'),
  );
  $form['polygons_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Polygon Coordinates'),
    '#default_value' => $defaults['polygons_coords'],
    '#description' => t('A pipe delimited list of latitude,longitude pairs, one polygon per line. You must have at least 3 pairs for each polygon.'),
  );
  $form['polygons_coords']['#suffix'] = '</div>';
  $form['rectangles_enable'] = getlocations_element_map_checkbox(t('Enable rectangles'), $defaults['rectangles_enable'], t('Show rectangles if defined.'));
  $form['rectangles_enable']['#suffix'] = '<div id="wrap-getlocations-rectangles">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['rectangles_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Rectangle line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['rectangles_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['rectangles_strokecolor'] = getlocations_element_map_tf(t('Rectangle line color'), $defaults['rectangles_strokecolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['rectangles_strokeopacity'] = getlocations_element_map_tf(t('Rectangle line opacity'), $defaults['rectangles_strokeopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['rectangles_strokeweight'] = getlocations_element_map_tf(t('Rectangle line thickness'), $defaults['rectangles_strokeweight'], t('Must be an integer.'), 10, 10, TRUE);

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['rectangles_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Rectangle fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['rectangles_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['rectangles_fillcolor'] = getlocations_element_map_tf(t('Rectangle fill color'), $defaults['rectangles_fillcolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['rectangles_fillopacity'] = getlocations_element_map_tf(t('Rectangle fill opacity'), $defaults['rectangles_fillopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['rectangles_clickable'] = getlocations_element_map_checkbox(t('Clickable'), $defaults['rectangles_clickable'], t('Show Popup on clicking on the rectangle.'));
  $form['rectangles_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['rectangles_message'],
    '#description' => t('The content of the popup.'),
  );
  if ($source == 'getlocations_search') {
    $form['rectangles_apply'] = array(
      '#type' => 'value',
      '#value' => 0,
    );
    $form['rectangles_dist'] = array(
      '#type' => 'value',
      '#value' => 0,
    );
  }
  else {
    $form['rectangles_apply'] = getlocations_element_map_checkbox(t('Apply a rectangle to all locations'), $defaults['rectangles_apply'], t('Draw a rectangle centered on all locations being displayed. These coordinates will be used instead of the ones below.'));
    $form['rectangles_dist'] = getlocations_element_map_tf(t('Rectangle distance'), $defaults['rectangles_dist'], t("The distance from the center of the rectangle to the edge in meters on the Earth's surface. This will only be used if Apply a rectangle is enabled."), 10, 10, FALSE);
  }
  $form['rectangles_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Rectangle Coordinates'),
    '#default_value' => $defaults['rectangles_coords'],
    '#description' => t('A pipe delimited list of latitude,longitude pairs, one rectangle per line. You must have exactly 2 pairs for each rectangle, south-west and north-east corners.'),
  );
  $form['rectangles_coords']['#suffix'] = '</div>';
  $form['circles_enable'] = getlocations_element_map_checkbox(t('Enable circles'), $defaults['circles_enable'], t('Show circles if defined.'));
  $form['circles_enable']['#suffix'] = '<div id="wrap-getlocations-circles">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['circles_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Circle line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['circles_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['circles_strokecolor'] = getlocations_element_map_tf(t('Circle line color'), $defaults['circles_strokecolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['circles_strokeopacity'] = getlocations_element_map_tf(t('Circle line opacity'), $defaults['circles_strokeopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['circles_strokeweight'] = getlocations_element_map_tf(t('Circle line thickness'), $defaults['circles_strokeweight'], t('Must be an integer.'), 10, 10, TRUE);

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['circles_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Circle fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['circles_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['circles_fillcolor'] = getlocations_element_map_tf(t('Circle fill color'), $defaults['circles_fillcolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['circles_fillopacity'] = getlocations_element_map_tf(t('Circle fill opacity'), $defaults['circles_fillopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['circles_radius'] = getlocations_element_map_tf(t('Circle radius'), $defaults['circles_radius'], t("The radius in meters on the Earth's surface."), 10, 10, TRUE);
  $form['circles_clickable'] = getlocations_element_map_checkbox(t('Clickable'), $defaults['circles_clickable'], t('Show Popup on clicking on the circle.'));
  $form['circles_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['circles_message'],
    '#description' => t('The content of the popup.'),
  );
  if ($source == 'getlocations_search') {
    $form['circles_apply'] = array(
      '#type' => 'value',
      '#value' => 0,
    );
  }
  else {
    $form['circles_apply'] = getlocations_element_map_checkbox(t('Apply a circle to all locations'), $defaults['circles_apply'], t('Draw a circle centered on all locations being displayed. These coordinates will be used instead of the ones below.'));
  }
  $form['circles_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Circle Center'),
    '#default_value' => $defaults['circles_coords'],
    '#description' => t('A latitude,longitude pair, one circle per line.'),
  );
  $form['circles_coords']['#suffix'] = '</div>';
  $form['polylines_enable'] = getlocations_element_map_checkbox(t('Enable polylines'), $defaults['polylines_enable'], t('Show polylines if defined.'));
  $form['polylines_enable']['#suffix'] = '<div id="wrap-getlocations-polylines">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['polylines_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Polyline line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['polylines_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['polylines_strokecolor'] = getlocations_element_map_tf(t('Polyline line color'), $defaults['polylines_strokecolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['polylines_strokeopacity'] = getlocations_element_map_tf(t('Polyline line opacity'), $defaults['polylines_strokeopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['polylines_strokeweight'] = getlocations_element_map_tf(t('Polyline line thickness'), $defaults['polylines_strokeweight'], t('Must be an integer.'), 10, 10, TRUE);
  $form['polylines_clickable'] = getlocations_element_map_checkbox(t('Clickable'), $defaults['polylines_clickable'], t('Show Popup on clicking on the polyline.'));
  $form['polylines_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['polylines_message'],
    '#description' => t('The content of the popup.'),
  );
  $form['polylines_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Polyline Coordinates'),
    '#default_value' => $defaults['polylines_coords'],
    '#description' => t('A pipe delimited list of latitude,longitude pairs, one set of polylines per line. You must have at least 2 pairs for each set.'),
  );
  $form['polylines_coords']['#suffix'] = '</div>';
  return $form;
}
function getlocations_geojson_form($defaults) {

  // geojson
  $form = array();
  if (getlocations_get_geojson_path()) {
    $form['geojson_enable'] = getlocations_element_map_checkbox(t('Enable GeoJSON library'), $defaults['geojson_enable'], t('Show GeoJSON data if defined'));
    $form['geojson_enable']['#suffix'] = '<div id="wrap-getlocations-geojson-enable">';
    $form['geojson_data'] = array(
      '#type' => 'textarea',
      '#title' => t('GeoJSON data'),
      '#default_value' => $defaults['geojson_data'],
      '#description' => t('A GeoJSON object. For more information about GeoJSON see !u', array(
        '!u' => l(t('geojson.org'), 'http://www.geojson.org/', array(
          'attributes' => array(
            'target' => '_blank',
          ),
        )),
      )),
    );
    $form['geojson_options'] = array(
      '#type' => 'textarea',
      '#title' => t('GeoJSON options'),
      '#default_value' => $defaults['geojson_options'],
      '#description' => t('A JSON object.'),
    );
    $form['geojson_options']['#suffix'] = '</div>';
  }
  else {
    $form['geojson_enable'] = array(
      '#type' => 'value',
      '#value' => 0,
    );
    $form['geojson_data'] = array(
      '#type' => 'value',
      '#value' => '',
    );
    $form['geojson_options'] = array(
      '#type' => 'value',
      '#value' => '',
    );
  }
  return $form;
}
function getlocations_kml_form($defaults) {

  // KML
  $form = array();
  $form['kml_group'] = array(
    '#type' => 'fieldset',
    '#title' => t('Kml file'),
    '#description' => t('Attach a kml file.'),
    '#collapsible' => TRUE,
    '#collapsed' => empty($defaults['kml_group']['kml_url']) ? TRUE : FALSE,
    '#tree' => TRUE,
  );
  $form['kml_group']['kml_url'] = getlocations_element_map_tf(t('Kml url'), $defaults['kml_group']['kml_url'], t('A full url to a publicly accessible kml file.'));
  $form['kml_group']['kml_url_click'] = getlocations_element_map_checkbox(t('Kml layer clickable'), $defaults['kml_group']['kml_url_click']);
  $form['kml_group']['kml_url_infowindow'] = getlocations_element_map_checkbox(t('Suppress Kml layer InfoWindows'), $defaults['kml_group']['kml_url_infowindow']);
  $form['kml_group']['kml_url_viewport'] = getlocations_element_map_checkbox(t('Preserve viewport'), $defaults['kml_group']['kml_url_viewport']);
  $form['kml_group']['kml_url_button'] = getlocations_element_map_checkbox(t('Show toggle button'), $defaults['kml_group']['kml_url_button']);
  $form['kml_group']['kml_url_button_label'] = getlocations_element_map_tf(t('Label for toggle button'), $defaults['kml_group']['kml_url_button_label'], '', 30);
  $form['kml_group']['kml_url_button_state'] = getlocations_element_map_checkbox(t('Activate Kml layer'), $defaults['kml_group']['kml_url_button_state'], t('Activate Kml layer when map is first displayed.'));
  return $form;
}
function getlocations_highlight_form($defaults) {

  // marker highlighting
  $form = array();
  $form['highlight_enable'] = getlocations_element_map_checkbox(t('Enable Marker highlighting'), $defaults['highlight_enable'], t('Highlight a marker with a circle on mouseover'));
  $form['highlight_enable']['#suffix'] = '<div id="wrap-getlocations-highlight">';
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['highlight_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Highlight Circle line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['highlight_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['highlight_strokecolor'] = getlocations_element_map_tf(t('Highlight Circle line color'), $defaults['highlight_strokecolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['highlight_strokeopacity'] = getlocations_element_map_tf(t('Highlight Circle line opacity'), $defaults['highlight_strokeopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['highlight_strokeweight'] = getlocations_element_map_tf(t('Highlight Circle line thickness'), $defaults['highlight_strokeweight'], t('Must be an integer.'), 10, 10, TRUE);

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['highlight_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Highlight Circle fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['highlight_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['highlight_fillcolor'] = getlocations_element_map_tf(t('Highlight Circle fill color'), $defaults['highlight_fillcolor'], t('HTML hex, eg #FF0000.'), 10, 10, TRUE);
  }
  $form['highlight_fillopacity'] = getlocations_element_map_tf(t('Highlight Circle fill opacity'), $defaults['highlight_fillopacity'], t('Must be between 0 and 1.'), 10, 10, TRUE);
  $form['highlight_radius'] = getlocations_element_map_tf(t('Highlight Circle size'), $defaults['highlight_radius'], t("The size of the highlight circle, 10 or 20 recommended."), 5, 5, TRUE);
  $form['highlight_radius']['#suffix'] = '</div>';
  return $form;
}
function getlocations_google_places_form($defaults, $config) {

  // search_places
  $form = array();

  // enable
  $desc = t('Provide a textfield to query Google Places Search.');
  if ($config) {
    $desc .= ' ' . t('This will be enabled for all Google maps if enabled here.');
  }
  $form['search_places'] = getlocations_element_map_checkbox(t('Enable Google Places Search'), $defaults['search_places'], $desc);
  $form['search_places']['#suffix'] = '<div id="wrap-getlocations-search-places">';

  // size
  $form['search_places_size'] = getlocations_element_map_tf(t('Textbox width'), $defaults['search_places_size'], t('The width of the Google Places Search textbox. Must be a positive number.'), 10, 10, TRUE);

  // placement
  $pos = array(
    'outside_above' => t('Above the map'),
    'outside_below' => t('Below the map'),
  );
  $form['search_places_position'] = getlocations_element_dd(t('Textbox Position'), $defaults['search_places_position'], $pos, t('The position of the Google Places Search textbox.'));

  // label
  $form['search_places_label'] = getlocations_element_map_tf(t('Textbox label'), $defaults['search_places_label'], t('The label for the Google Places Search textbox.'), 30, 40);

  // placeholder
  $form['search_places_placeholder'] = getlocations_element_map_tf(t('Text in Textbox'), $defaults['search_places_placeholder'], t('The text inside the Google Places Search textbox. Leave empty for the default.'), 30, 40);

  // list
  $form['search_places_list'] = getlocations_element_map_checkbox(t('Provide a List of what was found linked to a bubble'), $defaults['search_places_list']);

  // dropdown
  $form['search_places_dd'] = getlocations_element_map_checkbox(t('Provide a Dropdown instead of a Textbox for Google Places Search'), $defaults['search_places_dd']);
  $form['search_places_dd']['#suffix'] = '</div>';
  return $form;
}
function getlocations_geocoder_form($defaults) {
  $form = array();
  if (getlocations_get_geocoder_path()) {
    $form['geocoder_enable'] = getlocations_element_dd(t('Geocoder type'), $defaults['geocoder_enable'], array(
      0 => t('Quick Google Search'),
      1 => t('Full Google Search'),
      2 => t('OpenStreetMap Search'),
    ), t('The type of geocoder to use. Quick Google search only applies if Google Autocomplete has been used.'));
  }
  else {
    $form['geocoder_enable'] = array(
      '#type' => 'value',
      '#value' => 0,
    );
  }
  return $form;
}
function getlocations_markeraction_form($defaults) {
  $form = array();
  $form['markeractiontype'] = getlocations_element_map_markeractiontype($defaults['markeractiontype']);
  $form['markeraction'] = getlocations_element_map_markeraction($defaults['markeraction']);
  $form['markeraction_click_center'] = getlocations_element_dd(t('Center or Pan on Marker click'), $defaults['markeraction_click_center'], array(
    0 => t('None'),
    1 => t('Center'),
    2 => t('Pan to'),
  ));
  $form['markeraction_click_zoom'] = array(
    '#type' => 'select',
    '#title' => t('Zoom on Marker click'),
    '#default_value' => $defaults['markeraction_click_zoom'],
    '#options' => array(
      '-1' => t('None'),
    ) + drupal_map_assoc(range(0, 21)),
  );
  return $form;
}
function getlocations_markermanager_form($defaults) {
  $form = array();
  $form['usemarkermanager'] = getlocations_element_map_checkbox(t('Use Marker manager'), $defaults['usemarkermanager'], t('Use Marker manager. Switching this off will use no manager.'));
  $form['minzoom'] = getlocations_element_map_zoom(t('Minimum Zoom'), $defaults['minzoom'], t('The Minimum zoom level at which markers will be visible.'));
  $form['maxzoom'] = getlocations_element_map_zoom(t('Maximum Zoom'), $defaults['maxzoom'], t('The Maximum zoom level at which markers will be visible.'));
  return $form;
}
function getlocations_markercluster_form($defaults) {
  if (file_exists(GETLOCATIONS_PATH . '/getlocations.markercluster_override.inc')) {
    module_load_include('inc', 'getlocations', 'getlocations.markercluster_override');
  }
  else {
    module_load_include('inc', 'getlocations', 'getlocations.markercluster');
  }
  $form = array();
  $form['useclustermanager'] = getlocations_element_map_checkbox(t('Use Cluster manager'), $defaults['useclustermanager'], t('Use Cluster manager. Switching this off will use no manager.'));
  $form['markerclusterer_style'] = getlocations_element_markerclusterer_style($defaults['markerclusterer_style']);
  $form['markerclusterer_imgpath'] = getlocations_element_map_tf(t('Markerclusterer image path'), $defaults['markerclusterer_imgpath'], '', 40, 255);
  $form['markerclusterer_title'] = getlocations_element_map_tf(t('Markerclusterer tooltip'), $defaults['markerclusterer_title'], t('The text of a Markerclusterer tooltip'), 30, 64, TRUE);
  $form['markerclusterer_zoom'] = getlocations_element_markerclusterer_zoom($defaults['markerclusterer_zoom']);
  $form['markerclusterer_size'] = getlocations_element_markerclusterer_size($defaults['markerclusterer_size']);
  $form['markerclusterer_minsize'] = getlocations_element_markerclusterer_minsize($defaults['markerclusterer_minsize']);
  return $form;
}

/**
 * What3words config form
 *
 */
function getlocations_what3words_form($defaults) {
  $form = array();
  $what3words_lic = variable_get('getlocations_what3words_lic', array(
    'key' => '',
    'url' => 'http://api.what3words.com',
  ));
  if ($what3words_lic['key']) {
    $form['what3words_enable'] = getlocations_element_map_checkbox(t('Enable What3Words service'), $defaults['what3words_enable'], t('This service requires an API key'));
    $form['what3words_enable']['#suffix'] = '<div id="wrap-getlocations-what3words">';

    // what3words_search
    $form['what3words_search'] = getlocations_element_map_checkbox(t('Show What3Words search box'), $defaults['what3words_search']);

    // what3words_size
    $form['what3words_size'] = getlocations_element_map_tf(t('What3Words search box width'), $defaults['what3words_size'], '', 10);

    // what3words_marker_show
    $form['what3words_marker_show'] = getlocations_element_map_checkbox(t('Display What3Words marker'), $defaults['what3words_marker_show']);

    // what3words_map_marker
    $markers = getlocations_get_marker_titles();
    $form['what3words_map_marker'] = getlocations_element_map_marker(t('What3Words Map marker'), $markers, $defaults['what3words_map_marker']);

    // what3words_center
    $form['what3words_center'] = getlocations_element_map_checkbox(t('Center map on What3Words location'), $defaults['what3words_center'], t('Center the map on Search success'));

    // what3words_zoom

    #$form['what3words_zoom'] = getlocations_element_map_zoom_map(

    #  t('Zoom for What3Words location'),

    #  $defaults['what3words_zoom']

    #);
    $opts = array(
      '-2' => t('Keep current zoom'),
      '-1' => t('Use map type settings'),
    ) + drupal_map_assoc(range(0, 21));
    $form['what3words_zoom'] = array(
      '#type' => 'select',
      '#title' => t('Zoom for What3Words location'),
      '#default_value' => $defaults['what3words_zoom'],
      '#options' => $opts,
    );

    // what3words_click
    $form['what3words_click'] = getlocations_element_map_checkbox(t('Click on map to find What3Words'), $defaults['what3words_click']);

    // what3words_show
    $form['what3words_show'] = getlocations_element_map_checkbox(t('Display What3Words for current location'), $defaults['what3words_show']);
    $form['what3words_show']['#suffix'] = '</div>';
  }
  else {
    $form['what3words_enable'] = array(
      '#type' => 'value',
      '#value' => 0,
    );
  }
  return $form;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns array of javascript paths
 *
 */
function getlocations_paths_get($reset = FALSE, $min = FALSE) {
  $jq_upd = getlocations_check_jquery_version(TRUE);
  if ($min) {
    $defaults = array(
      'infobubble_path' => GETLOCATIONS_PATH . '/js/infobubble.min.js',
      'infobubble_options_path' => GETLOCATIONS_PATH . '/js/infobubble_options.js',
      'infobubble_extended_path' => GETLOCATIONS_PATH . '/js/infobubble_extended.min.js',
      'markermanager_path' => GETLOCATIONS_PATH . '/js/markermanager_packed.js',
      'markerclusterer_path' => GETLOCATIONS_PATH . '/js/markerclusterer_packed.js',
      'infowindow_options_path' => GETLOCATIONS_PATH . '/js/infowindow_options.js',
      'getlocations_path' => GETLOCATIONS_PATH . '/js/getlocations.min.js',
      'getlocations_polygons_path' => GETLOCATIONS_PATH . '/js/getlocations_polygons.min.js',
      'getlocations_rectangles_path' => GETLOCATIONS_PATH . '/js/getlocations_rectangles.min.js',
      'getlocations_circles_path' => GETLOCATIONS_PATH . '/js/getlocations_circles.min.js',
      'getlocations_polylines_path' => GETLOCATIONS_PATH . '/js/getlocations_polylines.min.js',
      'getlocations_categories_path' => GETLOCATIONS_PATH . '/js/getlocations_categories.min.js',
      'getlocations_search_places_path' => GETLOCATIONS_PATH . '/js/getlocations_search_places.min.js',
      'getlocations_geo_path' => GETLOCATIONS_PATH . '/js/getlocations_geo.min.js',
      'getlocations_preview_path' => GETLOCATIONS_PATH . '/js/getlocations_preview.min.js',
      'getlocations_geojson_path' => GETLOCATIONS_PATH . '/js/getlocations_geojson.min.js',
      'getlocations_admin_path' => GETLOCATIONS_PATH . ($jq_upd ? '/js/getlocations_admin_1.min.js' : '/js/getlocations_admin.min.js'),
      'getlocations_box_path' => GETLOCATIONS_PATH . '/js/getlocations_box.min.js',
      'getlocations_colorbox_path' => GETLOCATIONS_PATH . '/js/getlocations_colorbox.min.js',
      'getlocations_marker_box_path' => GETLOCATIONS_PATH . '/js/getlocations_marker_box.min.js',
      'getlocations_views_path' => GETLOCATIONS_PATH . ($jq_upd ? '/js/getlocations_views_1.min.js' : '/js/getlocations_views.min.js'),
      'getlocations_icons_path' => GETLOCATIONS_PATH . '/js/icons.min.js',
      'getlocations_field_group_path' => GETLOCATIONS_PATH . '/js/getlocations_field_group.min.js',
      'getlocations_what3words_path' => GETLOCATIONS_PATH . '/js/getlocations_what3words.min.js',
    );
  }
  else {
    $defaults = array(
      'infobubble_path' => GETLOCATIONS_PATH . '/js/infobubble.js',
      'infobubble_options_path' => GETLOCATIONS_PATH . '/js/infobubble_options.js',
      'infobubble_extended_path' => GETLOCATIONS_PATH . '/js/infobubble_extended.js',
      'markermanager_path' => GETLOCATIONS_PATH . '/js/markermanager.js',
      'markerclusterer_path' => GETLOCATIONS_PATH . '/js/markerclusterer.js',
      'infowindow_options_path' => GETLOCATIONS_PATH . '/js/infowindow_options.js',
      'getlocations_path' => GETLOCATIONS_PATH . '/js/getlocations.js',
      'getlocations_polygons_path' => GETLOCATIONS_PATH . '/js/getlocations_polygons.js',
      'getlocations_rectangles_path' => GETLOCATIONS_PATH . '/js/getlocations_rectangles.js',
      'getlocations_circles_path' => GETLOCATIONS_PATH . '/js/getlocations_circles.js',
      'getlocations_polylines_path' => GETLOCATIONS_PATH . '/js/getlocations_polylines.js',
      'getlocations_categories_path' => GETLOCATIONS_PATH . '/js/getlocations_categories.js',
      'getlocations_search_places_path' => GETLOCATIONS_PATH . '/js/getlocations_search_places.js',
      'getlocations_geo_path' => GETLOCATIONS_PATH . '/js/getlocations_geo.js',
      'getlocations_preview_path' => GETLOCATIONS_PATH . '/js/getlocations_preview.js',
      'getlocations_geojson_path' => GETLOCATIONS_PATH . '/js/getlocations_geojson.js',
      #'getlocations_admin_path'         => GETLOCATIONS_PATH . '/js/getlocations_admin.js',
      'getlocations_admin_path' => GETLOCATIONS_PATH . ($jq_upd ? '/js/getlocations_admin_1.js' : '/js/getlocations_admin.js'),
      'getlocations_box_path' => GETLOCATIONS_PATH . '/js/getlocations_box.js',
      'getlocations_colorbox_path' => GETLOCATIONS_PATH . '/js/getlocations_colorbox.js',
      'getlocations_marker_box_path' => GETLOCATIONS_PATH . '/js/getlocations_marker_box.js',
      #'getlocations_views_path'         => GETLOCATIONS_PATH . '/js/getlocations_views.js',
      'getlocations_views_path' => GETLOCATIONS_PATH . ($jq_upd ? '/js/getlocations_views_1.js' : '/js/getlocations_views.js'),
      'getlocations_icons_path' => GETLOCATIONS_PATH . '/js/icons.js',
      'getlocations_field_group_path' => GETLOCATIONS_PATH . '/js/getlocations_field_group.js',
      'getlocations_what3words_path' => GETLOCATIONS_PATH . '/js/getlocations_what3words.js',
    );
  }
  if ($reset || $min) {
    $getlocations_paths = $defaults;
  }
  else {
    $settings = variable_get('getlocations_paths', $defaults);
    $getlocations_paths = getlocations_adjust_vars($defaults, $settings);
  }
  return $getlocations_paths;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_markerpicker_link($id, $cat, $infoimg = '') {
  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['marker_enable']) {
      $boxwidth = $getlocations_colorbox['marker_width'];
      $boxheight = $getlocations_colorbox['marker_height'];
      if (empty($infoimg)) {
        $infoimg = '<img class="getlocations_infoimg" src="' . base_path() . GETLOCATIONS_PATH . '/images/info.png' . '" title="' . t('Click here to select an icon from a colorbox') . '" >';
      }
      $link = l($infoimg, 'getlocations/markerinfo', array(
        'attributes' => array(
          'class' => 'colorbox-load',
        ),
        'html' => TRUE,
        'query' => array(
          'width' => $boxwidth,
          'height' => $boxheight,
          'iframe' => 'true',
          'lt' => $id,
          'cat' => $cat,
        ),
      ));
      return $link;
    }
  }
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_colorbox_settings() {
  $colorbox_defaults = array(
    'enable' => 0,
    'width' => 600,
    'height' => 600,
    'marker_enable' => 0,
    'marker_width' => 600,
    'marker_height' => 600,
  );
  $colorbox_settings = variable_get('getlocations_colorbox', $colorbox_defaults);
  $getlocations_colorbox = getlocations_adjust_vars($colorbox_defaults, $colorbox_settings);
  if (!module_exists('colorbox')) {
    $getlocations_colorbox['enable'] = 0;
    $getlocations_colorbox['marker_enable'] = 0;
  }
  return $getlocations_colorbox;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_polygon_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['polygons_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $polygons = array();
  $ct = 0;
  if (!preg_match("/^#/", $defaults['polygons_strokecolor'])) {
    $defaults['polygons_strokecolor'] = '#' . $defaults['polygons_strokecolor'];
  }
  if (!preg_match("/^#/", $defaults['polygons_fillcolor'])) {
    $defaults['polygons_fillcolor'] = '#' . $defaults['polygons_fillcolor'];
  }
  foreach ($coords_arr as $line) {
    $lla = array();

    // set defaults
    $polygons['polygons'][$ct]['strokeColor'] = $defaults['polygons_strokecolor'];
    $polygons['polygons'][$ct]['strokeOpacity'] = $defaults['polygons_strokeopacity'];
    $polygons['polygons'][$ct]['strokeWeight'] = $defaults['polygons_strokeweight'];
    $polygons['polygons'][$ct]['fillColor'] = $defaults['polygons_fillcolor'];
    $polygons['polygons'][$ct]['fillOpacity'] = $defaults['polygons_fillopacity'];
    $polygons['polygons'][$ct]['clickable'] = $defaults['polygons_clickable'];
    $polygons['polygons'][$ct]['message'] = $defaults['polygons_message'];
    $linebits = explode("|", $line);
    foreach ($linebits as $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {

        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/fillColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['fillColor'] = trim($m);
        }
        elseif (preg_match("/fillOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['fillOpacity'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['message'] = trim($m);
        }
      }
    }
    if (count($lla) > 2) {
      $polygons['polygons'][$ct]['coords'] = implode("|", $lla);
    }
    $ct++;
  }
  return $polygons;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_rectangle_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['rectangles_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $rectangles = array();
  $ct = 0;
  if (!preg_match("/^#/", $defaults['rectangles_strokecolor'])) {
    $defaults['rectangles_strokecolor'] = '#' . $defaults['rectangles_strokecolor'];
  }
  if (!preg_match("/^#/", $defaults['rectangles_fillcolor'])) {
    $defaults['rectangles_fillcolor'] = '#' . $defaults['rectangles_fillcolor'];
  }
  foreach ($coords_arr as $line) {
    $lla = array();

    // set defaults
    $rectangles['rectangles'][$ct]['strokeColor'] = $defaults['rectangles_strokecolor'];
    $rectangles['rectangles'][$ct]['strokeOpacity'] = $defaults['rectangles_strokeopacity'];
    $rectangles['rectangles'][$ct]['strokeWeight'] = $defaults['rectangles_strokeweight'];
    $rectangles['rectangles'][$ct]['fillColor'] = $defaults['rectangles_fillcolor'];
    $rectangles['rectangles'][$ct]['fillOpacity'] = $defaults['rectangles_fillopacity'];
    $rectangles['rectangles'][$ct]['clickable'] = $defaults['rectangles_clickable'];
    $rectangles['rectangles'][$ct]['message'] = $defaults['rectangles_message'];
    $linebits = explode("|", $line);
    foreach ($linebits as $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {

        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/fillColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['fillColor'] = trim($m);
        }
        elseif (preg_match("/fillOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['fillOpacity'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['message'] = trim($m);
        }
      }
    }
    if (count($lla) == 2) {
      $rectangles['rectangles'][$ct]['coords'] = implode("|", $lla);
    }
    $ct++;
  }
  return $rectangles;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_circle_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['circles_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $circles = array();
  $ct = 0;
  if (!preg_match("/^#/", $defaults['circles_strokecolor'])) {
    $defaults['circles_strokecolor'] = '#' . $defaults['circles_strokecolor'];
  }
  if (!preg_match("/^#/", $defaults['circles_fillcolor'])) {
    $defaults['circles_fillcolor'] = '#' . $defaults['circles_fillcolor'];
  }
  foreach ($coords_arr as $line) {
    $lla = array();

    // set defaults
    $circles['circles'][$ct]['strokeColor'] = $defaults['circles_strokecolor'];
    $circles['circles'][$ct]['strokeOpacity'] = $defaults['circles_strokeopacity'];
    $circles['circles'][$ct]['strokeWeight'] = $defaults['circles_strokeweight'];
    $circles['circles'][$ct]['fillColor'] = $defaults['circles_fillcolor'];
    $circles['circles'][$ct]['fillOpacity'] = $defaults['circles_fillopacity'];
    $circles['circles'][$ct]['clickable'] = $defaults['circles_clickable'];
    $circles['circles'][$ct]['message'] = $defaults['circles_message'];
    $circles['circles'][$ct]['radius'] = $defaults['circles_radius'];
    $linebits = explode("|", $line);
    foreach ($linebits as $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {

        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/fillColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['fillColor'] = trim($m);
        }
        elseif (preg_match("/fillOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['fillOpacity'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['message'] = trim($m);
        }
        elseif (preg_match("/radius:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['radius'] = trim($m);
        }
      }
    }
    if (count($lla) == 1) {
      $circles['circles'][$ct]['coords'] = $lla;
    }
    $ct++;
  }
  return $circles;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_polyline_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['polylines_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $polylines = array();
  $ct = 0;
  if (!preg_match("/^#/", $defaults['polylines_strokecolor'])) {
    $defaults['polylines_strokecolor'] = '#' . $defaults['polylines_strokecolor'];
  }
  foreach ($coords_arr as $line) {
    $lla = array();

    // set defaults
    $polylines['polylines'][$ct]['strokeColor'] = $defaults['polylines_strokecolor'];
    $polylines['polylines'][$ct]['strokeOpacity'] = $defaults['polylines_strokeopacity'];
    $polylines['polylines'][$ct]['strokeWeight'] = $defaults['polylines_strokeweight'];
    $polylines['polylines'][$ct]['clickable'] = $defaults['polylines_clickable'];
    $polylines['polylines'][$ct]['message'] = $defaults['polylines_message'];
    $linebits = explode("|", $line);
    foreach ($linebits as $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {

        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['message'] = trim($m);
        }
      }
    }
    if (count($lla) > 1) {
      $polylines['polylines'][$ct]['coords'] = implode("|", $lla);
    }
    $ct++;
  }
  return $polylines;
}

/**
 * Function to get the path to the GeoJSON library
 *
 * @param
 *
 * @return
 *   Returns string or false
 *
 */
function getlocations_get_geojson_path() {
  if ($geojsonpath = libraries_get_path('GeoJSON')) {
    return $geojsonpath . '/GeoJSON.js';
  }
  return FALSE;
}

/**
 * Function to get the path to the Geocoder-js library
 *
 * @param
 *
 * @return
 *   Returns string or false
 *
 */
function getlocations_get_geocoder_path() {
  if ($path = libraries_get_path('geocoder-js')) {
    return $path . '/geocoder.min.js';
  }
  return FALSE;
}

/**
 * Function to run string through check_plain but then restore apostrophes
 *
 * @param
 *
 * @return
 *   Returns string
 *
 */
function getlocations_apoclean($string) {
  $string = trim($string);
  $string = check_plain($string);
  return htmlspecialchars_decode($string, ENT_QUOTES);
}

/**
 * Recursively merge the defaults with the current settings
 *
 * @param array $defaults
 *
 * @param array $settings
 *
 * @return array The merged settings
 *
 */
function getlocations_adjust_vars($defaults, $settings) {
  $newdefaults = array();
  foreach ($defaults as $k => $v) {
    if (isset($settings[$k])) {
      if (is_array($v)) {
        $newdefaults[$k] = getlocations_adjust_vars($v, $settings[$k]);
      }
      else {
        $newdefaults[$k] = $settings[$k];
      }
    }
    else {
      $newdefaults[$k] = $v;
    }
  }
  return $newdefaults;
}

/**
 * Fetch fieldnames for a given module and type
 *
 * @param array $module module name
 * @param array $type type name
 *
 * @return array suitable for use in a dropdown.
 */
function getlocations_get_fieldnames($module = 'getlocations_fields', $type = 'getlocations_fields') {
  $field_names = array();
  $query = db_select('field_config', 'f');
  $query
    ->fields('f', array(
    'field_name',
  ));
  $query
    ->join('field_config_instance', 'i', 'f.id=i.field_id');
  $query
    ->condition('f.module', $module)
    ->condition('f.type', $type)
    ->condition('f.active', 1);
  $rows = $query
    ->execute();
  foreach ($rows as $row) {
    $field_names[$row->field_name] = $row->field_name;
  }
  return $field_names;
}

/**
 * Fetch bundle names for a given module and type
 *
 * @param array $module module name
 * @param array $type type name
 *
 * @return array suitable for use in a dropdown.
 */
function getlocations_get_bundles($module = 'getlocations_fields', $type = 'getlocations_fields') {
  $bundles = array();
  $query = db_select('field_config', 'f');
  $query
    ->fields('i', array(
    'bundle',
  ));
  $query
    ->join('field_config_instance', 'i', 'f.id=i.field_id');
  $query
    ->condition('f.module', $module)
    ->condition('f.type', $type)
    ->condition('f.active', 1);
  $rows = $query
    ->execute();
  foreach ($rows as $row) {
    $bundles[$row->bundle] = $row->bundle;
  }
  return $bundles;
}

/**
 * Fetch a list of the core Drupal list of countries.
 * from location module
 *
 * @param bool $upper Default uppercase
 *
 * @return array The countries array
 */
function getlocations_get_countries_list($upper = TRUE, $only_continents = '', $only_countries = '') {
  if (module_exists('countries')) {
    $filter = array(
      'enabled' => COUNTRIES_ENABLED,
    );
    if ($only_countries) {
      $only_countries = drupal_strtoupper($only_countries);
      $oc = explode(',', $only_countries);
      if (!empty($oc)) {
        $filter['countries'] = $oc;
      }
    }
    elseif (is_array($only_continents)) {
      $oc = array();
      foreach ($only_continents as $v) {
        $oc[] = $v;
      }
      if (!empty($oc)) {
        $filter['continents'] = $oc;
      }
    }
    $countries = countries_get_countries('name', $filter);
  }
  else {
    include_once DRUPAL_ROOT . '/includes/locale.inc';

    // Statically cache a version of the core Drupal list of countries
    $countries =& drupal_static(__FUNCTION__);
    if (!isset($countries) || empty($countries)) {
      $countries = country_get_list();
    }
  }
  if (!$upper) {
    $countries = array_change_key_case($countries, CASE_LOWER);
  }
  return $countries;
}

/**
 * Get the full country name
 *
 * @param string $id The two letter iso code of a country
 *
 * @return string Full country name.
 *
 */
function getlocations_get_country_name($id) {
  $countries = getlocations_get_countries_list();
  $id = drupal_strtoupper($id);
  $country = FALSE;
  if (isset($countries[$id])) {
    $country = $countries[$id];
  }
  return $country;
}

/**
 * Get the two letter code for a country
 *
 * @param string $country Full country name.
 *
 * @return string The two letter iso code of a country
 */
function getlocations_get_country_id($country) {
  $id = FALSE;
  $countries = getlocations_get_countries_list();
  foreach ($countries as $k => $v) {
    if (drupal_strtoupper($country) == drupal_strtoupper($v)) {
      $id = drupal_strtoupper($k);
      break;
    }
  }
  return $id;
}

/**
 * Convert decimal degrees to degrees,minutes,seconds.
 * from location module
 *
 * @param float Decimal degrees
 *
 * @return array degrees,minutes,seconds,sign
 */
function getlocations_dd_to_dms($coord) {
  $negative = $coord < 0 ? TRUE : FALSE;
  $coord = abs($coord);
  $degrees = floor($coord);
  $coord -= $degrees;
  $coord *= 60;
  $minutes = floor($coord);
  $coord -= $minutes;
  $coord *= 60;
  $seconds = round($coord, 6);
  return array(
    $degrees,
    $minutes,
    $seconds,
    $negative,
  );
}

/**
 * Convert dms string to decimal degrees.
 * Should be reasonably tolerant of sloppy input
 *
 * @param string
 *
 * @return string
 */
function getlocations_dms_to_dd($dms) {

  // If it ends with a word starting with S or W, then it's a negative
  // case insensitive
  $direction = 1;
  preg_match("/\\s(\\w+)\\b\$/", $dms, $m);
  if (preg_match("/^s/i", $m[1]) || preg_match("/^w/i", $m[1])) {
    $direction = -1;
  }
  $dmsarr = explode(' ', $dms);
  $dmsarr2 = array();
  foreach ($dmsarr as $v) {
    if ($v) {

      // strip out non-numbers found at the end of the string so we keep '.'
      $tmp = preg_replace("/\\D+\$/", '', $v);
      $tmp = trim($tmp);
      if ($tmp) {
        $dmsarr2[] = $tmp;
      }
    }
  }
  $dd = FALSE;
  if (count($dmsarr2) == 3) {
    list($degrees, $minutes, $seconds) = $dmsarr2;
    $dd = floatval($degrees + ($minutes * 60 + $seconds) / 3600);
    if ($dd > 0) {
      $dd = $direction * $dd;
    }
  }
  return $dd;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_addressfield_convert($address) {
  $location = theme('getlocations_addressfield_convert', array(
    'address' => $address,
  ));
  return $location;
}

/**
 * Make sure a string is a valid css dimension.
 */

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_dim_check($string) {
  if (!is_string($string) || empty($string)) {
    return FALSE;
  }
  $s = drupal_strtolower(trim($string));
  $matches = array();
  if (preg_match('/^([\\d.]+)\\s*(em|ex|px|in|cm|mm|pt|pc|%)$/', $s, $matches)) {
    return $matches[1] . $matches[2];
  }
  else {
    return FALSE;
  }
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_element_validate_dim($element, &$form_state) {
  $value = FALSE;
  if (isset($element['#value'])) {
    $value = $element['#value'];
  }
  elseif (isset($element['#default_value'])) {
    $value = $element['#default_value'];
  }
  $check = getlocations_dim_check($value);
  if (!$check) {
    form_error($element, t('%name must be valid css.', array(
      '%name' => $element['#title'],
    )));
  }
  else {
    $parents = $element['#parents'];

    // not a good solution
    $tot = count($parents);
    if ($tot == 3) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]] = $check;
    }
    elseif ($tot == 5) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]][$parents[3]][$parents[4]] = $check;
    }
  }
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_element_validate_latlon($element, &$form_state) {
  $value = FALSE;
  if (isset($element['#value'])) {
    $value = $element['#value'];
  }
  elseif (isset($element['#default_value'])) {
    $value = $element['#default_value'];
  }
  $check = getlocations_latlon_check($value);
  if (!$check) {
    form_error($element, t('%name must be expressed as a decimal latitude and longitude, separated by a comma.', array(
      '%name' => $element['#title'],
    )));
  }
  else {
    $parents = $element['#parents'];

    // not a good solution
    $tot = count($parents);
    if ($tot == 3) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]] = $check;
    }
    elseif ($tot == 5) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]][$parents[3]][$parents[4]] = $check;
    }
  }
}

/**
 * Calculations functions.
 * from location module
 */

/**
 * License clarification:
 *
 * On Feb 13, 2005, in message <Pine.LNX.4.58.0502131827510.5072@server1.LFW.org>,
 * the creator of these routines, Ka-Ping Yee, authorized these routines to be
 * distributed under the GPL.
 */

/**
 * @file
 * Trigonometry for calculating geographical distances.
 * All function arguments and return values measure distances in metres
 * and angles in degrees.  The ellipsoid model is from the WGS-84 datum.
 * Ka-Ping Yee, 2003-08-11
 */

// This library is an original implementation of UCB CS graduate student, Ka-Ping Yee (http://www.zesty.ca).
define('GETLOCATIONS_EARTH_RADIUS_SEMIMAJOR', 6378137.0);
define('GETLOCATIONS_EARTH_FLATTENING', 1 / 298.257223563);
define('GETLOCATIONS_EARTH_RADIUS_SEMIMINOR', 6378137.0 * (1 - 1 / 298.257223563));
define('GETLOCATIONS_EARTH_ECCENTRICITY_SQ', 2 * (1 / 298.257223563) - pow(1 / 298.257223563, 2));

// Default latitude halfway between north pole and equator
function getlocations_earth_radius($latitude = 45) {

  // Estimate the Earth's radius at a given latitude.
  $lat = deg2rad($latitude);
  $x = cos($lat) / GETLOCATIONS_EARTH_RADIUS_SEMIMAJOR;
  $y = sin($lat) / GETLOCATIONS_EARTH_RADIUS_SEMIMINOR;
  $return = 1 / sqrt($x * $x + $y * $y);
  return $return;
}

/**
 * Returns the SQL fragment needed to add a column called 'distance' to a query. For use in Views distance/proximity calculations
 *
 * @param $latitude    The measurement point
 * @param $longitude   The measurement point
 * @param $tbl_alias   If necessary, the alias name. Used by SQL to clearly identify a field.
 */
function getlocations_earth_distance_sql($latitude, $longitude, $tbl_alias = '') {

  // Make a SQL expression that estimates the distance to the given location.
  $radius = getlocations_earth_radius($latitude);

  // If the table alias is specified, add on the separator.
  $tbl_alias = empty($tbl_alias) ? '' : $tbl_alias . '.';
  $latfield = $tbl_alias . 'latitude';
  $lonfield = $tbl_alias . 'longitude';

  // all calcs in mysql

  #$sql = "(IFNULL(ACOS(COS(RADIANS($latitude)) * COS(RADIANS($latfield)) * (COS(RADIANS($longitude)) * COS(RADIANS($lonfield)) + SIN(RADIANS($longitude)) * SIN(RADIANS($lonfield))) + SIN(RADIANS($latitude)) * SIN(RADIANS($latfield))), 0.00000) * $radius)";

  // some calcs predone in php
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $coslong = cos($long);
  $coslat = cos($lat);
  $sinlong = sin($long);
  $sinlat = sin($lat);
  $sql = "(IFNULL(ACOS({$coslat} * COS(RADIANS({$latfield})) * ({$coslong}*COS(RADIANS({$lonfield})) + {$sinlong} * SIN(RADIANS({$lonfield}))) + {$sinlat} * SIN(RADIANS({$latfield}))), 0.00000) * {$radius})";
  return $sql;
}

/**
 * @param float $longitude1
 *
 * @param float $latitude1
 *
 * @param float $longitude2
 *
 * @param float $latitude2
 *
 * @return
 *   Returns distance in meters
 *
 */
function getlocations_earth_distance($longitude1, $latitude1, $longitude2, $latitude2) {
  $longitude1 = floatval($longitude1);
  $latitude1 = floatval($latitude1);
  $longitude2 = floatval($longitude2);
  $latitude2 = floatval($latitude2);

  // Estimate the earth-surface distance between two locations.
  $long1 = deg2rad($longitude1);
  $lat1 = deg2rad($latitude1);
  $long2 = deg2rad($longitude2);
  $lat2 = deg2rad($latitude2);
  $radius = getlocations_earth_radius(($latitude1 + $latitude2) / 2);
  $cosangle = cos($lat1) * cos($lat2) * (cos($long1) * cos($long2) + sin($long1) * sin($long2)) + sin($lat1) * sin($lat2);
  return acos($cosangle) * $radius;
}

/**
 * This function uses earth_asin_safe so is not accurate for all possible
 *   parameter combinations. This means this function doesn't work properly
 *   for high distance values. This function needs to be re-written to work properly for
 *   larger distance values. See http://drupal.org/node/821628
 *
 * http://drupal.org/node/471040 provides a fix, this has been applied here.
 *
 */
function getlocations_earth_longitude_range($latitude, $longitude, $distance) {

  // Estimate the min and max longitudes within $distance of a given location.
  if (!$distance > 0) {
    $distance = 1;
  }
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $radius = getlocations_earth_radius($latitude) * cos($lat);
  if ($radius > 0) {
    $angle = abs($distance / $radius);
    $angle = min($angle, pi());
  }
  else {
    $angle = pi();
  }
  $minlong = $long - $angle;
  $maxlong = $long + $angle;
  if ($minlong < -pi()) {
    $minlong = $minlong + pi() * 2;
  }
  if ($maxlong > pi()) {
    $maxlong = $maxlong - pi() * 2;
  }
  return array(
    rad2deg($minlong),
    rad2deg($maxlong),
  );
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_earth_latitude_range($latitude, $longitude, $distance) {

  // Estimate the min and max latitudes within $distance of a given location.
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $radius = getlocations_earth_radius($latitude);
  $angle = $distance / $radius;
  $minlat = $lat - $angle;
  $maxlat = $lat + $angle;
  $rightangle = pi() / 2;
  if ($minlat < -$rightangle) {

    // wrapped around the south pole
    $overshoot = -$minlat - $rightangle;
    $minlat = -$rightangle + $overshoot;
    if ($minlat > $maxlat) {
      $maxlat = $minlat;
    }
    $minlat = -$rightangle;
  }
  if ($maxlat > $rightangle) {

    // wrapped around the north pole
    $overshoot = $maxlat - $rightangle;
    $maxlat = $rightangle - $overshoot;
    if ($maxlat < $minlat) {
      $minlat = $maxlat;
    }
    $maxlat = $rightangle;
  }
  return array(
    rad2deg($minlat),
    rad2deg($maxlat),
  );
}

/**
 * This is a helper function to avoid errors when using the asin() PHP function.
 * asin is only real for values between -1 and 1.
 * If a value outside that range is given it returns NAN (not a number), which
 * we don't want to happen.
 * So this just rounds values outside this range to -1 or 1 first.
 *
 * This means that calculations done using this function with $x outside the range
 * will not be accurate.  The alternative though is getting NAN, which is an error
 * and won't give accurate results anyway.
 */

#function getlocations_earth_asin_safe($x) {

#  return asin(max(-1, min($x, 1)));

#}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_search_distance_sql($latitude, $longitude, $searchdistance, $tbl_alias = '') {
  $radius = getlocations_earth_radius($latitude);
  $tbl_alias = empty($tbl_alias) ? $tbl_alias : $tbl_alias . '.';
  $latfield = $tbl_alias . 'latitude';
  $lonfield = $tbl_alias . 'longitude';

  // all calcs in mysql

  #$sql = "(IFNULL(ACOS((SIN(RADIANS($latitude)) * SIN(RADIANS($latfield)) + (COS(RADIANS($latitude)) * COS(RADIANS($latfield)) * COS(RADIANS($lonfield) - RADIANS($longitude))))), 0.00000) * $radius) BETWEEN 0 AND $searchdistance ";

  // some calcs predone in php
  $lat = deg2rad($latitude);
  $long = deg2rad($longitude);

  #$coslong = cos($long);
  $coslat = cos($lat);

  #$sinlong = sin($long);
  $sinlat = sin($lat);
  $sql = "(IFNULL(ACOS(({$sinlat} * SIN(RADIANS({$latfield})) + ({$coslat} * COS(RADIANS({$latfield})) * COS(RADIANS({$lonfield}) - {$long} )))), 0.00000) * {$radius})";
  if ($searchdistance > 0) {
    $sql .= " BETWEEN 0 AND {$searchdistance}";
  }
  return $sql;
}

/**
 * @param $distance
 *   A number in either kilometers, meters, miles, yards or nautical miles.
 *
 * @param $distance_unit
 *   String (optional). in either kilometers (km), meters (m), miles (mi), yards (yd) or nautical miles (nmi).
 *
 * @return
 *   A floating point number where the number in meters after the initially passed scalar has been round()'d
 */
function getlocations_convert_distance_to_meters($distance, $distance_unit = 'km') {
  if (!is_numeric($distance) || !$distance > 0) {
    return NULL;
  }
  $units = array(
    'km' => 1000.0,
    'm' => 1.0,
    'mi' => 1609.344,
    'yd' => 0.9144,
    'nmi' => 1852.0,
  );
  if (!in_array($distance_unit, array_keys($units))) {
    $distance_unit = 'km';
  }
  $conv = $units[$distance_unit];

  // Convert distance to meters
  $retval = round(floatval($distance) * $conv, 2);
  return $retval;
}

/**
 * @param $meters
 *   The distance in meters.
 *
 * @param $distance_unit
 *   String (optional). in either kilometers (km), meters (m), miles (mi), yards (yd) or nautical miles (nmi).
 *
 * @return
 *   A floating point number where the converted number has been round()'d
 */
function getlocations_convert_meters_to_distance($meters, $distance_unit = 'km') {
  if (!is_numeric($meters) || !$meters > 0) {
    return NULL;
  }
  $units = array(
    'km' => 0.001,
    'm' => 1.0,
    'mi' => 0.000621371,
    'yd' => 1.093613298,
    'nmi' => 0.000539957,
  );
  if (!in_array($distance_unit, array_keys($units))) {
    $distance_unit = 'km';
  }
  $conv = $units[$distance_unit];

  // Convert meters to display units. formatting in theme_getlocations_fields_distance();
  $retval = $meters * $conv;
  return $retval;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_unit_names($unit = '', $type = 'plural') {
  $units_plural = array(
    'km' => t('Kilometers'),
    'm' => t('Meters'),
    'mi' => t('Miles'),
    'yd' => t('Yards'),
    'nmi' => t('Nautical miles'),
  );
  $units_plurals = array(
    'km' => t('Kilometer(s)'),
    'm' => t('Meter(s)'),
    'mi' => t('Mile(s)'),
    'yd' => t('Yard(s)'),
    'nmi' => t('Nautical mile(s)'),
  );
  $units = array(
    'km' => t('Kilometer'),
    'm' => t('Meter'),
    'mi' => t('Mile'),
    'yd' => t('Yard'),
    'nmi' => t('Nautical mile'),
  );

  // for dropdown
  $return = FALSE;
  if (empty($unit)) {
    if ($type == 'plural') {
      $return = $units_plural;
    }
    elseif ($type == 'plurals') {
      $return = $units_plurals;
    }
    else {
      $return = $units;
    }
  }
  else {

    // if $unit is supplied, return display name
    if (!in_array($unit, array_keys($units))) {
      $unit = 'km';
    }
    if ($type == 'plural') {
      $return = $units_plural[$unit];
    }
    elseif ($type == 'plurals') {
      $return = $units_plurals[$unit];
    }
    else {
      $return = $units[$unit];
    }
  }
  return $return;
}

// form elements

/**
 * @param string $default
 * @param string $title
 * @param string $description
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_distance_unit($default, $title = '', $description = '') {
  if (empty($title)) {
    $title = t('Units');
  }
  $units = getlocations_get_unit_names();
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#options' => $units,
    '#default_value' => $default,
  );
  if (!empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * @param string $default
 * @param string $title
 * @param string $description
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_search_distance($default, $title = '', $description = '') {
  if (empty($title)) {
    $title = t('Distance');
  }
  $element = array(
    '#type' => 'textfield',
    '#title' => $title,
    '#default_value' => $default,
    '#size' => 10,
    '#required' => TRUE,
  );
  if (!empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Normalizes a latitude to the [-90,90] range. Latitudes above 90 or
 * below -90 are capped, not wrapped.
 * @param {Number} lat The latitude to normalize, in degrees.
 * @type Number
 * @return Returns the latitude, fit within the [-90,90] range.
 */
function getlocations_normalizelat($lat) {
  return max(-90, min(90, $lat));
}

/**
 * Normalizes a longitude to the [-180,180] range. Longitudes above 180
 * or below -180 are wrapped.
 * @param {Number} lng The longitude to normalize, in degrees.
 * @type Number
 * @return Returns the longitude, fit within the [-180,180] range.
 */
function getlocations_normalizelng($lng) {
  if ($lng % 360 == 180) {
    return 180;
  }
  while ($lng > 180) {
    $lng -= 360;
  }
  while ($lng < -180) {
    $lng += 360;
  }
  return $lng;
}

/**
 * Function
 *
 * @param bool $override
 *
 * @return
 *   Returns TRUE if user agent says its a mobile device
 *
 */
function getlocations_is_mobile($override = FALSE) {
  if ($override) {
    return TRUE;
  }
  $getlocations_ua = getlocations_ua_get();
  $str = "/" . $getlocations_ua['ua_string'] . "/i";
  $is_mobile = FALSE;
  $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
  if ($ua && preg_match($str, $ua)) {
    $is_mobile = TRUE;
  }
  return $is_mobile;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_ua_get() {
  $default = array(
    'ua_string' => "iphone|ipad|android|blackberry|blazer|bolt|symbian|mobile safari|fennec|gobrowser|iemobile|maemo browser|profile midp|minimo|kindle|opera mini|opera mobi|skyfire|teashark|uzardweb",
  );
  $getlocations_ua = variable_get('getlocations_ua', $default);
  return $getlocations_ua;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_aggr_get() {
  $getlocations_aggr = variable_get('getlocations_aggr', 1);
  return $getlocations_aggr;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_term_marker($nid, $marker) {
  $getlocations_defaults = getlocations_defaults();

  // term markers
  $getlocations_term_marker = variable_get('getlocations_term_marker', array(
    'enable' => 0,
    'vids' => 0,
    'max_depth' => '',
  ));
  if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
    $vids = $getlocations_term_marker['vids'];
    foreach ($vids as $vid) {
      $results = db_query('SELECT i.tid FROM {taxonomy_index} i JOIN {taxonomy_term_data} d ON i.tid=d.tid WHERE i.nid = :nid AND d.vid =:vid', array(
        ':nid' => $nid,
        ':vid' => $vid,
      ));
      $record = $results
        ->fetchObject();
      if ($record) {
        $marker = isset($getlocations_term_marker['vid'][$vid]['term'][$record->tid]['map_marker']) ? $getlocations_term_marker['vid'][$vid]['term'][$record->tid]['map_marker'] : $getlocations_defaults['term_map_marker'];
      }
    }
  }
  return $marker;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_supported_modules() {
  return array(
    'getlocations_fields',
    'geofield',
    'geolocation',
    'location_cck',
  );
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_current_supported_module() {
  $modules = getlocations_supported_modules();
  foreach ($modules as $module) {
    if (module_exists($module)) {
      return $module;
    }
  }
  return FALSE;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_controlpositions($dd = TRUE) {
  if ($dd) {
    $controlpositions = array(
      '' => t('Default'),
      'tl' => t('Top Left'),
      'tc' => t('Top Center'),
      'tr' => t('Top Right'),
      'rt' => t('Right Top'),
      'rc' => t('Right Center'),
      'rb' => t('Right Bottom'),
      'br' => t('Bottom Right'),
      'bc' => t('Bottom Center'),
      'bl' => t('Bottom Left'),
      'lb' => t('Left Bottom'),
      'lc' => t('Left Center'),
      'lt' => t('Left Top'),
    );
  }
  else {
    $controlpositions = array(
      'tl',
      'tc',
      'tr',
      'rt',
      'rc',
      'rb',
      'br',
      'bc',
      'bl',
      'lb',
      'lc',
      'lt',
    );
  }
  return $controlpositions;
}

/**
 * Allows for aliases in entity types
 *
 */
function getlocations_get_entity_type_from_path($path) {
  $entity_type = $path;

  // getlocations path => entity_type
  $aliases = array(
    'term' => 'taxonomy_term',
  );
  if (isset($aliases[$path])) {
    $entity_type = $aliases[$path];
  }
  return $entity_type;
}

/**
 * Given two points in lat/lon form, returns the distance between them.
 * @param $latlon_a
 *   An associative array where
 *      'lon' => is a floating point of the longitude coordinate for the point given by latlonA
 *      'lat' => is a floating point of the latitude coordinate for the point given by latlonB
 * @param $latlon_b
 *      Another point formatted like $latlon_b
 * @param $distance_unit
 *      A string that is one of 'km', 'm', 'mi', 'yd', 'nmi'.
 *      Defaults to 'km'
 * @return
 *    NULL if sense can't be made of the parameters.
 *    An associative array where
 *      'scalar' => Is the distance between the two lat/lon parameter points
 *      'distance_unit' => Is the unit of distance being represented by 'scalar'.
 *
 */
function getlocations_distance_between($latlon_a = array(), $latlon_b = array(), $distance_unit = 'km') {
  if (!isset($latlon_a['lon']) || !isset($latlon_a['lat']) || !isset($latlon_b['lon']) || !isset($latlon_b['lat'])) {
    return NULL;
  }
  $meters = getlocations_earth_distance($latlon_a['lon'], $latlon_a['lat'], $latlon_b['lon'], $latlon_b['lat']);
  $distance = getlocations_convert_meters_to_distance($meters, $distance_unit);
  return array(
    'scalar' => $distance,
    'distance_unit' => $distance_unit,
  );
}

/***********************************************************/

// these functions currently not in use
function getlocations_earth_xyz($longitude, $latitude, $height = 0) {

  // Convert longitude and latitude to earth-centered earth-fixed coordinates.
  // X axis is 0 long, 0 lat; Y axis is 90 deg E; Z axis is north pole.
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $coslong = cos($long);
  $coslat = cos($lat);
  $sinlong = sin($long);
  $sinlat = sin($lat);
  $radius = GETLOCATIONS_EARTH_RADIUS_SEMIMAJOR / sqrt(1 - GETLOCATIONS_EARTH_ECCENTRICITY_SQ * $sinlat * $sinlat);
  $x = ($radius + $height) * $coslat * $coslong;
  $y = ($radius + $height) * $coslat * $sinlong;
  $z = ($radius * (1 - GETLOCATIONS_EARTH_ECCENTRICITY_SQ) + $height) * $sinlat;
  return array(
    $x,
    $y,
    $z,
  );
}
function getlocations_earth_arclength($angle, $latitude = 37.9) {

  // Convert a given angle to earth-surface distance.
  return deg2rad($angle) * getlocations_earth_radius($latitude);
}
function getlocations_get_exact_distance_sql($latitude, $longitude, $tbl_alias = '') {
  $radius = getlocations_earth_radius($latitude);
  $tbl_alias = empty($tbl_alias) ? $tbl_alias : $tbl_alias . '.';
  $latfield = $tbl_alias . 'latitude';
  $lonfield = $tbl_alias . 'longitude';

  // all calcs in mysql

  #$sql = "(IFNULL(ACOS((SIN(RADIANS($latitude)) * SIN(RADIANS($latfield))) + (COS(RADIANS($latitude)) * COS(RADIANS($latfield)) * COS(RADIANS($longitude - $lonfield)))), 0.00000) * $radius)";

  // some calcs predone in php
  $lat = deg2rad($latitude);
  $long = deg2rad($longitude);

  #$coslong = cos($long);
  $coslat = cos($lat);

  #$sinlong = sin($long);
  $sinlat = sin($lat);
  $sql = "(IFNULL(ACOS(({$sinlat} * SIN(RADIANS({$latfield}))) + ({$coslat} * COS(RADIANS({$latfield})) * COS(RADIANS({$longitude} - {$lonfield})))), 0.00000) * {$radius})";
  return $sql;
}
function getlocations_check_jquery_version($admin = TRUE) {
  $version = '1.4.4';
  $v = FALSE;
  if (module_exists('jquery_update')) {
    if ($admin) {
      $version = variable_get('jquery_update_jquery_admin_version', FALSE);
      if ($version == 0) {
        $version = variable_get('jquery_update_jquery_version', FALSE);
      }
    }
    else {
      $version = variable_get('jquery_update_jquery_version', FALSE);
    }
  }
  if ($version) {
    $a = explode(".", $version);
    if ($a[0] > 1) {
      $v = TRUE;
    }
    elseif ($a[1] > 5) {
      $v = TRUE;
    }
  }
  return $v;
}

// Theming functions

/**
 * Implements hook_theme().
 *
 * This lets us tell Drupal about our theme functions and their arguments.
 */
function getlocations_theme() {
  return array(
    'getlocations_show' => array(
      'variables' => array(
        'width' => '',
        'height' => '',
        'defaults' => '',
        'mapid' => '',
        'latlons' => '',
        'minmaxes' => '',
        'type' => '',
        'node' => '',
      ),
    ),
    'getlocations_adinfo' => array(
      'variables' => array(
        'location' => NULL,
      ),
    ),
    'getlocations_box' => array(
      'variables' => array(
        'content' => NULL,
      ),
      'template' => 'getlocations_box',
    ),
    'getlocations_marker_box' => array(
      'variables' => array(
        'content' => NULL,
      ),
      'template' => 'getlocations_marker_box',
    ),
    'getlocations_settings_form' => array(
      'render element' => 'form',
    ),
    'getlocations_plugin_style_map_options_form' => array(
      'render element' => 'form',
    ),
    'getlocations_plugin_style_streetview_options_form' => array(
      'render element' => 'form',
    ),
    'getlocations_latitude_dms' => array(
      'variables' => array(
        'latitude' => '',
      ),
    ),
    'getlocations_longitude_dms' => array(
      'variables' => array(
        'longitude' => '',
      ),
    ),
    'getlocations_addressfield_convert' => array(
      'variables' => array(
        'address' => array(),
      ),
    ),
    'getlocations_lidinfo' => array(
      'variables' => array(
        'lid' => '',
        'lidkey' => '',
      ),
    ),
  );
}

/**
 * Returns HTML for a map.
 *
 * All the map displays pass through here.
 *
 * @param array $variables
 *   An associative array containing:
 *   - width: The width of the map.
 *   - height: The height of the map.
 *   - defaults: The settings to be applied to the map, links, buttons and form elements.
 *   - mapid: The unique identifier for the map.
 *   - type: The entity type, eg node, user, term or comment.
 *   - node: The entity object.
 *
 * @return string $output
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_show($variables) {
  $width = $variables['width'];
  $height = $variables['height'];
  $defaults = $variables['defaults'];
  $mapid = $variables['mapid'];
  $type = $variables['type'];
  $node = $variables['node'];
  $latlons = $variables['latlons'];
  $minmaxes = $variables['minmaxes'];
  $datanum = count($latlons);
  $output = '';
  $returnlink = FALSE;

  // return link
  if ($type == 'node' && $defaults['returnlink_page_enable']) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_page_link'];
      if (preg_match("/%t/", $linktext)) {
        $linktext = preg_replace("/%t/", $node->title, $linktext);
      }
      $l = l($linktext, 'node/' . $node->nid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  elseif ($type == 'user' && $defaults['returnlink_user_enable']) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_user_link'];
      if (preg_match("/%n/", $linktext)) {
        $linktext = preg_replace("/%n/", $node->name, $linktext);
      }
      $l = l($linktext, 'user/' . $node->uid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  elseif ($type == 'term' && $defaults['returnlink_term_enable'] && module_exists('taxonomy')) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_term_link'];
      if (preg_match("/%n/", $linktext)) {
        $linktext = preg_replace("/%n/", $node->name, $linktext);
      }
      $l = l($linktext, 'taxonomy/term/' . $node->tid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  elseif ($type == 'comment' && $defaults['returnlink_comment_enable'] && module_exists('comment')) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_comment_link'];
      if (preg_match("/%n/", $linktext)) {
        $linktext = preg_replace("/%n/", $node->subject, $linktext);
      }
      $l = l($linktext, 'comment/' . $node->cid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  if ($returnlink) {
    $output .= $returnlink;
  }
  if ($defaults['map_resize'] && getlocations_is_mobile()) {
    $width = '100%';

    #$height = '100%';
  }

  // show maplinks if enabled
  if ($defaults['show_maplinks']) {
    $output .= '<a id="maptop_' . $mapid . '" name="maptop_' . $mapid . '"></a>';
  }

  // search_places
  $sp = '';
  if ($defaults['search_places']) {
    $sp .= '<div class="search_places_input_wrapper">';
    if ($defaults['search_places_label']) {
      $sp .= '<label for="search_places_select_' . $mapid . '">' . $defaults['search_places_label'] . '</label>';
    }
    if ($defaults['search_places_dd']) {

      // alternative dropdown
      $sp_opts = array(
        'accounting' => t('Accounting'),
        'airport' => t('Airport'),
        'amusement_park' => t('Amusement park'),
        'aquarium' => t('Aquarium'),
        'art_gallery' => t('Art gallery'),
        'atm' => t('ATM'),
        'bakery' => t('Bakery'),
        'bank' => t('Bank'),
        'bar' => t('Bar'),
        'beauty_salon' => t('Beauty salon'),
        'bicycle_store' => t('Bicycle store'),
        'book_store' => t('Book store'),
        'bowling_alley' => t('Bowling alley'),
        'bus_station' => t('Bus station'),
        'cafe' => t('Cafe'),
        'campground' => t('Campground'),
        'car_dealer' => t('Car dealer'),
        'car_rental' => t('Car rental'),
        'car_repair' => t('Car repair'),
        'car_wash' => t('Car wash'),
        'casino' => t('Casino'),
        'cemetery' => t('Cemetery'),
        'church' => t('Church'),
        'city_hall' => t('City hall'),
        'clothing_store' => t('Clothing store'),
        'convenience_store' => t('Convenience store'),
        'courthouse' => t('Courthouse'),
        'dentist' => t('Dentist'),
        'department_store' => t('Department store'),
        'doctor' => t('Doctor'),
        'electrician' => t('Electrician'),
        'electronics_store' => t('Electronics store'),
        'embassy' => t('Embassy'),
        'establishment' => t('Establishment'),
        'finance' => t('Finance'),
        'fire_station' => t('Fire station'),
        'florist' => t('Florist'),
        'food' => t('Food'),
        'funeral_home' => t('Funeral home'),
        'furniture_store' => t('Furniture store'),
        'gas_station' => t('Gas station'),
        'general_contractor' => t('General contractor'),
        'grocery_or_supermarket' => t('Grocery or supermarket'),
        'gym' => t('Gym'),
        'hair_care' => t('Hair care'),
        'hardware_store' => t('Hardware store'),
        'health' => t('Health'),
        'hindu_temple' => t('Hindu temple'),
        'home_goods_store' => t('Home goods store'),
        'hospital' => t('Hospital'),
        'insurance_agency' => t('Insurance agency'),
        'jewelry_store' => t('Jewelry store'),
        'laundry' => t('Laundry'),
        'lawyer' => t('Lawyer'),
        'library' => t('Library'),
        'liquor_store' => t('Liquor store'),
        'local_government_office' => t('Local government office'),
        'locksmith' => t('Locksmith'),
        'lodging' => t('Lodging'),
        'meal_delivery' => t('Meal delivery'),
        'meal_takeaway' => t('Meal takeaway'),
        'mosque' => t('Mosque'),
        'movie_rental' => t('Movie rental'),
        'movie_theater' => t('Movie theater'),
        'moving_company' => t('Moving company'),
        'museum' => t('Museum'),
        'night_club' => t('Night club'),
        'painter' => t('Painter'),
        'park' => t('Park'),
        'parking' => t('Parking'),
        'pet_store' => t('Pet store'),
        'pharmacy' => t('Pharmacy'),
        'physiotherapist' => t('Physiotherapist'),
        'place_of_worship' => t('Place of worship'),
        'plumber' => t('Plumber'),
        'police' => t('Police'),
        'post_office' => t('Post office'),
        'real_estate_agency' => t('Real estate agency'),
        'restaurant' => t('Restaurant'),
        'roofing_contractor' => t('Roofing contractor'),
        'rv_park' => t('RV park'),
        'school' => t('School'),
        'shoe_store' => t('Shoe store'),
        'shopping_mall' => t('Shopping mall'),
        'spa' => t('Spa'),
        'stadium' => t('Stadium'),
        'storage' => t('Storage'),
        'store' => t('Store'),
        'subway_station' => t('Subway station'),
        'synagogue' => t('Synagogue'),
        'taxi_stand' => t('Taxi stand'),
        'train_station' => t('Train station'),
        'travel_agency' => t('Travel agency'),
        'university' => t('University'),
        'veterinary_care' => t('Veterinary care'),
        'zoo' => t('Zoo'),
      );
      $sp .= '<select id="search_places_select_' . $mapid . '" class="form-select" >';
      foreach ($sp_opts as $k_opt => $opt) {
        $sel = '';
        if ($k_opt == 'establishment') {
          $sel = 'selected';
        }
        $sp .= '<option value="' . $k_opt . '" ' . $sel . '>' . $opt . '</option>';
      }
      $sp .= '</select>';
      $sp .= '&nbsp;&nbsp;<input type="button" value="' . t('Go') . '" id="search_places_go_btn_' . $mapid . '" class="form-submit" />';
      $sp .= '&nbsp;&nbsp;<input type="button" value="' . t('Reset') . '" onClick="Drupal.getlocations_search_places_clearmarkers(\'' . $mapid . '\', true)"  class="form-submit" />';
      $sp .= '</div>';
    }
    else {
      $placeholder = '';
      if ($defaults['search_places_placeholder']) {
        $placeholder = 'placeholder="' . $defaults['search_places_placeholder'] . '"';
      }
      $sp .= '<input type="text" id="search_places_input_' . $mapid . '" size="' . $defaults['search_places_size'] . '" class="form-text" ' . $placeholder . ' />';
      $sp .= '&nbsp;&nbsp;<input type="button" value="' . t('Reset') . '" onClick="Drupal.getlocations_search_places_clearmarkers(\'' . $mapid . '\', true)"  class="form-submit" />';
      $sp .= '</div>';
    }
    if ($defaults['search_places_list']) {
      $sp .= '<div class="sp_listing_wrapper"><h4>' . t('Google Places search results') . '</h4><div class="sp_listing"><ul class="sp_ul" id="search_places_results_' . $mapid . '"></ul></div></div>';
    }
  }
  if ($defaults['search_places'] && $defaults['search_places_position'] == 'outside_above') {
    $output .= $sp;
  }

  // type class
  $class = '';
  if ($type) {
    $class = ' getlocations_' . $type;
  }

  // wrap the map
  $output .= '<div class="getlocations_map_wrapper_inner' . $class . '">';
  $output .= '<div id="getlocations_map_wrapper_' . $mapid . '"  style="width: ' . $width . '; height: ' . $height . '" >';
  $output .= '<div class="getlocations_map_canvas" id="getlocations_map_canvas_' . $mapid . '" style="width: 100%; height: 100%" ></div>';
  $output .= '</div>';
  $output .= '</div>';

  // getlocations_map_wrapper_inner
  // give each map its own data
  $localdata = json_encode(array(
    'datanum' => $datanum,
    'latlons' => $latlons,
    'minmaxes' => $minmaxes,
  ));
  $output .= "\n" . '<script type="text/javascript">' . "\n" . '<!--//--><![CDATA[//><!--' . "\n";
  $output .= 'Drupal.getlocations_data["' . $mapid . '"] = ' . $localdata . ';' . "\n";
  $output .= '//--><!]]>' . "\n" . '</script>' . "\n";

  // show_search_distance
  if (module_exists('getlocations_fields') && isset($defaults['search_dist_info'])) {
    $output .= '<div id="getlocations_fields_search_views_search_wrapper_' . $mapid . '" class="js-hide">';
    $output .= '<div id="getlocations_fields_search_views_search_units_' . $mapid . '">' . $defaults['search_dist_info']['search_units'] . '</div>';
    $output .= '<div id="getlocations_fields_search_views_search_latitude_' . $mapid . '">' . $defaults['search_dist_info']['latitude'] . '</div>';
    $output .= '<div id="getlocations_fields_search_views_search_longitude_' . $mapid . '">' . $defaults['search_dist_info']['longitude'] . '</div>';
    $output .= '<div id="getlocations_fields_search_views_search_distance_meters_' . $mapid . '">' . getlocations_convert_distance_to_meters($defaults['search_dist_info']['search_distance'], $defaults['search_dist_info']['search_units']) . '</div>';
    $output .= '</div>';
  }

  // show maplinks if enabled
  if ($defaults['show_maplinks']) {
    $output .= '<div class="getlocations_map_links" id="getlocations_map_links_' . $mapid . '" ><ul></ul></div>';
  }

  // buttons
  $buttons = array();
  if ($defaults['trafficinfo']) {
    $buttons[] = '<input type="button" value="' . t('Traffic Info !t', array(
      '!t' => $defaults['trafficinfo_state'] ? t('Off') : t('On'),
    )) . '" title="' . t('Limited Availability') . '" id="getlocations_toggleTraffic_' . $mapid . '" class="form-submit" />';
  }
  if ($defaults['bicycleinfo']) {
    $buttons[] = '<input type="button" value="' . t('Bicycle Info !t', array(
      '!t' => $defaults['bicycleinfo_state'] ? t('Off') : t('On'),
    )) . '" title="' . t('Limited Availability') . '" id="getlocations_toggleBicycle_' . $mapid . '" class="form-submit" />';
  }
  if ($defaults['transitinfo']) {
    $buttons[] = '<input type="button" value="' . t('Transit Info !t', array(
      '!t' => $defaults['transitinfo_state'] ? t('Off') : t('On'),
    )) . '" title="' . t('Limited Availability') . '" id="getlocations_toggleTransit_' . $mapid . '" class="form-submit" />';
  }

  // views_search_marker
  if (module_exists('getlocations_fields') && isset($defaults['search_dist_info'])) {
    if ($defaults['views_search_marker_enable'] && $defaults['views_search_marker_toggle']) {
      $buttons[] = '<input type="button" value="' . t('Search marker !t', array(
        '!t' => $defaults['views_search_marker_toggle_active'] ? t('Off') : t('On'),
      )) . '" id="getlocations_toggleSearchMarker_' . $mapid . '" class="form-submit" />';
    }
    if ($defaults['views_search_radshape_enable'] && $defaults['views_search_radshape_toggle']) {
      $buttons[] = '<input type="button" value="' . t('Search area !t', array(
        '!t' => $defaults['views_search_radshape_toggle_active'] ? t('Off') : t('On'),
      )) . '" id="getlocations_toggleSearchArea_' . $mapid . '" class="form-submit" />';
    }
  }

  // categories
  if (isset($defaults['category_showhide_buttons']) && $defaults['category_showhide_buttons']) {
    if (isset($defaults['categories']) && $defaults['categories']) {
      foreach ($defaults['categories'] as $cat => $label) {
        $buttons[] = '<input type="button" value="' . t('!cat Off', array(
          '!cat' => $label,
        )) . '" id="getlocations_toggle_' . $cat . '_' . $mapid . '" class="form-submit" />';
      }
    }
  }

  // KML
  if ($defaults['kml_group']['kml_url'] && $defaults['kml_group']['kml_url_button']) {
    $kmlbuttonlabel = t('Kml Layer');
    if ($defaults['kml_group']['kml_url_button_label']) {
      $kmlbuttonlabel = $defaults['kml_group']['kml_url_button_label'];
    }
    $kmlbuttonlabel .= ' ' . ($defaults['kml_group']['kml_url_button_state'] ? t('Off') : t('On'));
    $buttons[] = '<input type="button" value="' . $kmlbuttonlabel . '" id="getlocations_toggleKmlLayer_' . $mapid . '" class="form-submit"  />';
  }
  if (module_exists('getlocations_search')) {

    // search area shape
    if (isset($defaults['search_radshape_toggle']) && $defaults['search_radshape_toggle'] && $defaults['search_radshape_enable']) {
      $buttons[] = '<input type="button" value="' . t('Search area !t', array(
        '!t' => $defaults['search_radshape_toggle_active'] ? t('Off') : t('On'),
      )) . '" id="getlocations_search_toggleShape_' . $mapid . '" class="form-submit" />';
    }

    // search marker toggle button
    if (isset($defaults['do_search_marker']) && $defaults['do_search_marker'] && $defaults['search_marker_toggle']) {
      $buttons[] = '<input type="button" value="' . t('Marker !t', array(
        '!t' => $defaults['search_marker_toggle_active'] ? t('Off') : t('On'),
      )) . '" id="getlocations_search_toggleMarker_' . $mapid . '" class="form-submit" />';
    }
  }

  // getlocations_gps
  if (module_exists('getlocations_gps')) {
    $buttons[] = theme('getlocations_gps_button', array(
      'defaults' => $defaults,
      'mapid' => $mapid,
    ));
  }

  // getlocations_smartip
  if (module_exists('getlocations_smartip')) {
    $buttons[] = theme('getlocations_smartip_button', array(
      'defaults' => $defaults,
      'mapid' => $mapid,
    ));
  }
  if (count($buttons)) {
    $output .= '<div class="getlocations_map_buttons container-inline">';
    $output .= implode('&nbsp;', $buttons);
    $output .= '</div>';
  }

  // search_places
  if ($defaults['search_places'] && $defaults['search_places_position'] == 'outside_below') {
    $output .= $sp;
  }

  // What3Words
  $what3words_lic = variable_get('getlocations_what3words_lic', array(
    'key' => '',
    'url' => 'http://api.what3words.com',
  ));
  if ($what3words_lic['key'] && $defaults['what3words_enable']) {
    $output .= '<div class="getlocations_what3words container-inline">';
    if ($defaults['what3words_search']) {

      // textbox
      $output .= t('What3Words') . '&nbsp;&nbsp;<input type="text" id="edit-getlocations-what3words-search" name="edit-getlocations-what3words-search" value="" size="' . $defaults['what3words_size'] . '" class="form-text" />';
      $output .= '&nbsp;&nbsp;<input type="button" value="' . t('Search') . '" id="edit-getlocations-what3words-search-submit" class="form-submit" />';
      $output .= '<div class="getlocations_w3w_throbber getlocations_w3w_throbber_inactive" id="getlocations_w3w_throbber_' . $mapid . '">&nbsp;&nbsp;&nbsp;&nbsp;</div>';
      $output .= '<br />';
    }
    if ($defaults['what3words_show']) {
      $output .= '<div id="edit-getlocations-what3words-show"></div>';
    }
    $output .= '</div>';
  }
  return $output;
}

/**
 * Returns HTML of a location's vcard, requested by ajax.
 *
 * @param array $variables
 *   An associative array containing:
 *   - location: The information pertaining to the address to be formatted.
 *
 * @return string $output
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_adinfo($variables) {
  $location = $variables['location'];
  $output = '';
  $output .= '<div class="location vcard">';

  // this logic gives the location name field precedence over the node title
  // similarly for users, terms and comments
  $link = FALSE;
  $l = FALSE;
  if (isset($location['nid']) && $location['nid'] > 0) {
    if (!empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $node = node_load($location['nid']);
      $link = $node->title;
    }
    $l = l($link, 'node/' . $location['nid'], array(
      'attributes' => array(
        'class' => array(
          'getlocations_infolink',
        ),
        'target' => '_parent',
      ),
    ));
  }
  elseif (isset($location['uid']) && $location['uid'] > 0) {
    if (!empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $account = user_load($location['uid']);
      $link = $account->name;
    }
    $l = l($link, 'user/' . $location['uid'], array(
      'attributes' => array(
        'class' => array(
          'getlocations_infolink',
        ),
        'target' => '_parent',
      ),
    ));
  }
  elseif (isset($location['tid']) && $location['tid'] > 0 && module_exists('taxonomy')) {
    if (!empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $term = taxonomy_term_load($location['tid']);
      $link = $term->name;
    }
    $l = l($link, 'taxonomy/term/' . $location['tid'], array(
      'attributes' => array(
        'class' => array(
          'getlocations_infolink',
        ),
        'target' => '_parent',
      ),
    ));
  }
  elseif (isset($location['cid']) && $location['cid'] > 0 && module_exists('comment')) {
    if (!empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $comment = comment_load($location['cid']);
      $link = $comment->subject;
    }
    $l = l($link, 'comment/' . $location['cid'], array(
      'attributes' => array(
        'class' => array(
          'getlocations_infolink',
        ),
        'target' => '_parent',
      ),
    ));
  }
  if ($l) {
    $output .= '<h4>' . $l . '</h4>';
  }
  $output .= '<div class="adr">';
  if (!empty($location['street'])) {
    $output .= '<div class="street-address">' . $location['street'];
    if (!empty($location['additional'])) {
      $output .= "&nbsp;" . '<span class="extended-address">' . $location['additional'] . '</span>';
    }
    $output .= '</div>';
  }
  if (!empty($location['city'])) {
    $output .= '<span class="locality">' . $location['city'] . '</span>';
    if (!empty($location['province_name'])) {
      $output .= ",&nbsp;";
    }
    elseif (!empty($location['province'])) {
      $output .= ",&nbsp;";
    }
    else {
      $output .= "&nbsp;";
    }
  }
  if (isset($location['province_name']) && !empty($location['province_name'])) {
    $output .= '<span class="region">' . $location['province_name'] . '</span>';
    if (!empty($location['postal_code'])) {
      $output .= "&nbsp;";
    }
  }
  elseif (isset($location['province']) && !empty($location['province'])) {
    $output .= '<span class="region">' . $location['province'] . '</span>';
    if (!empty($location['postal_code'])) {
      $output .= "&nbsp;";
    }
  }
  if (!empty($location['postal_code'])) {
    $output .= '<span class="postal-code">' . drupal_strtoupper($location['postal_code']) . '</span>';
  }
  if (isset($location['country_name']) && !empty($location['country_name'])) {
    $output .= '<div class="country-name">' . $location['country_name'] . '</div>';
  }
  elseif (isset($location['country']) && !empty($location['country'])) {
    $output .= '<div class="country-name">' . $location['country'] . '</div>';
  }
  $output .= '</div>';
  if (isset($location['sdist'])) {
    if ($location['sdist'] != 1) {
      $unit_disp = getlocations_get_unit_names($location['sunit']);
    }
    else {
      $unit_disp = getlocations_get_unit_names($location['sunit'], 'single');
    }
    $output .= '<div class="search-distance">' . number_format(floatval($location['sdist']), 2) . "&nbsp;" . $unit_disp . '</div>';
  }
  if (module_exists('getdirections') && isset($location['getdirections_link']) && $location['getdirections_link']) {
    $gdlink = '';
    if (isset($location['nid']) && $location['nid']) {
      $gdlink = l(t('Directions'), 'getdirections/location/to/' . $location['nid'], array(
        'attributes' => array(
          'class' => array(
            'getlocations_infolink',
          ),
          'target' => '_parent',
        ),
      ));
    }
    elseif (isset($location['uid']) && $location['uid']) {
      $gdlink = l(t('Directions'), 'getdirections/location_user/to/' . $location['uid'], array(
        'attributes' => array(
          'class' => array(
            'getlocations_infolink',
          ),
          'target' => '_parent',
        ),
      ));
    }
    elseif (isset($location['cid']) && $location['cid'] && getdirections_check_entity_type('comment')) {
      $gdlink = l(t('Directions'), 'getdirections/location_comment/to/' . $location['cid'], array(
        'attributes' => array(
          'class' => array(
            'getlocations_infolink',
          ),
          'target' => '_parent',
        ),
      ));
    }
    elseif (isset($location['tid']) && $location['tid'] && getdirections_get_vocabularies()) {
      $gdlink = l(t('Directions'), 'getdirections/location_term/to/' . $location['tid'], array(
        'attributes' => array(
          'class' => array(
            'getlocations_infolink',
          ),
          'target' => '_parent',
        ),
      ));
    }
    if ($gdlink) {
      $output .= '<div class="getdirections-link">' . $gdlink . '</div>';
    }
  }
  $output .= '</div>';
  return $output;
}

/**
 * Prepares variables for getlocations_box.tpl.php
 *
 * @param array $variables
 *   An associative array containing all the elements to construct an HTML document
 *   suitable for use in a colorbox.
 *
 */
function template_preprocess_getlocations_box(&$variables) {
  if (module_exists('admin_menu')) {
    admin_menu_suppress();
  }
  $getlocations_paths = getlocations_paths_get();
  drupal_add_js($getlocations_paths['getlocations_box_path']);

  // Construct page title
  if (drupal_get_title()) {
    $head_title = array(
      strip_tags(drupal_get_title()),
      variable_get('site_name', 'Drupal'),
    );
  }
  else {
    $head_title = array(
      variable_get('site_name', 'Drupal'),
    );
    if (variable_get('site_slogan', '')) {
      $head_title[] = variable_get('site_slogan', '');
    }
  }
  $variables['head_title'] = implode(' | ', $head_title);
  $variables['base_path'] = base_path();
  $variables['head'] = drupal_get_html_head();
  $variables['language'] = $GLOBALS['language'];
  $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
  $variables['css'] = drupal_add_css();
  $variables['styles'] = drupal_get_css();
  $variables['scripts'] = drupal_get_js();
  $variables['title'] = drupal_get_title();

  // Closure should be filled last.
  $variables['closure'] = theme('closure');

  // Compile a list of classes that are going to be applied to the body element.
  // This allows advanced theming based on context (home page, node of certain type, etc.).
  $body_classes = array();

  // Add a class that tells us whether we're on the front page or not.
  $body_classes[] = $variables['is_front'] ? 'front' : 'not-front';

  // Add a class that tells us whether the page is viewed by an authenticated user or not.
  $body_classes[] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in';
  $body_classes[] = 'no-sidebars';

  // Implode with spaces.
  $variables['body_classes'] = implode(' ', $body_classes);
}

/**
 * Prepares variables for getlocations_marker_box.tpl.php
 *
 * @param array $variables
 *   An associative array containing all the elements to construct an HTML document
 *   suitable for use in a colorbox.
 *
 */
function template_preprocess_getlocations_marker_box(&$variables) {
  if (module_exists('admin_menu')) {
    admin_menu_suppress();
  }
  $getlocations_paths = getlocations_paths_get();
  drupal_add_js($getlocations_paths['getlocations_marker_box_path']);
  $head_title = t('Getlocations markers');
  $variables['head_title'] = $head_title;
  $variables['base_path'] = base_path();
  $variables['head'] = drupal_get_html_head();
  $variables['language'] = $GLOBALS['language'];
  $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
  $variables['css'] = drupal_add_css();
  $variables['styles'] = drupal_get_css();
  $variables['scripts'] = drupal_get_js();
  $variables['title'] = $head_title;

  // Closure should be filled last.
  $variables['closure'] = theme('closure');

  // Compile a list of classes that are going to be applied to the body element.
  // This allows advanced theming based on context (home page, node of certain type, etc.).
  $body_classes = array();

  // Add a class that tells us whether we're on the front page or not.
  $body_classes[] = $variables['is_front'] ? 'front' : 'not-front';

  // Add a class that tells us whether the page is viewed by an authenticated user or not.
  $body_classes[] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in';
  $body_classes[] = 'no-sidebars';

  // Implode with spaces.
  $variables['body_classes'] = implode(' ', $body_classes);
}

/**
 * Returns HTML of the getlocations settings form.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: The form array.
 *
 * @return string The rendered form
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_settings_form($variables) {
  $form = $variables['form'];
  $output = '';
  $form['getlocations_default']['returnlink_page_link']['#prefix'] = '<div id="wrap-page-link">';
  $form['getlocations_default']['returnlink_page_link']['#suffix'] = '</div>';
  if (isset($form['getlocations_default']['returnlink_user_link'])) {
    $form['getlocations_default']['returnlink_user_link']['#prefix'] = '<div id="wrap-user-link">';
    $form['getlocations_default']['returnlink_user_link']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_default']['returnlink_term_link'])) {
    $form['getlocations_default']['returnlink_term_link']['#prefix'] = '<div id="wrap-term-link">';
    $form['getlocations_default']['returnlink_term_link']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_default']['returnlink_comment_link'])) {
    $form['getlocations_default']['returnlink_comment_link']['#prefix'] = '<div id="wrap-comment-link">';
    $form['getlocations_default']['returnlink_comment_link']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_colorbox']['width']) && isset($form['getlocations_colorbox']['height'])) {
    $form['getlocations_colorbox']['width']['#prefix'] = '<div id="wrap-getlocations-colorbox">';
    $form['getlocations_colorbox']['height']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_colorbox']['marker_width']) && isset($form['getlocations_colorbox']['marker_height'])) {
    $form['getlocations_colorbox']['marker_width']['#prefix'] = '<div id="wrap-getlocations-marker-colorbox">';
    $form['getlocations_colorbox']['marker_height']['#suffix'] = '</div>';
  }

  // marker colorbox
  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['marker_enable']) {
      $link = getlocations_markerpicker_link($form['getlocations_default']['node_map_marker']['#id'], 'n');
      $form['getlocations_default']['node_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      if (isset($form['getlocations_default']['user_map_marker'])) {
        $link = getlocations_markerpicker_link($form['getlocations_default']['user_map_marker']['#id'], 'u');
        $form['getlocations_default']['user_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (module_exists('taxonomy')) {
        if (isset($form['getlocations_default']['vocabulary_map_marker'])) {
          $link = getlocations_markerpicker_link($form['getlocations_default']['vocabulary_map_marker']['#id'], 'v');
          $form['getlocations_default']['vocabulary_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
        if (isset($form['getlocations_default']['term_map_marker'])) {
          $link = getlocations_markerpicker_link($form['getlocations_default']['term_map_marker']['#id'], 't');
          $form['getlocations_default']['term_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
      }
      if (isset($form['getlocations_default']['comment_map_marker'])) {
        $link = getlocations_markerpicker_link($form['getlocations_default']['comment_map_marker']['#id'], 'c');
        $form['getlocations_default']['comment_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (module_exists('getlocations_fields')) {
        $link = getlocations_markerpicker_link($form['getlocations_default']['input_map_marker']['#id'], 'i');
        $form['getlocations_default']['input_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if ($types = getlocations_get_types()) {
        foreach ($types as $type => $name) {
          $field_names = getlocations_get_fieldname2($type, 'node');
          foreach ($field_names as $field_name) {
            if (isset($form['getlocations_node_marker']['content_type'][$type]['field_name'][$field_name]['map_marker'])) {
              $link = getlocations_markerpicker_link($form['getlocations_node_marker']['content_type'][$type]['field_name'][$field_name]['map_marker']['#id'], 'n');
              $form['getlocations_node_marker']['content_type'][$type]['field_name'][$field_name]['map_marker']['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }
      }
      if (module_exists('taxonomy')) {
        if ($types = getlocations_get_vocabularies()) {
          foreach ($types as $type => $name) {
            if (isset($form['getlocations_vocabulary_marker']['vocabulary'][$type]['map_marker'])) {
              $link = getlocations_markerpicker_link($form['getlocations_vocabulary_marker']['vocabulary'][$type]['map_marker']['#id'], 'v');
              $form['getlocations_vocabulary_marker']['vocabulary'][$type]['map_marker']['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }

        // term
        $getlocations_term_marker = variable_get('getlocations_term_marker', array(
          'enable' => 0,
          'vids' => 0,
          'max_depth' => '',
        ));
        if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
          $depth = is_numeric($getlocations_term_marker['max_depth']) && $getlocations_term_marker['max_depth'] > 0 ? $getlocations_term_marker['max_depth'] : NULL;
          $vids = $getlocations_term_marker['vids'];
          foreach ($vids as $vid) {
            $terms = taxonomy_get_tree($vid, 0, $depth);
            $tct = 0;
            foreach ($terms as $term) {
              $tid = $term->tid;
              if (isset($form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker'])) {
                $link = getlocations_markerpicker_link($form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker']['#id'], 't');
                $form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker']['#field_suffix'] = '&nbsp;' . $link;
                if (!$tct) {
                  $v = taxonomy_vocabulary_load($vid);
                  $vocab_name = $v->name;
                  $form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker']['#prefix'] = t('Terms for %name', array(
                    '%name' => $vocab_name,
                  ));
                }
              }
              $tct++;
            }
          }
        }
      }
    }
  }
  $form['getlocations_default']['useclustermanager']['#prefix'] = '<div id="wrap-getlocations-clusteropts">';
  $form['getlocations_default']['markerclusterer_minsize']['#suffix'] = '</div>';
  $form['getlocations_default']['usemarkermanager']['#prefix'] = '<div id="wrap-getlocations-markeropts">';
  $form['getlocations_default']['maxzoom']['#suffix'] = '</div>';
  if (isset($form['getlocations_default']['gps_button']) && $form['getlocations_default']['gps_button']['#type'] !== 'value') {
    $form['getlocations_default']['gps_button']['#prefix'] = '<fieldset class="collapsible getlocations_fieldset form-wrapper"><legend><span class="fieldset-legend">' . t('GPS Button') . '</span></legend><div class="fieldset-wrapper">';
    $tsuf = $form['getlocations_default']['gps_center']['#suffix'];
    $form['getlocations_default']['gps_center']['#suffix'] = $tsuf . '</div></fieldset>';
  }
  if (isset($form['getlocations_default']['smartip_button']) && $form['getlocations_default']['smartip_button']['#type'] !== 'value') {
    $form['getlocations_default']['smartip_button']['#prefix'] = '<fieldset class="collapsible getlocations_fieldset form-wrapper"><legend><span class="fieldset-legend">' . t('Smartip Button') . '</span></legend><div class="fieldset-wrapper">';
    $tsuf = $form['getlocations_default']['smartip_center']['#suffix'];
    $form['getlocations_default']['smartip_center']['#suffix'] = $tsuf . '</div></fieldset>';
  }

  // preview
  $getlocations_defaults = getlocations_defaults();
  $getlocations_defaults['extcontrol'] = 'preview_map';
  $mapid = getlocations_setup_map($getlocations_defaults);
  $minmaxes = '';
  $latlons = array();
  getlocations_js_settings_do($getlocations_defaults, $latlons, $minmaxes, $mapid, FALSE, $getlocations_defaults['extcontrol']);
  $preview_map = theme('getlocations_show', array(
    'width' => $getlocations_defaults['width'],
    'height' => $getlocations_defaults['height'],
    'defaults' => $getlocations_defaults,
    'mapid' => $mapid,
    'latlons' => $latlons,
    'minmaxes' => $minmaxes,
    'type' => '',
    'node' => '',
  ));
  $form['getlocations_preview']['preview_map']['#markup'] = '<div id="getlocations_preview_map">' . $preview_map . '</div>';
  $output .= drupal_render_children($form);
  return $output;
}

/**
 * Returns HTML of the getlocations plugin_style_map_options form.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: The form array.
 *
 * @return string The rendered form
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_plugin_style_map_options_form($variables) {
  $form = $variables['form'];
  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['marker_enable']) {
      if (isset($form['node_map_marker'])) {
        $link = getlocations_markerpicker_link($form['node_map_marker']['#id'], 'n');
        $form['node_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      $getlocations_node_marker = variable_get('getlocations_node_marker', array(
        'enable' => 0,
      ));
      if ($getlocations_node_marker['enable']) {
        if ($types = getlocations_get_types()) {
          foreach ($types as $type => $name) {
            $field_names = getlocations_get_fieldname2($type, 'node');
            foreach ($field_names as $field_name) {
              $mkey = 'node_marker__' . drupal_strtolower($type) . '__' . $field_name;
              $link = getlocations_markerpicker_link($form[$mkey]['#id'], 'n');
              $form[$mkey]['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }
      }
      if (isset($form['user_map_marker'])) {
        $link = getlocations_markerpicker_link($form['user_map_marker']['#id'], 'u');
        $form['user_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (module_exists('taxonomy')) {
        if (isset($form['vocabulary_map_marker'])) {
          $link = getlocations_markerpicker_link($form['vocabulary_map_marker']['#id'], 'v');
          $form['vocabulary_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
        $getlocations_vocabulary_marker = variable_get('getlocations_vocabulary_marker', array(
          'enable' => 0,
        ));
        if ($getlocations_vocabulary_marker['enable']) {
          foreach ($types as $type => $name) {
            $field_name = getlocations_get_fieldname($type, 'taxonomy_term');
            $mkey = 'vocabulary_marker_' . $field_name;
            $link = getlocations_markerpicker_link($form[$mkey]['#id'], 'v');
            $form[$mkey]['#field_suffix'] = '&nbsp;' . $link;
          }
        }
        if (isset($form['term_map_marker'])) {
          $link = getlocations_markerpicker_link($form['term_map_marker']['#id'], 't');
          $form['term_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
        $getlocations_term_marker = variable_get('getlocations_term_marker', array(
          'enable' => 0,
          'vids' => 0,
          'max_depth' => '',
        ));
        if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
          $depth = is_numeric($getlocations_term_marker['max_depth']) && $getlocations_term_marker['max_depth'] > 0 ? $getlocations_term_marker['max_depth'] : NULL;
          $vids = $getlocations_term_marker['vids'];
          foreach ($vids as $vid) {
            $terms = taxonomy_get_tree($vid, 0, $depth);
            foreach ($terms as $term) {
              $name = $term->name;
              $tid = $term->tid;
              $mkey = 'term_marker_' . $tid;
              $link = getlocations_markerpicker_link($form[$mkey]['#id'], 't');
              $form[$mkey]['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }
      }
      if (isset($form['comment_map_marker'])) {
        $link = getlocations_markerpicker_link($form['comment_map_marker']['#id'], 'c');
        $form['comment_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (isset($form['gps_marker'])) {
        $link = getlocations_markerpicker_link($form['gps_marker']['#id'], 'g');
        $form['gps_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (isset($form['smartip_marker'])) {
        $link = getlocations_markerpicker_link($form['smartip_marker']['#id'], 'm');
        $form['smartip_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
    }
  }
  if (isset($form['gps_button']) && $form['gps_button']['#type'] !== 'value') {
    $form['gps_button']['#prefix'] = '<fieldset class="collapsible getlocations_fieldset form-wrapper"><legend><span class="fieldset-legend">' . t('GPS Button') . '</span></legend><div class="fieldset-wrapper">';
    $tsuf = $form['gps_center']['#suffix'];
    $form['gps_center']['#suffix'] = $tsuf . '</div></fieldset>';
  }
  if (isset($form['smartip_button']) && $form['smartip_button']['#type'] !== 'value') {
    $form['smartip_button']['#prefix'] = '<fieldset class="collapsible getlocations_fieldset form-wrapper"><legend><span class="fieldset-legend">' . t('Smartip Button') . '</span></legend><div class="fieldset-wrapper">';
    $tsuf = $form['smartip_center']['#suffix'];
    $form['smartip_center']['#suffix'] = $tsuf . '</div></fieldset>';
  }
  $output = drupal_render_children($form);
  return $output;
}

/**
 * Returns HTML of the getlocations plugin_style_streetview_options form.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: The form array.
 *
 * @return string The rendered form
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_plugin_style_streetview_options_form($variables) {
  $form = $variables['form'];
  $output = drupal_render_children($form);
  return $output;
}

/**
 * Returns HTML of a latitude in decimal degress expressed in degrees, minutes and seconds.
 *
 * from location module
 *
 * @param array $variables
 *   An associative array containing:
 *   - latitude: A latitude in decimal degrees.
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_latitude_dms($variables) {
  $latitude = $variables['latitude'];
  $output = '';
  list($degrees, $minutes, $seconds, $negative) = getlocations_dd_to_dms($latitude);
  $output .= $degrees . "&deg; " . $minutes . "&#39; " . $seconds . "&#34; ";
  if (!$negative) {
    $output .= 'N';
  }
  else {
    $output .= 'S';
  }
  return $output;
}

/**
 * Returns HTML of a longitude in decimal degress expressed in degrees, minutes and seconds.
 *
 * from location module
 *
 * @param array $variables
 *   An associative array containing:
 *   - longitude: A longitude in decimal degrees.
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_longitude_dms($variables) {
  $longitude = $variables['longitude'];
  $output = '';
  list($degrees, $minutes, $seconds, $negative) = getlocations_dd_to_dms($longitude);
  $output .= $degrees . "&deg; " . $minutes . "&#39; " . $seconds . "&#34; ";
  if (!$negative) {
    $output .= 'E';
  }
  else {
    $output .= 'W';
  }
  return $output;
}

/**
 * Returns an array of an address from the addressfield module converted for use in getlocations.
 *
 * from location module
 *
 * @param array $variables
 *   An associative array containing:
 *   - address: an array of address components.
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_addressfield_convert($variables) {
  $address = $variables['address'];
  $location = array();
  if (is_array($address) && !empty($address)) {
    $name = array();
    if (isset($address['name_line']) && $address['name_line']) {
      $name[] = $address['name_line'];
    }
    if (isset($address['first_name']) && $address['first_name']) {
      if (isset($address['last_name']) && $address['last_name']) {
        $name[] = $address['first_name'] . ' ' . $address['last_name'];
      }
      else {
        $name[] = $address['first_name'];
      }
    }
    elseif (isset($address['last_name']) && $address['last_name']) {
      $name[] = $address['last_name'];
    }
    if (isset($address['organisation_name']) && $address['organisation_name']) {
      $name[] = $address['organisation_name'];
    }
    $location['name'] = count($name) ? implode(", ", $name) : '';
    $location['street'] = isset($address['thoroughfare']) ? $address['thoroughfare'] : '';
    $additional = array();
    if (isset($address['premise']) && $address['premise']) {
      $additional[] = $address['premise'];
    }
    if (isset($address['sub_premise']) && $address['sub_premise']) {
      $additional[] = $address['sub_premise'];
    }
    $location['additional'] = count($additional) ? implode(", ", $additional) : '';
    $city = array();
    if (isset($address['dependent_locality']) && $address['dependent_locality']) {
      $city[] = $address['dependent_locality'];
    }
    if (isset($address['locality']) && $address['locality']) {
      $city[] = $address['locality'];
    }
    $location['city'] = count($city) ? implode(", ", $city) : '';
    $admin_area = array();
    if (isset($address['sub_administrative_area']) && $address['sub_administrative_area']) {
      $admin_area[] = $address['sub_administrative_area'];
    }
    if (isset($address['administrative_area']) && $address['administrative_area']) {
      $admin_area[] = $address['administrative_area'];
    }
    $location['province_name'] = count($admin_area) ? implode(", ", $admin_area) : '';
    $location['postal_code'] = isset($address['postal_code']) ? drupal_strtoupper($address['postal_code']) : '';
    $location['country_name'] = isset($address['country_name']) ? $address['country_name'] : $address['country'];
    $location['country'] = $address['country'];
  }
  return $location;
}

/**
 * Returns HTML of a url, requested by ajax.
 *
 * @param array $variables
 *   An associative array containing:
 *   - lid: The location identifier or glid.
 *   - lidkey: The entity identifier type
 *
 * @return string $output
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_lidinfo($variables) {
  $lid = $variables['lid'];
  $lidkey = $variables['lidkey'];
  $output = FALSE;
  if ($lid > 0) {
    if (module_exists('getlocations_fields') || module_exists('location')) {
      $path = getlocations_get_path_from_lid($lid);
      if ($path) {
        $output = $path;
      }
    }
    elseif (module_exists('geofield') || module_exists('geolocation')) {
      if ($lidkey == 'nid') {
        $path = url('node/' . $lid);
      }
      elseif ($lidkey == 'vid') {
        $nid = getlocations_get_nid($lid);
        $path = url('node/' . $nid);
      }
      elseif ($lidkey == 'uid') {
        $path = url('user/' . $lid);
      }
      elseif ($lidkey == 'tid' && module_exists('taxonomy')) {
        $path = url('taxonomy/term/' . $lid);
      }
      elseif ($lidkey == 'cid' && module_exists('comment')) {
        $path = url('comment/' . $lid);
      }
      if ($path) {
        $output = $path;
      }
    }
  }
  return $output;
}

Functions

Namesort descending Description
getlocations_access_location Access callback: Checks for access permission and if there is a supported locative module installed
getlocations_access_user_location Access callback: Checks for access permission and if there is a supported locative module installed
getlocations_addressfield_convert Function
getlocations_adinfo Ajax callback Fetches bubble content
getlocations_adjust_vars Recursively merge the defaults with the current settings
getlocations_aggr_get Function
getlocations_apoclean Function to run string through check_plain but then restore apostrophes
getlocations_box Function for colorbox and suchlike
getlocations_cb_w3w
getlocations_cb_w3w_get
getlocations_cdints_load sanity check on list of nids
getlocations_check_entity_type Function is an entity_type location enabled?
getlocations_check_jquery_version
getlocations_check_node Function to check if bundle has a locative field
getlocations_check_vocabulary Function to check a vocabulary
getlocations_colorbox_settings Function
getlocations_commentmap Page callback: Displays a map.
getlocations_controlpositions Function
getlocations_convert_distance_to_meters
getlocations_convert_meters_to_distance
getlocations_dd_to_dms Convert decimal degrees to degrees,minutes,seconds. from location module
getlocations_defaults Some defaults.
getlocations_defaults_check Function to check if the configuration has been done yet
getlocations_dim_check Function
getlocations_distance_between Given two points in lat/lon form, returns the distance between them.
getlocations_dms_to_dd Convert dms string to decimal degrees. Should be reasonably tolerant of sloppy input
getlocations_do_minmaxes
getlocations_earth_arclength
getlocations_earth_distance
getlocations_earth_distance_sql Returns the SQL fragment needed to add a column called 'distance' to a query. For use in Views distance/proximity calculations
getlocations_earth_latitude_range Function
getlocations_earth_longitude_range This function uses earth_asin_safe so is not accurate for all possible parameter combinations. This means this function doesn't work properly for high distance values. This function needs to be re-written to work properly for larger distance…
getlocations_earth_radius
getlocations_earth_xyz
getlocations_element_dd
getlocations_element_distance_unit
getlocations_element_map_baselayers Function
getlocations_element_map_checkbox Function
getlocations_element_map_limits Function
getlocations_element_map_maptype Function
getlocations_element_map_marker Function
getlocations_element_map_markeraction Function
getlocations_element_map_markeractiontype Function
getlocations_element_map_mtc Function
getlocations_element_map_pansetting Function
getlocations_element_map_tf Function
getlocations_element_map_zoom Function
getlocations_element_map_zoom_controltype Function
getlocations_element_map_zoom_map Function
getlocations_element_markermanagertype Function
getlocations_element_path Function
getlocations_element_search_distance
getlocations_element_validate_dim Function
getlocations_element_validate_latlon Function
getlocations_entity_type_load sanity check on entity type
getlocations_flush_caches Implements hook_flush_caches().
getlocations_geocoder_form
getlocations_geojson_form
getlocations_getinfo
getlocations_getlidinfo
getlocations_getlocations_map_providers
getlocations_getlocations_markerdir hook_getlocations_markerdir() from jhm http://drupal.org/user/15946
getlocations_get_bundles Fetch bundle names for a given module and type
getlocations_get_cid_from_lid Function to get cid from getlocations_fields_entities table.
getlocations_get_circle_settings Function
getlocations_get_countries_list Fetch a list of the core Drupal list of countries. from location module
getlocations_get_country_id Get the two letter code for a country
getlocations_get_country_name Get the full country name
getlocations_get_current_supported_module Function
getlocations_get_entity_type_from_path Allows for aliases in entity types
getlocations_get_exact_distance_sql
getlocations_get_fieldname Function to collect field name
getlocations_get_fieldname2 Function to collect field names
getlocations_get_fieldnames Fetch fieldnames for a given module and type
getlocations_get_geocoder_path Function to get the path to the Geocoder-js library
getlocations_get_geojson_path Function to get the path to the GeoJSON library
getlocations_get_icondata Get the JSON icon data for all the default markers. adapted from gmap
getlocations_get_machine_vocabularies Function gets list of vocabulary machine names
getlocations_get_map_providers
getlocations_get_markerfile Function to find and return the filesystem path and filename of the markers definition javascript file
getlocations_get_markertypes Function to fetch list of markers
getlocations_get_marker_titles Get the list of marker titles. adapted from gmap
getlocations_get_nid Function to get the nid from node table.
getlocations_get_nid_from_lid Function to get nid from getlocations_fields_entities or location_instance table.
getlocations_get_nodetype Function to fetch a node type or bundle
getlocations_get_path_from_lid Function to get entity path from getlocations_fields_entities or location_instance table.
getlocations_get_polygon_settings Function
getlocations_get_polyline_settings Function
getlocations_get_rectangle_settings Function
getlocations_get_search_distance_sql Function
getlocations_get_supported_entities Function to collect entities being used by the given module
getlocations_get_term_marker Function
getlocations_get_term_reference_fields Function list of term reference fields
getlocations_get_tid_from_lid Function to get tid from getlocations_fields_entities table.
getlocations_get_types Function to fetch node types
getlocations_get_type_from_lid Function to get entity type from getlocations_fields_entities or location_instance table.
getlocations_get_uid_from_lid Function to get uid from getlocations_fields_entities or location_instance table.
getlocations_get_unit_names Function
getlocations_get_vid Function to get the vid from node table.
getlocations_get_vocabularies Function gets list of vocabularies
getlocations_google_places_form
getlocations_help Implements hook_help().
getlocations_highlight_form
getlocations_id_load check that the argument is numeric
getlocations_init Implements hook_init().
getlocations_is_mobile Function
getlocations_js_settings_do Function sets up javascript settings
getlocations_kml_form
getlocations_latlon_check Function to check a lat,lon string
getlocations_lidinfo Ajax callback Provides a link
getlocations_lids Page callback: Displays a map.
getlocations_load_location Function to fetch a location
getlocations_load_locations Function to fetch locations
getlocations_map_display_basics_form Function
getlocations_map_display_options_form Function
getlocations_markeraction_form
getlocations_markercluster_form
getlocations_markerinfo Ajax callback provides data for marker colorbox
getlocations_markermanager_form
getlocations_markerpicker_link Function
getlocations_menu Implements hook_menu().
getlocations_nids Page callback: Displays a map.
getlocations_nodemap Page callback: displays a map.
getlocations_normalizelat Normalizes a latitude to the [-90,90] range. Latitudes above 90 or below -90 are capped, not wrapped.
getlocations_normalizelng Normalizes a longitude to the [-180,180] range. Longitudes above 180 or below -180 are wrapped.
getlocations_other_get_fieldname Function
getlocations_other_load_locations Function to fetch locations. Supports Geofield and Geolocation modules
getlocations_paths_get Function
getlocations_permission Implements hook_permission().
getlocations_places_check Function to check wether the google places library should be enabled.
getlocations_regenerate_markers Regenerate the markerdata file. adapted from gmap
getlocations_setlocations Set up javascript settings and map
getlocations_setup_js Function to setup the map scripts
getlocations_setup_map Function to setup the map scripts
getlocations_shapes_form
getlocations_supported_modules Function
getlocations_termmap Page callback: Displays a map.
getlocations_theme Implements hook_theme().
getlocations_typemap Page callback: Displays a map.
getlocations_type_load Check that the node type exists
getlocations_ua_get Function
getlocations_usermap Page callback: Displays a map.
getlocations_usersmap Page callback: Displays a map.
getlocations_views_api Implements hook_views_api().
getlocations_what3words_form What3words config form
template_preprocess_getlocations_box Prepares variables for getlocations_box.tpl.php
template_preprocess_getlocations_marker_box Prepares variables for getlocations_marker_box.tpl.php
theme_getlocations_addressfield_convert Returns an array of an address from the addressfield module converted for use in getlocations.
theme_getlocations_adinfo Returns HTML of a location's vcard, requested by ajax.
theme_getlocations_latitude_dms Returns HTML of a latitude in decimal degress expressed in degrees, minutes and seconds.
theme_getlocations_lidinfo Returns HTML of a url, requested by ajax.
theme_getlocations_longitude_dms Returns HTML of a longitude in decimal degress expressed in degrees, minutes and seconds.
theme_getlocations_plugin_style_map_options_form Returns HTML of the getlocations plugin_style_map_options form.
theme_getlocations_plugin_style_streetview_options_form Returns HTML of the getlocations plugin_style_streetview_options form.
theme_getlocations_settings_form Returns HTML of the getlocations settings form.
theme_getlocations_show Returns HTML for a map.

Constants