Passed
Pull Request — master (#8)
by Mark
02:31
created

syntax_plugin_openlayersmap_olmap::convertLon()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
eloc 6
c 2
b 1
f 0
nc 2
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
/*
4
 * Copyright (c) 2008-2023 Mark C. Prins <[email protected]>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 *
18
 * @phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
19
 */
20
use dokuwiki\Extension\SyntaxPlugin;
0 ignored issues
show
Bug introduced by
The type dokuwiki\Extension\SyntaxPlugin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use geoPHP\Geometry\Point;
0 ignored issues
show
Bug introduced by
The type geoPHP\Geometry\Point was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
23
/**
24
 * DokuWiki Plugin openlayersmap (Syntax Component).
25
 * Provides for display of an OpenLayers based map in a wiki page.
26
 *
27
 * @author Mark Prins
28
 */
29
class syntax_plugin_openlayersmap_olmap extends SyntaxPlugin
30
{
31
    /**
32
     * defaults of the known attributes of the olmap tag.
33
     */
34
    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'       => ''];
35
36
    /**
37
     *
38
     * @see DokuWiki_Syntax_Plugin::getType()
39
     */
40
    public function getType(): string
41
    {
42
        return 'substition';
43
    }
44
45
    /**
46
     *
47
     * @see DokuWiki_Syntax_Plugin::getPType()
48
     */
49
    public function getPType(): string
50
    {
51
        return 'block';
52
    }
53
54
    /**
55
     *
56
     * @see Doku_Parser_Mode::getSort()
57
     */
58
    public function getSort(): int
59
    {
60
        return 901;
61
    }
62
63
    /**
64
     *
65
     * @see Doku_Parser_Mode::connectTo()
66
     */
67
    public function connectTo($mode)
68
    {
69
        $this->Lexer->addSpecialPattern(
70
            '<olmap ?[^>\n]*>.*?</olmap>',
71
            $mode,
72
            'plugin_openlayersmap_olmap'
73
        );
74
    }
75
76
    /**
77
     *
78
     * @see DokuWiki_Syntax_Plugin::handle()
79
     */
80
    public function handle($match, $state, $pos, Doku_Handler $handler): array
0 ignored issues
show
Bug introduced by
The type Doku_Handler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
81
    {
82
        // break matched data into its components
83
        $_tag       = explode('>', substr($match, 7, -9), 2);
84
        $str_params = $_tag[0];
85
        if (array_key_exists(1, $_tag)) {
86
            $str_points = $_tag[1];
87
        } else {
88
            $str_points = '';
89
        }
90
        // get the lat/lon for adding them to the metadata (used by geotag)
91
        preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat);
92
        preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon);
93
        $mainLat = substr($mainLat [0], 5, -1);
94
        $mainLon = substr($mainLon [0], 5, -1);
95
        if (!is_numeric($mainLat)) {
96
            $mainLat = $this->dflt ['lat'];
97
        }
98
        if (!is_numeric($mainLon)) {
99
            $mainLon = $this->dflt ['lon'];
100
        }
101
102
        $gmap          = $this->extractParams($str_params);
103
        $overlay = $this->extractPoints($str_points);
104
        $_firstimageID = '';
105
106
        $_nocache = false;
107
        // choose maptype based on the specified tag
108
        $imgUrl = "{{";
109
        if (stripos($gmap ['baselyr'], 'google') !== false) {
110
            // Google
111
            $imgUrl .= $this->getGoogle($gmap, $overlay);
112
            $imgUrl .= "&.png";
113
        } elseif (stripos($gmap ['baselyr'], 'bing') !== false) {
114
            // Bing
115
            if (!$this->getConf('bingAPIKey')) {
116
                // in case there is no Bing api key we'll use OSM
117
                $_firstimageID = $this->getStaticOSM($gmap, $overlay);
118
                $imgUrl        .= $_firstimageID;
119
                if ($this->getConf('optionStaticMapGenerator') == 'remote') {
120
                    $imgUrl .= "&.png";
121
                }
122
            } else {
123
                // seems that Bing doesn't like the DW client, turn off caching
124
                $_nocache = true;
125
                $imgUrl   .= $this->getBing($gmap, $overlay) . "&.png";
126
            }
127
         /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) {
128
            // MapQuest
129
            if (! $this->getConf ( 'mapquestAPIKey' )) {
130
                // no API key for MapQuest, use OSM
131
                $_firstimageID = $this->getStaticOSM ( $gmap, $overlay );
132
                $imgUrl .= $_firstimageID;
133
                if ($this->getConf ( 'optionStaticMapGenerator' ) == 'remote') {
134
                    $imgUrl .= "&.png";
135
                }
136
            } else {
137
                $imgUrl .= $this->_getMapQuest ( $gmap, $overlay );
138
                $imgUrl .= "&.png";
139
            }
140
        } */
141
        } else {
142
            // default OSM
143
            $_firstimageID = $this->getStaticOSM($gmap, $overlay);
144
            $imgUrl        .= $_firstimageID;
145
            if ($this->getConf('optionStaticMapGenerator') == 'remote') {
146
                $imgUrl .= "&.png";
147
            }
148
        }
