xref: /plugin/openlayersmap/syntax/olmap.php (revision 628e43cc3a6624787a1689fcd4920a44ec800286)
1<?php
2/*
3 * Copyright (c) 2008-2012 Mark C. Prins <mprins@users.sf.net>
4*
5* Permission to use, copy, modify, and distribute this software for any
6* purpose with or without fee is hereby granted, provided that the above
7* copyright notice and this permission notice appear in all copies.
8*
9* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*/
17
18/**
19 * Plugin OL Maps: Allow Display of a OpenLayers Map in a wiki page.
20 *
21 * @author Mark Prins
22 */
23
24if (!defined('DOKU_INC'))define('DOKU_INC', realpath(dirname(__FILE__) . '/../../') . '/');
25if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
26require_once (DOKU_PLUGIN . 'syntax.php');
27
28/**
29 * All DokuWiki plugins to extend the parser/rendering mechanism
30 * need to inherit from this class
31 */
32class syntax_plugin_openlayersmap_olmap extends DokuWiki_Syntax_Plugin {
33
34	/** defaults of the known attributes of the olmap tag. */
35	private $dflt = array (
36			'id'		=> 'olmap',
37			'width'		=> '550px',
38			'height'	=> '450px',
39			'lat'		=> 50.0,
40			'lon'		=> 5.1,
41			'zoom'		=> 12,
42			'toolbar'	=> true,
43			'statusbar'	=> true,
44			'controls'	=> true,
45			'poihoverstyle'	=> false,
46			'baselyr'	=> 'OpenStreetMap',
47			'gpxfile'	=> '',
48			'kmlfile'	=> '',
49			'summary'	=> ''
50	);
51
52	private $usingLocalStaticMap = false;
53
54	/**
55	 * Return the type of syntax this plugin defines.
56	 * @Override
57	 */
58	function getType() {
59		return 'substition';
60	}
61
62	/**
63	 * Defines how this syntax is handled regarding paragraphs.
64	 * @Override
65	 */
66	function getPType() {
67		//normal block stack
68		return 'block';
69	}
70
71	/**
72	 * Returns a number used to determine in which order modes are added.
73	 * @Override
74	 */
75	function getSort() {
76		return 901;
77	}
78
79	/**
80	 * This function is inherited from Doku_Parser_Mode.
81	 * Here is the place to register the regular expressions needed
82	 * to match your syntax.
83	 * @Override
84	 */
85	function connectTo($mode) {
86		$this->Lexer->addSpecialPattern('<olmap ?[^>\n]*>.*?</olmap>', $mode, 'plugin_openlayersmap_olmap');
87	}
88
89	/**
90	 * handle each olmap tag. prepare the matched syntax for use in the renderer.
91	 * @Override
92	 */
93	function handle($match, $state, $pos, &$handler) {
94		// break matched cdata into its components
95		list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
96		// get the lat/lon for adding them to the metadata (used by geotag)
97		preg_match('(lat[:|=]\"-?\d*\.\d*\")',$match,$mainLat);
98		preg_match('(lon[:|=]\"-?\d*\.\d*\")',$match,$mainLon);
99		$mainLat=substr($mainLat[0],5,-1);
100		$mainLon=substr($mainLon[0],5,-1);
101
102		$gmap = $this->_extract_params($str_params);
103		$overlay = $this->_extract_points($str_points);
104
105		// choose maptype based on tag
106		$imgUrl = "{{";
107		if (stripos($gmap['baselyr'],'google') !== false){
108			// use google
109			$imgUrl .= $this->_getGoogle($gmap, $overlay);
110			$imgUrl .="&.png";
111		} elseif (stripos($gmap['baselyr'],'ve') !== false){
112			// use bing
113			$imgUrl .= $this->_getBing($gmap, $overlay);
114			$imgUrl .="&.png";
115		} elseif (stripos($gmap['baselyr'],'bing') !== false){
116			// use bing
117			$imgUrl .= $this->_getBing($gmap, $overlay);
118			$imgUrl .="&.png";
119		} elseif (stripos($gmap['baselyr'],'mapquest') !== false){
120			if($this->getConf('optionStaticMapGenerator')=='remote'){
121				// use mapquest remote
122				$imgUrl .=$this->_getMapQuest($gmap,$overlay);
123				$imgUrl .="&.png";
124			} else{
125				$imgUrl .=$this->_getStaticOSM($gmap,$overlay);
126			}
127		} else {
128			$imgUrl .=$this->_getStaticOSM($gmap,$overlay);
129		}
130
131		// append dw p_render specific params and render
132		$imgUrl .="?".str_replace("px", "",$gmap['width'])."x".str_replace("px", "",$gmap['height']);
133		$imgUrl .= "&nolink";
134		$imgUrl .= " |".$gmap['summary']." }}";
135		$imgUrl=p_render("xhtml", p_get_instructions($imgUrl), $info);
136
137		$mapid = $gmap['id'];
138		// create a javascript parameter string for the map
139		$param = '';
140		foreach ($gmap as $key => $val) {
141			$param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
142		}
143		if (!empty ($param)) {
144			$param = substr($param, 0, -2);
145		}
146		unset ($gmap['id']);
147
148		// create a javascript serialisation of the point data
149		$poi = '';
150		$poitable='';
151		$rowId=0;
152		if (!empty ($overlay)) {
153			foreach ($overlay as $data) {
154				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
155				$rowId++;
156				$poi .= ", {lat: $lat, lon: $lon, txt: '$text', angle: $angle, opacity: $opacity, img: '$img', rowId: $rowId}";
157				$poitable .='
158				<tr>
159				<td class="rowId">'.$rowId.'</td>
160				<td class="icon"><img src="'.DOKU_BASE.'lib/plugins/openlayersmap/icons/'.$img.'" alt="icon" /></td>
161				<td class="lat" title="'.$this->getLang('olmapPOIlatTitle').'">'.$lat.'</td>
162				<td class="lon" title="'.$this->getLang('olmapPOIlonTitle').'">'.$lon.'</td>
163				<td class="txt">'.$text.'</td>
164				</tr>';
165			}
166			$poi = substr($poi, 2);
167		}
168		$js .= "{mapOpts:{" . $param . " },poi:[$poi]};";
169		// unescape the json
170		$poitable = stripslashes($poitable);
171
172		return array($mapid,$js,$mainLat,$mainLon,$poitable,$gmap['summary'],$imgUrl);
173	}
174
175	/**
176	 * render html tag/output. render the content.
177	 * @Override
178	 */
179	function render($mode, &$renderer, $data) {
180		static $initialised = false; // set to true after script initialisation
181		static $mapnumber = 0; // incremented for each map tag in the page source
182		list ($mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl) = $data;
183
184		if ($mode == 'xhtml') {
185			$olscript = '';
186			$olEnable = false;
187			$gscript = '';
188			$gEnable = $this->getConf('enableGoogle');
189			$mqEnable = $this->getConf('enableMapQuest');
190			$osmEnable = $this->getConf('enableOSM');
191			$enableBing = $this->getConf('enableBing');
192
193			$scriptEnable = '';
194
195			if (!$initialised) {
196				$initialised = true;
197				// render necessary script tags
198				if($gEnable){
199					$gscript ='<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.8&amp;sensor=false"></script>';
200				}
201				$olscript = $this->getConf('olScriptUrl');
202				$olscript = $olscript ? '<script type="text/javascript" src="' . $olscript . '"></script>' : "";
203				$olscript = str_replace('DOKU_BASE/', DOKU_BASE, $olscript);
204
205				$scriptEnable = '<script type="text/javascript"><!--//--><![CDATA[//><!--' . "\n";
206				$scriptEnable .= $olscript ? 'olEnable = true;' : 'olEnable = false;';
207				$scriptEnable .= 'gEnable = '.($gEnable ? 'true' : 'false').';';
208				$scriptEnable .= 'osmEnable = '.($osmEnable ? 'true' : 'false').';';
209				$scriptEnable .= 'mqEnable = '.($mqEnable ? 'true' : 'false').';';
210				$scriptEnable .= 'bEnable = '.($enableBing ? 'true' : 'false').';';
211				$scriptEnable .= 'bApiKey="'.$this->getConf('bingAPIKey').'";';
212				$scriptEnable .= 'OpenLayers.ImgPath = "'.DOKU_BASE.'lib/plugins/openlayersmap/lib/'.$this->getConf('olMapStyle').'/";';
213				$scriptEnable .= "\n" . '//--><!]]></script>';
214			}
215			$renderer->doc .= "
216			$gscript
217			$olscript
218			$scriptEnable";
219			if ($this->getConf('enableA11y')){
220				$renderer->doc .= '<div id="'.$mapid.'-static" class="olStaticMap">'.$staticImgUrl.'</div>';
221			}
222			$renderer->doc .= '<div id="'.$mapid.'-clearer" class="clearer"><p>&nbsp;</p></div>';
223			if ($this->getConf('enableA11y')){
224				// render a (hidden) table of the POI for the print and a11y presentation
225				$renderer->doc .= '<div class="olPOItableSpan" id="'.$mapid.'-table-span"><table class="olPOItable" id="'.$mapid.'-table" summary="'.$poitabledesc.'" title="'.$this->getLang('olmapPOItitle').'">
226				<caption class="olPOITblCaption">'.$this->getLang('olmapPOItitle').'</caption>
227				<thead class="olPOITblHeader">
228				<tr>
229				<th class="rowId" scope="col">id</th>
230				<th class="icon" scope="col">'.$this->getLang('olmapPOIicon').'</th>
231				<th class="lat" scope="col" title="'.$this->getLang('olmapPOIlatTitle').'">'.$this->getLang('olmapPOIlat').'</th>
232				<th class="lon" scope="col" title="'.$this->getLang('olmapPOIlonTitle').'">'.$this->getLang('olmapPOIlon').'</th>
233				<th class="txt" scope="col">'.$this->getLang('olmapPOItxt').'</th>
234				</tr>
235				</thead>';
236				if ($poitabledesc !=''){
237					$renderer->doc .='<tfoot class="olPOITblFooter"><tr><td colspan="5">'.$poitabledesc.'</td></tr></tfoot>';
238				}
239				$renderer->doc .='<tbody class="olPOITblBody">'.$poitable.'</tbody>
240				</table></div>';
241			}
242			// render inline mapscript
243			$renderer->doc .="\n		<script type='text/javascript'><!--//--><![CDATA[//><!--\n";
244			// var $mapid = $param
245			$renderer->doc .="		olMapData[$mapnumber] = $param
246			//--><!]]></script>";
247			$mapnumber++;
248			return true;
249		} elseif ($mode == 'metadata') {
250			// render metadata if available
251			if (!(($this->dflt['lat']==$mainLat)||($thisdflt['lon']==$mainLon))){
252				// unless they are the default
253				$renderer->meta['geo']['lat'] = $mainLat;
254				$renderer->meta['geo']['lon'] = $mainLon;
255			}
256			return true;
257		}
258		return false;
259	}
260
261	/**
262	 * extract parameters for the map from the parameter string
263	 *
264	 * @param   string    $str_params   string of key="value" pairs
265	 * @return  array                   associative array of parameters key=>value
266	 */
267	private function _extract_params($str_params) {
268		$param = array ();
269		preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
270		// parse match for instructions, break into key value pairs
271		$gmap = $this->dflt;
272		foreach ($param as $kvpair) {
273			list ($match, $key, $val) = $kvpair;
274			$key = strtolower($key);
275			if (isset ($gmap[$key])){
276				if ($key == 'summary'){
277					// preserve case for summary field
278					$gmap[$key] = $val;
279				}else {
280					$gmap[$key] = strtolower($val);
281				}
282			}
283		}
284		return $gmap;
285	}
286
287	/**
288	 * extract overlay points for the map from the wiki syntax data
289	 *
290	 * @param   string    $str_points   multi-line string of lat,lon,text triplets
291	 * @return  array                   multi-dimensional array of lat,lon,text triplets
292	 */
293	private function _extract_points($str_points) {
294		$point = array ();
295		//preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um', $str_points, $point, PREG_SET_ORDER);
296		/*
297		group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
298		group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
299		group 3: (.*?)
300		group 4: (.*?)
301		group 5: (.*?)
302		group 6: (.*)
303		*/
304		preg_match_all('/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um', $str_points, $point, PREG_SET_ORDER);
305		// create poi array
306		$overlay = array ();
307		foreach ($point as $pt) {
308			list ($match, $lat, $lon, $angle, $opacity, $img, $text) = $pt;
309			$lat = is_numeric($lat) ? $lat : 0;
310			$lon = is_numeric($lon) ? $lon : 0;
311			$angle = is_numeric($angle) ? $angle : 0;
312			$opacity = is_numeric($opacity) ? $opacity : 0.8;
313			$img = trim($img);
314			// TODO validate using exist & set up default img?
315			$text = addslashes(str_replace("\n", "", p_render("xhtml", p_get_instructions($text), $info)));
316			$overlay[] = array($lat, $lon, $text, $angle, $opacity, $img);
317		}
318		return $overlay;
319	}
320
321	/**
322	 * Create a MapQuest static map API image url.
323	 * @param array $gmap
324	 * @param array $overlay
325	 */
326	private function _getMapQuest($gmap,$overlay) {
327		$sUrl=$this->getConf('iconUrlOverload');
328		if (!$sUrl){
329			$sUrl=DOKU_URL;
330		}
331		switch ($gmap['baselyr']){
332			case 'mapquest hybrid':
333				$maptype='hyb';
334				break;
335			case 'mapquest sat':
336				// $maptype='sat'
337				// because sat coverage is very limited use 'hyb' instead of 'sat' so we don't get a blank map
338				$maptype='hyb';
339				break;
340			case 'mapquest road':
341			default:
342				$maptype='map';
343				break;
344		}
345		$imgUrl = "http://open.mapquestapi.com/staticmap/v3/getmap?declutter=true&";
346		if (count($overlay)< 1){
347			$imgUrl .= "?center=".$gmap['lat'].",".$gmap['lon'];
348			//max level for mapquest is 16
349			if ($gmap['zoom']>16) {
350				$imgUrl .= "&zoom=16";
351			} else			{
352				$imgUrl .= "&zoom=".$gmap['zoom'];
353			}
354		}
355		// use bestfit instead of center/zoom, needs upperleft/lowerright corners
356		//$bbox=$this->_calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
357		//$imgUrl .= "bestfit=".$bbox['minlat'].",".$bbox['maxlon'].",".$bbox['maxlat'].",".$bbox['minlon'];
358
359		// TODO declutter option works well for square maps but not for rectangular, maybe compensate for that or compensate the mbr..
360		$imgUrl .= "&size=".str_replace("px", "",$gmap['width']).",".str_replace("px", "",$gmap['height']);
361
362		// TODO mapquest allows using one image url with a multiplier $NUMBER eg:
363		// $NUMBER = 2
364		// $imgUrl .= DOKU_URL."/".DOKU_PLUGIN."/".getPluginName()."/icons/".$img.",$NUMBER,C,".$lat1.",".$lon1.",0,0,0,0,C,".$lat2.",".$lon2.",0,0,0,0";
365		if (!empty ($overlay)) {
366			$imgUrl .= "&xis=";
367			foreach ($overlay as $data) {
368				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
369				//$imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",0,0,0,0,";
370				$imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",";
371			}
372			$imgUrl = substr($imgUrl,0,-1);
373		}
374		$imgUrl .= "&imageType=png&type=".$maptype;
375		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getMapQuest: MapQuest image url is:');
376		return $imgUrl;
377	}
378	/**
379	 *
380	 * Create a Google maps static image url w/ the poi.
381	 * @param array $gmap
382	 * @param array $overlay
383	 */
384	private function _getGoogle($gmap, $overlay){
385		$sUrl=$this->getConf('iconUrlOverload');
386		if (!$sUrl){
387			$sUrl=DOKU_URL;
388		}
389		switch ($gmap['baselyr']){
390			case 'google hybrid':
391				$maptype='hybrid';
392				break;
393			case 'google sat':
394				$maptype='satellite';
395				break;
396			case 'google relief':
397				$maptype='terrain';
398				break;
399			case 'google road':
400			default:
401				$maptype='roadmap';
402				break;
403		}
404		// TODO maybe use viewport / visible instead of center/zoom,
405		//		see: https://code.google.com/intl/nl/apis/maps/documentation/staticmaps/#ImplicitPositioning
406		//http://maps.google.com/maps/api/staticmap?center=51.565690,5.456756&zoom=16&size=600x400&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/marker.png|label:1|51.565690,5.456756&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/marker-blue.png|51.566197,5.458966|label:2&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/parking.png|51.567177,5.457909|label:3&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/parking.png|51.566283,5.457330|label:4&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/parking.png|51.565630,5.457695|label:5&sensor=false&format=png&maptype=roadmap
407		$imgUrl = "http://maps.google.com/maps/api/staticmap?sensor=false";
408		$imgUrl .= "&size=".str_replace("px", "",$gmap['width'])."x".str_replace("px", "",$gmap['height']);
409		$imgUrl .= "&center=".$gmap['lat'].",".$gmap['lon'];
410		// max is 21 (== building scale), but that's overkill..
411		if ($gmap['zoom']>16) {
412			$imgUrl .= "&zoom=16";
413		} else			{
414			$imgUrl .= "&zoom=".$gmap['zoom'];
415		}
416
417		if (!empty ($overlay)) {
418			$rowId=0;
419			foreach ($overlay as $data) {
420				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
421				$imgUrl .= "&markers=icon%3a".$sUrl."lib/plugins/openlayersmap/icons/".$img."%7c".$lat.",".$lon."%7clabel%3a".++$rowId;
422			}
423		}
424		$imgUrl .= "&format=png&maptype=".$maptype;
425		global $conf;
426		$imgUrl .= "&language=".$conf['lang'];
427		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getGoogle: Google image url is:');
428		return $imgUrl;
429	}
430
431	/**
432	 *
433	 * Create a Bing maps static image url w/ the poi.
434	 * @param array $gmap
435	 * @param array $overlay
436	 */
437	private function _getBing($gmap, $overlay){
438		if(!$this->getConf('bingAPIKey')){
439			// in case there is no Bing api key
440			$this->_getMapQuest($gmap, $overlay);
441		}
442		switch ($gmap['baselyr']){
443			case 've hybrid':
444			case 'bing hybrid':
445				$maptype='AerialWithLabels';
446				break;
447			case 've sat':
448			case 'bing sat':
449				$maptype='Aerial';
450				break;
451			case 've normal':
452			case 've road':
453			case 've':
454			case 'bing road':
455			default:
456				$maptype='Road';
457				break;
458		}
459		$bbox=$this->_calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
460		//$imgUrl = "http://dev.virtualearth.net/REST/v1/Imagery/Map/".$maptype."/".$gmap['lat'].",".$gmap['lon']."/".$gmap['zoom'];
461		$imgUrl = "http://dev.virtualearth.net/REST/v1/Imagery/Map/".$maptype."/";
462		$imgUrl .= "?mapArea=".$bbox['minlat'].",".$bbox['minlon'].",".$bbox['maxlat'].",".$bbox['maxlon'];
463		// TODO declutter option works well for square maps but not for rectangular, maybe compensate for that or compensate the mbr..
464		$imgUrl .= "&declutter=1";
465		$imgUrl .= "&ms=".str_replace("px", "",$gmap['width']).",".str_replace("px", "",$gmap['height']);
466		$imgUrl .= "&key=".$this->getConf('bingAPIKey');
467		if (!empty ($overlay)) {
468			$rowId=0;
469			foreach ($overlay as $data) {
470				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
471				// TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
472				$iconStyle=32;
473				$rowId++;
474				// NOTE: the max number of pushpins is 18!
475				if ($rowId==18) {
476					break;
477				}
478				$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
479			}
480		}
481		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getBing: bing image url is:');
482		return $imgUrl;
483	}
484
485	/**
486	 *
487	 * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
488	 * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
489	 * @param array $gmap
490	 * @param array $overlay
491	 *
492	 * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
493	 */
494	private function _getStaticOSM($gmap, $overlay){
495		//http://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10.117187497601&zoom=5&size=500x350
496		// &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
497		global $conf;
498
499		switch ( $this->getConf('optionStaticMapGenerator')){
500			case 'local':
501				$imgUrl =$conf['baseurl']."/lib/plugins/openlayersmap/staticmap/map.php";
502				$imgUrl .= '?kml='.$gmap['kmlfile'];
503				$imgUrl .= '&gpx='.$gmap['gpxfile'];
504				break;
505			case 'remote':
506			default:
507				$imgUrl = "http://staticmap.openstreetmap.de/staticmap.php";
508		}
509
510		$imgUrl .= "&center=".$gmap['lat'].",".$gmap['lon'];
511		$imgUrl .= "&size=".str_replace("px", "",$gmap['width'])."x".str_replace("px", "",$gmap['height']);
512		$size =str_replace("px", "",$gmap['width'])."x".str_replace("px", "",$gmap['height']);
513
514		if ($gmap['zoom']>16) {
515			// actually this could even be 18, but that seems overkill
516			$imgUrl .= "&zoom=16";
517		} else {
518			$imgUrl .= "&zoom=".$gmap['zoom'];
519		}
520
521		switch ($gmap['baselyr']){
522			case 'mapnik':
523			case 'openstreetmap':
524				$maptype='openstreetmap';
525				break;
526			case 'transport':
527				$maptype='transport';
528				break;
529			case 'landscape':
530				$maptype='landscape';
531				break;
532			case 'cycle map':
533				$maptype='cycle';
534				break;
535			case 'cloudmade':
536				$maptype='cloudmade';
537				break;
538			case 'cloudmade fresh':
539				$maptype='fresh';
540				break;
541			case 'hike and bike map':
542				$maptype='hikeandbike';
543				break;
544			case 'mapquest hybrid':
545			case 'mapquest road':
546			case 'mapquest sat':
547				$maptype='mapquest';
548				break;
549			default:
550				$maptype='';
551				break;
552		}
553		$imgUrl .= "&maptype=".$maptype;
554
555		$markers='';
556		if (!empty ($overlay)) {
557			$rowId=0;
558			$imgUrl .= "&markers=";
559			foreach ($overlay as $data) {
560				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
561				$rowId++;
562				if ($this->getConf('optionStaticMapGenerator')=='remote') $iconStyle = "lightblue$rowId";
563				if ($this->getConf('optionStaticMapGenerator')=='local') $iconStyle = substr($img, 0,strlen($img)-4);
564				$imgUrl .= "$lat,$lon,$iconStyle%7c";
565				$markers[] = array(
566						'lat'=>$lat,
567						'lon'=>$lon,
568						'type'=>$iconStyle);
569			}
570			$imgUrl = substr($imgUrl,0,-3);
571		}
572
573		if (!$my = &plugin_load('helper', 'openlayersmap_staticmap')){
574			dbglog($my,'syntax_plugin_openlayersmap_olmap::_getStaticOSM: openlayersmap_staticmap plugin is false');
575			return false;
576		}
577
578		if ($this->getConf('optionStaticMapGenerator')=='local') {
579			$result = $my->getMap($gmap['lat'],$gmap['lon'],$gmap['zoom'],$size,$maptype,$markers,$gmap['gpxfile'],$gmap['kmlfile']);
580		}else{
581			$result= $imgUrl;
582		}
583
584		dbglog($result,'syntax_plugin_openlayersmap_olmap::_getStaticOSM: osm image url is:');
585		return $result;
586	}
587
588	/**
589	 * Calculate the minimum bbox for a start location + poi.
590	 *
591	 * @param array $overlay  multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
592	 * @param float $lat latitude for map center
593	 * @param float $lon longitude for map center
594	 * @return multitype:float array describing the mbr and center point
595	 */
596	private function _calcBBOX($overlay, $lat, $lon){
597		$lats[] = $lat;
598		$lons[] = $lon;
599		foreach ($overlay as $data) {
600			list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
601			$lats[] = $lat;
602			$lons[] = $lon;
603		}
604		sort($lats);
605		sort($lons);
606		// TODO: make edge/wrap around cases work
607		$centerlat = $lats[0]+($lats[count($lats)-1]-$lats[0]);
608		$centerlon = $lons[0]+($lons[count($lats)-1]-$lons[0]);
609		return array('minlat'=>$lats[0], 'minlon'=>$lons[0],
610				'maxlat'=>$lats[count($lats)-1], 'maxlon'=>$lons[count($lats)-1],
611				'centerlat'=>$centerlat,'centerlon'=>$centerlon);
612	}
613}