138a47c60SMark Prins<?php 2a760825cSgithub-actions[bot] 338a47c60SMark Prins/* 4f204b8caSMark Prins * Copyright (c) 2008-2023 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 */ 20a760825cSgithub-actions[bot]use dokuwiki\Extension\SyntaxPlugin; 213ebe658bSMark Prinsuse geoPHP\Geometry\Point; 22f204b8caSMark Prinsuse dokuwiki\Logger; 233ebe658bSMark Prins 2438a47c60SMark Prins/** 25cc74a83cSMark Prins * DokuWiki Plugin openlayersmap (Syntax Component). 26cc74a83cSMark Prins * Provides for display of an OpenLayers based map in a wiki page. 27cc74a83cSMark Prins * 28cc74a83cSMark Prins * @author Mark Prins 2938a47c60SMark Prins */ 30a760825cSgithub-actions[bot]class syntax_plugin_openlayersmap_olmap extends SyntaxPlugin 31a760825cSgithub-actions[bot]{ 321c640875SMark Prins /** 331c640875SMark Prins * defaults of the known attributes of the olmap tag. 341c640875SMark Prins */ 35a760825cSgithub-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' => '']; 3638a47c60SMark Prins 3738a47c60SMark Prins /** 381c640875SMark Prins * 39cc74a83cSMark Prins * @see DokuWiki_Syntax_Plugin::getType() 4038a47c60SMark Prins */ 41a760825cSgithub-actions[bot] public function getType(): string 42a760825cSgithub-actions[bot] { 4375c98788SMark Prins return 'substition'; 4475c98788SMark Prins } 4538a47c60SMark Prins 4638a47c60SMark Prins /** 471c640875SMark Prins * 48cc74a83cSMark Prins * @see DokuWiki_Syntax_Plugin::getPType() 4938a47c60SMark Prins */ 50a760825cSgithub-actions[bot] public function getPType(): string 51a760825cSgithub-actions[bot] { 5275c98788SMark Prins return 'block'; 5375c98788SMark Prins } 5438a47c60SMark Prins 5538a47c60SMark Prins /** 561c640875SMark Prins * 57cc74a83cSMark Prins * @see Doku_Parser_Mode::getSort() 5838a47c60SMark Prins */ 59a760825cSgithub-actions[bot] public function getSort(): int 60a760825cSgithub-actions[bot] { 6175c98788SMark Prins return 901; 6275c98788SMark Prins } 63fc16f3cdSMark Prins 6438a47c60SMark Prins /** 651c640875SMark Prins * 66cc74a83cSMark Prins * @see Doku_Parser_Mode::connectTo() 6738a47c60SMark Prins */ 68a760825cSgithub-actions[bot] public function connectTo($mode) 69a760825cSgithub-actions[bot] { 7057f8d5bbSMark Prins $this->Lexer->addSpecialPattern( 71a760825cSgithub-actions[bot] '<olmap ?[^>\n]*>.*?</olmap>', 72a760825cSgithub-actions[bot] $mode, 7357f8d5bbSMark Prins 'plugin_openlayersmap_olmap' 7457f8d5bbSMark Prins ); 7538a47c60SMark Prins } 76fc16f3cdSMark Prins 7738a47c60SMark Prins /** 781c640875SMark Prins * 79cc74a83cSMark Prins * @see DokuWiki_Syntax_Plugin::handle() 8038a47c60SMark Prins */ 81a760825cSgithub-actions[bot] public function handle($match, $state, $pos, Doku_Handler $handler): array 82a760825cSgithub-actions[bot] { 833f760703SMark Prins // break matched data into its components 843f760703SMark Prins $_tag = explode('>', substr($match, 7, -9), 2); 853f760703SMark Prins $str_params = $_tag[0]; 863f760703SMark Prins if (array_key_exists(1, $_tag)) { 873f760703SMark Prins $str_points = $_tag[1]; 883f760703SMark Prins } else { 893f760703SMark Prins $str_points = ''; 903f760703SMark Prins } 91554f43b5SMark Prins // get the lat/lon for adding them to the metadata (used by geotag) 92d2f4772aSMark Prins preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat); 93d2f4772aSMark Prins preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon); 94554f43b5SMark Prins $mainLat = substr($mainLat [0], 5, -1); 95554f43b5SMark Prins $mainLon = substr($mainLon [0], 5, -1); 96d2f4772aSMark Prins if (!is_numeric($mainLat)) { 97d2f4772aSMark Prins $mainLat = $this->dflt ['lat']; 98d2f4772aSMark Prins } 99d2f4772aSMark Prins if (!is_numeric($mainLon)) { 100d2f4772aSMark Prins $mainLon = $this->dflt ['lon']; 101d2f4772aSMark Prins } 10238a47c60SMark Prins 10357f8d5bbSMark Prins $gmap = $this->extractParams($str_params); 10457f8d5bbSMark Prins $overlay = $this->extractPoints($str_points); 105fc16f3cdSMark Prins $_firstimageID = ''; 10638a47c60SMark Prins 1078e7c4263SMark Prins $_nocache = false; 108807d36baSMark Prins // choose maptype based on the specified tag 109628e43ccSMark Prins $imgUrl = "{{"; 110585afb49SMark Prins if (stripos($gmap ['baselyr'], 'google') !== false) { 1118e7c4263SMark Prins // Google 11257f8d5bbSMark Prins $imgUrl .= $this->getGoogle($gmap, $overlay); 1138e7c4263SMark Prins $imgUrl .= "&.png"; 114585afb49SMark Prins } elseif (stripos($gmap ['baselyr'], 'bing') !== false) { 1158e7c4263SMark Prins // Bing 116d974ea02SMark Prins if (!$this->getConf('bingAPIKey')) { 117d974ea02SMark Prins // in case there is no Bing api key we'll use OSM 11857f8d5bbSMark Prins $_firstimageID = $this->getStaticOSM($gmap, $overlay); 119d974ea02SMark Prins $imgUrl .= $_firstimageID; 120628e43ccSMark Prins if ($this->getConf('optionStaticMapGenerator') == 'remote') { 121628e43ccSMark Prins $imgUrl .= "&.png"; 122d974ea02SMark Prins } 123d974ea02SMark Prins } else { 1248e7c4263SMark Prins // seems that Bing doesn't like the DW client, turn off caching 1258e7c4263SMark Prins $_nocache = true; 12657f8d5bbSMark Prins $imgUrl .= $this->getBing($gmap, $overlay) . "&.png"; 127d974ea02SMark Prins } 128f204b8caSMark Prins /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) { 1298e7c4263SMark Prins // MapQuest 1308e7c4263SMark Prins if (! $this->getConf ( 'mapquestAPIKey' )) { 1318e7c4263SMark Prins // no API key for MapQuest, use OSM 13257f8d5bbSMark Prins $_firstimageID = $this->getStaticOSM ( $gmap, $overlay ); 133fc16f3cdSMark Prins $imgUrl .= $_firstimageID; 1348e7c4263SMark Prins if ($this->getConf ( 'optionStaticMapGenerator' ) == 'remote') { 1358e7c4263SMark Prins $imgUrl .= "&.png"; 136628e43ccSMark Prins } 13763037f21SMark Prins } else { 1388e7c4263SMark Prins $imgUrl .= $this->_getMapQuest ( $gmap, $overlay ); 1398e7c4263SMark Prins $imgUrl .= "&.png"; 1408e7c4263SMark Prins } 141f204b8caSMark Prins } */ 142f204b8caSMark Prins } else { 1438e7c4263SMark Prins // default OSM 14457f8d5bbSMark 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 15257f8d5bbSMark Prins $imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x" 15357f8d5bbSMark 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 16338a47c60SMark Prins $mapid = $gmap ['id']; 16438a47c60SMark Prins // create a javascript parameter string for the map 16538a47c60SMark Prins $param = ''; 16638a47c60SMark Prins foreach ($gmap as $key => $val) { 16738a47c60SMark Prins $param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', "; 16838a47c60SMark Prins } 16938a47c60SMark Prins if (!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; 178a760825cSgithub-actions[bot] if ($overlay !== []) { 17938a47c60SMark Prins foreach ($overlay as $data) { 180a760825cSgithub-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 Prins if (!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 Prins if (!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 Prins if (!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 243a760825cSgithub-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 */ 253a760825cSgithub-actions[bot] private function extractParams(string $str_params): array 254a760825cSgithub-actions[bot] { 255a760825cSgithub-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) { 267a760825cSgithub-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 */ 291a760825cSgithub-actions[bot] private function extractPoints(string $str_points): array 292a760825cSgithub-actions[bot] { 293a760825cSgithub-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', 306a760825cSgithub-actions[bot] $str_points, 307a760825cSgithub-actions[bot] $point, 308a760825cSgithub-actions[bot] PREG_SET_ORDER 30957f8d5bbSMark Prins ); 310554f43b5SMark Prins // create poi array 311a760825cSgithub-actions[bot] $overlay = []; 31238a47c60SMark Prins foreach ($point as $pt) { 313a760825cSgithub-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)); 325a760825cSgithub-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 */ 336a760825cSgithub-actions[bot] private function getGoogle(array $gmap, array $overlay): string 337a760825cSgithub-actions[bot] { 33857f8d5bbSMark Prins $sUrl = $this->getConf('iconUrlOverload'); 33957f8d5bbSMark Prins if (!$sUrl) { 34057f8d5bbSMark Prins $sUrl = DOKU_URL; 34157f8d5bbSMark Prins } 342*d29478dfSmprins $maptype = match ($gmap ['baselyr']) { 343*d29478dfSmprins 'google hybrid' => 'hybrid', 344*d29478dfSmprins 'google sat' => 'satellite', 345*d29478dfSmprins 'terrain', 'google relief' => 'terrain', 346*d29478dfSmprins default => 'roadmap', 347*d29478dfSmprins }; 34857f8d5bbSMark Prins // TODO maybe use viewport / visible instead of center/zoom, 34957f8d5bbSMark Prins // see: https://developers.google.com/maps/documentation/staticmaps/index#Viewports 35057f8d5bbSMark 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 35157f8d5bbSMark Prins $imgUrl = "https://maps.googleapis.com/maps/api/staticmap?"; 35257f8d5bbSMark Prins $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x" 35357f8d5bbSMark Prins . str_replace("px", "", $gmap ['height']); 35457f8d5bbSMark Prins //if (!$this->getConf( 'autoZoomMap')) { // no need for center & zoom params } 35557f8d5bbSMark Prins $imgUrl .= "¢er=" . $gmap ['lat'] . "," . $gmap ['lon']; 35657f8d5bbSMark Prins // max is 21 (== building scale), but that's overkill.. 35757f8d5bbSMark Prins if ($gmap ['zoom'] > 17) { 35857f8d5bbSMark Prins $imgUrl .= "&zoom=17"; 35957f8d5bbSMark Prins } else { 36057f8d5bbSMark Prins $imgUrl .= "&zoom=" . $gmap ['zoom']; 36157f8d5bbSMark Prins } 362a760825cSgithub-actions[bot] if ($overlay !== []) { 36357f8d5bbSMark Prins $rowId = 0; 36457f8d5bbSMark Prins foreach ($overlay as $data) { 365a760825cSgithub-actions[bot] [$lat, $lon, $text, $angle, $opacity, $img] = $data; 36657f8d5bbSMark Prins $imgUrl .= "&markers=icon%3a" . $sUrl . "lib/plugins/openlayersmap/icons/" . $img . "%7c" 36757f8d5bbSMark Prins . $lat . "," . $lon . "%7clabel%3a" . ++$rowId; 36857f8d5bbSMark Prins } 36957f8d5bbSMark Prins } 37057f8d5bbSMark Prins $imgUrl .= "&format=png&maptype=" . $maptype; 37157f8d5bbSMark Prins global $conf; 37257f8d5bbSMark Prins $imgUrl .= "&language=" . $conf ['lang']; 37357f8d5bbSMark Prins if ($this->getConf('googleAPIkey')) { 37457f8d5bbSMark Prins $imgUrl .= "&key=" . $this->getConf('googleAPIkey'); 37557f8d5bbSMark Prins } 37657f8d5bbSMark Prins return $imgUrl; 37757f8d5bbSMark Prins } 37857f8d5bbSMark Prins 37957f8d5bbSMark Prins /** 380fcd79b50SMark Prins * Create a MapQuest static map API image url. 3811c640875SMark Prins * 382fcd79b50SMark Prins * @param array $gmap 383fcd79b50SMark Prins * @param array $overlay 384fcd79b50SMark Prins */ 385e72390dbSMark Prins /* 386fcd79b50SMark Prins private function _getMapQuest($gmap, $overlay) { 387787a5195SMark Prins $sUrl = $this->getConf ( 'iconUrlOverload' ); 388787a5195SMark Prins if (! $sUrl) { 389787a5195SMark Prins $sUrl = DOKU_URL; 390787a5195SMark Prins } 39187d958d4SMark Prins switch ($gmap ['baselyr']) { 39294c2e868SMark Prins case 'mapquest hybrid' : 393837eba2fSMark Prins $maptype = 'hyb'; 39487d958d4SMark Prins break; 39518edeaa5SMark Prins case 'mapquest sat' : 39644aba0bcSMark Prins // because sat coverage is very limited use 'hyb' instead of 'sat' so we don't get a blank map 39744aba0bcSMark Prins $maptype = 'hyb'; 39887d958d4SMark Prins break; 39994c2e868SMark Prins case 'mapquest road' : 40087d958d4SMark Prins default : 40187d958d4SMark Prins $maptype = 'map'; 40287d958d4SMark Prins break; 40387d958d4SMark Prins } 404004ad4e2SMark Prins $imgUrl = "http://open.mapquestapi.com/staticmap/v4/getmap?declutter=true&"; 40544aba0bcSMark Prins if (count ( $overlay ) < 1) { 406787a5195SMark Prins $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon']; 407787a5195SMark Prins // max level for mapquest is 16 408fcd79b50SMark Prins if ($gmap ['zoom'] > 16) { 409fcd79b50SMark Prins $imgUrl .= "&zoom=16"; 410fcd79b50SMark Prins } else { 411fcd79b50SMark Prins $imgUrl .= "&zoom=" . $gmap ['zoom']; 412fcd79b50SMark Prins } 41344aba0bcSMark Prins } 41444aba0bcSMark Prins // use bestfit instead of center/zoom, needs upperleft/lowerright corners 41557f8d5bbSMark Prins // $bbox=$this->calcBBOX($overlay, $gmap['lat'], $gmap['lon']); 41644aba0bcSMark Prins // $imgUrl .= "bestfit=".$bbox['minlat'].",".$bbox['maxlon'].",".$bbox['maxlat'].",".$bbox['minlon']; 41744aba0bcSMark Prins 41857f8d5bbSMark Prins // TODO declutter option works well for square maps but not for rectangular, maybe compensate for that 41957f8d5bbSMark Prins // or compensate the mbr.. 42057f8d5bbSMark Prins 42144aba0bcSMark Prins $imgUrl .= "&size=" . str_replace ( "px", "", $gmap ['width'] ) . "," . str_replace ("px","",$gmap['height']); 42244aba0bcSMark Prins 423fcd79b50SMark Prins // TODO mapquest allows using one image url with a multiplier $NUMBER eg: 424fcd79b50SMark Prins // $NUMBER = 2 42557f8d5bbSMark Prins // $imgUrl .= DOKU_URL."/".DOKU_PLUGIN."/".getPluginName()."/icons/".$img.",$NUMBER,C," 42657f8d5bbSMark Prins // .$lat1.",".$lon1.",0,0,0,0,C,".$lat2.",".$lon2.",0,0,0,0"; 427fcd79b50SMark Prins if (! empty ( $overlay )) { 428fcd79b50SMark Prins $imgUrl .= "&xis="; 429fcd79b50SMark Prins foreach ( $overlay as $data ) { 430fcd79b50SMark Prins list ( $lat, $lon, $text, $angle, $opacity, $img ) = $data; 43144aba0bcSMark Prins // $imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",0,0,0,0,"; 43244aba0bcSMark Prins $imgUrl .= $sUrl . "lib/plugins/openlayersmap/icons/" . $img . ",1,C," . $lat . "," . $lon . ","; 433fcd79b50SMark Prins } 434fcd79b50SMark Prins $imgUrl = substr ( $imgUrl, 0, - 1 ); 435fcd79b50SMark Prins } 43687d958d4SMark Prins $imgUrl .= "&imageType=png&type=" . $maptype; 437d974ea02SMark Prins $imgUrl .= "&key=".$this->getConf ( 'mapquestAPIKey' ); 438787a5195SMark Prins return $imgUrl; 439787a5195SMark Prins } 440e72390dbSMark Prins */ 441cc74a83cSMark Prins 4426e633dd6SMark Prins /** 44387d958d4SMark Prins * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite) 444fcf646d2SMark Prins * use http://staticmap.openstreetmap.de "staticMapLite" or a local version 4451c640875SMark Prins * 44687d958d4SMark Prins * @param array $gmap 44787d958d4SMark Prins * @param array $overlay 448fcf646d2SMark Prins * 44957f8d5bbSMark Prins * @return false|string 450fcf646d2SMark Prins * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/ 45187d958d4SMark Prins */ 452a760825cSgithub-actions[bot] private function getStaticOSM(array $gmap, array $overlay) 453a760825cSgithub-actions[bot] { 454fcf646d2SMark Prins global $conf; 455372f1508SMark Prins 456751c8ef2SMark Prins if ($this->getConf('optionStaticMapGenerator') === 'local') { 457d974ea02SMark Prins // using local basemap composer 458a760825cSgithub-actions[bot] if (($myMap = plugin_load('helper', 'openlayersmap_staticmap')) === null) { 459f204b8caSMark Prins Logger::error( 460f204b8caSMark Prins 'openlayersmap_staticmap plugin is not available for use.', 461f204b8caSMark Prins $myMap 46257f8d5bbSMark Prins ); 46353bfe4a3SMark Prins } 464a760825cSgithub-actions[bot] if (($geophp = plugin_load('helper', 'geophp')) === null) { 465f204b8caSMark Prins Logger::debug('geophp plugin is not available for use.', $geophp); 46653bfe4a3SMark Prins } 46757f8d5bbSMark Prins $size = str_replace("px", "", $gmap ['width']) . "x" 46857f8d5bbSMark Prins . str_replace("px", "", $gmap ['height']); 46953bfe4a3SMark Prins 470a760825cSgithub-actions[bot] $markers = []; 471a760825cSgithub-actions[bot] if ($overlay !== []) { 47253bfe4a3SMark Prins foreach ($overlay as $data) { 473a760825cSgithub-actions[bot] [$lat, $lon, $text, $angle, $opacity, $img] = $data; 474751c8ef2SMark Prins $iconStyle = substr($img, 0, -4); 475a760825cSgithub-actions[bot] $markers [] = ['lat' => $lat, 'lon' => $lon, 'type' => $iconStyle]; 47653bfe4a3SMark Prins } 477372f1508SMark Prins } 478372f1508SMark Prins 479d2f4772aSMark Prins $apikey = ''; 48018edeaa5SMark Prins switch ($gmap ['baselyr']) { 48118edeaa5SMark Prins case 'mapnik': 482fcf646d2SMark Prins case 'openstreetmap': 483fcf646d2SMark Prins $maptype = 'openstreetmap'; 48418edeaa5SMark Prins break; 485fcf646d2SMark Prins case 'transport': 486fcf646d2SMark Prins $maptype = 'transport'; 487b63742deSMark Prins $apikey = '?apikey=' . $this->getConf('tfApiKey'); 488fcf646d2SMark Prins break; 489fcf646d2SMark Prins case 'landscape': 490fcf646d2SMark Prins $maptype = 'landscape'; 491b63742deSMark Prins $apikey = '?apikey=' . $this->getConf('tfApiKey'); 492d2f4772aSMark Prins break; 493d2f4772aSMark Prins case 'outdoors': 494d2f4772aSMark Prins $maptype = 'outdoors'; 495b63742deSMark Prins $apikey = '?apikey=' . $this->getConf('tfApiKey'); 49618edeaa5SMark Prins break; 49718edeaa5SMark Prins case 'cycle map': 49818edeaa5SMark Prins $maptype = 'cycle'; 499b63742deSMark Prins $apikey = '?apikey=' . $this->getConf('tfApiKey'); 500372f1508SMark Prins break; 501fcf646d2SMark Prins case 'hike and bike map': 502fcf646d2SMark Prins $maptype = 'hikeandbike'; 503fcf646d2SMark Prins break; 504fcf646d2SMark Prins case 'mapquest hybrid': 505fcf646d2SMark Prins case 'mapquest road': 506fcf646d2SMark Prins case 'mapquest sat': 507fcf646d2SMark Prins $maptype = 'mapquest'; 508fcf646d2SMark Prins break; 50918edeaa5SMark Prins default: 51018edeaa5SMark Prins $maptype = ''; 51118edeaa5SMark Prins break; 51218edeaa5SMark Prins } 513d974ea02SMark Prins 51457f8d5bbSMark Prins $result = $myMap->getMap( 515a760825cSgithub-actions[bot] $gmap ['lat'], 516a760825cSgithub-actions[bot] $gmap ['lon'], 517a760825cSgithub-actions[bot] $gmap ['zoom'], 518a760825cSgithub-actions[bot] $size, 519a760825cSgithub-actions[bot] $maptype, 520a760825cSgithub-actions[bot] $markers, 521a760825cSgithub-actions[bot] $gmap ['gpxfile'], 522a760825cSgithub-actions[bot] $gmap ['kmlfile'], 523a760825cSgithub-actions[bot] $gmap ['geojsonfile'], 524a760825cSgithub-actions[bot] $apikey 52557f8d5bbSMark Prins ); 526d974ea02SMark Prins } else { 527d974ea02SMark Prins // using external basemap composer 528d974ea02SMark Prins 52957f8d5bbSMark Prins // https://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10 53057f8d5bbSMark Prins //.117187497601&zoom=5&size=500x350 53157f8d5bbSMark Prins // &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306, 53257f8d5bbSMark Prins // lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369, 53357f8d5bbSMark Prins // ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236, 53457f8d5bbSMark Prins // ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green 53557f8d5bbSMark Prins $imgUrl = "https://staticmap.openstreetmap.de/staticmap.php"; 536d974ea02SMark Prins $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon']; 53757f8d5bbSMark Prins $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x" 53857f8d5bbSMark Prins . str_replace("px", "", $gmap ['height']); 539d974ea02SMark Prins 540d974ea02SMark Prins if ($gmap ['zoom'] > 16) { 541d974ea02SMark Prins // actually this could even be 18, but that seems overkill 542d974ea02SMark Prins $imgUrl .= "&zoom=16"; 543d974ea02SMark Prins } else { 544d974ea02SMark Prins $imgUrl .= "&zoom=" . $gmap ['zoom']; 545d974ea02SMark Prins } 54618edeaa5SMark Prins 547a760825cSgithub-actions[bot] if ($overlay !== []) { 54887d958d4SMark Prins $rowId = 0; 54987d958d4SMark Prins $imgUrl .= "&markers="; 55087d958d4SMark Prins foreach ($overlay as $data) { 551a760825cSgithub-actions[bot] [$lat, $lon, $text, $angle, $opacity, $img] = $data; 55287d958d4SMark Prins $rowId++; 55353bfe4a3SMark Prins $iconStyle = "lightblue$rowId"; 55487d958d4SMark Prins $imgUrl .= "$lat,$lon,$iconStyle%7c"; 55587d958d4SMark Prins } 55687d958d4SMark Prins $imgUrl = substr($imgUrl, 0, -3); 55787d958d4SMark Prins } 55887d958d4SMark Prins 559f4b9bdacSMark Prins $result = $imgUrl; 560628e43ccSMark Prins } 561628e43ccSMark Prins return $result; 562628e43ccSMark Prins } 563628e43ccSMark Prins 56444aba0bcSMark Prins /** 56557f8d5bbSMark Prins * Create a Bing maps static image url w/ the poi. 56657f8d5bbSMark Prins * 56757f8d5bbSMark Prins * @param array $gmap 56857f8d5bbSMark Prins * @param array $overlay 56957f8d5bbSMark Prins */ 570a760825cSgithub-actions[bot] private function getBing(array $gmap, array $overlay): string 571a760825cSgithub-actions[bot] { 572*d29478dfSmprins $maptype = match ($gmap ['baselyr']) { 573*d29478dfSmprins 've hybrid', 'bing hybrid' => 'AerialWithLabels', 574*d29478dfSmprins 've sat', 'bing sat' => 'Aerial', 575*d29478dfSmprins default => 'Road', 576*d29478dfSmprins }; 57757f8d5bbSMark Prins $imgUrl = "https://dev.virtualearth.net/REST/v1/Imagery/Map/" . $maptype;// . "/"; 57857f8d5bbSMark Prins if ($this->getConf('autoZoomMap')) { 57957f8d5bbSMark Prins $bbox = $this->calcBBOX($overlay, $gmap ['lat'], $gmap ['lon']); 58057f8d5bbSMark Prins //$imgUrl .= "?ma=" . $bbox ['minlat'] . "," . $bbox ['minlon'] . "," 58157f8d5bbSMark Prins // . $bbox ['maxlat'] . "," . $bbox ['maxlon']; 58257f8d5bbSMark Prins $imgUrl .= "?ma=" . $bbox ['minlat'] . "%2C" . $bbox ['minlon'] . "%2C" . $bbox ['maxlat'] 58357f8d5bbSMark Prins . "%2C" . $bbox ['maxlon']; 58457f8d5bbSMark Prins $imgUrl .= "&dcl=1"; 58557f8d5bbSMark Prins } 586*d29478dfSmprins if (!str_contains($imgUrl, "?")) 58757f8d5bbSMark Prins $imgUrl .= "?"; 58857f8d5bbSMark Prins 58957f8d5bbSMark Prins //$imgUrl .= "&ms=" . str_replace ( "px", "", $gmap ['width'] ) . "," 59057f8d5bbSMark Prins // . str_replace ( "px", "", $gmap ['height'] ); 59157f8d5bbSMark Prins $imgUrl .= "&ms=" . str_replace("px", "", $gmap ['width']) . "%2C" 59257f8d5bbSMark Prins . str_replace("px", "", $gmap ['height']); 59357f8d5bbSMark Prins $imgUrl .= "&key=" . $this->getConf('bingAPIKey'); 594a760825cSgithub-actions[bot] if ($overlay !== []) { 59557f8d5bbSMark Prins $rowId = 0; 59657f8d5bbSMark Prins foreach ($overlay as $data) { 597a760825cSgithub-actions[bot] [$lat, $lon, $text, $angle, $opacity, $img] = $data; 59857f8d5bbSMark Prins // TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle 59957f8d5bbSMark Prins $iconStyle = 32; 60057f8d5bbSMark Prins $rowId++; 60157f8d5bbSMark Prins // NOTE: the max number of pushpins is 18! or we have to use POST 60257f8d5bbSMark Prins // (http://msdn.microsoft.com/en-us/library/ff701724.aspx) 60357f8d5bbSMark Prins if ($rowId == 18) { 60457f8d5bbSMark Prins break; 60557f8d5bbSMark Prins } 60657f8d5bbSMark Prins //$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId"; 60757f8d5bbSMark Prins $imgUrl .= "&pp=$lat%2C$lon%3B$iconStyle%3B$rowId"; 60857f8d5bbSMark Prins } 60957f8d5bbSMark Prins } 61057f8d5bbSMark Prins global $conf; 61157f8d5bbSMark Prins $imgUrl .= "&fmt=png"; 61257f8d5bbSMark Prins $imgUrl .= "&c=" . $conf ['lang']; 61357f8d5bbSMark Prins return $imgUrl; 61457f8d5bbSMark Prins } 61557f8d5bbSMark Prins 61657f8d5bbSMark Prins /** 61744aba0bcSMark Prins * Calculate the minimum bbox for a start location + poi. 61844aba0bcSMark Prins * 6191c640875SMark Prins * @param array $overlay 6201c640875SMark Prins * multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img) 6211c640875SMark Prins * @param float $lat 6221c640875SMark Prins * latitude for map center 6231c640875SMark Prins * @param float $lon 6241c640875SMark Prins * longitude for map center 62557f8d5bbSMark Prins * @return array :float array describing the mbr and center point 62644aba0bcSMark Prins */ 627a760825cSgithub-actions[bot] private function calcBBOX(array $overlay, float $lat, float $lon): array 628a760825cSgithub-actions[bot] { 629a760825cSgithub-actions[bot] $lats = [$lat]; 630a760825cSgithub-actions[bot] $lons = [$lon]; 631837eba2fSMark Prins foreach ($overlay as $data) { 632a760825cSgithub-actions[bot] [$lat, $lon, $text, $angle, $opacity, $img] = $data; 633837eba2fSMark Prins $lats [] = $lat; 634837eba2fSMark Prins $lons [] = $lon; 635837eba2fSMark Prins } 636837eba2fSMark Prins sort($lats); 637837eba2fSMark Prins sort($lons); 63844aba0bcSMark Prins // TODO: make edge/wrap around cases work 63944aba0bcSMark Prins $centerlat = $lats [0] + ($lats [count($lats) - 1] - $lats [0]); 64044aba0bcSMark Prins $centerlon = $lons [0] + ($lons [count($lats) - 1] - $lons [0]); 641a760825cSgithub-actions[bot] return ['minlat' => $lats [0], 'minlon' => $lons [0], 'maxlat' => $lats [count($lats) - 1], 'maxlon' => $lons [count($lats) - 1], 'centerlat' => $centerlat, 'centerlon' => $centerlon]; 64287d958d4SMark Prins } 643cc74a83cSMark Prins 644cc74a83cSMark Prins /** 64557f8d5bbSMark Prins * convert latitude in decimal degrees to DMS+hemisphere. 6461c640875SMark Prins * 64757f8d5bbSMark Prins * @param float $decimaldegrees 64857f8d5bbSMark Prins * @todo move this into a shared library 649cc74a83cSMark Prins */ 650a760825cSgithub-actions[bot] private function convertLat(float $decimaldegrees): string 651a760825cSgithub-actions[bot] { 652*d29478dfSmprins if (str_contains($decimaldegrees, '-')) { 65357f8d5bbSMark Prins $latPos = "S"; 65457f8d5bbSMark Prins } else { 65557f8d5bbSMark Prins $latPos = "N"; 65657f8d5bbSMark Prins } 65757f8d5bbSMark Prins $dms = $this->convertDDtoDMS(abs($decimaldegrees)); 65857f8d5bbSMark Prins return hsc($dms . $latPos); 659cc74a83cSMark Prins } 6608c4eb2fdSMark Prins 6618c4eb2fdSMark Prins /** 6628c4eb2fdSMark Prins * Convert decimal degrees to degrees, minutes, seconds format 6638c4eb2fdSMark Prins * 6648c4eb2fdSMark Prins * @param float $decimaldegrees 6658c4eb2fdSMark Prins * @return string dms 66657f8d5bbSMark Prins * @todo move this into a shared library 6678c4eb2fdSMark Prins */ 668a760825cSgithub-actions[bot] private function convertDDtoDMS(float $decimaldegrees): string 669a760825cSgithub-actions[bot] { 6708c4eb2fdSMark Prins $dms = floor($decimaldegrees); 6718c4eb2fdSMark Prins $secs = ($decimaldegrees - $dms) * 3600; 6728c4eb2fdSMark Prins $min = floor($secs / 60); 6738c4eb2fdSMark Prins $sec = round($secs - ($min * 60), 3); 6748c4eb2fdSMark Prins $dms .= 'º' . $min . '\'' . $sec . '"'; 6758c4eb2fdSMark Prins return $dms; 6768c4eb2fdSMark Prins } 6778c4eb2fdSMark Prins 6788c4eb2fdSMark Prins /** 6798c4eb2fdSMark Prins * convert longitude in decimal degrees to DMS+hemisphere. 6808c4eb2fdSMark Prins * 6818c4eb2fdSMark Prins * @param float $decimaldegrees 68257f8d5bbSMark Prins * @todo move this into a shared library 6838c4eb2fdSMark Prins */ 684a760825cSgithub-actions[bot] private function convertLon(float $decimaldegrees): string 685a760825cSgithub-actions[bot] { 686*d29478dfSmprins if (str_contains($decimaldegrees, '-')) { 6878c4eb2fdSMark Prins $lonPos = "W"; 6888c4eb2fdSMark Prins } else { 6898c4eb2fdSMark Prins $lonPos = "E"; 6908c4eb2fdSMark Prins } 69157f8d5bbSMark Prins $dms = $this->convertDDtoDMS(abs($decimaldegrees)); 6928c4eb2fdSMark Prins return hsc($dms . $lonPos); 6938c4eb2fdSMark Prins } 69457f8d5bbSMark Prins 69557f8d5bbSMark Prins /** 69657f8d5bbSMark Prins * Figures out the base filename of a media path. 69757f8d5bbSMark Prins * 69857f8d5bbSMark Prins * @param string $mediaLink 69957f8d5bbSMark Prins */ 700a760825cSgithub-actions[bot] private function getFileName(string $mediaLink): string 701a760825cSgithub-actions[bot] { 70257f8d5bbSMark Prins $mediaLink = str_replace('[[', '', $mediaLink); 70357f8d5bbSMark Prins $mediaLink = str_replace(']]', '', $mediaLink); 70457f8d5bbSMark Prins $mediaLink = substr($mediaLink, 0, -4); 705a760825cSgithub-actions[bot] 70657f8d5bbSMark Prins $parts = explode(':', $mediaLink); 70757f8d5bbSMark Prins $mediaLink = end($parts); 70857f8d5bbSMark Prins return str_replace('_', ' ', $mediaLink); 70957f8d5bbSMark Prins } 71057f8d5bbSMark Prins 71157f8d5bbSMark Prins /** 71257f8d5bbSMark Prins * 71357f8d5bbSMark Prins * @see DokuWiki_Syntax_Plugin::render() 71457f8d5bbSMark Prins */ 715a760825cSgithub-actions[bot] public function render($format, Doku_Renderer $renderer, $data): bool 716a760825cSgithub-actions[bot] { 71757f8d5bbSMark Prins // set to true after external scripts tags are written 71857f8d5bbSMark Prins static $initialised = false; 71957f8d5bbSMark Prins // incremented for each map tag in the page source so we can keep track of each map in this page 72057f8d5bbSMark Prins static $mapnumber = 0; 72157f8d5bbSMark Prins 722a760825cSgithub-actions[bot] [$mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage] = $data; 72357f8d5bbSMark Prins 724751c8ef2SMark Prins if ($format === 'xhtml') { 72557f8d5bbSMark Prins $olscript = ''; 726751c8ef2SMark Prins $stadiaEnable = $this->getConf('enableStadia'); 72757f8d5bbSMark Prins $osmEnable = $this->getConf('enableOSM'); 72857f8d5bbSMark Prins $enableBing = $this->getConf('enableBing'); 72957f8d5bbSMark Prins 73057f8d5bbSMark Prins $scriptEnable = ''; 73157f8d5bbSMark Prins if (!$initialised) { 73257f8d5bbSMark Prins $initialised = true; 7337390889dSMark Prins // render necessary script tags only once 734660554e1SMark Prins $olscript = '<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol/ol.js"></script> 735660554e1SMark Prins<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol/ol-layerswitcher.js"></script>'; 73657f8d5bbSMark Prins 73757f8d5bbSMark Prins $scriptEnable = '<script defer="defer" src="data:text/javascript;base64,'; 7387390889dSMark Prins $scriptSrc = $olscript ? 'const olEnable=true;' : 'const olEnable=false;'; 7397390889dSMark Prins $scriptSrc .= 'const osmEnable=' . ($osmEnable ? 'true' : 'false') . ';'; 740751c8ef2SMark Prins $scriptSrc .= 'const stadiaEnable=' . ($stadiaEnable ? 'true' : 'false') . ';'; 7417390889dSMark Prins $scriptSrc .= 'const bEnable=' . ($enableBing ? 'true' : 'false') . ';'; 7427390889dSMark Prins $scriptSrc .= 'const bApiKey="' . $this->getConf('bingAPIKey') . '";'; 7437390889dSMark Prins $scriptSrc .= 'const tfApiKey="' . $this->getConf('tfApiKey') . '";'; 7447390889dSMark Prins $scriptSrc .= 'const gApiKey="' . $this->getConf('googleAPIkey') . '";'; 7457390889dSMark Prins $scriptSrc .= 'olMapData = []; let olMaps = {}; let olMapOverlays = {};'; 74657f8d5bbSMark Prins $scriptEnable .= base64_encode($scriptSrc); 74757f8d5bbSMark Prins $scriptEnable .= '"></script>'; 74857f8d5bbSMark Prins } 7497390889dSMark Prins $renderer->doc .= "$olscript\n$scriptEnable"; 75057f8d5bbSMark Prins $renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>'; 75157f8d5bbSMark Prins if ($this->getConf('enableA11y')) { 75257f8d5bbSMark Prins $renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">' 75357f8d5bbSMark Prins . p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>'; 75457f8d5bbSMark Prins } 75557f8d5bbSMark Prins $renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p> </p></div>'; 75657f8d5bbSMark Prins if ($this->getConf('enableA11y')) { 75757f8d5bbSMark Prins // render a table of the POI for the print and a11y presentation, it is hidden using javascript 7587390889dSMark Prins $renderer->doc .= ' 7593f760703SMark Prins <div id="' . $mapid . '-table-span" class="olPOItableSpan"> 7603f760703SMark Prins <table id="' . $mapid . '-table" class="olPOItable"> 76157f8d5bbSMark Prins <caption class="olPOITblCaption">' . $this->getLang('olmapPOItitle') . '</caption> 76257f8d5bbSMark Prins <thead class="olPOITblHeader"> 76357f8d5bbSMark Prins <tr> 76457f8d5bbSMark Prins <th class="rowId" scope="col">id</th> 76557f8d5bbSMark Prins <th class="icon" scope="col">' . $this->getLang('olmapPOIicon') . '</th> 76657f8d5bbSMark Prins <th class="lat" scope="col" title="' . $this->getLang('olmapPOIlatTitle') . '">' 76757f8d5bbSMark Prins . $this->getLang('olmapPOIlat') . '</th> 76857f8d5bbSMark Prins <th class="lon" scope="col" title="' . $this->getLang('olmapPOIlonTitle') . '">' 76957f8d5bbSMark Prins . $this->getLang('olmapPOIlon') . '</th> 77057f8d5bbSMark Prins <th class="txt" scope="col">' . $this->getLang('olmapPOItxt') . '</th> 77157f8d5bbSMark Prins </tr> 77257f8d5bbSMark Prins </thead>'; 77357f8d5bbSMark Prins if ($poitabledesc != '') { 77457f8d5bbSMark Prins $renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc 77557f8d5bbSMark Prins . '</td></tr></tfoot>'; 77657f8d5bbSMark Prins } 77757f8d5bbSMark Prins $renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody> 7787390889dSMark Prins </table> 7797390889dSMark Prins </div>'; 7807390889dSMark Prins $renderer->doc .= "\n"; 78157f8d5bbSMark Prins } 78257f8d5bbSMark Prins // render inline mapscript parts 78357f8d5bbSMark Prins $renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,'; 78457f8d5bbSMark Prins $renderer->doc .= base64_encode("olMapData[$mapnumber] = $param"); 78557f8d5bbSMark Prins $renderer->doc .= '"></script>'; 78657f8d5bbSMark Prins $mapnumber++; 78757f8d5bbSMark Prins return true; 788751c8ef2SMark Prins } elseif ($format === 'metadata') { 78957f8d5bbSMark Prins if (!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) { 79057f8d5bbSMark Prins // render geo metadata, unless they are the default 79157f8d5bbSMark Prins $renderer->meta ['geo'] ['lat'] = $mainLat; 79257f8d5bbSMark Prins $renderer->meta ['geo'] ['lon'] = $mainLon; 793a760825cSgithub-actions[bot] if (($geophp = plugin_load('helper', 'geophp')) !== null) { 79457f8d5bbSMark Prins // if we have the geoPHP helper, add the geohash 795f204b8caSMark Prins try { 796f204b8caSMark Prins $renderer->meta['geo']['geohash'] = (new Point($mainLon, $mainLat))->out('geohash'); 797*d29478dfSmprins } catch (Exception) { 798f204b8caSMark Prins Logger::error("Failed to create geohash for: $mainLat, $mainLon"); 799f204b8caSMark Prins } 80057f8d5bbSMark Prins } 80157f8d5bbSMark Prins } 80257f8d5bbSMark Prins 80357f8d5bbSMark Prins if (($this->getConf('enableA11y')) && (!empty($_firstimage))) { 80457f8d5bbSMark Prins // add map local image into relation/firstimage if not already filled and when it is a local image 80557f8d5bbSMark Prins 80657f8d5bbSMark Prins global $ID; 80757f8d5bbSMark Prins $rel = p_get_metadata($ID, 'relation', METADATA_RENDER_USING_CACHE); 80868188742SMark Prins // $img = $rel ['firstimage']; 80968188742SMark Prins if (empty($rel ['firstimage']) /* || $img == $_firstimage*/) { 810f204b8caSMark Prins //Logger::debug( 811f204b8caSMark Prins // 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.', 812f204b8caSMark Prins // $_firstimage); 813f204b8caSMark Prins 81457f8d5bbSMark Prins // This seems to never work; the firstimage entry in the .meta file is empty 81557f8d5bbSMark Prins // $renderer->meta['relation']['firstimage'] = $_firstimage; 81657f8d5bbSMark Prins // ... and neither does this; the firstimage entry in the .meta file is empty 81757f8d5bbSMark Prins // $relation = array('relation'=>array('firstimage'=>$_firstimage)); 81857f8d5bbSMark Prins // p_set_metadata($ID, $relation, false, false); 81957f8d5bbSMark Prins // ... this works 82057f8d5bbSMark Prins $renderer->internalmedia($_firstimage, $poitabledesc); 82157f8d5bbSMark Prins } 82257f8d5bbSMark Prins } 82357f8d5bbSMark Prins return true; 82457f8d5bbSMark Prins } 82557f8d5bbSMark Prins return false; 82657f8d5bbSMark Prins } 82738a47c60SMark Prins} 828