149
150
        // append dw p_render specific params and render
151
        $imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x"
152
            . str_replace("px", "", $gmap ['height']);
153
        $imgUrl .= "&nolink";
154
155
        // add nocache option for selected services
156
        if ($_nocache) {
157
            $imgUrl .= "&nocache";
158
        }
159
160
        $imgUrl .= " |" . $gmap ['summary'] . " }}";
161
162
        $mapid = $gmap ['id'];
163
        // create a javascript parameter string for the map
164
        $param = '';
165
        foreach ($gmap as $key => $val) {
166
            $param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
0 ignored issues
show
Bug introduced by
The function hsc was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

166
            $param .= is_numeric($val) ? "$key: $val, " : "$key: '" . /** @scrutinizer ignore-call */ hsc($val) . "', ";
Loading history...
167
        }
168
        if (!empty($param)) {
169
            $param = substr($param, 0, -2);
170
        }
171
        unset($gmap ['id']);
172
173
        // create a javascript serialisation of the point data
174
        $poi      = '';
175
        $poitable = '';
176
        $rowId    = 0;
177
        if ($overlay !== []) {
178
            foreach ($overlay as $data) {
179
                [$lat, $lon, $text, $angle, $opacity, $img] = $data;
180
                $rowId++;
181
                $poi .= ", {lat:$lat,lon:$lon,txt:'$text',angle:$angle,opacity:$opacity,img:'$img',rowId: $rowId}";
182
183
                if ($this->getConf('displayformat') === 'DMS') {
184
                    $lat = $this->convertLat($lat);
185
                    $lon = $this->convertLon($lon);
186
                } else {
187
                    $lat .= 'º';
188
                    $lon .= 'º';
189
                }
190
191
                $poitable .= '
192
                    <tr>
193
                    <td class="rowId">' . $rowId . '</td>
194
                    <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/icons/' . $img . '" alt="'
0 ignored issues
show
Bug introduced by
The constant DOKU_BASE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
195
                    . substr($img, 0, -4) . $this->getlang('alt_legend_poi') . '" /></td>
196
                    <td class="lat" title="' . $this->getLang('olmapPOIlatTitle') . '">' . $lat . '</td>
197
                    <td class="lon" title="' . $this->getLang('olmapPOIlonTitle') . '">' . $lon . '</td>
198
                    <td class="txt">' . $text . '</td>
199
                    </tr>';
200
            }
201
            $poi = substr($poi, 2);
202
        }
203
        if (!empty($gmap ['kmlfile'])) {
204
            $poitable .= '
205
                    <tr>
206
                    <td class="rowId"><img src="' . DOKU_BASE
207
                . 'lib/plugins/openlayersmap/toolbar/kml_file.png" alt="KML file" /></td>
208
                    <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/toolbar/kml_line.png" alt="'
209
                . $this->getlang('alt_legend_kml') . '" /></td>
210
                    <td class="txt" colspan="3">KML track: ' . $this->getFileName($gmap ['kmlfile']) . '</td>
211
                    </tr>';
212
        }
213
        if (!empty($gmap ['gpxfile'])) {
214
            $poitable .= '
215
                    <tr>
216
                    <td class="rowId"><img src="' . DOKU_BASE
217
                . 'lib/plugins/openlayersmap/toolbar/gpx_file.png" alt="GPX file" /></td>
218
                    <td class="icon"><img src="' . DOKU_BASE
219
                . 'lib/plugins/openlayersmap/toolbar/gpx_line.png" alt="'
220
                . $this->getlang('alt_legend_gpx') . '" /></td>
221
                    <td class="txt" colspan="3">GPX track: ' . $this->getFileName($gmap ['gpxfile']) . '</td>
222
                    </tr>';
223
        }
