1<?php
2/**
3 * Plugin Google Maps: Allow Display of a Google Map in a wiki page.
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Christopher Smith <chris@jalakai.co.uk>
7 */
8
9if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
10if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11require_once(DOKU_PLUGIN.'syntax.php');
12
13// ---------- [ Settings ] -----------------------------------------
14
15/**
16 * All DokuWiki plugins to extend the parser/rendering mechanism
17 * need to inherit from this class
18 */
19class syntax_plugin_googlemaps_googlemap extends DokuWiki_Syntax_Plugin {
20
21    var $dflt = array(
22      'type' => 'map',
23      'width' => '',
24      'height' => '',
25      'lat'  => -4.25,
26      'lon' => 55.833,
27      'zoom' => 8,
28      'controls' => 'on',
29      'kml' => 'off',
30    );
31
32    function getInfo(){
33      return array(
34        'author' => 'Christopher Smith',
35        'email'  => 'chris@jalakai.co.uk',
36        'date'   => '2008-11-11',
37        'name'   => 'Google Maps Plugin',
38        'desc'   => 'Add maps to your wiki
39                     Syntax: <googlemap params>overlaypoints</googlemap>',
40        'url'    => 'http://www.dokuwiki.org/plugin:google_maps',
41      );
42    }
43
44    function getType() { return 'substition'; }
45    function getPType() { return 'block'; }
46    function getSort() { return 900; }
47
48    function connectTo($mode) {
49        $this->Lexer->addSpecialPattern('<googlemap ?[^>\n]*>.*?</googlemap>',$mode,'plugin_googlemaps_googlemap');
50    }
51
52    function handle($match, $state, $pos, &$handler){
53
54      // break matched cdata into its components
55      list($str_params,$str_points) = explode('>',substr($match,10,-12),2);
56
57      $gmap = $this->_extract_params($str_params);
58      $overlay = $this->_extract_points($str_points);
59
60      // determine width and height (inline styles) for the map image
61      if ($gmap['width'] || $gmap['height']) {
62        $style = $gmap['width'] ? 'width: '.$gmap['width'].";" : "";
63        $style .= $gmap['height'] ? 'height: '.$gmap['height'].";" : "";
64        $style = "style='$style'";
65      } else {
66        $style = '';
67      }
68
69      // unset gmap values for width and height - they don't go into javascript
70      unset($gmap['width'],$gmap['height']);
71
72      // create a javascript parameter string for the map
73      $param = '';
74      foreach ($gmap as $key => $val) {
75          $param .= is_numeric($val) ? " $key : $val," : "$key : '".hsc($val)."',";
76      }
77
78      if (!empty($param)) $param = substr($param,0,-1);
79
80      // create a javascript serialisation of the point data
81      $points = '';
82      if (!empty($overlay)) {
83        foreach ($overlay as $data) {
84          list($lat,$lon,$text) = $data;
85          $points .= ",{lat:$lat,lon:$lon,txt:'$text'}";
86        }
87        $points = ", overlay : [ ".substr($points,1)." ]";
88      }
89
90      $js = "googlemap[googlemap.length] = {".$param.$points." };";
91
92      return array($style, $js);
93    }
94
95    function render($mode, &$renderer, $data) {
96
97      static $initialised = false;    // set to true after script initialisation
98
99      if ($mode == 'xhtml') {
100        list($style, $param) = $data;
101
102        $script = '';
103
104        if (!$initialised) {
105          $initialised = true;
106          $script = $this->getConf('script').$this->getConf('key');
107          $script = '<script type="text/javascript" src="'.$script.'"></script>';
108        }
109
110        $renderer->doc .= "
111<div class='googlemap' $style>
112$script
113<script type='text/javascript'>
114$param
115</script>
116</div>";
117      }
118
119      return false;
120    }
121
122    /**
123     * extract parameters for the googlemap from the parameter string
124     *
125     * @param   string    $str_params   string of key="value" pairs
126     * @return  array                   associative array of parameters key=>value
127     */
128    function _extract_params($str_params) {
129
130      $param = array();
131      preg_match_all('/(\w*)="(.*?)"/us',$str_params,$param,PREG_SET_ORDER);
132
133      // parse match for instructions, break into key value pairs
134      $gmap = $this->dflt;
135      foreach($param as $kvpair) {
136        list($match,$key,$val) = $kvpair;
137        $key = strtolower($key);
138        if (isset($gmap[$key])) $gmap[$key] = strtolower($val);
139      }
140
141      return $gmap;
142    }
143
144    /**
145     * extract overlay points for the googlemap from the wiki syntax data
146     *
147     * @param   string    $str_points   multi-line string of lat,lon,text triplets
148     * @return  array                   multi-dimensional array of lat,lon,text triplets
149     */
150    function _extract_points($str_points) {
151
152      $point = array();
153      preg_match_all('/^(.*?),(.*?),(.*)$/um',$str_points,$point,PREG_SET_ORDER);
154
155      $overlay = array();
156      foreach ($point as $pt) {
157        list($match,$lat,$lon,$text) = $pt;
158
159        $lat = is_numeric($lat) ? $lat : 0;
160        $lon = is_numeric($lon) ? $lon : 0;
161        $text = addslashes(str_replace("\n","",p_render("xhtml",p_get_instructions($text),$info)));
162
163        $overlay[] = array($lat,$lon,$text);
164      }
165
166      return $overlay;
167    }
168
169}