Passed
Pull Request — master (#8)
by Mark
05:42 queued 02:48
created

syntax_plugin_openlayersmap_olmap::render()   D

Complexity

Conditions 18
Paths 115

Size

Total Lines 114
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 40
Bugs 7 Features 6
Metric Value
cc 18
eloc 68
c 40
b 7
f 6
nc 115
nop 3
dl 0
loc 114
rs 4.7416

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Copyright (c) 2008-2021 Mark C. Prins <[email protected]>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 *
17
 * @phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
18
 */
19
20
use dokuwiki\Logger;
0 ignored issues
show
Bug introduced by
The type dokuwiki\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...
21
22
/**
23
 * DokuWiki Plugin openlayersmap (Syntax Component).
24
 * Provides for display of an OpenLayers based map in a wiki page.
25
 *
26
 * @author Mark Prins
27
 */
28
class syntax_plugin_openlayersmap_olmap extends DokuWiki_Syntax_Plugin
0 ignored issues
show
Bug introduced by
The type DokuWiki_Syntax_Plugin 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...
29
{
30
31
    /**
32
     * defaults of the known attributes of the olmap tag.
33
     */
34
    private $dflt = array(
35
        'id'            => 'olmap',
36
        'width'         => '550px',
37
        'height'        => '450px',
38
        'lat'           => 50.0,
39
        'lon'           => 5.1,
40
        'zoom'          => 12,
41
        'autozoom'      => 1,
42
        'controls'      => true,
43
        'baselyr'       => 'OpenStreetMap',
44
        'gpxfile'       => '',
45
        'kmlfile'       => '',
46
        'geojsonfile'   => '',
47
        'summary'       => ''
48
    );
49
50
    /**
51
     *
52
     * @see DokuWiki_Syntax_Plugin::getType()
53
     */
54
    public function getType(): string
55
    {
56
        return 'substition';
57
    }
58
59
    /**
60
     *
61
     * @see DokuWiki_Syntax_Plugin::getPType()
62
     */
63
    public function getPType(): string
64
    {
65
        return 'block';
66
    }
67
68
    /**
69
     *
70
     * @see Doku_Parser_Mode::getSort()
71
     */
72
    public function getSort(): int
73
    {
74
        return 901;
75
    }
76
77
    /**
78
     *
79
     * @see Doku_Parser_Mode::connectTo()
80
     */
81
    public function connectTo($mode)
82
    {
83
        $this->Lexer->addSpecialPattern(
84
            '<olmap ?[^>\n]*>.*?</olmap>',
85
            $mode,
86
            'plugin_openlayersmap_olmap'
87
        );
88
    }
89
90
    /**
91
     *
92
     * @see DokuWiki_Syntax_Plugin::handle()
93
     */
94
    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...
95
    {
96
        // break matched cdata into its components
97
        list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
98
        // get the lat/lon for adding them to the metadata (used by geotag)
99
        preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat);
100
        preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon);
101
        $mainLat = substr($mainLat [0], 5, -1);
102
        $mainLon = substr($mainLon [0], 5, -1);
103
        if (!is_numeric($mainLat)) {
104
            $mainLat = $this->dflt ['lat'];
105
        }
106
        if (!is_numeric($mainLon)) {
107
            $mainLon = $this->dflt ['lon'];
108
        }
109
110
        $gmap          = $this->extractParams($str_params);
111
        $overlay       = $this->extractPoints($str_points);
112
        $_firstimageID = '';
113
114
        $_nocache = false;
115
        // choose maptype based on the specified tag
116
        $imgUrl = "{{";
117
        if (stripos($gmap ['baselyr'], 'google') !== false) {
118
            // Google
119
            $imgUrl .= $this->getGoogle($gmap, $overlay);
120
            $imgUrl .= "&.png";
121
        } elseif (stripos($gmap ['baselyr'], 'bing') !== false) {
122
            // Bing
123
            if (!$this->getConf('bingAPIKey')) {
124
                // in case there is no Bing api key we'll use OSM
125
                $_firstimageID = $this->getStaticOSM($gmap, $overlay);
126
                $imgUrl        .= $_firstimageID;
127
                if ($this->getConf('optionStaticMapGenerator') == 'remote') {
128
                    $imgUrl .= "&.png";
129
                }
130
            } else {
131
                // seems that Bing doesn't like the DW client, turn off caching
132
                $_nocache = true;
133
                $imgUrl   .= $this->getBing($gmap, $overlay) . "&.png";
134
            }
135
        } /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) {
136
            // MapQuest
137
            if (! $this->getConf ( 'mapquestAPIKey' )) {
138
                // no API key for MapQuest, use OSM
139
                $_firstimageID = $this->getStaticOSM ( $gmap, $overlay );
140
                $imgUrl .= $_firstimageID;
141
                if ($this->getConf ( 'optionStaticMapGenerator' ) == 'remote') {
142
                    $imgUrl .= "&.png";
143
                }
144
            } else {
145
                $imgUrl .= $this->_getMapQuest ( $gmap, $overlay );
146
                $imgUrl .= "&.png";
147
            }
148
        } */ else {
149
            // default OSM
150
            $_firstimageID = $this->getStaticOSM($gmap, $overlay);
151
            $imgUrl        .= $_firstimageID;
152
            if ($this->getConf('optionStaticMapGenerator') == 'remote') {
153
                $imgUrl .= "&.png";
154
            }
155
        }