224
        if (!empty($gmap ['geojsonfile'])) {
225
            $poitable .= '
226
                    <tr>
227
                    <td class="rowId"><img src="' . DOKU_BASE
228
                . 'lib/plugins/openlayersmap/toolbar/geojson_file.png" alt="GeoJSON file" /></td>
229
                    <td class="icon"><img src="' . DOKU_BASE
230
                . 'lib/plugins/openlayersmap/toolbar/geojson_line.png" alt="'
231
                . $this->getlang('alt_legend_geojson') . '" /></td>
232
                    <td class="txt" colspan="3">GeoJSON track: ' . $this->getFileName($gmap ['geojsonfile']) . '</td>
233
                    </tr>';
234
        }
235
236
        $autozoom = empty($gmap ['autozoom']) ? $this->getConf('autoZoomMap') : $gmap ['autozoom'];
237
        $js       = "{mapOpts: {" . $param . ", displayformat: '" . $this->getConf('displayformat')
238
            . "', autozoom: " . $autozoom . "}, poi: [$poi]};";
239
        // unescape the json
240
        $poitable = stripslashes($poitable);
241
242
        return [$mapid, $js, $mainLat, $mainLon, $poitable, $gmap ['summary'], $imgUrl, $_firstimageID];
243
    }
244
245
    /**
246
     * extract parameters for the map from the parameter string
247
     *
248
     * @param string $str_params
249
     *            string of key="value" pairs
250
     * @return array associative array of parameters key=>value
251
     */
252
    private function extractParams(string $str_params): array
253
    {
254
        $param = [];
255
        preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
256
        // parse match for instructions, break into key value pairs
257
        $gmap = $this->dflt;
258
        foreach ($gmap as $key => &$value) {
259
            $defval = $this->getConf('default_' . $key);
260
            if ($defval !== '') {
261
                $value = $defval;
262
            }
263
        }
264
        unset($value);
265
        foreach ($param as $kvpair) {
266
            [$match, $key, $val] = $kvpair;
267
            $key = strtolower($key);
268
            if (isset($gmap [$key])) {
269
                if ($key == 'summary') {
270
                    // preserve case for summary field
271
                    $gmap [$key] = $val;
272
                } elseif ($key == 'id') {
273
                    // preserve case for id field
274
                    $gmap [$key] = $val;
275
                } else {
276
                    $gmap [$key] = strtolower($val);
277
                }
278
            }
279
        }
280
        return $gmap;
281
    }
282
283
    /**
284
     * extract overlay points for the map from the wiki syntax data
285
     *
286
     * @param string $str_points
287
     *            multi-line string of lat,lon,text triplets
288
     * @return array multi-dimensional array of lat,lon,text triplets
289
     */
290
    private function extractPoints(string $str_points): array
291
    {
292
        $point = [];
293
        // preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um',
294
        //      $str_points, $point, PREG_SET_ORDER);
295
        /*
296
         * group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
297
         * group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
298
         * group 3: (.*?)
299
         * group 4: (.*?)
300
         * group 5: (.*?)
301
         * group 6: (.*)
302
         */
303
        preg_match_all(
304
            '/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um',
305
            $str_points,
306
            $point,
307
            PREG_SET_ORDER
308
        );
309
        // create poi array
310
        $overlay = [];
311
        foreach ($point as $pt) {
312
            [$match, $lat, $lon, $angle, $opacity, $img, $text] = $pt;
313
            $lat     = is_numeric($lat) ? $lat : 0;
314
            $lon     = is_numeric($lon) ? $lon : 0;
315
            $angle   = is_numeric($angle) ? $angle : 0;
316
            $opacity = is_numeric($opacity) ? $opacity : 0.8;
317
            // TODO validate using exist & set up default img?
318
            $img  = trim($img);
319
            $text = p_get_instructions($text);
0 ignored issues
show
Bug introduced by
The function p_get_instructions was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

319
            $text = /** @scrutinizer ignore-call */ p_get_instructions($text);
Loading history...
320
            // dbg ( $text );
321
            $text = p_render("xhtml", $text, $info);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $info seems to be never defined.
Loading history...
Bug introduced by
The function p_render was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

321
            $text = /** @scrutinizer ignore-call */ p_render("xhtml", $text, $info);
Loading history...
322
            // dbg ( $text );
323
            $text       = addslashes(str_replace("\n", "", $text));
324
            $overlay [] = [$lat, $lon, $text, $angle, $opacity, $img];
325
        }
326
        return $overlay;
327
    }
328
329
    /**
330
     * Create a Google maps static image url w/ the poi.
331
     *
332
     * @param array $gmap
333
     * @param array $overlay
334
     */
335
    private function getGoogle(array $gmap, array $overlay): string
