xref: /plugin/openlayersmap/syntax/olmap.php (revision 57f8d5bb7862220bc86367226edbe0c27b689270)
138a47c60SMark Prins<?php
238a47c60SMark Prins/*
3*57f8d5bbSMark Prins * Copyright (c) 2008-2021 Mark C. Prins <mprins@users.sf.net>
438a47c60SMark Prins *
538a47c60SMark Prins * Permission to use, copy, modify, and distribute this software for any
638a47c60SMark Prins * purpose with or without fee is hereby granted, provided that the above
738a47c60SMark Prins * copyright notice and this permission notice appear in all copies.
838a47c60SMark Prins *
938a47c60SMark Prins * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1038a47c60SMark Prins * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1138a47c60SMark Prins * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1238a47c60SMark Prins * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1338a47c60SMark Prins * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1438a47c60SMark Prins * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1538a47c60SMark Prins * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*57f8d5bbSMark Prins *
17*57f8d5bbSMark Prins * @phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
1838a47c60SMark Prins */
1938a47c60SMark Prins
2038a47c60SMark Prins/**
21cc74a83cSMark Prins * DokuWiki Plugin openlayersmap (Syntax Component).
22cc74a83cSMark Prins * Provides for display of an OpenLayers based map in a wiki page.
23cc74a83cSMark Prins *
24cc74a83cSMark Prins * @author Mark Prins
2538a47c60SMark Prins */
2638a47c60SMark Prinsclass syntax_plugin_openlayersmap_olmap extends DokuWiki_Syntax_Plugin {
27fcf646d2SMark Prins
281c640875SMark Prins    /**
291c640875SMark Prins     * defaults of the known attributes of the olmap tag.
301c640875SMark Prins     */
3138a47c60SMark Prins    private $dflt = array(
3238a47c60SMark Prins        'id'            => 'olmap',
3338a47c60SMark Prins        'width'         => '550px',
3438a47c60SMark Prins        'height'        => '450px',
3538a47c60SMark Prins        'lat'           => 50.0,
3638a47c60SMark Prins        'lon'           => 5.1,
3738a47c60SMark Prins        'zoom'          => 12,
38c8eb1362SMark Prins        'autozoom'      => 1,
3938a47c60SMark Prins        'statusbar'     => true,
40c8eb1362SMark Prins        'toolbar'       => true,
4138a47c60SMark Prins        'controls'      => true,
4238a47c60SMark Prins        'poihoverstyle' => false,
4338a47c60SMark Prins        'baselyr'       => 'OpenStreetMap',
4438a47c60SMark Prins        'gpxfile'       => '',
4545c50327SMark Prins        'kmlfile'       => '',
466914b920SMark Prins        'geojsonfile'   => '',
4745c50327SMark Prins        'summary'       => ''
4838a47c60SMark Prins    );
4938a47c60SMark Prins
5038a47c60SMark Prins    /**
511c640875SMark Prins     *
52cc74a83cSMark Prins     * @see DokuWiki_Syntax_Plugin::getType()
5338a47c60SMark Prins     */
54*57f8d5bbSMark Prins    public function getType(): string {
5575c98788SMark Prins        return 'substition';
5675c98788SMark Prins    }
5738a47c60SMark Prins
5838a47c60SMark Prins    /**
591c640875SMark Prins     *
60cc74a83cSMark Prins     * @see DokuWiki_Syntax_Plugin::getPType()
6138a47c60SMark Prins     */
62*57f8d5bbSMark Prins    public function getPType(): string {
6375c98788SMark Prins        return 'block';
6475c98788SMark Prins    }
6538a47c60SMark Prins
6638a47c60SMark Prins    /**
671c640875SMark Prins     *
68cc74a83cSMark Prins     * @see Doku_Parser_Mode::getSort()
6938a47c60SMark Prins     */
70*57f8d5bbSMark Prins    public function getSort(): int {
7175c98788SMark Prins        return 901;
7275c98788SMark Prins    }
73fc16f3cdSMark Prins
7438a47c60SMark Prins    /**
751c640875SMark Prins     *
76cc74a83cSMark Prins     * @see Doku_Parser_Mode::connectTo()
7738a47c60SMark Prins     */
78*57f8d5bbSMark Prins    public function connectTo($mode) {
79*57f8d5bbSMark Prins        $this->Lexer->addSpecialPattern(
80*57f8d5bbSMark Prins            '<olmap ?[^>\n]*>.*?</olmap>', $mode,
81*57f8d5bbSMark Prins            'plugin_openlayersmap_olmap'
82*57f8d5bbSMark Prins        );
8338a47c60SMark Prins    }
84fc16f3cdSMark Prins
8538a47c60SMark Prins    /**
861c640875SMark Prins     *
87cc74a83cSMark Prins     * @see DokuWiki_Syntax_Plugin::handle()
8838a47c60SMark Prins     */
89*57f8d5bbSMark Prins    public function handle($match, $state, $pos, Doku_Handler $handler): array {
9038a47c60SMark Prins        // break matched cdata into its components
9138a47c60SMark Prins        list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
92554f43b5SMark Prins        // get the lat/lon for adding them to the metadata (used by geotag)
93d2f4772aSMark Prins        preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat);
94d2f4772aSMark Prins        preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon);
95554f43b5SMark Prins        $mainLat = substr($mainLat [0], 5, -1);
96554f43b5SMark Prins        $mainLon = substr($mainLon [0], 5, -1);
97d2f4772aSMark Prins        if(!is_numeric($mainLat)) {
98d2f4772aSMark Prins            $mainLat = $this->dflt ['lat'];
99d2f4772aSMark Prins        }
100d2f4772aSMark Prins        if(!is_numeric($mainLon)) {
101d2f4772aSMark Prins            $mainLon = $this->dflt ['lon'];
102d2f4772aSMark Prins        }
10338a47c60SMark Prins
104*57f8d5bbSMark Prins        $gmap          = $this->extractParams($str_params);
105*57f8d5bbSMark Prins        $overlay       = $this->extractPoints($str_points);
106fc16f3cdSMark Prins        $_firstimageID = '';
10738a47c60SMark Prins
1088e7c4263SMark Prins        $_nocache = false;
109807d36baSMark Prins        // choose maptype based on the specified tag
110628e43ccSMark Prins        $imgUrl = "{{";
111585afb49SMark Prins        if(stripos($gmap ['baselyr'], 'google') !== false) {
1128e7c4263SMark Prins            // Google
113*57f8d5bbSMark Prins            $imgUrl .= $this->getGoogle($gmap, $overlay);
1148e7c4263SMark Prins            $imgUrl .= "&.png";
115585afb49SMark Prins        } elseif(stripos($gmap ['baselyr'], 'bing') !== false) {
1168e7c4263SMark Prins            // Bing
117d974ea02SMark Prins            if(!$this->getConf('bingAPIKey')) {
118d974ea02SMark Prins                // in case there is no Bing api key we'll use OSM
119*57f8d5bbSMark Prins                $_firstimageID = $this->getStaticOSM($gmap, $overlay);
120d974ea02SMark Prins                $imgUrl        .= $_firstimageID;
121628e43ccSMark Prins                if($this->getConf('optionStaticMapGenerator') == 'remote') {
122628e43ccSMark Prins                    $imgUrl .= "&.png";
123d974ea02SMark Prins                }
124d974ea02SMark Prins            } else {
1258e7c4263SMark Prins                // seems that Bing doesn't like the DW client, turn off caching
1268e7c4263SMark Prins                $_nocache = true;
127*57f8d5bbSMark Prins                $imgUrl   .= $this->getBing($gmap, $overlay) . "&.png";
128d974ea02SMark Prins            }
129e72390dbSMark Prins        } /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) {
1308e7c4263SMark Prins            // MapQuest
1318e7c4263SMark Prins            if (! $this->getConf ( 'mapquestAPIKey' )) {
1328e7c4263SMark Prins                // no API key for MapQuest, use OSM
133*57f8d5bbSMark Prins                $_firstimageID = $this->getStaticOSM ( $gmap, $overlay );
134fc16f3cdSMark Prins                $imgUrl .= $_firstimageID;
1358e7c4263SMark Prins                if ($this->getConf ( 'optionStaticMapGenerator' ) == 'remote') {
1368e7c4263SMark Prins                    $imgUrl .= "&.png";
137628e43ccSMark Prins                }
13863037f21SMark Prins            } else {
1398e7c4263SMark Prins                $imgUrl .= $this->_getMapQuest ( $gmap, $overlay );
1408e7c4263SMark Prins                $imgUrl .= "&.png";
1418e7c4263SMark Prins            }
142e72390dbSMark Prins        } */ else {
1438e7c4263SMark Prins            // default OSM
144*57f8d5bbSMark Prins            $_firstimageID = $this->getStaticOSM($gmap, $overlay);
145fc16f3cdSMark Prins            $imgUrl        .= $_firstimageID;
14653bfe4a3SMark Prins            if($this->getConf('optionStaticMapGenerator') == 'remote') {
14753bfe4a3SMark Prins                $imgUrl .= "&.png";
14853bfe4a3SMark Prins            }
14987d958d4SMark Prins        }
15087d958d4SMark Prins
151628e43ccSMark Prins        // append dw p_render specific params and render
152*57f8d5bbSMark Prins        $imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x"
153*57f8d5bbSMark Prins            . str_replace("px", "", $gmap ['height']);
1546ba8d085SMark Prins        $imgUrl .= "&nolink";
1558e7c4263SMark Prins
1568e7c4263SMark Prins        // add nocache option for selected services
1578e7c4263SMark Prins        if($_nocache) {
1588e7c4263SMark Prins            $imgUrl .= "&nocache";
1598e7c4263SMark Prins        }
1608e7c4263SMark Prins
161fcd79b50SMark Prins        $imgUrl .= " |" . $gmap ['summary'] . " }}";
162fcd79b50SMark Prins
1638e7c4263SMark Prins        // dbglog($imgUrl,"complete image tags is:");
1648e7c4263SMark Prins
16538a47c60SMark Prins        $mapid = $gmap ['id'];
16638a47c60SMark Prins        // create a javascript parameter string for the map
16738a47c60SMark Prins        $param = '';
16838a47c60SMark Prins        foreach($gmap as $key => $val) {
16938a47c60SMark Prins            $param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
17038a47c60SMark Prins        }
17138a47c60SMark Prins        if(!empty ($param)) {
17245c50327SMark Prins            $param = substr($param, 0, -2);
17338a47c60SMark Prins        }
17438a47c60SMark Prins        unset ($gmap ['id']);
17538a47c60SMark Prins
17638a47c60SMark Prins        // create a javascript serialisation of the point data
17738a47c60SMark Prins        $poi      = '';
17845c50327SMark Prins        $poitable = '';
17945c50327SMark Prins        $rowId    = 0;
18038a47c60SMark Prins        if(!empty ($overlay)) {
18138a47c60SMark Prins            foreach($overlay as $data) {
18238a47c60SMark Prins                list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
18345c50327SMark Prins                $rowId++;
18445c50327SMark Prins                $poi .= ", {lat:$lat,lon:$lon,txt:'$text',angle:$angle,opacity:$opacity,img:'$img',rowId: $rowId}";
1858c4eb2fdSMark Prins
1868c4eb2fdSMark Prins                if($this->getConf('displayformat') === 'DMS') {
1878c4eb2fdSMark Prins                    $lat = $this->convertLat($lat);
1888c4eb2fdSMark Prins                    $lon = $this->convertLon($lon);
1898c4eb2fdSMark Prins                } else {
1908c4eb2fdSMark Prins                    $lat .= 'º';
1918c4eb2fdSMark Prins                    $lon .= 'º';
1928c4eb2fdSMark Prins                }
1938c4eb2fdSMark Prins
194a757236dSMark Prins                $poitable .= '
195a757236dSMark Prins                    <tr>
196a757236dSMark Prins                    <td class="rowId">' . $rowId . '</td>
197*57f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/icons/' . $img . '" alt="'
198*57f8d5bbSMark Prins                    . substr($img, 0, -4) . $this->getlang('alt_legend_poi') . '" /></td>
199a57aaf07SMark Prins                    <td class="lat" title="' . $this->getLang('olmapPOIlatTitle') . '">' . $lat . '</td>
200a57aaf07SMark Prins                    <td class="lon" title="' . $this->getLang('olmapPOIlonTitle') . '">' . $lon . '</td>
201a757236dSMark Prins                    <td class="txt">' . $text . '</td>
202a757236dSMark Prins                    </tr>';
20338a47c60SMark Prins            }
20445c50327SMark Prins            $poi = substr($poi, 2);
20538a47c60SMark Prins        }
206e61425c7SMark Prins        if(!empty ($gmap ['kmlfile'])) {
207e61425c7SMark Prins            $poitable .= '
208e61425c7SMark Prins                    <tr>
209*57f8d5bbSMark Prins                    <td class="rowId"><img src="' . DOKU_BASE
210*57f8d5bbSMark Prins                . 'lib/plugins/openlayersmap/toolbar/kml_file.png" alt="KML file" /></td>
211*57f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/toolbar/kml_line.png" alt="'
212*57f8d5bbSMark Prins                . $this->getlang('alt_legend_kml') . '" /></td>
213cc74a83cSMark Prins                    <td class="txt" colspan="3">KML track: ' . $this->getFileName($gmap ['kmlfile']) . '</td>
214e61425c7SMark Prins                    </tr>';
215e61425c7SMark Prins        }
216e61425c7SMark Prins        if(!empty ($gmap ['gpxfile'])) {
217e61425c7SMark Prins            $poitable .= '
218e61425c7SMark Prins                    <tr>
219*57f8d5bbSMark Prins                    <td class="rowId"><img src="' . DOKU_BASE
220*57f8d5bbSMark Prins                . 'lib/plugins/openlayersmap/toolbar/gpx_file.png" alt="GPX file" /></td>
221*57f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE
222*57f8d5bbSMark Prins                . 'lib/plugins/openlayersmap/toolbar/gpx_line.png" alt="'
223*57f8d5bbSMark Prins                . $this->getlang('alt_legend_gpx') . '" /></td>
224cc74a83cSMark Prins                    <td class="txt" colspan="3">GPX track: ' . $this->getFileName($gmap ['gpxfile']) . '</td>
225e61425c7SMark Prins                    </tr>';
226e61425c7SMark Prins        }
2276914b920SMark Prins        if(!empty ($gmap ['geojsonfile'])) {
2286914b920SMark Prins            $poitable .= '
2296914b920SMark Prins                    <tr>
230*57f8d5bbSMark Prins                    <td class="rowId"><img src="' . DOKU_BASE
231*57f8d5bbSMark Prins                . 'lib/plugins/openlayersmap/toolbar/geojson_file.png" alt="GeoJSON file" /></td>
232*57f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE
233*57f8d5bbSMark Prins                . 'lib/plugins/openlayersmap/toolbar/geojson_line.png" alt="'
234*57f8d5bbSMark Prins                . $this->getlang('alt_legend_geojson') . '" /></td>
2356914b920SMark Prins                    <td class="txt" colspan="3">GeoJSON track: ' . $this->getFileName($gmap ['geojsonfile']) . '</td>
2366914b920SMark Prins                    </tr>';
2376914b920SMark Prins        }
238e61425c7SMark Prins
239c8eb1362SMark Prins        $autozoom = empty ($gmap ['autozoom']) ? $this->getConf('autoZoomMap') : $gmap ['autozoom'];
240*57f8d5bbSMark Prins        $js       = "{mapOpts: {" . $param . ", displayformat: '" . $this->getConf('displayformat')
241*57f8d5bbSMark Prins            . "', autozoom: " . $autozoom . "}, poi: [$poi]};";
242a757236dSMark Prins        // unescape the json
243a757236dSMark Prins        $poitable = stripslashes($poitable);
24438a47c60SMark Prins
2451c640875SMark Prins        return array(
2461c640875SMark Prins            $mapid,
2471c640875SMark Prins            $js,
2481c640875SMark Prins            $mainLat,
2491c640875SMark Prins            $mainLon,
2501c640875SMark Prins            $poitable,
2511c640875SMark Prins            $gmap ['summary'],
2521c640875SMark Prins            $imgUrl,
2531c640875SMark Prins            $_firstimageID
2541c640875SMark Prins        );
25538a47c60SMark Prins    }
25638a47c60SMark Prins
25738a47c60SMark Prins    /**
25838a47c60SMark Prins     * extract parameters for the map from the parameter string
25938a47c60SMark Prins     *
2601c640875SMark Prins     * @param string $str_params
2611c640875SMark Prins     *            string of key="value" pairs
26238a47c60SMark Prins     * @return array associative array of parameters key=>value
26338a47c60SMark Prins     */
264*57f8d5bbSMark Prins    private function extractParams(string $str_params): array {
26538a47c60SMark Prins        $param = array();
26638a47c60SMark Prins        preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
26738a47c60SMark Prins        // parse match for instructions, break into key value pairs
26838a47c60SMark Prins        $gmap = $this->dflt;
269c8eb1362SMark Prins        foreach($gmap as $key => &$value) {
270c8eb1362SMark Prins            $defval = $this->getConf('default_' . $key);
271c8eb1362SMark Prins            if($defval !== '') {
272c8eb1362SMark Prins                $value = $defval;
273c8eb1362SMark Prins            }
274c8eb1362SMark Prins        }
275c8eb1362SMark Prins        unset ($value);
27638a47c60SMark Prins        foreach($param as $kvpair) {
27738a47c60SMark Prins            list ($match, $key, $val) = $kvpair;
27838a47c60SMark Prins            $key = strtolower($key);
27938a47c60SMark Prins            if(isset ($gmap [$key])) {
28045c50327SMark Prins                if($key == 'summary') {
28145c50327SMark Prins                    // preserve case for summary field
28245c50327SMark Prins                    $gmap [$key] = $val;
2831c640875SMark Prins                } elseif($key == 'id') {
2841c640875SMark Prins                    // preserve case for id field
2851c640875SMark Prins                    $gmap [$key] = $val;
28645c50327SMark Prins                } else {
28738a47c60SMark Prins                    $gmap [$key] = strtolower($val);
28838a47c60SMark Prins                }
28938a47c60SMark Prins            }
29045c50327SMark Prins        }
29138a47c60SMark Prins        return $gmap;
29238a47c60SMark Prins    }
29338a47c60SMark Prins
29438a47c60SMark Prins    /**
29538a47c60SMark Prins     * extract overlay points for the map from the wiki syntax data
29638a47c60SMark Prins     *
2971c640875SMark Prins     * @param string $str_points
2981c640875SMark Prins     *            multi-line string of lat,lon,text triplets
29938a47c60SMark Prins     * @return array multi-dimensional array of lat,lon,text triplets
30038a47c60SMark Prins     */
301*57f8d5bbSMark Prins    private function extractPoints(string $str_points): array {
30238a47c60SMark Prins        $point = array();
303*57f8d5bbSMark Prins        // preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um',
304*57f8d5bbSMark Prins        //      $str_points, $point, PREG_SET_ORDER);
3057a3f422cSMark Prins        /*
306*57f8d5bbSMark Prins         * group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
307*57f8d5bbSMark Prins         * group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
308*57f8d5bbSMark Prins         * group 3: (.*?)
309*57f8d5bbSMark Prins         * group 4: (.*?)
310*57f8d5bbSMark Prins         * group 5: (.*?)
311*57f8d5bbSMark Prins         * group 6: (.*)
3127a3f422cSMark Prins         */
313*57f8d5bbSMark Prins        preg_match_all(
314*57f8d5bbSMark Prins            '/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um',
315*57f8d5bbSMark Prins            $str_points, $point, PREG_SET_ORDER
316*57f8d5bbSMark Prins        );
317554f43b5SMark Prins        // create poi array
31838a47c60SMark Prins        $overlay = array();
31938a47c60SMark Prins        foreach($point as $pt) {
32038a47c60SMark Prins            list ($match, $lat, $lon, $angle, $opacity, $img, $text) = $pt;
32138a47c60SMark Prins            $lat     = is_numeric($lat) ? $lat : 0;
32238a47c60SMark Prins            $lon     = is_numeric($lon) ? $lon : 0;
32338a47c60SMark Prins            $angle   = is_numeric($angle) ? $angle : 0;
32438a47c60SMark Prins            $opacity = is_numeric($opacity) ? $opacity : 0.8;
32587d958d4SMark Prins            // TODO validate using exist & set up default img?
3261c640875SMark Prins            $img  = trim($img);
3271c640875SMark Prins            $text = p_get_instructions($text);
3281c640875SMark Prins            // dbg ( $text );
3291c640875SMark Prins            $text = p_render("xhtml", $text, $info);
3301c640875SMark Prins            // dbg ( $text );
3311c640875SMark Prins            $text       = addslashes(str_replace("\n", "", $text));
3321c640875SMark Prins            $overlay [] = array(
3331c640875SMark Prins                $lat,
3341c640875SMark Prins                $lon,
3351c640875SMark Prins                $text,
3361c640875SMark Prins                $angle,
3371c640875SMark Prins                $opacity,
3381c640875SMark Prins                $img
3391c640875SMark Prins            );
34038a47c60SMark Prins        }
34138a47c60SMark Prins        return $overlay;
34238a47c60SMark Prins    }
343fcd79b50SMark Prins
344fcd79b50SMark Prins    /**
345*57f8d5bbSMark Prins     * Create a Google maps static image url w/ the poi.
346*57f8d5bbSMark Prins     *
347*57f8d5bbSMark Prins     * @param array $gmap
348*57f8d5bbSMark Prins     * @param array $overlay
349*57f8d5bbSMark Prins     * @return string
350*57f8d5bbSMark Prins     */
351*57f8d5bbSMark Prins    private function getGoogle(array $gmap, array $overlay): string {
352*57f8d5bbSMark Prins        $sUrl = $this->getConf('iconUrlOverload');
353*57f8d5bbSMark Prins        if(!$sUrl) {
354*57f8d5bbSMark Prins            $sUrl = DOKU_URL;
355*57f8d5bbSMark Prins        }
356*57f8d5bbSMark Prins        switch($gmap ['baselyr']) {
357*57f8d5bbSMark Prins            case 'google hybrid' :
358*57f8d5bbSMark Prins                $maptype = 'hybrid';
359*57f8d5bbSMark Prins                break;
360*57f8d5bbSMark Prins            case 'google sat' :
361*57f8d5bbSMark Prins                $maptype = 'satellite';
362*57f8d5bbSMark Prins                break;
363*57f8d5bbSMark Prins            case 'terrain' :
364*57f8d5bbSMark Prins            case 'google relief' :
365*57f8d5bbSMark Prins                $maptype = 'terrain';
366*57f8d5bbSMark Prins                break;
367*57f8d5bbSMark Prins            case 'google road' :
368*57f8d5bbSMark Prins            default :
369*57f8d5bbSMark Prins                $maptype = 'roadmap';
370*57f8d5bbSMark Prins                break;
371*57f8d5bbSMark Prins        }
372*57f8d5bbSMark Prins        // TODO maybe use viewport / visible instead of center/zoom,
373*57f8d5bbSMark Prins        // see: https://developers.google.com/maps/documentation/staticmaps/index#Viewports
374*57f8d5bbSMark Prins        // 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
375*57f8d5bbSMark Prins        $imgUrl = "https://maps.googleapis.com/maps/api/staticmap?";
376*57f8d5bbSMark Prins        $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
377*57f8d5bbSMark Prins            . str_replace("px", "", $gmap ['height']);
378*57f8d5bbSMark Prins        //if (!$this->getConf( 'autoZoomMap')) { // no need for center & zoom params }
379*57f8d5bbSMark Prins        $imgUrl .= "&center=" . $gmap ['lat'] . "," . $gmap ['lon'];
380*57f8d5bbSMark Prins        // max is 21 (== building scale), but that's overkill..
381*57f8d5bbSMark Prins        if($gmap ['zoom'] > 17) {
382*57f8d5bbSMark Prins            $imgUrl .= "&zoom=17";
383*57f8d5bbSMark Prins        } else {
384*57f8d5bbSMark Prins            $imgUrl .= "&zoom=" . $gmap ['zoom'];
385*57f8d5bbSMark Prins        }
386*57f8d5bbSMark Prins        if(!empty ($overlay)) {
387*57f8d5bbSMark Prins            $rowId = 0;
388*57f8d5bbSMark Prins            foreach($overlay as $data) {
389*57f8d5bbSMark Prins                list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
390*57f8d5bbSMark Prins                $imgUrl .= "&markers=icon%3a" . $sUrl . "lib/plugins/openlayersmap/icons/" . $img . "%7c"
391*57f8d5bbSMark Prins                    . $lat . "," . $lon . "%7clabel%3a" . ++$rowId;
392*57f8d5bbSMark Prins            }
393*57f8d5bbSMark Prins        }
394*57f8d5bbSMark Prins        $imgUrl .= "&format=png&maptype=" . $maptype;
395*57f8d5bbSMark Prins        global $conf;
396*57f8d5bbSMark Prins        $imgUrl .= "&language=" . $conf ['lang'];
397*57f8d5bbSMark Prins        if($this->getConf('googleAPIkey')) {
398*57f8d5bbSMark Prins            $imgUrl .= "&key=" . $this->getConf('googleAPIkey');
399*57f8d5bbSMark Prins        }
400*57f8d5bbSMark Prins        // dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::getGoogle: Google image url is:');
401*57f8d5bbSMark Prins        return $imgUrl;
402*57f8d5bbSMark Prins    }
403*57f8d5bbSMark Prins
404*57f8d5bbSMark Prins    /**
405fcd79b50SMark Prins     * Create a MapQuest static map API image url.
4061c640875SMark Prins     *
407fcd79b50SMark Prins     * @param array $gmap
408fcd79b50SMark Prins     * @param array $overlay
409fcd79b50SMark Prins     */
410e72390dbSMark Prins    /*
411fcd79b50SMark Prins   private function _getMapQuest($gmap, $overlay) {
412787a5195SMark Prins       $sUrl = $this->getConf ( 'iconUrlOverload' );
413787a5195SMark Prins       if (! $sUrl) {
414787a5195SMark Prins           $sUrl = DOKU_URL;
415787a5195SMark Prins       }
41687d958d4SMark Prins       switch ($gmap ['baselyr']) {
41794c2e868SMark Prins           case 'mapquest hybrid' :
418837eba2fSMark Prins               $maptype = 'hyb';
41987d958d4SMark Prins               break;
42018edeaa5SMark Prins           case 'mapquest sat' :
42144aba0bcSMark Prins               // because sat coverage is very limited use 'hyb' instead of 'sat' so we don't get a blank map
42244aba0bcSMark Prins               $maptype = 'hyb';
42387d958d4SMark Prins               break;
42494c2e868SMark Prins           case 'mapquest road' :
42587d958d4SMark Prins           default :
42687d958d4SMark Prins               $maptype = 'map';
42787d958d4SMark Prins               break;
42887d958d4SMark Prins       }
429004ad4e2SMark Prins       $imgUrl = "http://open.mapquestapi.com/staticmap/v4/getmap?declutter=true&";
43044aba0bcSMark Prins       if (count ( $overlay ) < 1) {
431787a5195SMark Prins           $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
432787a5195SMark Prins           // max level for mapquest is 16
433fcd79b50SMark Prins           if ($gmap ['zoom'] > 16) {
434fcd79b50SMark Prins               $imgUrl .= "&zoom=16";
435fcd79b50SMark Prins           } else {
436fcd79b50SMark Prins               $imgUrl .= "&zoom=" . $gmap ['zoom'];
437fcd79b50SMark Prins           }
43844aba0bcSMark Prins       }
43944aba0bcSMark Prins       // use bestfit instead of center/zoom, needs upperleft/lowerright corners
440*57f8d5bbSMark Prins       // $bbox=$this->calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
44144aba0bcSMark Prins       // $imgUrl .= "bestfit=".$bbox['minlat'].",".$bbox['maxlon'].",".$bbox['maxlat'].",".$bbox['minlon'];
44244aba0bcSMark Prins
443*57f8d5bbSMark Prins       // TODO declutter option works well for square maps but not for rectangular, maybe compensate for that
444*57f8d5bbSMark Prins       //       or compensate the mbr..
445*57f8d5bbSMark Prins
44644aba0bcSMark Prins       $imgUrl .= "&size=" . str_replace ( "px", "", $gmap ['width'] ) . "," . str_replace ("px","",$gmap['height']);
44744aba0bcSMark Prins
448fcd79b50SMark Prins       // TODO mapquest allows using one image url with a multiplier $NUMBER eg:
449fcd79b50SMark Prins       // $NUMBER = 2
450*57f8d5bbSMark Prins       // $imgUrl .= DOKU_URL."/".DOKU_PLUGIN."/".getPluginName()."/icons/".$img.",$NUMBER,C,"
451*57f8d5bbSMark Prins        //  .$lat1.",".$lon1.",0,0,0,0,C,".$lat2.",".$lon2.",0,0,0,0";
452fcd79b50SMark Prins       if (! empty ( $overlay )) {
453fcd79b50SMark Prins           $imgUrl .= "&xis=";
454fcd79b50SMark Prins           foreach ( $overlay as $data ) {
455fcd79b50SMark Prins               list ( $lat, $lon, $text, $angle, $opacity, $img ) = $data;
45644aba0bcSMark Prins               // $imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",0,0,0,0,";
45744aba0bcSMark Prins               $imgUrl .= $sUrl . "lib/plugins/openlayersmap/icons/" . $img . ",1,C," . $lat . "," . $lon . ",";
458fcd79b50SMark Prins           }
459fcd79b50SMark Prins           $imgUrl = substr ( $imgUrl, 0, - 1 );
460fcd79b50SMark Prins       }
46187d958d4SMark Prins       $imgUrl .= "&imageType=png&type=" . $maptype;
462d974ea02SMark Prins       $imgUrl .= "&key=".$this->getConf ( 'mapquestAPIKey' );
4638e7c4263SMark Prins       // dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getMapQuest: MapQuest image url is:');
464787a5195SMark Prins       return $imgUrl;
465787a5195SMark Prins   }
466e72390dbSMark Prins   */
467cc74a83cSMark Prins
4686e633dd6SMark Prins    /**
46987d958d4SMark Prins     * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
470fcf646d2SMark Prins     * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
4711c640875SMark Prins     *
47287d958d4SMark Prins     * @param array $gmap
47387d958d4SMark Prins     * @param array $overlay
474fcf646d2SMark Prins     *
475*57f8d5bbSMark Prins     * @return false|string
476fcf646d2SMark Prins     * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
47787d958d4SMark Prins     */
478*57f8d5bbSMark Prins    private function getStaticOSM(array $gmap, array $overlay) {
479fcf646d2SMark Prins        global $conf;
480372f1508SMark Prins
48153bfe4a3SMark Prins        if($this->getConf('optionStaticMapGenerator') == 'local') {
482d974ea02SMark Prins            // using local basemap composer
483*57f8d5bbSMark Prins            if(!$myMap = plugin_load('helper', 'openlayersmap_staticmap')) {
484*57f8d5bbSMark Prins                dbglog(
485*57f8d5bbSMark Prins                    $myMap,
486*57f8d5bbSMark Prins                    'openlayersmap_staticmap plugin is not available for use.'
487*57f8d5bbSMark Prins                );
48853bfe4a3SMark Prins            }
489*57f8d5bbSMark Prins            if(!$geophp = plugin_load('helper', 'geophp')) {
490*57f8d5bbSMark Prins                dbglog($geophp, 'geophp plugin is not available for use.');
49153bfe4a3SMark Prins            }
492*57f8d5bbSMark Prins            $size = str_replace("px", "", $gmap ['width']) . "x"
493*57f8d5bbSMark Prins                . str_replace("px", "", $gmap ['height']);
49453bfe4a3SMark Prins
4954c9f9dfcSMark Prins            $markers = array();
49653bfe4a3SMark Prins            if(!empty ($overlay)) {
49753bfe4a3SMark Prins                foreach($overlay as $data) {
49853bfe4a3SMark Prins                    list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
49953bfe4a3SMark Prins                    $iconStyle  = substr($img, 0, strlen($img) - 4);
50053bfe4a3SMark Prins                    $markers [] = array(
50153bfe4a3SMark Prins                        'lat'  => $lat,
50253bfe4a3SMark Prins                        'lon'  => $lon,
5031c640875SMark Prins                        'type' => $iconStyle
5041c640875SMark Prins                    );
50553bfe4a3SMark Prins                }
506372f1508SMark Prins            }
507372f1508SMark Prins
508d2f4772aSMark Prins            $apikey = '';
50918edeaa5SMark Prins            switch($gmap ['baselyr']) {
51018edeaa5SMark Prins                case 'mapnik' :
511fcf646d2SMark Prins                case 'openstreetmap' :
512fcf646d2SMark Prins                    $maptype = 'openstreetmap';
51318edeaa5SMark Prins                    break;
514fcf646d2SMark Prins                case 'transport' :
515fcf646d2SMark Prins                    $maptype = 'transport';
516d2f4772aSMark Prins                    $apikey  = $this->getConf('tfApiKey');
517fcf646d2SMark Prins                    break;
518fcf646d2SMark Prins                case 'landscape' :
519fcf646d2SMark Prins                    $maptype = 'landscape';
520d2f4772aSMark Prins                    $apikey  = $this->getConf('tfApiKey');
521d2f4772aSMark Prins                    break;
522d2f4772aSMark Prins                case 'outdoors' :
523d2f4772aSMark Prins                    $maptype = 'outdoors';
524d2f4772aSMark Prins                    $apikey  = $this->getConf('tfApiKey');
52518edeaa5SMark Prins                    break;
52618edeaa5SMark Prins                case 'cycle map' :
52718edeaa5SMark Prins                    $maptype = 'cycle';
528d2f4772aSMark Prins                    $apikey  = $this->getConf('tfApiKey');
529372f1508SMark Prins                    break;
530fcf646d2SMark Prins                case 'hike and bike map' :
531fcf646d2SMark Prins                    $maptype = 'hikeandbike';
532fcf646d2SMark Prins                    break;
533fcf646d2SMark Prins                case 'mapquest hybrid' :
534fcf646d2SMark Prins                case 'mapquest road' :
535fcf646d2SMark Prins                case 'mapquest sat' :
536fcf646d2SMark Prins                    $maptype = 'mapquest';
537fcf646d2SMark Prins                    break;
53818edeaa5SMark Prins                default :
53918edeaa5SMark Prins                    $maptype = '';
54018edeaa5SMark Prins                    break;
54118edeaa5SMark Prins            }
542d974ea02SMark Prins
543*57f8d5bbSMark Prins            $result = $myMap->getMap(
544*57f8d5bbSMark Prins                $gmap ['lat'], $gmap ['lon'], $gmap ['zoom'], $size, $maptype, $markers,
545*57f8d5bbSMark Prins                $gmap ['gpxfile'], $gmap ['kmlfile'], $gmap ['geojsonfile']
546*57f8d5bbSMark Prins            );
547d974ea02SMark Prins        } else {
548d974ea02SMark Prins            // using external basemap composer
549d974ea02SMark Prins
550*57f8d5bbSMark Prins            // https://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10
551*57f8d5bbSMark Prins            //.117187497601&zoom=5&size=500x350
552*57f8d5bbSMark Prins            // &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,
553*57f8d5bbSMark Prins            //  lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,
554*57f8d5bbSMark Prins            //  ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,
555*57f8d5bbSMark Prins            //  ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
556*57f8d5bbSMark Prins            $imgUrl = "https://staticmap.openstreetmap.de/staticmap.php";
557d974ea02SMark Prins            $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
558*57f8d5bbSMark Prins            $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
559*57f8d5bbSMark Prins                . str_replace("px", "", $gmap ['height']);
560d974ea02SMark Prins
561d974ea02SMark Prins            if($gmap ['zoom'] > 16) {
562d974ea02SMark Prins                // actually this could even be 18, but that seems overkill
563d974ea02SMark Prins                $imgUrl .= "&zoom=16";
564d974ea02SMark Prins            } else {
565d974ea02SMark Prins                $imgUrl .= "&zoom=" . $gmap ['zoom'];
566d974ea02SMark Prins            }
56718edeaa5SMark Prins
56887d958d4SMark Prins            if(!empty ($overlay)) {
56987d958d4SMark Prins                $rowId  = 0;
57087d958d4SMark Prins                $imgUrl .= "&markers=";
57187d958d4SMark Prins                foreach($overlay as $data) {
57287d958d4SMark Prins                    list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
57387d958d4SMark Prins                    $rowId++;
57453bfe4a3SMark Prins                    $iconStyle = "lightblue$rowId";
57587d958d4SMark Prins                    $imgUrl    .= "$lat,$lon,$iconStyle%7c";
57687d958d4SMark Prins                }
57787d958d4SMark Prins                $imgUrl = substr($imgUrl, 0, -3);
57887d958d4SMark Prins            }
57987d958d4SMark Prins
580f4b9bdacSMark Prins            $result = $imgUrl;
581628e43ccSMark Prins        }
582*57f8d5bbSMark Prins        // dbglog ( $result, 'syntax_plugin_openlayersmap_olmap::getStaticOSM: osm image url is:' );
583628e43ccSMark Prins        return $result;
584628e43ccSMark Prins    }
585628e43ccSMark Prins
58644aba0bcSMark Prins    /**
587*57f8d5bbSMark Prins     * Create a Bing maps static image url w/ the poi.
588*57f8d5bbSMark Prins     *
589*57f8d5bbSMark Prins     * @param array $gmap
590*57f8d5bbSMark Prins     * @param array $overlay
591*57f8d5bbSMark Prins     * @return string
592*57f8d5bbSMark Prins     */
593*57f8d5bbSMark Prins    private function getBing(array $gmap, array $overlay): string {
594*57f8d5bbSMark Prins        switch($gmap ['baselyr']) {
595*57f8d5bbSMark Prins            case 've hybrid' :
596*57f8d5bbSMark Prins            case 'bing hybrid' :
597*57f8d5bbSMark Prins                $maptype = 'AerialWithLabels';
598*57f8d5bbSMark Prins                break;
599*57f8d5bbSMark Prins            case 've sat' :
600*57f8d5bbSMark Prins            case 'bing sat' :
601*57f8d5bbSMark Prins                $maptype = 'Aerial';
602*57f8d5bbSMark Prins                break;
603*57f8d5bbSMark Prins            case 've normal' :
604*57f8d5bbSMark Prins            case 've road' :
605*57f8d5bbSMark Prins            case 've' :
606*57f8d5bbSMark Prins            case 'bing road' :
607*57f8d5bbSMark Prins            default :
608*57f8d5bbSMark Prins                $maptype = 'Road';
609*57f8d5bbSMark Prins                break;
610*57f8d5bbSMark Prins        }
611*57f8d5bbSMark Prins        $imgUrl = "https://dev.virtualearth.net/REST/v1/Imagery/Map/" . $maptype;// . "/";
612*57f8d5bbSMark Prins        if($this->getConf('autoZoomMap')) {
613*57f8d5bbSMark Prins            $bbox = $this->calcBBOX($overlay, $gmap ['lat'], $gmap ['lon']);
614*57f8d5bbSMark Prins            //$imgUrl .= "?ma=" . $bbox ['minlat'] . "," . $bbox ['minlon'] . ","
615*57f8d5bbSMark Prins            //          . $bbox ['maxlat'] . "," . $bbox ['maxlon'];
616*57f8d5bbSMark Prins            $imgUrl .= "?ma=" . $bbox ['minlat'] . "%2C" . $bbox ['minlon'] . "%2C" . $bbox ['maxlat']
617*57f8d5bbSMark Prins                . "%2C" . $bbox ['maxlon'];
618*57f8d5bbSMark Prins            $imgUrl .= "&dcl=1";
619*57f8d5bbSMark Prins        }
620*57f8d5bbSMark Prins        if(strpos($imgUrl, "?") === false)
621*57f8d5bbSMark Prins            $imgUrl .= "?";
622*57f8d5bbSMark Prins
623*57f8d5bbSMark Prins        //$imgUrl .= "&ms=" . str_replace ( "px", "", $gmap ['width'] ) . ","
624*57f8d5bbSMark Prins        //          . str_replace ( "px", "", $gmap ['height'] );
625*57f8d5bbSMark Prins        $imgUrl .= "&ms=" . str_replace("px", "", $gmap ['width']) . "%2C"
626*57f8d5bbSMark Prins            . str_replace("px", "", $gmap ['height']);
627*57f8d5bbSMark Prins        $imgUrl .= "&key=" . $this->getConf('bingAPIKey');
628*57f8d5bbSMark Prins        if(!empty ($overlay)) {
629*57f8d5bbSMark Prins            $rowId = 0;
630*57f8d5bbSMark Prins            foreach($overlay as $data) {
631*57f8d5bbSMark Prins                list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
632*57f8d5bbSMark Prins                // TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
633*57f8d5bbSMark Prins                $iconStyle = 32;
634*57f8d5bbSMark Prins                $rowId++;
635*57f8d5bbSMark Prins                // NOTE: the max number of pushpins is 18! or we have to use POST
636*57f8d5bbSMark Prins                //  (http://msdn.microsoft.com/en-us/library/ff701724.aspx)
637*57f8d5bbSMark Prins                if($rowId == 18) {
638*57f8d5bbSMark Prins                    break;
639*57f8d5bbSMark Prins                }
640*57f8d5bbSMark Prins                //$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
641*57f8d5bbSMark Prins                $imgUrl .= "&pp=$lat%2C$lon%3B$iconStyle%3B$rowId";
642*57f8d5bbSMark Prins
643*57f8d5bbSMark Prins            }
644*57f8d5bbSMark Prins        }
645*57f8d5bbSMark Prins        global $conf;
646*57f8d5bbSMark Prins        $imgUrl .= "&fmt=png";
647*57f8d5bbSMark Prins        $imgUrl .= "&c=" . $conf ['lang'];
648*57f8d5bbSMark Prins        // dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::getBing: bing image url is:');
649*57f8d5bbSMark Prins        return $imgUrl;
650*57f8d5bbSMark Prins    }
651*57f8d5bbSMark Prins
652*57f8d5bbSMark Prins    /**
65344aba0bcSMark Prins     * Calculate the minimum bbox for a start location + poi.
65444aba0bcSMark Prins     *
6551c640875SMark Prins     * @param array $overlay
6561c640875SMark Prins     *            multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
6571c640875SMark Prins     * @param float $lat
6581c640875SMark Prins     *            latitude for map center
6591c640875SMark Prins     * @param float $lon
6601c640875SMark Prins     *            longitude for map center
661*57f8d5bbSMark Prins     * @return array :float array describing the mbr and center point
66244aba0bcSMark Prins     */
663*57f8d5bbSMark Prins    private function calcBBOX(array $overlay, float $lat, float $lon): array {
6644c9f9dfcSMark Prins        $lats = array($lat);
6654c9f9dfcSMark Prins        $lons = array($lon);
666837eba2fSMark Prins        foreach($overlay as $data) {
667837eba2fSMark Prins            list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
668837eba2fSMark Prins            $lats [] = $lat;
669837eba2fSMark Prins            $lons [] = $lon;
670837eba2fSMark Prins        }
671837eba2fSMark Prins        sort($lats);
672837eba2fSMark Prins        sort($lons);
67344aba0bcSMark Prins        // TODO: make edge/wrap around cases work
67444aba0bcSMark Prins        $centerlat = $lats [0] + ($lats [count($lats) - 1] - $lats [0]);
67544aba0bcSMark Prins        $centerlon = $lons [0] + ($lons [count($lats) - 1] - $lons [0]);
6761c640875SMark Prins        return array(
6771c640875SMark Prins            'minlat'    => $lats [0],
6781c640875SMark Prins            'minlon'    => $lons [0],
6791c640875SMark Prins            'maxlat'    => $lats [count($lats) - 1],
6801c640875SMark Prins            'maxlon'    => $lons [count($lats) - 1],
6811c640875SMark Prins            'centerlat' => $centerlat,
6821c640875SMark Prins            'centerlon' => $centerlon
6831c640875SMark Prins        );
68487d958d4SMark Prins    }
685cc74a83cSMark Prins
686cc74a83cSMark Prins    /**
687*57f8d5bbSMark Prins     * convert latitude in decimal degrees to DMS+hemisphere.
6881c640875SMark Prins     *
689*57f8d5bbSMark Prins     * @param float $decimaldegrees
690*57f8d5bbSMark Prins     * @return string
691*57f8d5bbSMark Prins     * @todo move this into a shared library
692cc74a83cSMark Prins     */
693*57f8d5bbSMark Prins    private function convertLat(float $decimaldegrees): string {
694*57f8d5bbSMark Prins        if(strpos($decimaldegrees, '-') !== false) {
695*57f8d5bbSMark Prins            $latPos = "S";
696*57f8d5bbSMark Prins        } else {
697*57f8d5bbSMark Prins            $latPos = "N";
698*57f8d5bbSMark Prins        }
699*57f8d5bbSMark Prins        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
700*57f8d5bbSMark Prins        return hsc($dms . $latPos);
701cc74a83cSMark Prins    }
7028c4eb2fdSMark Prins
7038c4eb2fdSMark Prins    /**
7048c4eb2fdSMark Prins     * Convert decimal degrees to degrees, minutes, seconds format
7058c4eb2fdSMark Prins     *
7068c4eb2fdSMark Prins     * @param float $decimaldegrees
7078c4eb2fdSMark Prins     * @return string dms
708*57f8d5bbSMark Prins     * @todo move this into a shared library
7098c4eb2fdSMark Prins     */
710*57f8d5bbSMark Prins    private function convertDDtoDMS(float $decimaldegrees): string {
7118c4eb2fdSMark Prins        $dms  = floor($decimaldegrees);
7128c4eb2fdSMark Prins        $secs = ($decimaldegrees - $dms) * 3600;
7138c4eb2fdSMark Prins        $min  = floor($secs / 60);
7148c4eb2fdSMark Prins        $sec  = round($secs - ($min * 60), 3);
7158c4eb2fdSMark Prins        $dms  .= 'º' . $min . '\'' . $sec . '"';
7168c4eb2fdSMark Prins        return $dms;
7178c4eb2fdSMark Prins    }
7188c4eb2fdSMark Prins
7198c4eb2fdSMark Prins    /**
7208c4eb2fdSMark Prins     * convert longitude in decimal degrees to DMS+hemisphere.
7218c4eb2fdSMark Prins     *
7228c4eb2fdSMark Prins     * @param float $decimaldegrees
7238c4eb2fdSMark Prins     * @return string
724*57f8d5bbSMark Prins     * @todo move this into a shared library
7258c4eb2fdSMark Prins     */
726*57f8d5bbSMark Prins    private function convertLon(float $decimaldegrees): string {
7278c4eb2fdSMark Prins        if(strpos($decimaldegrees, '-') !== false) {
7288c4eb2fdSMark Prins            $lonPos = "W";
7298c4eb2fdSMark Prins        } else {
7308c4eb2fdSMark Prins            $lonPos = "E";
7318c4eb2fdSMark Prins        }
732*57f8d5bbSMark Prins        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
7338c4eb2fdSMark Prins        return hsc($dms . $lonPos);
7348c4eb2fdSMark Prins    }
735*57f8d5bbSMark Prins
736*57f8d5bbSMark Prins    /**
737*57f8d5bbSMark Prins     * Figures out the base filename of a media path.
738*57f8d5bbSMark Prins     *
739*57f8d5bbSMark Prins     * @param string $mediaLink
740*57f8d5bbSMark Prins     * @return string
741*57f8d5bbSMark Prins     */
742*57f8d5bbSMark Prins    private function getFileName(string $mediaLink): string {
743*57f8d5bbSMark Prins        $mediaLink = str_replace('[[', '', $mediaLink);
744*57f8d5bbSMark Prins        $mediaLink = str_replace(']]', '', $mediaLink);
745*57f8d5bbSMark Prins        $mediaLink = substr($mediaLink, 0, -4);
746*57f8d5bbSMark Prins        $parts     = explode(':', $mediaLink);
747*57f8d5bbSMark Prins        $mediaLink = end($parts);
748*57f8d5bbSMark Prins        return str_replace('_', ' ', $mediaLink);
749*57f8d5bbSMark Prins    }
750*57f8d5bbSMark Prins
751*57f8d5bbSMark Prins    /**
752*57f8d5bbSMark Prins     *
753*57f8d5bbSMark Prins     * @see DokuWiki_Syntax_Plugin::render()
754*57f8d5bbSMark Prins     */
755*57f8d5bbSMark Prins    public function render($format, Doku_Renderer $renderer, $data): bool {
756*57f8d5bbSMark Prins        // set to true after external scripts tags are written
757*57f8d5bbSMark Prins        static $initialised = false;
758*57f8d5bbSMark Prins        // incremented for each map tag in the page source so we can keep track of each map in this page
759*57f8d5bbSMark Prins        static $mapnumber = 0;
760*57f8d5bbSMark Prins
761*57f8d5bbSMark Prins        // dbglog($data, 'olmap::render() data.');
762*57f8d5bbSMark Prins        list ($mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage) = $data;
763*57f8d5bbSMark Prins
764*57f8d5bbSMark Prins        if($format == 'xhtml') {
765*57f8d5bbSMark Prins            $olscript     = '';
766*57f8d5bbSMark Prins            $olEnable     = false;
767*57f8d5bbSMark Prins            $gscript      = '';
768*57f8d5bbSMark Prins            $gEnable      = $this->getConf('enableGoogle');
769*57f8d5bbSMark Prins            $stamenEnable = $this->getConf('enableStamen');
770*57f8d5bbSMark Prins            $osmEnable    = $this->getConf('enableOSM');
771*57f8d5bbSMark Prins            $enableBing   = $this->getConf('enableBing');
772*57f8d5bbSMark Prins
773*57f8d5bbSMark Prins            $scriptEnable = '';
774*57f8d5bbSMark Prins            if(!$initialised) {
775*57f8d5bbSMark Prins                $initialised = true;
776*57f8d5bbSMark Prins                // render necessary script tags
777*57f8d5bbSMark Prins                if($gEnable) {
778*57f8d5bbSMark Prins                    $gscript = '<script defer="defer" src="//maps.google.com/maps/api/js?v=3.29&amp;key='
779*57f8d5bbSMark Prins                        . $this->getConf('googleAPIkey') . '"></script>';
780*57f8d5bbSMark Prins                }
781*57f8d5bbSMark Prins                $olscript = '<script defer="defer" src="' . DOKU_BASE
782*57f8d5bbSMark Prins                    . 'lib/plugins/openlayersmap/lib/OpenLayers.js"></script>';
783*57f8d5bbSMark Prins
784*57f8d5bbSMark Prins                $scriptEnable = '<script defer="defer" src="data:text/javascript;base64,';
785*57f8d5bbSMark Prins                $scriptSrc    = $olscript ? 'olEnable = true;' : 'olEnable = false;';
786*57f8d5bbSMark Prins                $scriptSrc    .= 'gEnable = ' . ($gEnable ? 'true' : 'false') . ';';
787*57f8d5bbSMark Prins                $scriptSrc    .= 'osmEnable = ' . ($osmEnable ? 'true' : 'false') . ';';
788*57f8d5bbSMark Prins                $scriptSrc    .= 'stamenEnable = ' . ($stamenEnable ? 'true' : 'false') . ';';
789*57f8d5bbSMark Prins                $scriptSrc    .= 'bEnable = ' . ($enableBing ? 'true' : 'false') . ';';
790*57f8d5bbSMark Prins                $scriptSrc    .= 'bApiKey="' . $this->getConf('bingAPIKey') . '";';
791*57f8d5bbSMark Prins                $scriptSrc    .= 'tfApiKey="' . $this->getConf('tfApiKey') . '";';
792*57f8d5bbSMark Prins                $scriptSrc    .= 'gApiKey="' . $this->getConf('googleAPIkey') . '";';
793*57f8d5bbSMark Prins                $scriptEnable .= base64_encode($scriptSrc);
794*57f8d5bbSMark Prins                $scriptEnable .= '"></script>';
795*57f8d5bbSMark Prins            }
796*57f8d5bbSMark Prins            $renderer->doc .= "$gscript\n$olscript\n$scriptEnable";
797*57f8d5bbSMark Prins            $renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>';
798*57f8d5bbSMark Prins            if($this->getConf('enableA11y')) {
799*57f8d5bbSMark Prins                $renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">'
800*57f8d5bbSMark Prins                    . p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
801*57f8d5bbSMark Prins            }
802*57f8d5bbSMark Prins            $renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p>&nbsp;</p></div>';
803*57f8d5bbSMark Prins            if($this->getConf('enableA11y')) {
804*57f8d5bbSMark Prins                // render a table of the POI for the print and a11y presentation, it is hidden using javascript
805*57f8d5bbSMark Prins                $renderer->doc .= '<div class="olPOItableSpan" id="' . $mapid . '-table-span">
806*57f8d5bbSMark Prins                    <table class="olPOItable" id="' . $mapid . '-table">
807*57f8d5bbSMark Prins                    <caption class="olPOITblCaption">' . $this->getLang('olmapPOItitle') . '</caption>
808*57f8d5bbSMark Prins                    <thead class="olPOITblHeader">
809*57f8d5bbSMark Prins                    <tr>
810*57f8d5bbSMark Prins                    <th class="rowId" scope="col">id</th>
811*57f8d5bbSMark Prins                    <th class="icon" scope="col">' . $this->getLang('olmapPOIicon') . '</th>
812*57f8d5bbSMark Prins                    <th class="lat" scope="col" title="' . $this->getLang('olmapPOIlatTitle') . '">'
813*57f8d5bbSMark Prins                    . $this->getLang('olmapPOIlat') . '</th>
814*57f8d5bbSMark Prins                    <th class="lon" scope="col" title="' . $this->getLang('olmapPOIlonTitle') . '">'
815*57f8d5bbSMark Prins                    . $this->getLang('olmapPOIlon') . '</th>
816*57f8d5bbSMark Prins                    <th class="txt" scope="col">' . $this->getLang('olmapPOItxt') . '</th>
817*57f8d5bbSMark Prins                    </tr>
818*57f8d5bbSMark Prins                    </thead>';
819*57f8d5bbSMark Prins                if($poitabledesc != '') {
820*57f8d5bbSMark Prins                    $renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc
821*57f8d5bbSMark Prins                        . '</td></tr></tfoot>';
822*57f8d5bbSMark Prins                }
823*57f8d5bbSMark Prins                $renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody>
824*57f8d5bbSMark Prins                    </table></div>';
825*57f8d5bbSMark Prins            }
826*57f8d5bbSMark Prins            // render inline mapscript parts
827*57f8d5bbSMark Prins            $renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,';
828*57f8d5bbSMark Prins            $renderer->doc .= base64_encode("olMapData[$mapnumber] = $param");
829*57f8d5bbSMark Prins            $renderer->doc .= '"></script>';
830*57f8d5bbSMark Prins            $mapnumber++;
831*57f8d5bbSMark Prins            return true;
832*57f8d5bbSMark Prins        } elseif($format == 'metadata') {
833*57f8d5bbSMark Prins            if(!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) {
834*57f8d5bbSMark Prins                // render geo metadata, unless they are the default
835*57f8d5bbSMark Prins                $renderer->meta ['geo'] ['lat'] = $mainLat;
836*57f8d5bbSMark Prins                $renderer->meta ['geo'] ['lon'] = $mainLon;
837*57f8d5bbSMark Prins                if($geophp = plugin_load('helper', 'geophp')) {
838*57f8d5bbSMark Prins                    // if we have the geoPHP helper, add the geohash
839*57f8d5bbSMark Prins
840*57f8d5bbSMark Prins                    // fails with older php versions..
841*57f8d5bbSMark Prins                    // $renderer->meta['geo']['geohash'] = (new Point($mainLon,$mainLat))->out('geohash');
842*57f8d5bbSMark Prins                    $p                                  = new Point ($mainLon, $mainLat);
843*57f8d5bbSMark Prins                    $renderer->meta ['geo'] ['geohash'] = $p->out('geohash');
844*57f8d5bbSMark Prins                }
845*57f8d5bbSMark Prins            }
846*57f8d5bbSMark Prins
847*57f8d5bbSMark Prins            if(($this->getConf('enableA11y')) && (!empty ($_firstimage))) {
848*57f8d5bbSMark Prins                // add map local image into relation/firstimage if not already filled and when it is a local image
849*57f8d5bbSMark Prins
850*57f8d5bbSMark Prins                global $ID;
851*57f8d5bbSMark Prins                $rel = p_get_metadata($ID, 'relation', METADATA_RENDER_USING_CACHE);
852*57f8d5bbSMark Prins                $img = $rel ['firstimage'];
853*57f8d5bbSMark Prins                if(empty ($img) /* || $img == $_firstimage*/) {
854*57f8d5bbSMark Prins                    //dbglog ( $_firstimage,
855*57f8d5bbSMark Prins                    // 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.' );
856*57f8d5bbSMark Prins                    // This seems to never work; the firstimage entry in the .meta file is empty
857*57f8d5bbSMark Prins                    // $renderer->meta['relation']['firstimage'] = $_firstimage;
858*57f8d5bbSMark Prins
859*57f8d5bbSMark Prins                    // ... and neither does this; the firstimage entry in the .meta file is empty
860*57f8d5bbSMark Prins                    // $relation = array('relation'=>array('firstimage'=>$_firstimage));
861*57f8d5bbSMark Prins                    // p_set_metadata($ID, $relation, false, false);
862*57f8d5bbSMark Prins
863*57f8d5bbSMark Prins                    // ... this works
864*57f8d5bbSMark Prins                    $renderer->internalmedia($_firstimage, $poitabledesc);
865*57f8d5bbSMark Prins                }
866*57f8d5bbSMark Prins            }
867*57f8d5bbSMark Prins            return true;
868*57f8d5bbSMark Prins        }
869*57f8d5bbSMark Prins        return false;
870*57f8d5bbSMark Prins    }
87138a47c60SMark Prins}
872