156
157
        // append dw p_render specific params and render
158
        $imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x"
159
            . str_replace("px", "", $gmap ['height']);
160
        $imgUrl .= "&nolink";
161
162
        // add nocache option for selected services
163
        if ($_nocache) {
164
            $imgUrl .= "&nocache";
165
        }
166
167
        $imgUrl .= " |" . $gmap ['summary'] . " }}";
168
169
        // Logger::debug("complete image tags is:",$imgUrl);
170
171
        $mapid = $gmap ['id'];
172
        // create a javascript parameter string for the map
173
        $param = '';
174
        foreach ($gmap as $key => $val) {
175
            $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

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

337
            $text = /** @scrutinizer ignore-call */ p_get_instructions($text);
Loading history...
338
            // dbg ( $text );
339
            $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

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

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

721
        return /** @scrutinizer ignore-call */ hsc($dms . $latPos);
Loading history...
722
    }
723
724
    /**
725
     * Convert decimal degrees to degrees, minutes, seconds format
726
     *
727
     * @param float $decimaldegrees
728
     * @return string dms
729
     * @todo move this into a shared library
730
     */
731
    private function convertDDtoDMS(float $decimaldegrees): string
732
    {
733
        $dms  = floor($decimaldegrees);
734
        $secs = ($decimaldegrees - $dms) * 3600;
735
        $min  = floor($secs / 60);
736
        $sec  = round($secs - ($min * 60), 3);
737
        $dms  .= 'º' . $min . '\'' . $sec . '"';
738
        return $dms;
739
    }
740
741
    /**
742
     * convert longitude in decimal degrees to DMS+hemisphere.
743
     *
744
     * @param float $decimaldegrees
745
     * @return string
746
     * @todo move this into a shared library
747
     */
748
    private function convertLon(float $decimaldegrees): string
749
    {
750
        if (strpos($decimaldegrees, '-') !== false) {
751
            $lonPos = "W";
752
        } else {
753
            $lonPos = "E";
754
        }
755
        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
756
        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

756
        return /** @scrutinizer ignore-call */ hsc($dms . $lonPos);
Loading history...
757
    }
758
759
    /**
760
     * Figures out the base filename of a media path.
761
     *
762
     * @param string $mediaLink
763
     * @return string
764
     */
765
    private function getFileName(string $mediaLink): string
766
    {
767
        $mediaLink = str_replace('[[', '', $mediaLink);
768
        $mediaLink = str_replace(']]', '', $mediaLink);
769
        $mediaLink = substr($mediaLink, 0, -4);
770
        $parts     = explode(':', $mediaLink);
771
        $mediaLink = end($parts);
772
        return str_replace('_', ' ', $mediaLink);
773
    }
774
775
    /**
776
     *
777
     * @see DokuWiki_Syntax_Plugin::render()
778
     */
779
    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...