336
    {
337
        $sUrl = $this->getConf('iconUrlOverload');
338
        if (!$sUrl) {
339
            $sUrl = DOKU_URL;
0 ignored issues
show
Bug introduced by
The constant DOKU_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
340
        }
341
        switch ($gmap ['baselyr']) {
342
            case 'google hybrid':
343
                $maptype = 'hybrid';
344
                break;
345
            case 'google sat':
346
                $maptype = 'satellite';
347
                break;
348
            case 'terrain':
349
            case 'google relief':
350
                $maptype = 'terrain';
351
                break;
352
            case 'google road':
353
            default:
354
                $maptype = 'roadmap';
355
                break;
356
        }
357
        // TODO maybe use viewport / visible instead of center/zoom,
358
        // see: https://developers.google.com/maps/documentation/staticmaps/index#Viewports
359
        // 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
360
        $imgUrl = "https://maps.googleapis.com/maps/api/staticmap?";
361
        $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
362
            . str_replace("px", "", $gmap ['height']);
363
        //if (!$this->getConf( 'autoZoomMap')) { // no need for center & zoom params }
364
        $imgUrl .= "&center=" . $gmap ['lat'] . "," . $gmap ['lon'];
365
        // max is 21 (== building scale), but that's overkill..
366
        if ($gmap ['zoom'] > 17) {
367
            $imgUrl .= "&zoom=17";
368
        } else {
369
            $imgUrl .= "&zoom=" . $gmap ['zoom'];
370
        }
371
        if ($overlay !== []) {
372
            $rowId = 0;
373
            foreach ($overlay as $data) {
374
                [$lat, $lon, $text, $angle, $opacity, $img] = $data;
375
                $imgUrl .= "&markers=icon%3a" . $sUrl . "lib/plugins/openlayersmap/icons/" . $img . "%7c"
376
                    . $lat . "," . $lon . "%7clabel%3a" . ++$rowId;
377
            }
378
        }
379
        $imgUrl .= "&format=png&maptype=" . $maptype;
380
        global $conf;
381
        $imgUrl .= "&language=" . $conf ['lang'];
382
        if ($this->getConf('googleAPIkey')) {
383
            $imgUrl .= "&key=" . $this->getConf('googleAPIkey');
384
        }
385
        return $imgUrl;
386
    }
387
388
    /**
389
     * Create a MapQuest static map API image url.
390
     *
391
     * @param array $gmap
392
     * @param array $overlay
393
     */
394
    /*
395
   private function _getMapQuest($gmap, $overlay) {
396
       $sUrl = $this->getConf ( 'iconUrlOverload' );
397
       if (! $sUrl) {
398
           $sUrl = DOKU_URL;
399
       }
400
       switch ($gmap ['baselyr']) {
401
           case 'mapquest hybrid' :
402
               $maptype = 'hyb';
403
               break;
404
           case 'mapquest sat' :
405
               // because sat coverage is very limited use 'hyb' instead of 'sat' so we don't get a blank map
406
               $maptype = 'hyb';
407
               break;
408
           case 'mapquest road' :
409
           default :
410
               $maptype = 'map';
411
               break;
412
       }
413
       $imgUrl = "http://open.mapquestapi.com/staticmap/v4/getmap?declutter=true&";
414
       if (count ( $overlay ) < 1) {
415
           $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
416
           // max level for mapquest is 16
417
           if ($gmap ['zoom'] > 16) {
418
               $imgUrl .= "&zoom=16";
419
           } else {
420
               $imgUrl .= "&zoom=" . $gmap ['zoom'];
421
           }
422
       }
423
       // use bestfit instead of center/zoom, needs upperleft/lowerright corners
424
       // $bbox=$this->calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
425
       // $imgUrl .= "bestfit=".$bbox['minlat'].",".$bbox['maxlon'].",".$bbox['maxlat'].",".$bbox['minlon'];
426
427
       // TODO declutter option works well for square maps but not for rectangular, maybe compensate for that
428
       //       or compensate the mbr..
429
430
       $imgUrl .= "&size=" . str_replace ( "px", "", $gmap ['width'] ) . "," . str_replace ("px","",$gmap['height']);
431
432
       // TODO mapquest allows using one image url with a multiplier $NUMBER eg:
433
       // $NUMBER = 2
434
       // $imgUrl .= DOKU_URL."/".DOKU_PLUGIN."/".getPluginName()."/icons/".$img.",$NUMBER,C,"
435
        //  .$lat1.",".$lon1.",0,0,0,0,C,".$lat2.",".$lon2.",0,0,0,0";
436
       if (! empty ( $overlay )) {
437
           $imgUrl .= "&xis=";
438
           foreach ( $overlay as $data ) {
439
               list ( $lat, $lon, $text, $angle, $opacity, $img ) = $data;
440
               // $imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",0,0,0,0,";
441
               $imgUrl .= $sUrl . "lib/plugins/openlayersmap/icons/" . $img . ",1,C," . $lat . "," . $lon . ",";
442
           }
443
           $imgUrl = substr ( $imgUrl, 0, - 1 );
444
       }
445
       $imgUrl .= "&imageType=png&type=" . $maptype;
446
       $imgUrl .= "&key=".$this->getConf ( 'mapquestAPIKey' );
447
       return $imgUrl;
448
   }
449
   */
