1<?php
2/**
3 * DokuWiki Plugin cnmap (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Lshan <ldg@szzxue.com>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14class syntax_plugin_cnmap extends DokuWiki_Syntax_Plugin
15{
16    private $css_len_pattern ="/(^(auto|0)$|^[+-]?[0-9]+\.?([0-9]+)?)(px|em|ex|%|in|cm|mm|pt|pc)$/";
17    private $providers = array('amap','bmap') ;
18
19    private $amap_script_src = '<script src="https://webapi.amap.com/maps?';
20    private $bmap_script_src = '<script type="text/javascript" src="http://api.map.baidu.com/api?';
21
22    /**
23     * @return string Syntax mode type
24     */
25    public function getType()
26    {
27        return 'substition';
28    }
29
30    /**
31     * @return string Paragraph type
32     */
33    public function getPType()
34    {
35        return 'block';
36    }
37
38    /**
39     * @return int Sort order - Low numbers go before high numbers
40     */
41    public function getSort()
42    {
43        return 70;
44    }
45
46    /**
47     * Connect lookup pattern to lexer.
48     *
49     * @param string $mode Parser mode
50     */
51    public function connectTo($mode)
52    {
53        $this->Lexer->addSpecialPattern('{{cnmap>.*?}}',$mode,'plugin_cnmap');
54    }
55
56//    public function postConnect()
57//    {
58//        $this->Lexer->addExitPattern('</FIXME>', 'plugin_cnmap');
59//    }
60
61    /**
62     * Handle matches of the cnmap syntax
63     *
64     * @param string       $match   The match of the syntax
65     * @param int          $state   The state of the handler
66     * @param int          $pos     The position in the document
67     * @param Doku_Handler $handler The handler
68     *
69     * @return array Data for the renderer
70     */
71    public function handle($match, $state, $pos, Doku_Handler $handler)
72    {
73        $data = $this->parseMatch($match);
74
75        return $data;
76    }
77
78    /**
79     * Render xhtml output or metadata
80     *
81     * @param string        $mode     Renderer mode (supported modes: xhtml)
82     * @param Doku_Renderer $renderer The renderer
83     * @param array         $data     The data from the handler() function
84     *
85     * @return bool If rendering was successful.
86     */
87    public function render($mode, Doku_Renderer $renderer, $data)
88    {
89        if ($mode !== 'xhtml') {
90            return false;
91        }
92
93        $pos = false;
94        switch($data['provider'])
95        {
96            case "amap":
97                $pos = strpos($renderer->doc, $this->amap_script_src);
98                break;
99            case "bmap":
100                $pos = strpos($renderer->doc, $this->bmap_script_src);
101                break;
102            default:
103                break;
104        }
105        if ($pos !== false)
106        {
107            $data[0]= "<!-- ";
108            $data[2]= " -->";
109        }
110
111        $html_tpl = @file_get_contents(__DIR__."/tpl/".$data['provider'].".tpl.html");
112        $html = @vsprintf($html_tpl,  $data);
113        $renderer->doc .= $html ;
114
115        return true;
116    }
117
118    /**
119     * Parse and validate matches of the cnmap syntax
120     *
121     * @param string       $match   The match of the syntax
122     * Example :
123     *   {{cnmap>?lng=116.397428&lat=39.90923}}
124     *   {{cnmap>bmap?lng=116.397428&lat=39.90923&width=100%&height=500px&zoom=17&title=title of marker&mark=yes&sat=yes}}
125     *
126     * @return array Data for the renderer
127     */
128    public function parseMatch($match) {
129        $match = substr($match, strlen('{{cnmap>'), -strlen('}}'));
130        list($provider, $query) = explode('?', $match, 2);
131
132        $args = array();
133        parse_str($query, $args);
134
135        $args['provider'] = in_array($provider, $this->providers)? $provider : $this->getConf('provider');
136
137        $args['zoom'] = intval($args['zoom']);
138        if($args['zoom'] < 3 || $args['zoom'] > 19)
139            $args['zoom'] = $this->getConf('zoom');
140
141        if(preg_match($this->css_len_pattern, $args['width']) != 1 )
142            $args['width'] = $this->getConf('width');
143
144        if(preg_match($this->css_len_pattern, $args['height']) != 1 )
145            $args['height'] = $this->getConf('height');
146
147        if(!isset($args['title']))
148            $args['title']='';
149
150        if(!isset($args['mark']))
151            $args['mark']= $this->getConf('mark');
152         else
153        {
154             $args['mark'] = strtolower($args['mark']);
155             $args['mark'] = (($args['mark'] == 'y') || ($args['mark'] == 'yes')|| ($args['mark'] == 'on'));
156        }
157
158        if(!isset($args['sat']))
159            $args['sat']= $this->getConf('sat');
160         else
161        {
162             $args['sat'] = strtolower($args['sat']);
163             $args['sat'] = (($args['sat'] == 'y') || ($args['sat'] == 'yes')|| ($args['sat'] == 'on'));
164        }
165
166        switch($args['provider'])
167        {
168            case "amap":
169                return $this->parseMatchAmap($args);
170            case "bmap":
171                return $this->parseMatchBmap($args);
172            default:
173                return $this->parseMatchAmap($args);
174        }
175    }
176
177    /**
178     * Parse and validate args of the amap syntax
179     *
180     * @param array       $args   The match of the syntax
181     *   Ref : https://lbs.amap.com/api/javascript-api/summary
182     *
183     * @return array Data for the renderer
184     */
185    public function parseMatchAmap($args) {
186        $id = rand(1000,2000);
187        $container_id ="amap_container_".$id;
188
189        $args['title']=addslashes($args['title']);
190        $args['title']=str_replace("<","\\<", $args['title']);
191        $args['title']=str_replace(">","\\>", $args['title']);
192
193        $data = array();
194        array_push($data,  "");
195        array_push($data,  $this->getConf('amap_api_key'));
196        array_push($data,  "");
197
198        array_push($data,  $container_id);
199        array_push($data,  $args['width']);
200        array_push($data,  $args['height']);
201        array_push($data,  $container_id);
202        array_push($data,  $id);
203        array_push($data,  $args['lng']);
204        array_push($data,  $args['lat']);
205        array_push($data,  $container_id);
206        array_push($data,  $args['zoom']);
207        array_push($data,  $args['mark']?"true":"false");
208        array_push($data,  $args['title']);
209        array_push($data,  $args['sat']?"true":"false");
210        array_push($data,  $id);
211
212        $data['provider']= $args['provider'];
213
214        return $data;
215    }
216
217    /**
218     * Parse and validate args of the bmap syntax
219     *
220     * @param array       $args   The match of the syntax
221     *   Ref : http://lbsyun.baidu.com/index.php?title=jspopular
222     *
223     * @return array Data for the renderer
224     */
225    public function parseMatchBmap($args) {
226        $id = rand(2000,3000);
227        $container_id ="bmap_container_".$id;
228
229        $args['title']=addslashes($args['title']);
230        $args['title']=str_replace("<","\\<", $args['title']);
231        $args['title']=str_replace(">","\\>", $args['title']);
232
233        $data = array();
234        array_push($data,  "");
235        array_push($data,  $this->getConf('bmap_api_key'));
236        array_push($data,  "");
237
238        array_push($data,  $container_id);
239        array_push($data,  $args['width']);
240        array_push($data,  $args['height']);
241        array_push($data,  $container_id);
242        array_push($data,  $id);
243        array_push($data,  $args['lng']);
244        array_push($data,  $args['lat']);
245        array_push($data,  $container_id);
246        array_push($data,  $args['zoom']);
247        array_push($data,  $args['mark']?"true":"false");
248        array_push($data,  $args['title']);
249        array_push($data,  $args['sat']?"true":"false");
250        array_push($data,  $id);
251
252        $data['provider']= $args['provider'];
253
254        return $data;
255    }
256}
257
258