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