450
451
    /**
452
     * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
453
     * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
454
     *
455
     * @param array $gmap
456
     * @param array $overlay
457
     *
458
     * @return false|string
459
     * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
460
     */
461
    private function getStaticOSM(array $gmap, array $overlay)
462
    {
463
        global $conf;
464
465
        if ($this->getConf('optionStaticMapGenerator') === 'local') {
466
            // using local basemap composer
467
            if (($myMap = plugin_load('helper', 'openlayersmap_staticmap')) === null) {
0 ignored issues
show
Bug introduced by
The function plugin_load was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

467
            if (($myMap = /** @scrutinizer ignore-call */ plugin_load('helper', 'openlayersmap_staticmap')) === null) {
Loading history...
468
                Logger::error(
0 ignored issues
show
Bug introduced by
The type Logger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
469
                    'openlayersmap_staticmap plugin is not available for use.',
470
                    $myMap
471
                );
472
            }
473
            if (($geophp = plugin_load('helper', 'geophp')) === null) {
474
                Logger::debug('geophp plugin is not available for use.', $geophp);
475
            }
476
            $size = str_replace("px", "", $gmap ['width']) . "x"
477
                . str_replace("px", "", $gmap ['height']);
478
479
            $markers = [];
480
            if ($overlay !== []) {
481
                foreach ($overlay as $data) {
482
                    [$lat, $lon, $text, $angle, $opacity, $img] = $data;
483
                    $iconStyle  = substr($img, 0, -4);
484
                    $markers [] = ['lat'  => $lat, 'lon'  => $lon, 'type' => $iconStyle];
485
                }
486
            }
487
488
            $apikey = '';
489
            switch ($gmap ['baselyr']) {
490
                case 'mapnik':
491
                case 'openstreetmap':
492
                    $maptype = 'openstreetmap';
493
                    break;
494
                case 'transport':
495
                    $maptype = 'transport';
496
                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
497
                    break;
498
                case 'landscape':
499
                    $maptype = 'landscape';
500
                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
501
                    break;
502
                case 'outdoors':
503
                    $maptype = 'outdoors';
504
                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
505
                    break;
506
                case 'cycle map':
507
                    $maptype = 'cycle';
508
                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
509
                    break;
510
                case 'hike and bike map':
511
                    $maptype = 'hikeandbike';
512
                    break;
513
                case 'mapquest hybrid':
514
                case 'mapquest road':
515
                case 'mapquest sat':
516
                    $maptype = 'mapquest';
517
                    break;
518
                default:
519
                    $maptype = '';
520
                    break;
521
            }
522
523
            $result = $myMap->getMap(
524
                $gmap ['lat'],
525
                $gmap ['lon'],
526
                $gmap ['zoom'],
527
                $size,
528
                $maptype,
529
                $markers,
530
                $gmap ['gpxfile'],
531
                $gmap ['kmlfile'],
532
                $gmap ['geojsonfile'],
533
                $apikey
534
            );
535
        } else {
536
            // using external basemap composer
537
538
            // https://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10
539
            //.117187497601&zoom=5&size=500x350
540
            // &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,
541
            //  lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,
542
            //  ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,
543
            //  ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
544
            $imgUrl = "https://staticmap.openstreetmap.de/staticmap.php";
545
            $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
546
            $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
547
                . str_replace("px", "", $gmap ['height']);
548
549
            if ($gmap ['zoom'] > 16) {
550
                // actually this could even be 18, but that seems overkill
551
                $imgUrl .= "&zoom=16";
552
            } else {
553
                $imgUrl .= "&zoom=" . $gmap ['zoom'];
554
            }
555
556
            if ($overlay !== []) {
557
                $rowId  = 0;
558
                $imgUrl .= "&markers=";
559
                foreach ($overlay as $data) {
560
                    [$lat, $lon, $text, $angle, $opacity, $img] = $data;
561
                    $rowId++;
562
                    $iconStyle = "lightblue$rowId";
563
                    $imgUrl    .= "$lat,$lon,$iconStyle%7c";
564
                }
565
                $imgUrl = substr($imgUrl, 0, -3);
566
            }
567
568
            $result = $imgUrl;
569
        }
570
        return $result;
571
    }
572
573
    /**
574
     * Create a Bing maps static image url w/ the poi.
575
     *
576
     * @param array $gmap
577
     * @param array $overlay
578
     */
579
    private function getBing(array $gmap, array $overlay): string
580
    {
581
        switch ($gmap ['baselyr']) {
582
            case 've hybrid':
583
            case 'bing hybrid':
584
                $maptype = 'AerialWithLabels';
585
                break;
586
            case 've sat':
587
            case 'bing sat':
588
                $maptype = 'Aerial';
589
                break;
590
            case 've normal':
591
            case 've road':
592
            case 've':
593
            case 'bing road':
594
            default:
595
                $maptype = 'Road';
596
                break;
597
        }
598
        $imgUrl = "https://dev.virtualearth.net/REST/v1/Imagery/Map/" . $maptype;// . "/";
599
        if ($this->getConf('autoZoomMap')) {
600
            $bbox = $this->calcBBOX($overlay, $gmap ['lat'], $gmap ['lon']);
601
            //$imgUrl .= "?ma=" . $bbox ['minlat'] . "," . $bbox ['minlon'] . ","
602
            //          . $bbox ['maxlat'] . "," . $bbox ['maxlon'];
603
            $imgUrl .= "?ma=" . $bbox ['minlat'] . "%2C" . $bbox ['minlon'] . "%2C" . $bbox ['maxlat']
604
                . "%2C" . $bbox ['maxlon'];
605
            $imgUrl .= "&dcl=1";
606
        }
607
        if (strpos($imgUrl, "?") === false)
608
            $imgUrl .= "?";
609
610
        //$imgUrl .= "&ms=" . str_replace ( "px", "", $gmap ['width'] ) . ","
611
        //          . str_replace ( "px", "", $gmap ['height'] );
612
        $imgUrl .= "&ms=" . str_replace("px", "", $gmap ['width']) . "%2C"
613
            . str_replace("px", "", $gmap ['height']);
614
        $imgUrl .= "&key=" . $this->getConf('bingAPIKey');
615
        if ($overlay !== []) {
616
            $rowId = 0;
617
            foreach ($overlay as $data) {
618
                [$lat, $lon, $text, $angle, $opacity, $img] = $data;
619
                // TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
620
                $iconStyle = 32;
621
                $rowId++;
622
                // NOTE: the max number of pushpins is 18! or we have to use POST
623
                //  (http://msdn.microsoft.com/en-us/library/ff701724.aspx)
624
                if ($rowId == 18) {
625
                    break;
626
                }
627
                //$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
628
                $imgUrl .= "&pp=$lat%2C$lon%3B$iconStyle%3B$rowId";
629
            }
630
        }
631
        global $conf;
632
        $imgUrl .= "&fmt=png";
633
        $imgUrl .= "&c=" . $conf ['lang'];
634
        return $imgUrl;
635
    }
636
637
    /**
638
     * Calculate the minimum bbox for a start location + poi.
639
     *
640
     * @param array $overlay
641
     *            multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
642
     * @param float $lat
643
     *            latitude for map center
644
     * @param float $lon
645
     *            longitude for map center
646
     * @return array :float array describing the mbr and center point
647
     */
648
    private function calcBBOX(array $overlay, float $lat, float $lon): array
649
    {
650
        $lats = [$lat];
651
        $lons = [$lon];
652
        foreach ($overlay as $data) {
653
            [$lat, $lon, $text, $angle, $opacity, $img] = $data;
654
            $lats [] = $lat;
655
            $lons [] = $lon;
656
        }
657
        sort($lats);
658
        sort($lons);
659
        // TODO: make edge/wrap around cases work
660
        $centerlat = $lats [0] + ($lats [count($lats) - 1] - $lats [0]);
661
        $centerlon = $lons [0] + ($lons [count($lats) - 1] - $lons [0]);
662
        return ['minlat'    => $lats [0], 'minlon'    => $lons [0], 'maxlat'    => $lats [count($lats) - 1], 'maxlon'    => $lons [count($lats) - 1], 'centerlat' => $centerlat, 'centerlon' => $centerlon];
663
    }
664
665
    /**
666
     * convert latitude in decimal degrees to DMS+hemisphere.
667
     *
668
     * @param float $decimaldegrees
669
     * @todo move this into a shared library
670
     */
671
    private function convertLat(float $decimaldegrees): string
672
    {
673
        if (strpos($decimaldegrees, '-') !== false) {
674
            $latPos = "S";
675
        } else {
676
            $latPos = "N";
677
        }
678
        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
679
        return hsc($dms . $latPos);
0 ignored issues
show
Bug introduced by
The function hsc was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

679
        return /** @scrutinizer ignore-call */ hsc($dms . $latPos);
Loading history...
680
    }
681
682
    /**
683
     * Convert decimal degrees to degrees, minutes, seconds format
684
     *
685
     * @param float $decimaldegrees
686
     * @return string dms
687
     * @todo move this into a shared library
688
     */
689
    private function convertDDtoDMS(float $decimaldegrees): string
690
    {
691
        $dms  = floor($decimaldegrees);
692
        $secs = ($decimaldegrees - $dms) * 3600;
693
        $min  = floor($secs / 60);
694
        $sec  = round($secs - ($min * 60), 3);
695
        $dms  .= 'º' . $min . '\'' . $sec . '"';
696
        return $dms;
697
    }
698
699
    /**
700
     * convert longitude in decimal degrees to DMS+hemisphere.
701
     *
702
     * @param float $decimaldegrees
703
     * @todo move this into a shared library
704
     */
705
    private function convertLon(float $decimaldegrees): string
706
    {
707
        if (strpos($decimaldegrees, '-') !== false) {
708
            $lonPos = "W";
709
        } else {
710
            $lonPos = "E";
711
        }
712
        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
713
        return hsc($dms . $lonPos);
0 ignored issues
show
Bug introduced by
The function hsc was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

713
        return /** @scrutinizer ignore-call */ hsc($dms . $lonPos);
Loading history...
714
    }
715
716
    /**
717
     * Figures out the base filename of a media path.
718
     *
719
     * @param string $mediaLink
720
     */
721
    private function getFileName(string $mediaLink): string
722
    {
723
        $mediaLink = str_replace('[[', '', $mediaLink);
724
        $mediaLink = str_replace(']]', '', $mediaLink);
725
        $mediaLink = substr($mediaLink, 0, -4);
726
727
        $parts     = explode(':', $mediaLink);
728
        $mediaLink = end($parts);
729
        return str_replace('_', ' ', $mediaLink);
730
    }
731
732
    /**
733
     *
734
     * @see DokuWiki_Syntax_Plugin::render()
735
     */
736
    public function render($format, Doku_Renderer $renderer, $data): bool
0 ignored issues
show
Bug introduced by
The type Doku_Renderer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
737
    {
738
        // set to true after external scripts tags are written
739
        static $initialised = false;
740
        // incremented for each map tag in the page source so we can keep track of each map in this page
741
        static $mapnumber = 0;
742
743
        [$mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage] = $data;
744
745
        if ($format === 'xhtml') {
746
            $olscript     = '';
747
            $stadiaEnable = $this->getConf('enableStadia');
748
            $osmEnable    = $this->getConf('enableOSM');
749
            $enableBing   = $this->getConf('enableBing');
750
751
            $scriptEnable = '';
752
            if (!$initialised) {
753
                $initialised = true;
754
                // render necessary script tags only once
755
                $olscript = '<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol/ol.js"></script>
0 ignored issues
show
Bug introduced by
The constant DOKU_BASE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
756
<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol/ol-layerswitcher.js"></script>';
757
758
                $scriptEnable = '<script defer="defer" src="data:text/javascript;base64,';
759
                $scriptSrc    = $olscript ? 'const olEnable=true;' : 'const olEnable=false;';
760
                $scriptSrc    .= 'const osmEnable=' . ($osmEnable ? 'true' : 'false') . ';';
761
                $scriptSrc    .= 'const stadiaEnable=' . ($stadiaEnable ? 'true' : 'false') . ';';
762
                $scriptSrc    .= 'const bEnable=' . ($enableBing ? 'true' : 'false') . ';';
763
                $scriptSrc    .= 'const bApiKey="' . $this->getConf('bingAPIKey') . '";';
764
                $scriptSrc    .= 'const tfApiKey="' . $this->getConf('tfApiKey') . '";';
765
                $scriptSrc    .= 'const gApiKey="' . $this->getConf('googleAPIkey') . '";';
766
                $scriptSrc    .= 'olMapData = []; let olMaps = {}; let olMapOverlays = {};';
767
                $scriptEnable .= base64_encode($scriptSrc);
768
                $scriptEnable .= '"></script>';
769
            }
770
            $renderer->doc .= "$olscript\n$scriptEnable";
771
            $renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>';
772
            if ($this->getConf('enableA11y')) {
773
                $renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">'
774
                    . p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
0 ignored issues
show
Bug introduced by
The function p_render was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

774
                    . /** @scrutinizer ignore-call */ p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
Loading history...
Comprehensibility Best Practice introduced by
The variable $info seems to be never defined.
Loading history...
Bug introduced by
The function p_get_instructions was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

774
                    . p_render($format, /** @scrutinizer ignore-call */ p_get_instructions($staticImgUrl), $info) . '</div>';
Loading history...
775
            }
776
            $renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p>&nbsp;</p></div>';
777
            if ($this->getConf('enableA11y')) {
778
                // render a table of the POI for the print and a11y presentation, it is hidden using javascript
779
                $renderer->doc .= '
780
                <div id="' . $mapid . '-table-span" class="olPOItableSpan">
781
                    <table id="' . $mapid . '-table" class="olPOItable">
782
                    <caption class="olPOITblCaption">' . $this->getLang('olmapPOItitle') . '</caption>
783
                    <thead class="olPOITblHeader">
784
                    <tr>
785
                    <th class="rowId" scope="col">id</th>
786
                    <th class="icon" scope="col">' . $this->getLang('olmapPOIicon') . '</th>
787
                    <th class="lat" scope="col" title="' . $this->getLang('olmapPOIlatTitle') . '">'
788
                    . $this->getLang('olmapPOIlat') . '</th>
789
                    <th class="lon" scope="col" title="' . $this->getLang('olmapPOIlonTitle') . '">'
790
                    . $this->getLang('olmapPOIlon') . '</th>
791
                    <th class="txt" scope="col">' . $this->getLang('olmapPOItxt') . '</th>
792
                    </tr>
793
                    </thead>';
794
                if ($poitabledesc != '') {
795
                    $renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc
796
                        . '</td></tr></tfoot>';
797
                }
798
                $renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody>
799
                    </table>
800
                </div>';
801
                $renderer->doc .= "\n";
802
            }
803
            // render inline mapscript parts
804
            $renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,';
805
            $renderer->doc .= base64_encode("olMapData[$mapnumber] = $param");
806
            $renderer->doc .= '"></script>';
807
            $mapnumber++;
808
            return true;
809
        } elseif ($format === 'metadata') {
810
            if (!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) {
811
                // render geo metadata, unless they are the default
812
                $renderer->meta ['geo'] ['lat'] = $mainLat;
813
                $renderer->meta ['geo'] ['lon'] = $mainLon;
814
                if (($geophp = plugin_load('helper', 'geophp')) !== null) {
0 ignored issues
show
Bug introduced by
The function plugin_load was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

814
                if (($geophp = /** @scrutinizer ignore-call */ plugin_load('helper', 'geophp')) !== null) {
Loading history...
Unused Code introduced by
The assignment to $geophp is dead and can be removed.
Loading history...
815
                    // if we have the geoPHP helper, add the geohash
816
                    try {
817
                        $renderer->meta['geo']['geohash'] = (new Point($mainLon, $mainLat))->out('geohash');
818
                    } catch (Exception $e) {
819
                        Logger::error("Failed to create geohash for: $mainLat, $mainLon");
820
                    }
821
                }
822
            }
823
824
            if (($this->getConf('enableA11y')) && (!empty($_firstimage))) {
825
                // add map local image into relation/firstimage if not already filled and when it is a local image
826
827
                global $ID;
828
                $rel = p_get_metadata($ID, 'relation', METADATA_RENDER_USING_CACHE);
0 ignored issues
show
Bug introduced by
The function p_get_metadata was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

828
                $rel = /** @scrutinizer ignore-call */ p_get_metadata($ID, 'relation', METADATA_RENDER_USING_CACHE);
Loading history...
Bug introduced by
The constant METADATA_RENDER_USING_CACHE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
829
                // $img = $rel ['firstimage'];
830
                if (empty($rel ['firstimage']) /* || $img == $_firstimage*/) {
831
                    //Logger::debug(
832
                    // 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.',
833
                    // $_firstimage);
834
835
                    // This seems to never work; the firstimage entry in the .meta file is empty
836
                    // $renderer->meta['relation']['firstimage'] = $_firstimage;
837
                    // ... and neither does this; the firstimage entry in the .meta file is empty
838
                    // $relation = array('relation'=>array('firstimage'=>$_firstimage));
839
                    // p_set_metadata($ID, $relation, false, false);
840
                    // ... this works
841
                    $renderer->internalmedia($_firstimage, $poitabledesc);
842
                }
843
            }
844
            return true;
845
        }
846
        return false;
847
    }
848
}
849