780
    {
781
        // set to true after external scripts tags are written
782
        static $initialised = false;
783
        // incremented for each map tag in the page source so we can keep track of each map in this page
784
        static $mapnumber = 0;
785
786
        // Logger::debug('olmap::render() data.',$data);
787
        list ($mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage) = $data;
788
789
        if ($format == 'xhtml') {
790
            $olscript     = '';
791
            $stamenEnable = $this->getConf('enableStamen');
792
            $osmEnable    = $this->getConf('enableOSM');
793
            $enableBing   = $this->getConf('enableBing');
794
795
            $scriptEnable = '';
796
            if (!$initialised) {
797
                $initialised = true;
798
                // render necessary script tags only once
799
                $olscript = '<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol6/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...
800
<script defer="defer" src="' . DOKU_BASE . 'lib/plugins/openlayersmap/ol6/ol-layerswitcher.js"></script>';
801
802
                $scriptEnable = '<script defer="defer" src="data:text/javascript;base64,';
803
                $scriptSrc    = $olscript ? 'const olEnable=true;' : 'const olEnable=false;';
804
                $scriptSrc    .= 'const osmEnable=' . ($osmEnable ? 'true' : 'false') . ';';
805
                $scriptSrc    .= 'const stamenEnable=' . ($stamenEnable ? 'true' : 'false') . ';';
806
                $scriptSrc    .= 'const bEnable=' . ($enableBing ? 'true' : 'false') . ';';
807
                $scriptSrc    .= 'const bApiKey="' . $this->getConf('bingAPIKey') . '";';
808
                $scriptSrc    .= 'const tfApiKey="' . $this->getConf('tfApiKey') . '";';
809
                $scriptSrc    .= 'const gApiKey="' . $this->getConf('googleAPIkey') . '";';
810
                $scriptSrc    .= 'olMapData = []; let olMaps = {}; let olMapOverlays = {};';
811
                $scriptEnable .= base64_encode($scriptSrc);
812
                $scriptEnable .= '"></script>';
813
            }
814
            $renderer->doc .= "$olscript\n$scriptEnable";
815
            $renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>';
816
            if ($this->getConf('enableA11y')) {
817
                $renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">'
818
                    . 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

818
                    . /** @scrutinizer ignore-call */ p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
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

818
                    . p_render($format, /** @scrutinizer ignore-call */ p_get_instructions($staticImgUrl), $info) . '</div>';
Loading history...
Comprehensibility Best Practice introduced by
The variable $info seems to be never defined.
Loading history...
819
            }
820
            $renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p>&nbsp;</p></div>';
821
            if ($this->getConf('enableA11y')) {
822
                // render a table of the POI for the print and a11y presentation, it is hidden using javascript
823
                $renderer->doc .= '
824
                <div class="olPOItableSpan" id="' . $mapid . '-table-span">
825
                    <table class="olPOItable" id="' . $mapid . '-table">
826
                    <caption class="olPOITblCaption">' . $this->getLang('olmapPOItitle') . '</caption>
827
                    <thead class="olPOITblHeader">
828
                    <tr>
829
                    <th class="rowId" scope="col">id</th>
830
                    <th class="icon" scope="col">' . $this->getLang('olmapPOIicon') . '</th>
831
                    <th class="lat" scope="col" title="' . $this->getLang('olmapPOIlatTitle') . '">'
832
                    . $this->getLang('olmapPOIlat') . '</th>
833
                    <th class="lon" scope="col" title="' . $this->getLang('olmapPOIlonTitle') . '">'
834
                    . $this->getLang('olmapPOIlon') . '</th>
835
                    <th class="txt" scope="col">' . $this->getLang('olmapPOItxt') . '</th>
836
                    </tr>
837
                    </thead>';
838
                if ($poitabledesc != '') {
839
                    $renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc
840
                        . '</td></tr></tfoot>';
841
                }
842
                $renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody>
843
                    </table>
844
                </div>';
845
                $renderer->doc .= "\n";
846
            }
847
            // render inline mapscript parts
848
            $renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,';
849
            $renderer->doc .= base64_encode("olMapData[$mapnumber] = $param");
850
            $renderer->doc .= '"></script>';
851
            $mapnumber++;
852
            return true;
853
        } elseif ($format == 'metadata') {
854
            if (!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) {
855
                // render geo metadata, unless they are the default
856
                $renderer->meta ['geo'] ['lat'] = $mainLat;
857
                $renderer->meta ['geo'] ['lon'] = $mainLon;
858
                if ($geophp = plugin_load('helper', 'geophp')) {
0 ignored issues
show
Unused Code introduced by
The assignment to $geophp is dead and can be removed.
Loading history...
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

858
                if ($geophp = /** @scrutinizer ignore-call */ plugin_load('helper', 'geophp')) {
Loading history...
859
                    // if we have the geoPHP helper, add the geohash
860
                    try {
861
                        $renderer->meta['geo']['geohash'] = (new Point($mainLon, $mainLat))->out('geohash');
862
                    } catch (Exception $e) {
863
                        Logger::error("Failed to create geohash for: $mainLat, $mainLon");
864
                    }
865
                }
866
            }
867
868
            if (($this->getConf('enableA11y')) && (!empty ($_firstimage))) {
869
                // add map local image into relation/firstimage if not already filled and when it is a local image
870
871
                global $ID;
872
                $rel = p_get_metadata($ID, 'relation');
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

872
                $rel = /** @scrutinizer ignore-call */ p_get_metadata($ID, 'relation');
Loading history...
873
                $img = $rel ['firstimage'];
874
                if (empty ($img) /* || $img == $_firstimage*/) {
875
                    //Logger::debug(
876
                    // 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.',
877
                    // $_firstimage);
878
879
                    // This seems to never work; the firstimage entry in the .meta file is empty
880
                    // $renderer->meta['relation']['firstimage'] = $_firstimage;
881
882
                    // ... and neither does this; the firstimage entry in the .meta file is empty
883
                    // $relation = array('relation'=>array('firstimage'=>$_firstimage));
884
                    // p_set_metadata($ID, $relation, false, false);
885
886
                    // ... this works
887
                    $renderer->internalmedia($_firstimage, $poitabledesc);
888
                }
889
            }
890
            return true;
891
        }
892
        return false;
893
    }
894
}
895