xref: /plugin/openlayersmap/syntax/olmap.php (revision a760825c0aa6eee7ec491397b3516b6237e4ad78)
138a47c60SMark Prins<?php
2*a760825cSgithub-actions[bot]
338a47c60SMark Prins/*
457f8d5bbSMark Prins * Copyright (c) 2008-2021 Mark C. Prins <mprins@users.sf.net>
538a47c60SMark Prins *
638a47c60SMark Prins * Permission to use, copy, modify, and distribute this software for any
738a47c60SMark Prins * purpose with or without fee is hereby granted, provided that the above
838a47c60SMark Prins * copyright notice and this permission notice appear in all copies.
938a47c60SMark Prins *
1038a47c60SMark Prins * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1138a47c60SMark Prins * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1238a47c60SMark Prins * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1338a47c60SMark Prins * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1438a47c60SMark Prins * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1538a47c60SMark Prins * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1638a47c60SMark Prins * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1757f8d5bbSMark Prins *
1857f8d5bbSMark Prins * @phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
1938a47c60SMark Prins */
20*a760825cSgithub-actions[bot]use dokuwiki\Extension\SyntaxPlugin;
213ebe658bSMark Prinsuse geoPHP\Geometry\Point;
223ebe658bSMark Prins
2338a47c60SMark Prins/**
24cc74a83cSMark Prins * DokuWiki Plugin openlayersmap (Syntax Component).
25cc74a83cSMark Prins * Provides for display of an OpenLayers based map in a wiki page.
26cc74a83cSMark Prins *
27cc74a83cSMark Prins * @author Mark Prins
2838a47c60SMark Prins */
29*a760825cSgithub-actions[bot]class syntax_plugin_openlayersmap_olmap extends SyntaxPlugin
30*a760825cSgithub-actions[bot]{
311c640875SMark Prins    /**
321c640875SMark Prins     * defaults of the known attributes of the olmap tag.
331c640875SMark Prins     */
34*a760825cSgithub-actions[bot]    private $dflt = ['id'            => 'olmap', 'width'         => '550px', 'height'        => '450px', 'lat'           => 50.0, 'lon'           => 5.1, 'zoom'          => 12, 'autozoom'      => 1, 'controls'      => true, 'baselyr'       => 'OpenStreetMap', 'gpxfile'       => '', 'kmlfile'       => '', 'geojsonfile'   => '', 'summary'       => ''];
3538a47c60SMark Prins
3638a47c60SMark Prins    /**
371c640875SMark Prins     *
38cc74a83cSMark Prins     * @see DokuWiki_Syntax_Plugin::getType()
3938a47c60SMark Prins     */
40*a760825cSgithub-actions[bot]    public function getType(): string
41*a760825cSgithub-actions[bot]    {
4275c98788SMark Prins        return 'substition';
4375c98788SMark Prins    }
4438a47c60SMark Prins
4538a47c60SMark Prins    /**
461c640875SMark Prins     *
47cc74a83cSMark Prins     * @see DokuWiki_Syntax_Plugin::getPType()
4838a47c60SMark Prins     */
49*a760825cSgithub-actions[bot]    public function getPType(): string
50*a760825cSgithub-actions[bot]    {
5175c98788SMark Prins        return 'block';
5275c98788SMark Prins    }
5338a47c60SMark Prins
5438a47c60SMark Prins    /**
551c640875SMark Prins     *
56cc74a83cSMark Prins     * @see Doku_Parser_Mode::getSort()
5738a47c60SMark Prins     */
58*a760825cSgithub-actions[bot]    public function getSort(): int
59*a760825cSgithub-actions[bot]    {
6075c98788SMark Prins        return 901;
6175c98788SMark Prins    }
62fc16f3cdSMark Prins
6338a47c60SMark Prins    /**
641c640875SMark Prins     *
65cc74a83cSMark Prins     * @see Doku_Parser_Mode::connectTo()
6638a47c60SMark Prins     */
67*a760825cSgithub-actions[bot]    public function connectTo($mode)
68*a760825cSgithub-actions[bot]    {
6957f8d5bbSMark Prins        $this->Lexer->addSpecialPattern(
70*a760825cSgithub-actions[bot]            '<olmap ?[^>\n]*>.*?</olmap>',
71*a760825cSgithub-actions[bot]            $mode,
7257f8d5bbSMark Prins            'plugin_openlayersmap_olmap'
7357f8d5bbSMark Prins        );
7438a47c60SMark Prins    }
75fc16f3cdSMark Prins
7638a47c60SMark Prins    /**
771c640875SMark Prins     *
78cc74a83cSMark Prins     * @see DokuWiki_Syntax_Plugin::handle()
7938a47c60SMark Prins     */
80*a760825cSgithub-actions[bot]    public function handle($match, $state, $pos, Doku_Handler $handler): array
81*a760825cSgithub-actions[bot]    {
823f760703SMark Prins        // break matched data into its components
833f760703SMark Prins        $_tag       = explode('>', substr($match, 7, -9), 2);
843f760703SMark Prins        $str_params = $_tag[0];
853f760703SMark Prins        if (array_key_exists(1, $_tag)) {
863f760703SMark Prins            $str_points = $_tag[1];
873f760703SMark Prins        } else {
883f760703SMark Prins            $str_points = '';
893f760703SMark Prins        }
90554f43b5SMark Prins        // get the lat/lon for adding them to the metadata (used by geotag)
91d2f4772aSMark Prins        preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat);
92d2f4772aSMark Prins        preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon);
93554f43b5SMark Prins        $mainLat = substr($mainLat [0], 5, -1);
94554f43b5SMark Prins        $mainLon = substr($mainLon [0], 5, -1);
95d2f4772aSMark Prins        if (!is_numeric($mainLat)) {
96d2f4772aSMark Prins            $mainLat = $this->dflt ['lat'];
97d2f4772aSMark Prins        }
98d2f4772aSMark Prins        if (!is_numeric($mainLon)) {
99d2f4772aSMark Prins            $mainLon = $this->dflt ['lon'];
100d2f4772aSMark Prins        }
10138a47c60SMark Prins
10257f8d5bbSMark Prins        $gmap          = $this->extractParams($str_params);
10357f8d5bbSMark Prins        $overlay = $this->extractPoints($str_points);
104fc16f3cdSMark Prins        $_firstimageID = '';
10538a47c60SMark Prins
1068e7c4263SMark Prins        $_nocache = false;
107807d36baSMark Prins        // choose maptype based on the specified tag
108628e43ccSMark Prins        $imgUrl = "{{";
109585afb49SMark Prins        if (stripos($gmap ['baselyr'], 'google') !== false) {
1108e7c4263SMark Prins            // Google
11157f8d5bbSMark Prins            $imgUrl .= $this->getGoogle($gmap, $overlay);
1128e7c4263SMark Prins            $imgUrl .= "&.png";
113585afb49SMark Prins        } elseif (stripos($gmap ['baselyr'], 'bing') !== false) {
1148e7c4263SMark Prins            // Bing
115d974ea02SMark Prins            if (!$this->getConf('bingAPIKey')) {
116d974ea02SMark Prins                // in case there is no Bing api key we'll use OSM
11757f8d5bbSMark Prins                $_firstimageID = $this->getStaticOSM($gmap, $overlay);
118d974ea02SMark Prins                $imgUrl        .= $_firstimageID;
119628e43ccSMark Prins                if ($this->getConf('optionStaticMapGenerator') == 'remote') {
120628e43ccSMark Prins                    $imgUrl .= "&.png";
121d974ea02SMark Prins                }
122d974ea02SMark Prins            } else {
1238e7c4263SMark Prins                // seems that Bing doesn't like the DW client, turn off caching
1248e7c4263SMark Prins                $_nocache = true;
12557f8d5bbSMark Prins                $imgUrl   .= $this->getBing($gmap, $overlay) . "&.png";
126d974ea02SMark Prins            }
127e72390dbSMark Prins        } /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) {
1288e7c4263SMark Prins            // MapQuest
1298e7c4263SMark Prins            if (! $this->getConf ( 'mapquestAPIKey' )) {
1308e7c4263SMark Prins                // no API key for MapQuest, use OSM
13157f8d5bbSMark Prins                $_firstimageID = $this->getStaticOSM ( $gmap, $overlay );
132fc16f3cdSMark Prins                $imgUrl .= $_firstimageID;
1338e7c4263SMark Prins                if ($this->getConf ( 'optionStaticMapGenerator' ) == 'remote') {
1348e7c4263SMark Prins                    $imgUrl .= "&.png";
135628e43ccSMark Prins                }
13663037f21SMark Prins            } else {
1378e7c4263SMark Prins                $imgUrl .= $this->_getMapQuest ( $gmap, $overlay );
1388e7c4263SMark Prins                $imgUrl .= "&.png";
1398e7c4263SMark Prins            }
140e72390dbSMark Prins        } */ else {
1418e7c4263SMark Prins            // default OSM
14257f8d5bbSMark Prins            $_firstimageID = $this->getStaticOSM($gmap, $overlay);
143fc16f3cdSMark Prins            $imgUrl        .= $_firstimageID;
14453bfe4a3SMark Prins            if ($this->getConf('optionStaticMapGenerator') == 'remote') {
14553bfe4a3SMark Prins                $imgUrl .= "&.png";
14653bfe4a3SMark Prins            }
14787d958d4SMark Prins}
14887d958d4SMark Prins
149628e43ccSMark Prins        // append dw p_render specific params and render
15057f8d5bbSMark Prins        $imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x"
15157f8d5bbSMark Prins            . str_replace("px", "", $gmap ['height']);
1526ba8d085SMark Prins        $imgUrl .= "&nolink";
1538e7c4263SMark Prins
1548e7c4263SMark Prins        // add nocache option for selected services
1558e7c4263SMark Prinsif ($_nocache) {
1568e7c4263SMark Prins    $imgUrl .= "&nocache";
1578e7c4263SMark Prins}
1588e7c4263SMark Prins
159fcd79b50SMark Prins        $imgUrl .= " |" . $gmap ['summary'] . " }}";
160fcd79b50SMark Prins
1618e7c4263SMark Prins        // dbglog($imgUrl,"complete image tags is:");
1628e7c4263SMark Prins
16338a47c60SMark Prins        $mapid = $gmap ['id'];
16438a47c60SMark Prins        // create a javascript parameter string for the map
16538a47c60SMark Prins        $param = '';
16638a47c60SMark Prinsforeach ($gmap as $key => $val) {
16738a47c60SMark Prins    $param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
16838a47c60SMark Prins}
16938a47c60SMark Prinsif (!empty($param)) {
17045c50327SMark Prins    $param = substr($param, 0, -2);
17138a47c60SMark Prins}
17238a47c60SMark Prins        unset($gmap ['id']);
17338a47c60SMark Prins
17438a47c60SMark Prins        // create a javascript serialisation of the point data
17538a47c60SMark Prins        $poi      = '';
17645c50327SMark Prins        $poitable = '';
17745c50327SMark Prins        $rowId    = 0;
178*a760825cSgithub-actions[bot]if ($overlay !== []) {
17938a47c60SMark Prins    foreach ($overlay as $data) {
180*a760825cSgithub-actions[bot]        [$lat, $lon, $text, $angle, $opacity, $img] = $data;
18145c50327SMark Prins        $rowId++;
18245c50327SMark Prins        $poi .= ", {lat:$lat,lon:$lon,txt:'$text',angle:$angle,opacity:$opacity,img:'$img',rowId: $rowId}";
1838c4eb2fdSMark Prins
1848c4eb2fdSMark Prins        if ($this->getConf('displayformat') === 'DMS') {
1858c4eb2fdSMark Prins            $lat = $this->convertLat($lat);
1868c4eb2fdSMark Prins            $lon = $this->convertLon($lon);
1878c4eb2fdSMark Prins        } else {
1888c4eb2fdSMark Prins            $lat .= 'º';
1898c4eb2fdSMark Prins            $lon .= 'º';
1908c4eb2fdSMark Prins        }
1918c4eb2fdSMark Prins
192a757236dSMark Prins        $poitable .= '
193a757236dSMark Prins                    <tr>
194a757236dSMark Prins                    <td class="rowId">' . $rowId . '</td>
19557f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/icons/' . $img . '" alt="'
19657f8d5bbSMark Prins            . substr($img, 0, -4) . $this->getlang('alt_legend_poi') . '" /></td>
197a57aaf07SMark Prins                    <td class="lat" title="' . $this->getLang('olmapPOIlatTitle') . '">' . $lat . '</td>
198a57aaf07SMark Prins                    <td class="lon" title="' . $this->getLang('olmapPOIlonTitle') . '">' . $lon . '</td>
199a757236dSMark Prins                    <td class="txt">' . $text . '</td>
200a757236dSMark Prins                    </tr>';
20138a47c60SMark Prins    }
20245c50327SMark Prins    $poi = substr($poi, 2);
20338a47c60SMark Prins}
204e61425c7SMark Prinsif (!empty($gmap ['kmlfile'])) {
205e61425c7SMark Prins    $poitable .= '
206e61425c7SMark Prins                    <tr>
20757f8d5bbSMark Prins                    <td class="rowId"><img src="' . DOKU_BASE
20857f8d5bbSMark Prins        . 'lib/plugins/openlayersmap/toolbar/kml_file.png" alt="KML file" /></td>
20957f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/toolbar/kml_line.png" alt="'
21057f8d5bbSMark Prins        . $this->getlang('alt_legend_kml') . '" /></td>
211cc74a83cSMark Prins                    <td class="txt" colspan="3">KML track: ' . $this->getFileName($gmap ['kmlfile']) . '</td>
212e61425c7SMark Prins                    </tr>';
213e61425c7SMark Prins}
214e61425c7SMark Prinsif (!empty($gmap ['gpxfile'])) {
215e61425c7SMark Prins    $poitable .= '
216e61425c7SMark Prins                    <tr>
21757f8d5bbSMark Prins                    <td class="rowId"><img src="' . DOKU_BASE
21857f8d5bbSMark Prins        . 'lib/plugins/openlayersmap/toolbar/gpx_file.png" alt="GPX file" /></td>
21957f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE
22057f8d5bbSMark Prins        . 'lib/plugins/openlayersmap/toolbar/gpx_line.png" alt="'
22157f8d5bbSMark Prins        . $this->getlang('alt_legend_gpx') . '" /></td>
222cc74a83cSMark Prins                    <td class="txt" colspan="3">GPX track: ' . $this->getFileName($gmap ['gpxfile']) . '</td>
223e61425c7SMark Prins                    </tr>';
224e61425c7SMark Prins}
2256914b920SMark Prinsif (!empty($gmap ['geojsonfile'])) {
2266914b920SMark Prins    $poitable .= '
2276914b920SMark Prins                    <tr>
22857f8d5bbSMark Prins                    <td class="rowId"><img src="' . DOKU_BASE
22957f8d5bbSMark Prins        . 'lib/plugins/openlayersmap/toolbar/geojson_file.png" alt="GeoJSON file" /></td>
23057f8d5bbSMark Prins                    <td class="icon"><img src="' . DOKU_BASE
23157f8d5bbSMark Prins        . 'lib/plugins/openlayersmap/toolbar/geojson_line.png" alt="'
23257f8d5bbSMark Prins        . $this->getlang('alt_legend_geojson') . '" /></td>
2336914b920SMark Prins                    <td class="txt" colspan="3">GeoJSON track: ' . $this->getFileName($gmap ['geojsonfile']) . '</td>
2346914b920SMark Prins                    </tr>';
2356914b920SMark Prins}
236e61425c7SMark Prins
237c8eb1362SMark Prins        $autozoom = empty($gmap ['autozoom']) ? $this->getConf('autoZoomMap') : $gmap ['autozoom'];
23857f8d5bbSMark Prins        $js       = "{mapOpts: {" . $param . ", displayformat: '" . $this->getConf('displayformat')
23957f8d5bbSMark Prins            . "', autozoom: " . $autozoom . "}, poi: [$poi]};";
240a757236dSMark Prins        // unescape the json
241a757236dSMark Prins        $poitable = stripslashes($poitable);
24238a47c60SMark Prins
243*a760825cSgithub-actions[bot]        return [$mapid, $js, $mainLat, $mainLon, $poitable, $gmap ['summary'], $imgUrl, $_firstimageID];
24438a47c60SMark Prins    }
24538a47c60SMark Prins
24638a47c60SMark Prins    /**
24738a47c60SMark Prins     * extract parameters for the map from the parameter string
24838a47c60SMark Prins     *
2491c640875SMark Prins     * @param string $str_params
2501c640875SMark Prins     *            string of key="value" pairs
25138a47c60SMark Prins     * @return array associative array of parameters key=>value
25238a47c60SMark Prins     */
253*a760825cSgithub-actions[bot]    private function extractParams(string $str_params): array
254*a760825cSgithub-actions[bot]    {
255*a760825cSgithub-actions[bot]        $param = [];
25638a47c60SMark Prins        preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
25738a47c60SMark Prins        // parse match for instructions, break into key value pairs
25838a47c60SMark Prins        $gmap = $this->dflt;
259c8eb1362SMark Prins        foreach ($gmap as $key => &$value) {
260c8eb1362SMark Prins            $defval = $this->getConf('default_' . $key);
261c8eb1362SMark Prins            if ($defval !== '') {
262c8eb1362SMark Prins                $value = $defval;
263c8eb1362SMark Prins            }
264c8eb1362SMark Prins        }
265c8eb1362SMark Prins        unset($value);
26638a47c60SMark Prins        foreach ($param as $kvpair) {
267*a760825cSgithub-actions[bot]            [$match, $key, $val] = $kvpair;
26838a47c60SMark Prins            $key = strtolower($key);
26938a47c60SMark Prins            if (isset($gmap [$key])) {
27045c50327SMark Prins                if ($key == 'summary') {
27145c50327SMark Prins                    // preserve case for summary field
27245c50327SMark Prins                    $gmap [$key] = $val;
2731c640875SMark Prins                } elseif ($key == 'id') {
2741c640875SMark Prins                    // preserve case for id field
2751c640875SMark Prins                    $gmap [$key] = $val;
27645c50327SMark Prins                } else {
27738a47c60SMark Prins                    $gmap [$key] = strtolower($val);
27838a47c60SMark Prins                }
27938a47c60SMark Prins            }
28045c50327SMark Prins        }
28138a47c60SMark Prins        return $gmap;
28238a47c60SMark Prins    }
28338a47c60SMark Prins
28438a47c60SMark Prins    /**
28538a47c60SMark Prins     * extract overlay points for the map from the wiki syntax data
28638a47c60SMark Prins     *
2871c640875SMark Prins     * @param string $str_points
2881c640875SMark Prins     *            multi-line string of lat,lon,text triplets
28938a47c60SMark Prins     * @return array multi-dimensional array of lat,lon,text triplets
29038a47c60SMark Prins     */
291*a760825cSgithub-actions[bot]    private function extractPoints(string $str_points): array
292*a760825cSgithub-actions[bot]    {
293*a760825cSgithub-actions[bot]        $point = [];
29457f8d5bbSMark Prins        // preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um',
29557f8d5bbSMark Prins        //      $str_points, $point, PREG_SET_ORDER);
2967a3f422cSMark Prins        /*
29757f8d5bbSMark Prins         * group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
29857f8d5bbSMark Prins         * group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
29957f8d5bbSMark Prins         * group 3: (.*?)
30057f8d5bbSMark Prins         * group 4: (.*?)
30157f8d5bbSMark Prins         * group 5: (.*?)
30257f8d5bbSMark Prins         * group 6: (.*)
3037a3f422cSMark Prins         */
30457f8d5bbSMark Prins        preg_match_all(
30557f8d5bbSMark Prins            '/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um',
306*a760825cSgithub-actions[bot]            $str_points,
307*a760825cSgithub-actions[bot]            $point,
308*a760825cSgithub-actions[bot]            PREG_SET_ORDER
30957f8d5bbSMark Prins        );
310554f43b5SMark Prins        // create poi array
311*a760825cSgithub-actions[bot]        $overlay = [];
31238a47c60SMark Prins        foreach ($point as $pt) {
313*a760825cSgithub-actions[bot]            [$match, $lat, $lon, $angle, $opacity, $img, $text] = $pt;
31438a47c60SMark Prins            $lat     = is_numeric($lat) ? $lat : 0;
31538a47c60SMark Prins            $lon     = is_numeric($lon) ? $lon : 0;
31638a47c60SMark Prins            $angle   = is_numeric($angle) ? $angle : 0;
31738a47c60SMark Prins            $opacity = is_numeric($opacity) ? $opacity : 0.8;
31887d958d4SMark Prins            // TODO validate using exist & set up default img?
3191c640875SMark Prins            $img  = trim($img);
3201c640875SMark Prins            $text = p_get_instructions($text);
3211c640875SMark Prins            // dbg ( $text );
3221c640875SMark Prins            $text = p_render("xhtml", $text, $info);
3231c640875SMark Prins            // dbg ( $text );
3241c640875SMark Prins            $text       = addslashes(str_replace("\n", "", $text));
325*a760825cSgithub-actions[bot]            $overlay [] = [$lat, $lon, $text, $angle, $opacity, $img];
32638a47c60SMark Prins        }
32738a47c60SMark Prins        return $overlay;
32838a47c60SMark Prins    }
329fcd79b50SMark Prins
330fcd79b50SMark Prins    /**
33157f8d5bbSMark Prins     * Create a Google maps static image url w/ the poi.
33257f8d5bbSMark Prins     *
33357f8d5bbSMark Prins     * @param array $gmap
33457f8d5bbSMark Prins     * @param array $overlay
33557f8d5bbSMark Prins     */
336*a760825cSgithub-actions[bot]    private function getGoogle(array $gmap, array $overlay): string
337*a760825cSgithub-actions[bot]    {
33857f8d5bbSMark Prins        $sUrl = $this->getConf('iconUrlOverload');
33957f8d5bbSMark Prins        if (!$sUrl) {
34057f8d5bbSMark Prins            $sUrl = DOKU_URL;
34157f8d5bbSMark Prins        }
34257f8d5bbSMark Prins        switch ($gmap ['baselyr']) {
34357f8d5bbSMark Prins            case 'google hybrid':
34457f8d5bbSMark Prins                $maptype = 'hybrid';
34557f8d5bbSMark Prins                break;
34657f8d5bbSMark Prins            case 'google sat':
34757f8d5bbSMark Prins                $maptype = 'satellite';
34857f8d5bbSMark Prins                break;
34957f8d5bbSMark Prins            case 'terrain':
35057f8d5bbSMark Prins            case 'google relief':
35157f8d5bbSMark Prins                $maptype = 'terrain';
35257f8d5bbSMark Prins                break;
35357f8d5bbSMark Prins            case 'google road':
35457f8d5bbSMark Prins            default:
35557f8d5bbSMark Prins                $maptype = 'roadmap';
35657f8d5bbSMark Prins                break;
35757f8d5bbSMark Prins        }
35857f8d5bbSMark Prins        // TODO maybe use viewport / visible instead of center/zoom,
35957f8d5bbSMark Prins        // see: https://developers.google.com/maps/documentation/staticmaps/index#Viewports
36057f8d5bbSMark 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
36157f8d5bbSMark Prins        $imgUrl = "https://maps.googleapis.com/maps/api/staticmap?";
36257f8d5bbSMark Prins        $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
36357f8d5bbSMark Prins            . str_replace("px", "", $gmap ['height']);
36457f8d5bbSMark Prins        //if (!$this->getConf( 'autoZoomMap')) { // no need for center & zoom params }
36557f8d5bbSMark Prins        $imgUrl .= "&center=" . $gmap ['lat'] . "," . $gmap ['lon'];
36657f8d5bbSMark Prins        // max is 21 (== building scale), but that's overkill..
36757f8d5bbSMark Prins        if ($gmap ['zoom'] > 17) {
36857f8d5bbSMark Prins            $imgUrl .= "&zoom=17";
36957f8d5bbSMark Prins        } else {
37057f8d5bbSMark Prins            $imgUrl .= "&zoom=" . $gmap ['zoom'];
37157f8d5bbSMark Prins        }
372*a760825cSgithub-actions[bot]        if ($overlay !== []) {
37357f8d5bbSMark Prins            $rowId = 0;
37457f8d5bbSMark Prins            foreach ($overlay as $data) {
375*a760825cSgithub-actions[bot]                [$lat, $lon, $text, $angle, $opacity, $img] = $data;
37657f8d5bbSMark Prins                $imgUrl .= "&markers=icon%3a" . $sUrl . "lib/plugins/openlayersmap/icons/" . $img . "%7c"
37757f8d5bbSMark Prins                    . $lat . "," . $lon . "%7clabel%3a" . ++$rowId;
37857f8d5bbSMark Prins            }
37957f8d5bbSMark Prins        }
38057f8d5bbSMark Prins        $imgUrl .= "&format=png&maptype=" . $maptype;
38157f8d5bbSMark Prins        global $conf;
38257f8d5bbSMark Prins        $imgUrl .= "&language=" . $conf ['lang'];
38357f8d5bbSMark Prins        if ($this->getConf('googleAPIkey')) {
38457f8d5bbSMark Prins            $imgUrl .= "&key=" . $this->getConf('googleAPIkey');
38557f8d5bbSMark Prins        }
38657f8d5bbSMark Prins        // dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::getGoogle: Google image url is:');
38757f8d5bbSMark Prins        return $imgUrl;
38857f8d5bbSMark Prins    }
38957f8d5bbSMark Prins
39057f8d5bbSMark Prins    /**
391fcd79b50SMark Prins     * Create a MapQuest static map API image url.
3921c640875SMark Prins     *
393fcd79b50SMark Prins     * @param array $gmap
394fcd79b50SMark Prins     * @param array $overlay
395fcd79b50SMark Prins     */
396e72390dbSMark Prins    /*
397fcd79b50SMark Prins   private function _getMapQuest($gmap, $overlay) {
398787a5195SMark Prins       $sUrl = $this->getConf ( 'iconUrlOverload' );
399787a5195SMark Prins       if (! $sUrl) {
400787a5195SMark Prins           $sUrl = DOKU_URL;
401787a5195SMark Prins       }
40287d958d4SMark Prins       switch ($gmap ['baselyr']) {
40394c2e868SMark Prins           case 'mapquest hybrid' :
404837eba2fSMark Prins               $maptype = 'hyb';
40587d958d4SMark Prins               break;
40618edeaa5SMark Prins           case 'mapquest sat' :
40744aba0bcSMark Prins               // because sat coverage is very limited use 'hyb' instead of 'sat' so we don't get a blank map
40844aba0bcSMark Prins               $maptype = 'hyb';
40987d958d4SMark Prins               break;
41094c2e868SMark Prins           case 'mapquest road' :
41187d958d4SMark Prins           default :
41287d958d4SMark Prins               $maptype = 'map';
41387d958d4SMark Prins               break;
41487d958d4SMark Prins       }
415004ad4e2SMark Prins       $imgUrl = "http://open.mapquestapi.com/staticmap/v4/getmap?declutter=true&";
41644aba0bcSMark Prins       if (count ( $overlay ) < 1) {
417787a5195SMark Prins           $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
418787a5195SMark Prins           // max level for mapquest is 16
419fcd79b50SMark Prins           if ($gmap ['zoom'] > 16) {
420fcd79b50SMark Prins               $imgUrl .= "&zoom=16";
421fcd79b50SMark Prins           } else {
422fcd79b50SMark Prins               $imgUrl .= "&zoom=" . $gmap ['zoom'];
423fcd79b50SMark Prins           }
42444aba0bcSMark Prins       }
42544aba0bcSMark Prins       // use bestfit instead of center/zoom, needs upperleft/lowerright corners
42657f8d5bbSMark Prins       // $bbox=$this->calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
42744aba0bcSMark Prins       // $imgUrl .= "bestfit=".$bbox['minlat'].",".$bbox['maxlon'].",".$bbox['maxlat'].",".$bbox['minlon'];
42844aba0bcSMark Prins
42957f8d5bbSMark Prins       // TODO declutter option works well for square maps but not for rectangular, maybe compensate for that
43057f8d5bbSMark Prins       //       or compensate the mbr..
43157f8d5bbSMark Prins
43244aba0bcSMark Prins       $imgUrl .= "&size=" . str_replace ( "px", "", $gmap ['width'] ) . "," . str_replace ("px","",$gmap['height']);
43344aba0bcSMark Prins
434fcd79b50SMark Prins       // TODO mapquest allows using one image url with a multiplier $NUMBER eg:
435fcd79b50SMark Prins       // $NUMBER = 2
43657f8d5bbSMark Prins       // $imgUrl .= DOKU_URL."/".DOKU_PLUGIN."/".getPluginName()."/icons/".$img.",$NUMBER,C,"
43757f8d5bbSMark Prins        //  .$lat1.",".$lon1.",0,0,0,0,C,".$lat2.",".$lon2.",0,0,0,0";
438fcd79b50SMark Prins       if (! empty ( $overlay )) {
439fcd79b50SMark Prins           $imgUrl .= "&xis=";
440fcd79b50SMark Prins           foreach ( $overlay as $data ) {
441fcd79b50SMark Prins               list ( $lat, $lon, $text, $angle, $opacity, $img ) = $data;
44244aba0bcSMark Prins               // $imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",0,0,0,0,";
44344aba0bcSMark Prins               $imgUrl .= $sUrl . "lib/plugins/openlayersmap/icons/" . $img . ",1,C," . $lat . "," . $lon . ",";
444fcd79b50SMark Prins           }
445fcd79b50SMark Prins           $imgUrl = substr ( $imgUrl, 0, - 1 );
446fcd79b50SMark Prins       }
44787d958d4SMark Prins       $imgUrl .= "&imageType=png&type=" . $maptype;
448d974ea02SMark Prins       $imgUrl .= "&key=".$this->getConf ( 'mapquestAPIKey' );
4498e7c4263SMark Prins       // dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getMapQuest: MapQuest image url is:');
450787a5195SMark Prins       return $imgUrl;
451787a5195SMark Prins   }
452e72390dbSMark Prins   */
453cc74a83cSMark Prins
4546e633dd6SMark Prins    /**
45587d958d4SMark Prins     * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
456fcf646d2SMark Prins     * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
4571c640875SMark Prins     *
45887d958d4SMark Prins     * @param array $gmap
45987d958d4SMark Prins     * @param array $overlay
460fcf646d2SMark Prins     *
46157f8d5bbSMark Prins     * @return false|string
462fcf646d2SMark Prins     * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
46387d958d4SMark Prins     */
464*a760825cSgithub-actions[bot]    private function getStaticOSM(array $gmap, array $overlay)
465*a760825cSgithub-actions[bot]    {
466fcf646d2SMark Prins        global $conf;
467372f1508SMark Prins
468751c8ef2SMark Prins        if ($this->getConf('optionStaticMapGenerator') === 'local') {
469d974ea02SMark Prins            // using local basemap composer
470*a760825cSgithub-actions[bot]            if (($myMap = plugin_load('helper', 'openlayersmap_staticmap')) === null) {
47157f8d5bbSMark Prins                dbglog(
47257f8d5bbSMark Prins                    $myMap,
47357f8d5bbSMark Prins                    'openlayersmap_staticmap plugin is not available for use.'
47457f8d5bbSMark Prins                );
47553bfe4a3SMark Prins            }
476*a760825cSgithub-actions[bot]            if (($geophp = plugin_load('helper', 'geophp')) === null) {
47757f8d5bbSMark Prins                dbglog($geophp, 'geophp plugin is not available for use.');
47853bfe4a3SMark Prins            }
47957f8d5bbSMark Prins            $size = str_replace("px", "", $gmap ['width']) . "x"
48057f8d5bbSMark Prins                . str_replace("px", "", $gmap ['height']);
48153bfe4a3SMark Prins
482*a760825cSgithub-actions[bot]            $markers = [];
483*a760825cSgithub-actions[bot]            if ($overlay !== []) {
48453bfe4a3SMark Prins                foreach ($overlay as $data) {
485*a760825cSgithub-actions[bot]                    [$lat, $lon, $text, $angle, $opacity, $img] = $data;
486751c8ef2SMark Prins                    $iconStyle  = substr($img, 0, -4);
487*a760825cSgithub-actions[bot]                    $markers [] = ['lat'  => $lat, 'lon'  => $lon, 'type' => $iconStyle];
48853bfe4a3SMark Prins                }
489372f1508SMark Prins            }
490372f1508SMark Prins
491d2f4772aSMark Prins            $apikey = '';
49218edeaa5SMark Prins            switch ($gmap ['baselyr']) {
49318edeaa5SMark Prins                case 'mapnik':
494fcf646d2SMark Prins                case 'openstreetmap':
495fcf646d2SMark Prins                    $maptype = 'openstreetmap';
49618edeaa5SMark Prins                    break;
497fcf646d2SMark Prins                case 'transport':
498fcf646d2SMark Prins                    $maptype = 'transport';
499b63742deSMark Prins                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
500fcf646d2SMark Prins                    break;
501fcf646d2SMark Prins                case 'landscape':
502fcf646d2SMark Prins                    $maptype = 'landscape';
503b63742deSMark Prins                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
504d2f4772aSMark Prins                    break;
505d2f4772aSMark Prins                case 'outdoors':
506d2f4772aSMark Prins                    $maptype = 'outdoors';
507b63742deSMark Prins                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
50818edeaa5SMark Prins                    break;
50918edeaa5SMark Prins                case 'cycle map':
51018edeaa5SMark Prins                    $maptype = 'cycle';
511b63742deSMark Prins                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
512372f1508SMark Prins                    break;
513fcf646d2SMark Prins                case 'hike and bike map':
514fcf646d2SMark Prins                    $maptype = 'hikeandbike';
515fcf646d2SMark Prins                    break;
516fcf646d2SMark Prins                case 'mapquest hybrid':
517fcf646d2SMark Prins                case 'mapquest road':
518fcf646d2SMark Prins                case 'mapquest sat':
519fcf646d2SMark Prins                    $maptype = 'mapquest';
520fcf646d2SMark Prins                    break;
52118edeaa5SMark Prins                default:
52218edeaa5SMark Prins                    $maptype = '';
52318edeaa5SMark Prins                    break;
52418edeaa5SMark Prins            }
525d974ea02SMark Prins
52657f8d5bbSMark Prins            $result = $myMap->getMap(
527*a760825cSgithub-actions[bot]                $gmap ['lat'],
528*a760825cSgithub-actions[bot]                $gmap ['lon'],
529*a760825cSgithub-actions[bot]                $gmap ['zoom'],
530*a760825cSgithub-actions[bot]                $size,
531*a760825cSgithub-actions[bot]                $maptype,
532*a760825cSgithub-actions[bot]                $markers,
533*a760825cSgithub-actions[bot]                $gmap ['gpxfile'],
534*a760825cSgithub-actions[bot]                $gmap ['kmlfile'],
535*a760825cSgithub-actions[bot]                $gmap ['geojsonfile'],
536*a760825cSgithub-actions[bot]                $apikey
53757f8d5bbSMark Prins            );
538d974ea02SMark Prins        } else {
539d974ea02SMark Prins            // using external basemap composer
540d974ea02SMark Prins
54157f8d5bbSMark Prins            // https://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10
54257f8d5bbSMark Prins            //.117187497601&zoom=5&size=500x350
54357f8d5bbSMark Prins            // &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,
54457f8d5bbSMark Prins            //  lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,
54557f8d5bbSMark Prins            //  ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,
54657f8d5bbSMark Prins            //  ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
54757f8d5bbSMark Prins            $imgUrl = "https://staticmap.openstreetmap.de/staticmap.php";
548d974ea02SMark Prins            $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
54957f8d5bbSMark Prins            $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
55057f8d5bbSMark Prins                . str_replace("px", "", $gmap ['height']);
551d974ea02SMark Prins
552d974ea02SMark Prins            if ($gmap ['zoom'] > 16) {
553d974ea02SMark Prins                // actually this could even be 18, but that seems overkill
554d974ea02SMark Prins                $imgUrl .= "&zoom=16";
555d974ea02SMark Prins            } else {
556d974ea02SMark Prins                $imgUrl .= "&zoom=" . $gmap ['zoom'];
557d974ea02SMark Prins            }
55818edeaa5SMark Prins
559*a760825cSgithub-actions[bot]            if ($overlay !== []) {
56087d958d4SMark Prins                $rowId  = 0;
56187d958d4SMark Prins                $imgUrl .= "&markers=";
56287d958d4SMark Prins                foreach ($overlay as $data) {
563*a760825cSgithub-actions[bot]                    [$lat, $lon, $text, $angle, $opacity, $img] = $data;
56487d958d4SMark Prins                    $rowId++;
56553bfe4a3SMark Prins                    $iconStyle = "lightblue$rowId";
56687d958d4SMark Prins                    $imgUrl    .= "$lat,$lon,$iconStyle%7c";
56787d958d4SMark Prins                }
56887d958d4SMark Prins                $imgUrl = substr($imgUrl, 0, -3);
56987d958d4SMark Prins            }
57087d958d4SMark Prins
571f4b9bdacSMark Prins            $result = $imgUrl;
572628e43ccSMark Prins        }
573628e43ccSMark Prins        return $result;
574628e43ccSMark Prins    }
575628e43ccSMark Prins
57644aba0bcSMark Prins    /**
57757f8d5bbSMark Prins     * Create a Bing maps static image url w/ the poi.
57857f8d5bbSMark Prins     *
57957f8d5bbSMark Prins     * @param array $gmap
58057f8d5bbSMark Prins     * @param array $overlay
58157f8d5bbSMark Prins     */
582*a760825cSgithub-actions[bot]    private function getBing(array $gmap, array $overlay): string
583*a760825cSgithub-actions[bot]    {
58457f8d5bbSMark Prins        switch ($gmap ['baselyr']) {
58557f8d5bbSMark Prins            case 've hybrid':
58657f8d5bbSMark Prins            case 'bing hybrid':
58757f8d5bbSMark Prins                $maptype = 'AerialWithLabels';
58857f8d5bbSMark Prins                break;
58957f8d5bbSMark Prins            case 've sat':
59057f8d5bbSMark Prins            case 'bing sat':
59157f8d5bbSMark Prins                $maptype = 'Aerial';
59257f8d5bbSMark Prins                break;
59357f8d5bbSMark Prins            case 've normal':
59457f8d5bbSMark Prins            case 've road':
59557f8d5bbSMark Prins            case 've':
59657f8d5bbSMark Prins            case 'bing road':
59757f8d5bbSMark Prins            default:
59857f8d5bbSMark Prins                $maptype = 'Road';
59957f8d5bbSMark Prins                break;
60057f8d5bbSMark Prins        }
60157f8d5bbSMark Prins        $imgUrl = "https://dev.virtualearth.net/REST/v1/Imagery/Map/" . $maptype;// . "/";
60257f8d5bbSMark Prins        if ($this->getConf('autoZoomMap')) {
60357f8d5bbSMark Prins            $bbox = $this->calcBBOX($overlay, $gmap ['lat'], $gmap ['lon']);
60457f8d5bbSMark Prins            //$imgUrl .= "?ma=" . $bbox ['minlat'] . "," . $bbox ['minlon'] . ","
60557f8d5bbSMark Prins            //          . $bbox ['maxlat'] . "," . $bbox ['maxlon'];
60657f8d5bbSMark Prins            $imgUrl .= "?ma=" . $bbox ['minlat'] . "%2C" . $bbox ['minlon'] . "%2C" . $bbox ['maxlat']
60757f8d5bbSMark Prins                . "%2C" . $bbox ['maxlon'];
60857f8d5bbSMark Prins            $imgUrl .= "&dcl=1";
60957f8d5bbSMark Prins        }
61057f8d5bbSMark Prins        if (strpos($imgUrl, "?") === false)
61157f8d5bbSMark Prins            $imgUrl .= "?";
61257f8d5bbSMark Prins
61357f8d5bbSMark Prins        //$imgUrl .= "&ms=" . str_replace ( "px", "", $gmap ['width'] ) . ","
61457f8d5bbSMark Prins        //          . str_replace ( "px", "", $gmap ['height'] );
61557f8d5bbSMark Prins        $imgUrl .= "&ms=" . str_replace("px", "", $gmap ['width']) . "%2C"
61657f8d5bbSMark Prins            . str_replace("px", "", $gmap ['height']);
61757f8d5bbSMark Prins        $imgUrl .= "&key=" . $this->getConf('bingAPIKey');
618*a760825cSgithub-actions[bot]        if ($overlay !== []) {
61957f8d5bbSMark Prins            $rowId = 0;
62057f8d5bbSMark Prins            foreach ($overlay as $data) {
621*a760825cSgithub-actions[bot]                [$lat, $lon, $text, $angle, $opacity, $img] = $data;
62257f8d5bbSMark Prins                // TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
62357f8d5bbSMark Prins                $iconStyle = 32;
62457f8d5bbSMark Prins                $rowId++;
62557f8d5bbSMark Prins                // NOTE: the max number of pushpins is 18! or we have to use POST
62657f8d5bbSMark Prins                //  (http://msdn.microsoft.com/en-us/library/ff701724.aspx)
62757f8d5bbSMark Prins                if ($rowId == 18) {
62857f8d5bbSMark Prins                    break;
62957f8d5bbSMark Prins                }
63057f8d5bbSMark Prins                //$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
63157f8d5bbSMark Prins                $imgUrl .= "&pp=$lat%2C$lon%3B$iconStyle%3B$rowId";
63257f8d5bbSMark Prins            }
63357f8d5bbSMark Prins        }
63457f8d5bbSMark Prins        global $conf;
63557f8d5bbSMark Prins        $imgUrl .= "&fmt=png";
63657f8d5bbSMark Prins        $imgUrl .= "&c=" . $conf ['lang'];
63757f8d5bbSMark Prins        return $imgUrl;
63857f8d5bbSMark Prins    }
63957f8d5bbSMark Prins
64057f8d5bbSMark Prins    /**
64144aba0bcSMark Prins     * Calculate the minimum bbox for a start location + poi.
64244aba0bcSMark Prins     *
6431c640875SMark Prins     * @param array $overlay
6441c640875SMark Prins     *            multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
6451c640875SMark Prins     * @param float $lat
6461c640875SMark Prins     *            latitude for map center
6471c640875SMark Prins     * @param float $lon
6481c640875SMark Prins     *            longitude for map center
64957f8d5bbSMark Prins     * @return array :float array describing the mbr and center point
65044aba0bcSMark Prins     */
651*a760825cSgithub-actions[bot]    private function calcBBOX(array $overlay, float $lat, float $lon): array
652*a760825cSgithub-actions[bot]    {
653*a760825cSgithub-actions[bot]        $lats = [$lat];
654*a760825cSgithub-actions[bot]        $lons = [$lon];
655837eba2fSMark Prins        foreach ($overlay as $data) {
656*a760825cSgithub-actions[bot]            [$lat, $lon, $text, $angle, $opacity, $img] = $data;
657837eba2fSMark Prins            $lats [] = $lat;
658837eba2fSMark Prins            $lons [] = $lon;
659837eba2fSMark Prins        }
660837eba2fSMark Prins        sort($lats);
661837eba2fSMark Prins        sort($lons);
66244aba0bcSMark Prins        // TODO: make edge/wrap around cases work
66344aba0bcSMark Prins        $centerlat = $lats [0] + ($lats [count($lats) - 1] - $lats [0]);
66444aba0bcSMark Prins        $centerlon = $lons [0] + ($lons [count($lats) - 1] - $lons [0]);
665*a760825cSgithub-actions[bot]        return ['minlat'    => $lats [0], 'minlon'    => $lons [0], 'maxlat'    => $lats [count($lats) - 1], 'maxlon'    => $lons [count($lats) - 1], 'centerlat' => $centerlat, 'centerlon' => $centerlon];
66687d958d4SMark Prins    }
667cc74a83cSMark Prins
668cc74a83cSMark Prins    /**
66957f8d5bbSMark Prins     * convert latitude in decimal degrees to DMS+hemisphere.
6701c640875SMark Prins     *
67157f8d5bbSMark Prins     * @param float $decimaldegrees
67257f8d5bbSMark Prins     * @todo move this into a shared library
673cc74a83cSMark Prins     */
674*a760825cSgithub-actions[bot]    private function convertLat(float $decimaldegrees): string
675*a760825cSgithub-actions[bot]    {
67657f8d5bbSMark Prins        if (strpos($decimaldegrees, '-') !== false) {
67757f8d5bbSMark Prins            $latPos = "S";
67857f8d5bbSMark Prins        } else {
67957f8d5bbSMark Prins            $latPos = "N";
68057f8d5bbSMark Prins        }
68157f8d5bbSMark Prins        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
68257f8d5bbSMark Prins        return hsc($dms . $latPos);
683cc74a83cSMark Prins    }
6848c4eb2fdSMark Prins
6858c4eb2fdSMark Prins    /**
6868c4eb2fdSMark Prins     * Convert decimal degrees to degrees, minutes, seconds format
6878c4eb2fdSMark Prins     *
6888c4eb2fdSMark Prins     * @param float $decimaldegrees
6898c4eb2fdSMark Prins     * @return string dms
69057f8d5bbSMark Prins     * @todo move this into a shared library
6918c4eb2fdSMark Prins     */
692*a760825cSgithub-actions[bot]    private function convertDDtoDMS(float $decimaldegrees): string
693*a760825cSgithub-actions[bot]    {
6948c4eb2fdSMark Prins        $dms  = floor($decimaldegrees);
6958c4eb2fdSMark Prins        $secs = ($decimaldegrees - $dms) * 3600;
6968c4eb2fdSMark Prins        $min  = floor($secs / 60);
6978c4eb2fdSMark Prins        $sec  = round($secs - ($min * 60), 3);
6988c4eb2fdSMark Prins        $dms  .= 'º' . $min . '\'' . $sec . '"';
6998c4eb2fdSMark Prins        return $dms;
7008c4eb2fdSMark Prins    }
7018c4eb2fdSMark Prins
7028c4eb2fdSMark Prins    /**
7038c4eb2fdSMark Prins     * convert longitude in decimal degrees to DMS+hemisphere.
7048c4eb2fdSMark Prins     *
7058c4eb2fdSMark Prins     * @param float $decimaldegrees
70657f8d5bbSMark Prins     * @todo move this into a shared library
7078c4eb2fdSMark Prins     */
708*a760825cSgithub-actions[bot]    private function convertLon(float $decimaldegrees): string
709*a760825cSgithub-actions[bot]    {
7108c4eb2fdSMark Prins        if (strpos($decimaldegrees, '-') !== false) {
7118c4eb2fdSMark Prins            $lonPos = "W";
7128c4eb2fdSMark Prins        } else {
7138c4eb2fdSMark Prins            $lonPos = "E";
7148c4eb2fdSMark Prins        }
71557f8d5bbSMark Prins        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
7168c4eb2fdSMark Prins        return hsc($dms . $lonPos);
7178c4eb2fdSMark Prins    }
71857f8d5bbSMark Prins
71957f8d5bbSMark Prins    /**
72057f8d5bbSMark Prins     * Figures out the base filename of a media path.
72157f8d5bbSMark Prins     *
72257f8d5bbSMark Prins     * @param string $mediaLink
72357f8d5bbSMark Prins     */
724*a760825cSgithub-actions[bot]    private function getFileName(string $mediaLink): string
725*a760825cSgithub-actions[bot]    {
72657f8d5bbSMark Prins        $mediaLink = str_replace('[[', '', $mediaLink);
72757f8d5bbSMark Prins        $mediaLink = str_replace(']]', '', $mediaLink);
72857f8d5bbSMark Prins        $mediaLink = substr($mediaLink, 0, -4);
729*a760825cSgithub-actions[bot]
73057f8d5bbSMark Prins        $parts     = explode(':', $mediaLink);
73157f8d5bbSMark Prins        $mediaLink = end($parts);
73257f8d5bbSMark Prins        return str_replace('_', ' ', $mediaLink);
73357f8d5bbSMark Prins    }
73457f8d5bbSMark Prins
73557f8d5bbSMark Prins    /**
73657f8d5bbSMark Prins     *
73757f8d5bbSMark Prins     * @see DokuWiki_Syntax_Plugin::render()
73857f8d5bbSMark Prins     */
739*a760825cSgithub-actions[bot]    public function render($format, Doku_Renderer $renderer, $data): bool
740*a760825cSgithub-actions[bot]    {
74157f8d5bbSMark Prins        // set to true after external scripts tags are written
74257f8d5bbSMark Prins        static $initialised = false;
74357f8d5bbSMark Prins        // incremented for each map tag in the page source so we can keep track of each map in this page
74457f8d5bbSMark Prins        static $mapnumber = 0;
74557f8d5bbSMark Prins
746*a760825cSgithub-actions[bot]        [$mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage] = $data;
74757f8d5bbSMark Prins
748751c8ef2SMark Prins        if ($format === 'xhtml') {
74957f8d5bbSMark Prins            $olscript     = '';
750751c8ef2SMark Prins            $stadiaEnable = $this->getConf('enableStadia');
75157f8d5bbSMark Prins            $osmEnable    = $this->getConf('enableOSM');
75257f8d5bbSMark Prins            $enableBing   = $this->getConf('enableBing');
75357f8d5bbSMark Prins
75457f8d5bbSMark Prins            $scriptEnable = '';
75557f8d5bbSMark Prins            if (!$initialised) {
75657f8d5bbSMark Prins                $initialised = true;
7577390889dSMark Prins                // render necessary script tags only once
758660554e1SMark Prins                $olscript = '<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol/ol.js"></script>
759660554e1SMark Prins<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol/ol-layerswitcher.js"></script>';
76057f8d5bbSMark Prins
76157f8d5bbSMark Prins                $scriptEnable = '<script defer="defer" src="data:text/javascript;base64,';
7627390889dSMark Prins                $scriptSrc    = $olscript ? 'const olEnable=true;' : 'const olEnable=false;';
7637390889dSMark Prins                $scriptSrc    .= 'const osmEnable=' . ($osmEnable ? 'true' : 'false') . ';';
764751c8ef2SMark Prins                $scriptSrc    .= 'const stadiaEnable=' . ($stadiaEnable ? 'true' : 'false') . ';';
7657390889dSMark Prins                $scriptSrc    .= 'const bEnable=' . ($enableBing ? 'true' : 'false') . ';';
7667390889dSMark Prins                $scriptSrc    .= 'const bApiKey="' . $this->getConf('bingAPIKey') . '";';
7677390889dSMark Prins                $scriptSrc    .= 'const tfApiKey="' . $this->getConf('tfApiKey') . '";';
7687390889dSMark Prins                $scriptSrc    .= 'const gApiKey="' . $this->getConf('googleAPIkey') . '";';
7697390889dSMark Prins                $scriptSrc    .= 'olMapData = []; let olMaps = {}; let olMapOverlays = {};';
77057f8d5bbSMark Prins                $scriptEnable .= base64_encode($scriptSrc);
77157f8d5bbSMark Prins                $scriptEnable .= '"></script>';
77257f8d5bbSMark Prins            }
7737390889dSMark Prins            $renderer->doc .= "$olscript\n$scriptEnable";
77457f8d5bbSMark Prins            $renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>';
77557f8d5bbSMark Prins            if ($this->getConf('enableA11y')) {
77657f8d5bbSMark Prins                $renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">'
77757f8d5bbSMark Prins                    . p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
77857f8d5bbSMark Prins            }
77957f8d5bbSMark Prins            $renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p>&nbsp;</p></div>';
78057f8d5bbSMark Prins            if ($this->getConf('enableA11y')) {
78157f8d5bbSMark Prins                // render a table of the POI for the print and a11y presentation, it is hidden using javascript
7827390889dSMark Prins                $renderer->doc .= '
7833f760703SMark Prins                <div id="' . $mapid . '-table-span" class="olPOItableSpan">
7843f760703SMark Prins                    <table id="' . $mapid . '-table" class="olPOItable">
78557f8d5bbSMark Prins                    <caption class="olPOITblCaption">' . $this->getLang('olmapPOItitle') . '</caption>
78657f8d5bbSMark Prins                    <thead class="olPOITblHeader">
78757f8d5bbSMark Prins                    <tr>
78857f8d5bbSMark Prins                    <th class="rowId" scope="col">id</th>
78957f8d5bbSMark Prins                    <th class="icon" scope="col">' . $this->getLang('olmapPOIicon') . '</th>
79057f8d5bbSMark Prins                    <th class="lat" scope="col" title="' . $this->getLang('olmapPOIlatTitle') . '">'
79157f8d5bbSMark Prins                    . $this->getLang('olmapPOIlat') . '</th>
79257f8d5bbSMark Prins                    <th class="lon" scope="col" title="' . $this->getLang('olmapPOIlonTitle') . '">'
79357f8d5bbSMark Prins                    . $this->getLang('olmapPOIlon') . '</th>
79457f8d5bbSMark Prins                    <th class="txt" scope="col">' . $this->getLang('olmapPOItxt') . '</th>
79557f8d5bbSMark Prins                    </tr>
79657f8d5bbSMark Prins                    </thead>';
79757f8d5bbSMark Prins                if ($poitabledesc != '') {
79857f8d5bbSMark Prins                    $renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc
79957f8d5bbSMark Prins                        . '</td></tr></tfoot>';
80057f8d5bbSMark Prins                }
80157f8d5bbSMark Prins                $renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody>
8027390889dSMark Prins                    </table>
8037390889dSMark Prins                </div>';
8047390889dSMark Prins                $renderer->doc .= "\n";
80557f8d5bbSMark Prins            }
80657f8d5bbSMark Prins            // render inline mapscript parts
80757f8d5bbSMark Prins            $renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,';
80857f8d5bbSMark Prins            $renderer->doc .= base64_encode("olMapData[$mapnumber] = $param");
80957f8d5bbSMark Prins            $renderer->doc .= '"></script>';
81057f8d5bbSMark Prins            $mapnumber++;
81157f8d5bbSMark Prins            return true;
812751c8ef2SMark Prins        } elseif ($format === 'metadata') {
81357f8d5bbSMark Prins            if (!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) {
81457f8d5bbSMark Prins                // render geo metadata, unless they are the default
81557f8d5bbSMark Prins                $renderer->meta ['geo'] ['lat'] = $mainLat;
81657f8d5bbSMark Prins                $renderer->meta ['geo'] ['lon'] = $mainLon;
817*a760825cSgithub-actions[bot]                if (($geophp = plugin_load('helper', 'geophp')) !== null) {
81857f8d5bbSMark Prins                    // if we have the geoPHP helper, add the geohash
81957f8d5bbSMark Prins
82057f8d5bbSMark Prins                    // fails with older php versions..
82157f8d5bbSMark Prins                    // $renderer->meta['geo']['geohash'] = (new Point($mainLon,$mainLat))->out('geohash');
82257f8d5bbSMark Prins                    $p                                  = new Point($mainLon, $mainLat);
82357f8d5bbSMark Prins                    $renderer->meta ['geo'] ['geohash'] = $p->out('geohash');
82457f8d5bbSMark Prins                }
82557f8d5bbSMark Prins            }
82657f8d5bbSMark Prins
82757f8d5bbSMark Prins            if (($this->getConf('enableA11y')) && (!empty($_firstimage))) {
82857f8d5bbSMark Prins                // add map local image into relation/firstimage if not already filled and when it is a local image
82957f8d5bbSMark Prins
83057f8d5bbSMark Prins                global $ID;
83157f8d5bbSMark Prins                $rel = p_get_metadata($ID, 'relation', METADATA_RENDER_USING_CACHE);
83268188742SMark Prins                // $img = $rel ['firstimage'];
83368188742SMark Prins                if (empty($rel ['firstimage']) /* || $img == $_firstimage*/) {
83457f8d5bbSMark Prins                    //dbglog ( $_firstimage,
83557f8d5bbSMark Prins                    // 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.' );
83657f8d5bbSMark Prins                    // This seems to never work; the firstimage entry in the .meta file is empty
83757f8d5bbSMark Prins                    // $renderer->meta['relation']['firstimage'] = $_firstimage;
83857f8d5bbSMark Prins
83957f8d5bbSMark Prins                    // ... and neither does this; the firstimage entry in the .meta file is empty
84057f8d5bbSMark Prins                    // $relation = array('relation'=>array('firstimage'=>$_firstimage));
84157f8d5bbSMark Prins                    // p_set_metadata($ID, $relation, false, false);
84257f8d5bbSMark Prins
84357f8d5bbSMark Prins                    // ... this works
84457f8d5bbSMark Prins                    $renderer->internalmedia($_firstimage, $poitabledesc);
84557f8d5bbSMark Prins                }
84657f8d5bbSMark Prins            }
84757f8d5bbSMark Prins            return true;
84857f8d5bbSMark Prins        }
84957f8d5bbSMark Prins        return false;
85057f8d5bbSMark Prins    }
85138a47c60SMark Prins}
852