'300px',
'height' => '200px',
'zoom' => 3,
'controltype' => 'Small',
'align' => 'None',
'latlong' => '40,0',
'maptype' => 'Map',
'line_colors' => array('#00cc00', '#ff0000', '#0000ff'),
);
$defaults['behavior'] = array();
$behaviors = module_invoke_all('gmap', 'behaviors');
foreach ($behaviors as $k => $v) {
$defaults['behavior'][$k] = $v['default'];
}
$defaults = array_merge($defaults, variable_get('gmap_default', array()));
return $defaults;
}
/**
* Implementation of hook_gmap().
*/
function gmap_gmap($op, $map=null) {
switch ($op) {
case 'macro':
return array(
'points' => array(
'multiple' => TRUE,
),
'markers' => array(
'multiple' => TRUE,
),
'feed' => array(
'multiple' => TRUE,
),
);
case 'pre_theme_map':
$path = drupal_get_path('module', 'gmap') .'/js/';
// Activate markers if needed
if ($map['behavior']['dynmarkers'] || !empty($map['markers'])) {
drupal_add_js($path .'icon.js');
drupal_add_js($path .'marker.js');
drupal_add_js($path . variable_get('gmap_mm_type', 'gmap') .'_marker.js');
}
if ($map['behavior']['locpick']) {
drupal_add_js($path .'locpick.js');
}
if (variable_get('gmap_load_zoom_plugin', TRUE) && !$map['behavior']['nomousezoom']) {
drupal_add_js(drupal_get_path('module', 'gmap') .'/thirdparty/mousewheel.js');
}
if ($map['markers'] || $map['lines']) {
drupal_add_js($path .'markerloader_static.js');
}
if ($map['shapes']) {
drupal_add_js($path .'shapeloader_static.js');
drupal_add_js($path .'gmap_shapes.js');
}
if (is_array($map['feed'])) {
drupal_add_js($path .'markerloader_georss.js');
}
break;
case 'macro_multiple':
return array('points', 'markers', 'feed', 'circle', 'rpolygon', 'polygon', 'line');
case 'behaviors':
return array(
'locpick' => array(
'title' => t('Location chooser'),
'default' => FALSE,
'help' => t('Used to activate location choosing using a gmap.'),
'internal' => TRUE,
),
'nodrag' => array(
'title' => t('Disable dragging'),
'default' => FALSE,
'help' => t('Remove the ability for the user to drag the map. If dragging is disabled, keyboard shortcuts are implicitly disabled.'),
),
'nokeyboard' => array(
'title' => t('Disable keyboard'),
'default' => TRUE,
'help' => t('Disable the keyboard shortcuts.'),
),
'nomousezoom' => array(
'title' => t('Disable mousezoom'),
'default' => FALSE,
'help' => t('Disable using the scroll wheel to zoom the map.'),
),
'autozoom' => array(
'title' => t('Use AutoZoom'),
'default' => FALSE,
'help' => t('Automatically zoom the map to fit all markers when markers are added.'),
),
'dynmarkers' => array(
'title' => t('Unconditionally enable marker interface'),
'default' => FALSE,
'help' => t('Load the marker loader system even if no markers to load are detected. Useful if you are injecting markers from somewhere else.'),
),
'overview' => array(
'title' => t('Enable Overview Map'),
'default' => FALSE,
'help' => t('Enable the "overview map" in the bottom right corner.'),
),
'notype' => array(
'title' => t('Disable map type control'),
'default' => FALSE,
'help' => t('Removes the map type control from the upper right corner. Recommended for very narrow maps.'),
),
'collapsehack' => array(
'title' => t('Work around bugs when maps appear in collapsible fieldsets'),
'default' => FALSE,
'help' => t('Enabling this will work around some issues that can occur when maps appear inside collapsible fieldsets.'),
),
'scale' => array(
'title' => t('Add scale control to map.'),
'default' => FALSE,
'help' => t('Adds a scale control to the map in the default position.'),
),
);
}
}
/**
* Set up the HTML header for GMap.
*/
function _gmap_doheader() {
static $gmap_initialized = FALSE;
if ($gmap_initialized) {
return;
}
$gmap_path = drupal_get_path('module', 'gmap');
drupal_add_css($gmap_path .'/gmap.css');
drupal_add_js($gmap_path .'/js/gmap.js');
$mm = variable_get('gmap_mm_type', 'gmap');
if ($mm=='clusterer') {
drupal_add_js($gmap_path .'/js/icon.js');
drupal_add_js($gmap_path .'/thirdparty/Clusterer2.js');
}
drupal_add_js($gmap_path .'/js/marker.js');
drupal_add_js($gmap_path .'/js/'. $mm .'_marker.js');
$mms = variable_get('gmap_markermanager', array());
if (empty($mms[$mm])) {
$mms[$mm] = array();
}
drupal_add_js(array('gmap_markermanager' => $mms[$mm]), 'setting');
// @@@
drupal_add_js($gmap_path .'/js/poly.js');
$key = variable_get('googlemap_api_key', '');
if (module_exists('keys_api')) {
$key = keys_api_get_key('gmap', $_SERVER['HTTP_HOST']);
}
drupal_set_html_head('');
$gmap_initialized = TRUE;
}
/**
* Cleans the gmap variables to prevent javascript interjection.
*
* @param $gmap
* A Gmap variable
*
* @return
* A GMap variable with any dangerous text removed.
*
* This does not really do much of anything right now.
*/
function gmap_sanitize(&$gmap) {
//sanitizes the gmap variables to reduce the possibility of javascript inserts
foreach ($gmap as $key => $value) {
if ($key=='id') {
$out = array();
preg_match('([a-zA-Z0-9_-]*)', $value, $out);
if (strlen($out[0])==0) {
$out[0]='map';
}
$gmap[$key]=$out[0];
}
else {
$gmap[$key]=str_replace(';', '', $value);
}
}
}
/**
*
* Returns a variable based on .
*
* @param $instring
* A string with the settings of gmap insertion in the format var=setting|var2=setting2
* The possible variables are
* id - the id of the map every map on a page must have a unique id
* width - width of the map
* height - height of the map
* center - a string of the longitude and latitude of the centre of the map
* zoom - the zoom factor of the google map
* align - the alignment of the map 'right', 'left' or 'center'
* control - the control shown on the map 'Large', 'Small', or 'None'
* type - 'Map', 'Hybrid' or 'Satellite'
* points/markers - a string of points to mark on the map with + between
* each point
* line - the line is defined by a set of points separated by a +
* track - Draws a line based on the points in the .plt file
* The following shape types require XMaps:
* circle - a circle based on a center point and a radius in km separated
* by a + and optionally can include the number of sizes.
* rpolygon - a regular polygon is defined by the center point and a point
* on the permiter separated by a +
* polygon - a polygon is defined by a set of points
*
* Each of the shapes types can optionally have charecteristics of colour,
* width, opacity, pattern, text, fill colour, fill opacity. Pattern, text
* and fill are all only used by xmaps.
* color - hexadecimal for the colour include the '#'
*
*
* @return
* A string with the google map ready to be inserted into a node.
*
*/
function gmap_parse_macro($instring, $ver=2) {
// Get a list of keys that are "multiple."
$multiple = module_invoke_all('gmap', 'macro_multiple');
// Remove leading and trailing tags
if (substr(trim($instring), -1)==']') {
$instring = substr(trim($instring), 0, -1);
}
if (substr($instring, 0, 5)=='[gmap') {
$instring = substr($instring, 6);
}
// Chop the macro into an array
$temp = explode('|', $instring);
$m = array();
foreach ($temp as $row) {
$offset = strpos($row, '=');
if ($offset !== FALSE) {
$k = trim(substr($row, 0, $offset));
$r = trim(substr($row, $offset+1));
if (in_array($k, $multiple)) {
// Things that can appear multiple times
if (!isset($m[$k])) {
$m[$k] = array();
}
$m[$k][] = $r;
}
else {
$m[$k] = $r;
}
}
}
// Synonyms
if ($m['type']) {
$m['maptype'] = $m['type'];
unset($m['type']);
}
if ($m['control']) {
$m['controltype'] = $m['control'];
unset($m['control']);
}
if (is_array($m['feed'])) {
foreach ($m['feed'] as $k => $v) {
$temp = explode('::', $v);
// Normalize url
if (substr($temp[1], 0, 1) == '/') {
$temp[1] = substr($temp[1], 1);
}
$temp[1] = url($temp[1]);
$m['feed'][$k] = array(
'markername' => $temp[0],
'url' => $temp[1],
);
}
}
// Merge points and markers
if (!is_array($m['points'])) $m['points'] = array();
if (!is_array($m['markers'])) $m['markers'] = array();
$m['markers-temp'] = array_merge($m['points'], $m['markers']);
unset($m['points']);
unset($m['markers']);
// all shapes in 1 array
if ($m['circle']) {
foreach ($m['circle'] as $shape) {
$s = array('type' => 'circle');
$cp = strpos($shape, ':');
if ($cp !== false) {
$stylestr = substr($shape, 0, $cp);
$s['style'] = explode('/', $stylestr);
foreach ($s['style'] as $k => $v) {
if (is_numeric($v)) $s['style'][$k] = (float)$v;
}
$shape = substr($shape, $cp+1);
}
$tmp = explode('+', $shape);
$s['radius'] = $tmp[1] ? $tmp[1] : 100;
if ($tmp[2]) $s['numpoints'] = trim($tmp[2]);
$tmp = _gmap_str2coord($tmp[0]);
$s['center'] = $tmp[0];
$m['shapes'][] = $s;
}
unset($m['circle']);
}
// Fixup legacy lines.
if ($m['line1']) {
if (!isset($m['line'])) $m['line'] = array();
$m['line'][] = GMAP_LINECOLOR1 .':'. $m['line1'];
unset($m['line1']);
}
if ($m['line2']) {
if (!isset($m['line'])) $m['line'] = array();
$m['line'][] = GMAP_LINECOLOR2 .':'. $m['line3'];
unset($m['line2']);
}
if ($m['line3']) {
if (!isset($m['line'])) $m['line'] = array();
$m['line'][] = GMAP_LINECOLOR3 .':'. $m['line3'];
unset($m['line3']);
}
if ($m['line']) {
foreach ($m['line'] as $shape) {
$s = array('type' => 'line');
$cp = strpos($shape, ':');
if ($cp != false) {
$stylestr = substr($shape, 0, $cp);
$s['style'] = explode('/', $stylestr);
foreach ($s['style'] as $k => $v) {
if (is_numeric($v)) $s['style'][$k] = (float)$v;
}
$shape = substr($shape, $cp+1);
}
$s['points'] = _gmap_str2coord($shape);
$m['shapes'][] = $s;
}
unset($m['line']);
}
if ($m['rpolygon']) {
foreach ($m['rpolygon'] as $shape) {
$s = array('type' => 'rpolygon');
$cp = strpos($shape, ':');
if ($cp !== false) {
$stylestr = substr($shape, 0, $cp);
$s['style'] = explode('/', $stylestr);
$shape = substr($shape, $cp+1);
}
$tmp = explode('+', $shape);
if ($tmp[2]) $s['numpoints'] = trim($tmp[2]);
$tmp = _gmap_str2points($shape);
$s['center'] = $tmp[0];
$s['point2'] = $tmp[1];
$m['shapes'][] = $s;
}
unset($m['rpolygon']);
}
if ($m['polygon']) {
foreach ($m['polygon'] as $shape) {
$s = array('type' => 'polygon');
$cp = strpos($shape, ':');
if ($cp !== false) {
$stylestr = substr($shape, 0, $cp);
$s['style'] = explode('/', $stylestr);
$shape = substr($shape, $cp+1);
}
$s['points'] = _gmap_str2points($shape);
$m['shapes'][] = $s;
}
unset($m['polygon']);
}
// Version 1 -> 2 conversion
if ($ver==1) {
// Zoom is flipped
if ($m['zoom']) {
$m['zoom'] = 18 - $m['zoom'];
if ($m['zoom'] < 1) {
$m['zoom'] = 1;
}
}
}
// Center -> latitude and longitude
if ($m['center']) {
list($m['latitude'], $m['longitude']) = explode(',', $m['center']);
unset($m['center']);
}
// Behavior
if ($m['behaviour']) {
$m['behavior'] = $m['behaviour'];
unset($m['behaviour']);
}
if ($m['behavior']) {
$m['behavior-temp'] = explode(' ', $m['behavior']);
$m['behavior'] = array();
foreach ($m['behavior-temp'] as $v) {
$m['behavior'][substr($v, 1)] = (substr($v, 0, 1) == '+') ? TRUE : FALSE;
}
unset($m['behavior-temp']);
}
// Stuff that was converted to behavior flags
if ($m['tcontrol']) {
if (strtolower(trim($m['tcontrol'])) == 'on') {
$m['behavior']['notype'] = FALSE;
}
else {
$m['behavior']['notype'] = TRUE;
}
}
// Markers fixup
foreach ($m['markers-temp'] as $t) {
unset($markername);
// Named?
if (strpos($t, '::')) { // Single : gets handled below.
list($markername, $t) = explode('::', $t, 2);
}
// Break down into points
$points = explode('+', $t);
$offset = 0;
foreach ($points as $point) {
$marker = array();
$offset++;
$marker['options'] = array();
// Labelled?
// @@@ Gmap allows both a tooltip and a popup, how to represent?
if (strpos($point, ':')) {
list($point, $marker['text']) = explode(':', $point, 2);
$marker['text'] = theme('gmap_marker_popup', $marker['text']);
}
if (strpos($point, '%')) {
list($point, $addons) = explode('%', $point, 2);
$motemp = explode('%', $addons);
foreach ($motemp as $option) {
$marker['options'][trim($option)] = true;
}
}
list($marker['latitude'], $marker['longitude']) = explode(',', $point, 2);
// Named markers get an offset too.
if (isset($markername)) {
$marker['markername'] = $markername;
$marker['offset'] = $offset;
}
$m['markers'][] = $marker;
}
}
unset($m['markers-temp']);
/* case 'track':
$tt['color']=GMAP_LINECOLOR1;
if (strpos($t[1],':')) { // note: we don't care about case starting with ':'
list($configs,$t[1])=explode(':',$t[1],2);
list($tt['color'],$tt['width'],$tt['opacity'],$tt['pattern'],$tt['text'])=explode('/',$configs);
}
$tt['filename'] =$t[1];
$gmap['tracks'][] = $tt;
break;
case 'feed':
if (strpos($t[1],'::')) { // note: we don't care about case starting with ':'
list($markername,$t[1])=explode('::',$t[1],2);
}
$tt['url'] =$t[1];
if (isset($markername)){
$tt['markername']=$markername;
}
$gmap['feeds'][] = $tt;
break;
case 'wmss':
unset($ttt);
$ttt = explode('+',$t[1]);
for ($i =0; $i $v) {
$m[$k] = $v;
}
}
return $m;
}
/**
* Parse "x.xxxxx , y.yyyyyy" into an array of points.
*/
function _gmap_str2coord($str) {
// Explode along + axis
$arr = explode('+', $str);
// Explode along , axis
$points = array();
foreach ($arr as $pt) {
list($lat, $lon) = explode(',', $pt);
$points[] = array((float)trim($lat), (float)trim($lon));
}
return $points;
}
/**
* Parse a set of points in string format.
* (Trying to convert this to the more efficient _gmap_str2coord...)
*/
function _gmap_str2points($str) {
// Explode along + axis
$arr = explode(' + ', $str);
// Explode along , axis
$points = array();
foreach ($arr as $pt) {
list($lat, $lon) = explode(',', $pt);
$points[] = array(
'latitude' => (float)trim($lat),
'longitude' => (float)trim($lon),
);
}
return $points;
}
/**
* Theme a marker popup.
* This will get called for markers embedded in macros.
*/
function theme_gmap_marker_popup($label) {
return $label;
}
/**
*
* Creates a map that can be interactively used to fill a form with a
* location (latitude, longitude and zoom level)
*
* @param $map
* Either a macro to use as the base map for setting a location, or an already set map associative array.
* @param $form
* A formset associative array. Cannot be more than one deep.
* @param $fields
* An associative array for the field names. 'latitude', 'longitude'=>name of respective array, 'address' is optional.
* @return
* A string with the google map code to be inserted onto the page.
*
*/
function gmap_set_location($map, &$form, $fields) {
static $ctr = 0;
$ctr++;
if (!is_array($map)) {
$map = array_merge(gmap_defaults(), gmap_parse_macro($map));
}
$id = 'loc'. $ctr;
$map['id'] = $id;
// This is a locpick map.
$map['behavior']['locpick'] = TRUE;
$element = array(
'#type' => 'gmap',
'#map' => $map['id'],
'#settings' => $map,
);
$form[$fields['latitude']]['#map']=$id;
gmap_widget_setup($form[$fields['latitude']], 'locpick_latitude');
$form[$fields['longitude']]['#map']=$id;
gmap_widget_setup($form[$fields['longitude']], 'locpick_longitude');
if (isset($fields['address'])) {
$form[$fields['address']]['#map'] = $id;
gmap_widget_setup($form[$fields['address']], 'locpick_address');
}
return theme('gmap', $element);
}
function _gmap_prepare($intext) {
$out = FALSE;
$matches = array();
preg_match_all('/\[gmap([^\[\]]+ )* \] /x', $intext, $matches);
$i = 0;
while (isset($matches[1][$i])) {
$out[0][$i] = $matches[0][$i];
if ($matches[1][$i][0] == '1') {
$ver = 1;
$matches[1][$i] = substr($matches[0][$i], 1);
}
else {
$ver = 2;
}
$map = array('#settings' => gmap_parse_macro($matches[1][$i], $ver));
$out[1][$i] = theme('gmap', $map);
$i++;
} // endwhile process macro
return $out;
}
/**
* Make sure a string is a valid css dimension.
*/
function gmap_todim($instring) {
$s = strtolower($instring);
$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;
}
}
/**
* Ensure a textfield is a valid css dimension string.
*/
function gmap_dimension_validate(&$elem) {
if (!gmap_todim($elem['#value'])) {
form_error($elem, t('The specified value is not a valid CSS dimension.'));
}
}
function gmap_dopoint($point, $ver) {
if ($ver == 1) {
$lonlat = explode(',', $point, 2);
return array('latitude' => $lonlat[1], 'longitude' => $lonlat[0]);
}
else {
$lonlat = explode(',', $point, 2);
return array('latitude' => $lonlat[0], 'longitude' => $lonlat[1]);
}
}
function gmap_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'list':
return (array(0 => t('GMap filter')));
case 'name':
return t('Google map filter');
case 'description':
return t('converts a google map macro into the html required for inserting a google map.');
case 'process':
$gmaps=_gmap_prepare($text); //returns an array of $tables[0] = table macro $table[1]= table html
if ($gmaps) { // there are table macros in this node
return str_replace($gmaps[0], $gmaps[1], $text);
}
else {
return $text;
}
case 'prepare':
return $text;
case 'no cache':
return TRUE;
return (variable_get('gmap_method', 'Static')=='Dynamic');
}
}
function gmap_filter_tips($delta, $format, $long = false) {
if (user_access('create macro')) { // only display macro if user can create one
return t('Insert Google Map macro.') .''. t('Create a macro') .'';
}
else {
return t('Insert Google Map macro.');
}
}
function gmap_menu($may_cache) {
if ($may_cache) {
$items = array();
/* $items[] = array(
'path' => 'map',
'type' => MENU_ITEM_GROUPING,
'title' => t('google maps'),
'access' => user_access('create macro')||user_access('show user map')||user_access('show node map'),
); */
$items[] = array(
'path' => 'admin/settings/gmap',
'title' => t('GMap'),
'description' => t('Configure GMap settings'),
'callback' => 'drupal_get_form',
'callback arguments' => 'gmap_admin_settings',
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
$items[] = array(
'path' => 'map/query',
'type' => MENU_CALLBACK,
'access' => TRUE, //@@@
'callback' => 'gmap_json_query',
);
return $items;
}
}
/**
* JSON request interface.
*/
function gmap_json_query() {
if (arg(2)=='markers') {
drupal_set_header('Content-Type: text/javascript');
echo drupal_to_js(array(
'path' => base_path() . drupal_get_path('module', 'gmap') .'/markers',
'markers' => gmap_get_icondata(TRUE),
));
exit();
}
if (arg(2)=='marker') {
$name = arg(3);
}
}
/**
* Settings page.
*/
function gmap_admin_settings() {
require_once(drupal_get_path('module', 'gmap') .'/gmap_settings_ui.inc');
return _gmap_admin_settings();
}
/**
* Implementation of hook_elements().
*/
function gmap_elements() {
return array(
'gmap' => array(
'#input' => FALSE, // This isn't a *form* input!!
'#settings' => array_merge(gmap_defaults(), array(
'points' => array(),
'pointsOverlays' => array(),
'lines' => array(),
)),
'#process' => array('expand_gmap' => array()),
),
'gmap_macrotext' => array(
'#input' => TRUE,
'#cols' => 60,
'#rows' => 5,
'#process' => array(
'process_gmap_control' => array('textarea', 'macrotext'),
),
),
'gmap_overlay_edit' => array('#input' => FALSE, '#process' => array('process_gmap_overlay_edit' => array())),
'gmap_address' => array('#input' => FALSE, '#process' => array('process_gmap_address' => array())),
'gmap_align' => array('#input' => TRUE, '#process' => array('process_gmap_align' => array())),
'gmap_latitude' => array('#input' => TRUE, '#process' => array('process_gmap_control' => array('textfield', 'latitude', 'gmap_coord'))),
'gmap_longitude' => array('#input' => TRUE, '#process' => array('process_gmap_control' => array('textfield', 'longitude', 'gmap_coord'))),
'gmap_latlon' => array('#input' => TRUE, '#process' => array('process_gmap_control' => array('textfield', 'latlon', 'gmap_coord'))),
'gmap_markerchooser' => array('#input' => TRUE, '#process' => array('process_gmap_markerchooser' => array())),
'gmap_dimension' => array('#input' => TRUE, '#theme' => 'textfield', '#validate' => array('gmap_dimension_validate' => array())),
);
}
/**
* Gmap element process hook
*/
function expand_gmap($element) {
$mapid = 'map';
if ($element['#map']) {
$mapid = $element['#map'];
}
else {
$element['#map'] = $mapid;
}
if (!$element['#settings']) {
$element['#settings'] = array();
}
$element['#settings'] = array_merge(gmap_defaults(), array(
'id' => $mapid,
'points' => array(),
'pointsOverlays' => array(),
'lines' => array(),
), $element['#settings']);
gmap_widget_setup($element, 'gmap');
return $element;
}
/**
* Generic gmap control processor
*/
function process_gmap_control($element, $edit, $fieldtype, $control, $theme='') {
$element['#type'] = $fieldtype;
gmap_widget_setup($element, $control);
if (!empty($theme)) {
$element['#theme'] = $theme;
}
else {
$element['#theme'] = 'gmap_'. $control;
}
return $element;
}
function process_gmap_overlay_edit($element) {
// Conver the root element into a fieldset.
$element['#type'] = 'fieldset';
if (!$element['#title']) {
$element['#title'] = t('Overlay editor');
}
$element['#tree'] = TRUE;
$element['mapclicktype'] = array(
'#type' => 'select',
'#title' => t('Click map'),
'#map' => $element['#map'],
'#options' => array(
'Points' => t('Points'),
'Lines' => t('Lines'),
'Circles' => t('Circles'),
),
);
gmap_widget_setup($element['mapclicktype'], 'overlayedit_mapclicktype');
$element['markerclicktype'] = array(
'#type' => 'select',
'#title' => t('Click marker'),
'#map' => $element['#map'],
'#options' => array(
'Remove' => t('Remove'),
'Edit Info' => t('Edit Info'),
),
);
gmap_widget_setup($element['markerclicktype'], 'overlayedit_markerclicktype');
$element['marker'] = array(
'#type' => 'select',
'#map' => $element['#map'],
'#options' => gmap_get_marker_titles(),
'#title' => t('Marker'),
'#theme' => 'gmap_overlay_edit',
);
gmap_widget_setup($element['marker'], 'overlayedit');
$element['linesettings'] = array(
'#type' => 'fieldset',
'#title' => t('Line/Polygon settings'),
'#tree' => TRUE,
);
$element['linesettings']['scol'] = array(
'#type' => 'textfield',
'#map' => $element['#map'],
'#size' => 6,
'#maxlength' => 6,
'#field_prefix' => '#',
'#title' => t('Stroke color'),
'#default_value' => '000000',
);
gmap_widget_setup($element['linesettings']['scol'], 'overlayedit_scol');
$element['linesettings']['sweight'] = array(
'#type' => 'textfield',
'#map' => $element['#map'],
'#size' => 3,
'#maxlength' => 3,
'#field_suffix' => t('px'),
'#title' => t('Stroke weight'),
'#default_value' => 1,
);
gmap_widget_setup($element['linesettings']['sweight'], 'overlayedit_sweight');
$element['linesettings']['sopac'] = array(
'#type' => 'textfield',
'#map' => $element['#map'],
'#size' => 3,
'#maxlength' => 3,
'#field_suffix' => '%',
'#title' => t('Stroke opacity'),
'#default_value' => '100',
);
gmap_widget_setup($element['linesettings']['sopac'], 'overlayedit_sopac');
$element['linesettings']['fcolor'] = array(
'#type' => 'textfield',
'#map' => $element['#map'],
'#size' => 6,
'#maxlength' => 6,
'#field_prefix' => '#',
'#title' => t('Fill color'),
'#default_value' => '00FF00',
);
gmap_widget_setup($element['linesettings']['fcolor'], 'overlayedit_fcolor');
$element['linesettings']['fopac'] = array(
'#type' => 'textfield',
'#map' => $element['#map'],
'#size' => 3,
'#maxlength' => 3,
'#field_suffix' => '%',
'#title' => t('Fill opacity'),
'#default_value' => '60',
);
gmap_widget_setup($element['linesettings']['fopac'], 'overlayedit_fopac');
return $element;
}
function process_gmap_align($element) {
$element['#type'] = 'select';
gmap_widget_setup($element, 'align');
$element['#options'] = drupal_map_assoc(array('None', 'Right', 'Left', 'Center'));
$element['#theme'] = 'gmap_align';
return $element;
}
function process_gmap_address($element) {
$element['#type'] = 'textfield';
gmap_widget_setup($element, 'address');
$element['#theme'] = 'gmap_address';
return $element;
}
function process_gmap_markerchooser($element) {
$element['#type'] = 'select';
$element['#options'] = gmap_get_marker_titles();
return $element;
}
function theme_gmap_overlay_edit($element) {
$path = drupal_get_path('module', 'gmap');
drupal_add_js($path .'/js/gmap.js');
drupal_add_js($path .'/js/gmap_shapes.js');
drupal_add_js($path .'/js/overlay_edit.js');
return theme('select', $element);
}
/**
* Perform some normalization on the map object
* to prevent errors.
*/
function gmap_map_cleanup(&$map) {
// Google is picky about this one.
$map['zoom'] = (int)$map['zoom'];
// JSON query handler
$map['querypath'] = url('map/query', NULL, NULL, TRUE);
// Normalize latitude / longitude
if ($map['latlong']) {
$map['latlon'] = $map['latlong'];
unset($map['latlong']);
}
if (isset($map['latlon']) && (!isset($map['latitude']) || !isset($map['longitude']))) {
list($map['latitude'], $map['longitude']) = explode(',', $map['latlon']);
}
unset($map['latlon']);
}
function theme_gmap_coord($element) {
//drupal_add_js
return theme('textfield', $element);
}
function theme_gmap_macrotext($element) {
drupal_add_js(drupal_get_path('module', 'gmap') .'/js/macro.js');
// @@@
drupal_add_js(drupal_get_path('module', 'gmap') .'/js/macrobuilder.js');
return theme('textarea', $element);
}
function theme_gmap_address($element) {
drupal_add_js(drupal_get_path('module', 'gmap') .'/js/address.js');
return theme('textfield', $element);
}
function theme_gmap_align($element) {
drupal_add_js(drupal_get_path('module', 'gmap') .'/js/align.js');
return theme('select', $element);
}
/**
* Gmap element theme hook
*/
function theme_gmap($element) {
_gmap_doheader();
// If the theme function is called directly, the map is not properly set up yet.
if (!$element['#id']) {
gmap_widget_setup($element, 'gmap');
}
// Possible if this gmap was created manually.
if (!$element['#settings']) {
$element['#settings'] = array();
}
$map = array_merge(gmap_defaults(), $element['#settings']);
gmap_map_cleanup($map);
switch (strtolower($map['align'])) {
case 'left':
$element['#attributes']['class'] += ' gmap-left';
break;
case 'right':
$element['#attributes']['class'] += ' gmap-right';
break;
case 'center':
case 'centre':
$element['#attributes']['class'] += ' gmap-center';
}
$style = array();
$style[] = 'width: '. $map['width'];
$style[] = 'height: '. $map['height'];
$element['#attributes']['class'] = trim($element['#attributes']['class'] .'gmap gmap-map gmap-'. $map['id'] .'-gmap');
$o = '';
module_invoke_all('gmap', 'pre_theme_map', $map);
// Inline settings extend.
$o .= '\n";
return $o;
}
/**
* Set up widget.
* This function will change a form element's ID so it is found
* by the GMap handlers system.
* @param &$element
* The form element to modify.
* @param $type
* The gmap widget type to map to.
* @param $map
* The map id. If not defined, $element['#map'] will be used.
* @return
* None.
*/
function gmap_widget_setup(&$element, $type, $map=NULL) {
if (!$map) {
if (isset($element['#map'])) {
$map = $element['#map'];
}
else {
// Hmm, missing #map. Try to figure it out.
if (isset($element['#settings']['id'])) {
$map = $element['#settings']['id'];
}
}
}
$element['#attributes']['class'] = trim(implode(' ', array(
$element['#attributes']['class'],
'gmap-control',
'gmap-'. $type,
)));
$element['#id'] = gmap_get_id($map, $type);
$element['#map'] = $map;
}
/**
* Get a CSS id for a map and type.
* Since CSS ids have to be unique, GMap related IDs are assigned by
* this function.
*/
function gmap_get_id($map, $type) {
static $serial = array();
if (!isset($serial[$map])) {
$serial[$map] = array();
}
if (!isset($serial[$map][$type])) {
$serial[$map][$type] = -1;
}
$serial[$map][$type]++;
return 'gmap-'. $map .'-'. $type . $serial[$map][$type];
}
/**
* Generate a dynamic map identifier.
*/
function gmap_get_auto_mapid() {
static $auto = 0;
$auto++;
return 'auto'. $auto .'map';
}
/**
* Get the list of marker titles.
*/
function gmap_get_marker_titles($reset = FALSE) {
static $titles;
if (is_array($titles) && !$reset) {
return $titles;
}
$titles = cache_get('gmap_marker_titles');
if ($titles) {
$titles = unserialize($titles->data);
}
if ($reset || !$titles) {
require_once(drupal_get_path('module', 'gmap') .'/gmap_markerinfo.inc');
$titles = _gmap_get_marker_titles();
}
cache_set('gmap_marker_titles', 'cache', serialize($titles));
return $titles;
}
/**
* Get the JSON icon data for all the default markers.
*/
function gmap_get_icondata($reset=FALSE) {
static $icons;
if (is_array($icons) && !$reset) {
return $icons;
}
$icons = cache_get('gmap_icondata');
if ($icons) {
$icons = unserialize($icons->data);
}
if ($reset || !$icons) {
require_once(drupal_get_path('module', 'gmap') .'/gmap_markerinfo.inc');
$icons = _gmap_get_icondata();
}
cache_set('gmap_icondata', 'cache', serialize($icons));
return $icons;
}
/**
* Utility function to allow high-precision decimals to work with the SQL layer.
* Use concatenation. (Apparently unquoted %s is bad.)
*/
function gmap_decimal($num) {
// Paraphrased from postgresql documentation:
//
// Numbers in SQL can be in one of these forms:
// digits
// digits.[digits][e[+-]digits]
// [digits].digits[e[+-]digits]
// digitse[+-]digits
// where "digits" is one or more decimal digits.
// Trim extra whitespace
$num = trim($num);
// Check if we're in an acceptable form.
if (preg_match('/^[+\-]?((\d+)|(\d+\.\d*)|(\d*\.\d+))(e[+\-]?\d+)?$/', $num)===1) {
// Good, we can pass that right along.
return $num;
}
// Otherwise, cast to float, possibly losing precision.
return (float) $num;
}
/**
* Utility function to use the google maps geocoder server side.
* This is an easy, quick way to geocode a single address.
* Note: This is a REMOTE CALL TO GOOGLE. Do NOT use this where performance matters,
* as it could possibly take several seconds for this function to return.
* See http://www.google.com/apis/maps/documentation/reference.html#GGeoStatusCode
* for a description of the possible status codes.
*/
function gmap_geocode($address, $tld = 'com') {
$key = variable_get('googlemap_api_key', '');
if (module_exists('keys_api')) {
$key = keys_api_get_key('gmap', $_SERVER['HTTP_HOST']);
}
$data = drupal_http_request('http://maps.google.'. $tld .'/maps/geo?q='. drupal_urlencode($address) .'&output=csv&key='. $key);
if ($data->code == 200) {
$r = explode(',', $data->data);
return array(
'status' => (int)$r[0],
'accuracy' => (int)$r[1],
'latitude' => $r[2],
'longitude' => $r[3],
);
}
// Non 200 is G_GEO_SERVER_ERROR (500).
return array(
'status' => 500,
);
}
/**
* Simple way to draw a map from inside a theme.
* @param $latitude
* Latitude of marker.
* @param $longitude
* Longitude of marker.
* @param $markername
* Marker to use.
* '' will fall back to google's default marker.
* @param $info
* What to show in the bubble when the marker is clicked.
* Leave blank if you don't want a bubble.
* @param $zoom
* Map zoom.
* 'default' will use the default zoom from the settings page.
* 3 is usually a good value to use.
* @param $width
* Map width.
* 'default' will use the default width from the settings page.
* @param $height
* Map height.
* 'default' will use the default height from the settings page.
* @param $autoshow
* If set to TRUE, automatically show the marker bubble.
* @param $map
* Override parts of the map array.
* If you need to do much with this, you should probabaly be putting together
* the map array manually.
*/
function gmap_simple_map($latitude, $longitude, $markername = '', $info = '', $zoom = 'auto', $width = 'default', $height = 'default', $autoshow = FALSE, $map = array()) {
$settings = array(
'id' => gmap_get_auto_mapid(),
'latitude' => $latitude, // Center the map
'longitude' => $longitude, // on the marker.
);
if ($zoom != 'default') {
$settings['zoom'] = $zoom;
}
if ($width != 'default') {
$settings['width'] = $width;
}
if ($height != 'default') {
$settings['height'] = $height;
}
$settings['markers'] = array(array(
'latitude' => $latitude,
'longitude' => $longitude,
'markername' => $markername,
'offset' => 0,
));
if (!empty($info)) {
$settings['markers'][0]['text'] = $info;
}
if ($autoshow) {
$settings['markers'][0]['autoclick'] = TRUE;
}
if (!empty($map)) {
$settings = array_merge($settings, $map);
}
return theme('gmap', array('#settings' => $settings));
}
/**
* Implementation of hook_keys_service(). (from the keys api)
*/
function gmap_keys_service() {
return array(
'gmap' => array(
'name' => t('Gmap'),
'description' => t('Google Maps API Key'),
),
);
}