xref: /plugin/openlayersmap/syntax/olmap.php (revision 7a3f422c679b11d2e847df4e5adaa338bfffb126)
1<?php
2/*
3 * Copyright (c) 2008-2011 Mark C. Prins <mc.prins@gmail.com>
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'))
25define('DOKU_INC', realpath(dirname(__FILE__) . '/../../') . '/');
26if (!defined('DOKU_PLUGIN'))
27define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
28require_once (DOKU_PLUGIN . 'syntax.php');
29
30/**
31 * All DokuWiki plugins to extend the parser/rendering mechanism
32 * need to inherit from this class
33 */
34class syntax_plugin_openlayersmap_olmap extends DokuWiki_Syntax_Plugin {
35	/** defaults of the recognized attributes of the olmap tag. */
36	private $dflt = array (
37		'id' => 'olmap',
38		'width' => '550px',
39		'height' => '450px',
40		'lat' => 50.0,
41		'lon' => 5.1,
42		'zoom' => 12,
43		'toolbar' => true,
44		'statusbar' => true,
45		'controls' => true,
46		'poihoverstyle' => false,
47		'baselyr'=>'OpenStreetMap',
48	 	'gpxfile' => '',
49 		'kmlfile' => ''
50 		);
51
52 		/**
53 		 * Return the type of syntax this plugin defines.
54 		 * @Override
55 		 */
56 		function getType() {
57 			return 'substition';
58 		}
59
60 		/**
61 		 * Defines how this syntax is handled regarding paragraphs.
62 		 * @Override
63 		 */
64 		function getPType() {
65 			return 'block';
66 		}
67
68 		/**
69 		 * Returns a number used to determine in which order modes are added.
70 		 * @Override
71 		 */
72 		function getSort() {
73 			return 901;
74 		}
75
76 		/**
77 		 * This function is inherited from Doku_Parser_Mode.
78 		 * Here is the place to register the regular expressions needed
79 		 * to match your syntax.
80 		 * @Override
81 		 */
82 		function connectTo($mode) {
83 			$this->Lexer->addSpecialPattern('<olmap ?[^>\n]*>.*?</olmap>', $mode, 'plugin_openlayersmap_olmap');
84 		}
85
86 		/**
87 		 * handle each olmap tag. prepare the matched syntax for use in the renderer.
88 		 * @Override
89 		 */
90 		function handle($match, $state, $pos, &$handler) {
91 			// break matched cdata into its components
92 			list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
93 			// get the lat/lon for adding them to the metadata (used by geotag)
94 			preg_match('(lat[:|=]\"\d*\.\d*\")',$match,$mainLat);
95 			preg_match('(lon[:|=]\"\d*\.\d*\")',$match,$mainLon);
96 			$mainLat=substr($mainLat[0],5,-1);
97 			$mainLon=substr($mainLon[0],5,-1);
98
99 			$gmap = $this->_extract_params($str_params);
100 			$overlay = $this->_extract_points($str_points);
101
102 			$mapid = $gmap['id'];
103
104 			// determine width and height (inline styles) for the map image
105 			if ($gmap['width'] || $gmap['height']) {
106 				$style = $gmap['width'] ? 'width: ' . $gmap['width'] . ";" : "";
107 				$style .= $gmap['height'] ? 'height: ' . $gmap['height'] . ";" : "";
108 				$style = "style='$style'";
109 			} else {
110 				$style = '';
111 			}
112
113 			// unset gmap values for width and height - they don't go into javascript
114 			unset ($gmap['width'], $gmap['height']);
115
116 			// create a javascript parameter string for the map
117 			$param = '';
118 			foreach ($gmap as $key => $val) {
119 				$param .= is_numeric($val) ? "$key:$val," : "$key:'" . hsc($val) . "',";
120 			}
121 			if (!empty ($param)) {
122 				$param = substr($param, 0, -1);
123 			}
124 			unset ($gmap['id']);
125
126 			// create a javascript serialisation of the point data
127 			$poi = '';
128 			if (!empty ($overlay)) {
129 				foreach ($overlay as $data) {
130 					list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
131 					$poi .= ",{lat: $lat, lon: $lon, txt: '$text', angle: $angle, opacity: $opacity, img: '$img'}";
132 				}
133 				$poi = substr($poi, 1);
134 			}
135 			$js .= "createMap({" . $param . " },[$poi]);";
136
137 			return array (
138 			$mapid,
139 			$style,
140 			$js,
141 			$mainLat,
142 			$mainLon
143 			);
144 		}
145
146 		/**
147 		 * render html tag/output. render the content.
148 		 * @Override
149 		 */
150 		function render($mode, &$renderer, $data) {
151 			static $initialised = false; // set to true after script initialisation
152 			list ($mapid, $style, $param, $mainLat, $mainLon) = $data;
153
154 			if ($mode == 'xhtml') {
155 				$olscript = '';
156 				$olEnable = false;
157 				$gscript = '';
158 				$gEnable = false;
159 				$vscript = '';
160 				$vEnable = false;
161 				$yscript = '';
162 				$yEnable = false;
163
164 				$scriptEnable = '';
165
166 				if (!$initialised) {
167 					$initialised = true;
168
169 					$gscript = $this->getConf('googleScriptUrl');
170 					$gscript = $gscript ? '<script type="text/javascript" src="' . $gscript . '"></script>' : "";
171
172 					$vscript = $this->getConf('veScriptUrl');
173 					$vscript = $vscript ? '<script type="text/javascript" src="' . $vscript . '"></script>' : "";
174
175 					$yscript = $this->getConf('yahooScriptUrl');
176 					$yscript = $yscript ? '<script type="text/javascript" src="' . $yscript . '"></script>' : "";
177
178 					$olscript = $this->getConf('olScriptUrl');
179 					$olscript = $olscript ? '<script type="text/javascript" src="' . $olscript . '"></script>' : "";
180 					$olscript = str_replace('DOKU_PLUGIN', DOKU_PLUGIN, $olscript);
181
182 					$scriptEnable = '<script type="text/javascript">' . "\n" . '//<![CDATA[' . "\n";
183 					$scriptEnable .= $olscript ? 'olEnable = true;' : 'olEnable = false;';
184 					$scriptEnable .= $yscript ? ' yEnable = true;' : ' yEnable = false;';
185 					$scriptEnable .= $vscript ? ' veEnable = true;' : ' veEnable = false;';
186 					$scriptEnable .= $gscript ? ' gEnable = true;' : ' gEnable = false;';
187 					$scriptEnable .= "\n" . '//]]>' . "\n" . '</script>';
188 				}
189 				$renderer->doc .= "
190 				$olscript
191 				$gscript
192 				$vscript
193 				$yscript
194 				$scriptEnable
195			    <div id='olContainer' class='olContainer'>
196			        <div id='$mapid-olToolbar' class='olToolbar'></div>
197			        <div style='clear:both;'></div>
198			        <div id='$mapid' $style ></div>
199			        <div id='$mapid-olStatusBar' class='olStatusBarContainer'>
200			            <div id='$mapid-statusbar-scale' class='olStatusBar olStatusBarScale'>scale</div>
201			            <div id='$mapid-statusbar-link' class='olStatusBar olStatusBarPermalink'>
202			                <a href='' id='$mapid-statusbar-link-ref'>map link</a>
203			            </div>
204			            <div id='$mapid-statusbar-mouseposition' class='olStatusBar olStatusBarMouseposition'></div>
205			            <div id='$mapid-statusbar-projection' class='olStatusBar olStatusBarProjection'>proj</div>
206			            <div id='$mapid-statusbar-text' class='olStatusBar olStatusBarText'>txt</div>
207			        </div>
208			    </div>
209			    <p>&nbsp;</p>
210			    <script type='text/javascript'>//<![CDATA[
211			    var $mapid = $param
212			   //]]></script>";
213 			} elseif ($mode == 'metadata') {
214 				// render metadata if available
215 				if (!(($this->dflt['lat']==$mainLat)||($thisdflt['lon']==$mainLon))){
216 					// unless they are the default
217 					$renderer->meta['geo']['lat'] = $mainLat;
218 					$renderer->meta['geo']['lon'] = $mainLon;
219 				}
220 				return true;
221 			}
222 			return false;
223 		}
224
225 		/**
226 		 * extract parameters for the map from the parameter string
227 		 *
228 		 * @param   string    $str_params   string of key="value" pairs
229 		 * @return  array                   associative array of parameters key=>value
230 		 */
231 		function _extract_params($str_params) {
232 			$param = array ();
233 			preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
234 			// parse match for instructions, break into key value pairs
235 			$gmap = $this->dflt;
236 			foreach ($param as $kvpair) {
237 				list ($match, $key, $val) = $kvpair;
238 				$key = strtolower($key);
239 				if (isset ($gmap[$key])){
240 					$gmap[$key] = strtolower($val);
241 				}
242 			}
243 			return $gmap;
244 		}
245
246 		/**
247 		 * extract overlay points for the map from the wiki syntax data
248 		 *
249 		 * @param   string    $str_points   multi-line string of lat,lon,text triplets
250 		 * @return  array                   multi-dimensional array of lat,lon,text triplets
251 		 */
252 		function _extract_points($str_points) {
253 			$point = array ();
254 			//preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um', $str_points, $point, PREG_SET_ORDER);
255 			/*
256 			group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
257 			group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
258 			group 3: (.*?)
259 			group 4: (.*?)
260 			group 5: (.*?)
261 			group 6: (.*)
262 			*/
263 			preg_match_all('/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um', $str_points, $point, PREG_SET_ORDER);
264 			// create poi array
265 			$overlay = array ();
266 			foreach ($point as $pt) {
267 				list ($match, $lat, $lon, $angle, $opacity, $img, $text) = $pt;
268 				$lat = is_numeric($lat) ? $lat : 0;
269 				$lon = is_numeric($lon) ? $lon : 0;
270 				$angle = is_numeric($angle) ? $angle : 0;
271 				$opacity = is_numeric($opacity) ? $opacity : 0.8;
272 				$img = trim($img);
273 				// TODO validate & set up default img?
274 				$text = addslashes(str_replace("\n", "", p_render("xhtml", p_get_instructions($text), $info)));
275 				$overlay[] = array($lat, $lon, $text, $angle, $opacity, $img);
276 			}
277 			return $overlay;
278 		}
279}