Passed
Pull Request — master (#8)
by Mark
02:57
created
helper/staticmap.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -25,127 +25,127 @@
 block discarded – undo
25 25
  */
26 26
 class helper_plugin_openlayersmap_staticmap extends DokuWiki_Plugin
27 27
 {
28
-    /** maximum width of the resulting image. */
29
-    private $maxWidth = 1024;
30
-    /** maximum heigth of the resulting image. */
31
-    private $maxHeight = 1024;
28
+	/** maximum width of the resulting image. */
29
+	private $maxWidth = 1024;
30
+	/** maximum heigth of the resulting image. */
31
+	private $maxHeight = 1024;
32 32
 
33
-    /**
34
-     * Provide metadata of the public methods of this class.
35
-     *
36
-     * @return array Information to all provided methods.
37
-     */
38
-    public function getMethods(): array
39
-    {
40
-        $result   = array();
41
-        $result[] = array(
42
-            'name'   => 'getMap',
43
-            'desc'   => 'returns url to the image',
44
-            'params' => array(
45
-                'lat'     => 'float',
46
-                'lon'     => 'float',
47
-                'zoom'    => 'integer',
48
-                'size'    => 'string',
49
-                'maptype' => 'string',
50
-                'markers' => 'string',
51
-                'gpx'     => 'string',
52
-                'kml'     => 'string',
53
-                'geojson' => 'string',
54
-                'apikey'  => 'string'
55
-            ),
56
-            'return' => array('image' => 'string'),
57
-        );
58
-        return $result;
59
-    }
33
+	/**
34
+	 * Provide metadata of the public methods of this class.
35
+	 *
36
+	 * @return array Information to all provided methods.
37
+	 */
38
+	public function getMethods(): array
39
+	{
40
+		$result   = array();
41
+		$result[] = array(
42
+			'name'   => 'getMap',
43
+			'desc'   => 'returns url to the image',
44
+			'params' => array(
45
+				'lat'     => 'float',
46
+				'lon'     => 'float',
47
+				'zoom'    => 'integer',
48
+				'size'    => 'string',
49
+				'maptype' => 'string',
50
+				'markers' => 'string',
51
+				'gpx'     => 'string',
52
+				'kml'     => 'string',
53
+				'geojson' => 'string',
54
+				'apikey'  => 'string'
55
+			),
56
+			'return' => array('image' => 'string'),
57
+		);
58
+		return $result;
59
+	}
60 60
 
61
-    /**
62
-     * Create the map.
63
-     *
64
-     * @param float  $lat     the latitude of the map's center, eg. 40.714728
65
-     * @param float  $lon     the longitude of the map's center, eg -73.998672
66
-     * @param int    $zoom    the zoom level in the tile cache, eg. 14
67
-     * @param string $size    the size in WxH px, eg. 512x512
68
-     * @param string $maptype the maptype, eg. cycle
69
-     * @param array  $markers associative array of markers, array('lat'=>$lat,'lon'=>$lon,'type'=>$iconStyle),
70
-     *                        eg. array('lat'=>40.702147,'lon'=>-74.015794,'type'=>lightblue1);
71
-     * @param string $gpx     media link
72
-     * @param string $kml     media link
73
-     * @param string $geojson media link
74
-     * @param string $apikey  optional API key eg. for Thunderforest maps
75
-     *
76
-     * @return string
77
-     */
78
-    public function getMap(
79
-        float $lat,
80
-        float $lon,
81
-        int $zoom,
82
-        string $size,
83
-        string $maptype,
84
-        array $markers,
85
-        string $gpx,
86
-        string $kml,
87
-        string $geojson,
88
-        string $apikey = ''
89
-    ): string {
90
-        global $conf;
91
-        // Logger::debug('helper_plugin_openlayersmap_staticmap::getMap: markers :',$markers);
61
+	/**
62
+	 * Create the map.
63
+	 *
64
+	 * @param float  $lat     the latitude of the map's center, eg. 40.714728
65
+	 * @param float  $lon     the longitude of the map's center, eg -73.998672
66
+	 * @param int    $zoom    the zoom level in the tile cache, eg. 14
67
+	 * @param string $size    the size in WxH px, eg. 512x512
68
+	 * @param string $maptype the maptype, eg. cycle
69
+	 * @param array  $markers associative array of markers, array('lat'=>$lat,'lon'=>$lon,'type'=>$iconStyle),
70
+	 *                        eg. array('lat'=>40.702147,'lon'=>-74.015794,'type'=>lightblue1);
71
+	 * @param string $gpx     media link
72
+	 * @param string $kml     media link
73
+	 * @param string $geojson media link
74
+	 * @param string $apikey  optional API key eg. for Thunderforest maps
75
+	 *
76
+	 * @return string
77
+	 */
78
+	public function getMap(
79
+		float $lat,
80
+		float $lon,
81
+		int $zoom,
82
+		string $size,
83
+		string $maptype,
84
+		array $markers,
85
+		string $gpx,
86
+		string $kml,
87
+		string $geojson,
88
+		string $apikey = ''
89
+	): string {
90
+		global $conf;
91
+		// Logger::debug('helper_plugin_openlayersmap_staticmap::getMap: markers :',$markers);
92 92
 
93
-        // normalize zoom
94
-        $zoom = $zoom ?: 0;
95
-        if ($zoom > 18) {
96
-            $zoom = 18;
97
-        }
98
-        // normalize WxH
99
-        list($width, $height) = explode('x', $size);
100
-        $width = (int)$width;
101
-        if ($width > $this->maxWidth) {
102
-            $width = $this->maxWidth;
103
-        }
104
-        $height = (int)$height;
105
-        if ($height > $this->maxHeight) {
106
-            $height = $this->maxHeight;
107
-        }
93
+		// normalize zoom
94
+		$zoom = $zoom ?: 0;
95
+		if ($zoom > 18) {
96
+			$zoom = 18;
97
+		}
98
+		// normalize WxH
99
+		list($width, $height) = explode('x', $size);
100
+		$width = (int)$width;
101
+		if ($width > $this->maxWidth) {
102
+			$width = $this->maxWidth;
103
+		}
104
+		$height = (int)$height;
105
+		if ($height > $this->maxHeight) {
106
+			$height = $this->maxHeight;
107
+		}
108 108
 
109
-        // cleanup/validate gpx/kml
110
-        $kml = $this->mediaIdToPath($kml);
111
-        // Logger::debug('helper_plugin_openlayersmap_staticmap::getMap: kml file:',$kml);
112
-        $gpx = $this->mediaIdToPath($gpx);
113
-        // Logger::debug('helper_plugin_openlayersmap_staticmap::getMap: gpx file:',$gpx);
114
-        $geojson = $this->mediaIdToPath($geojson);
109
+		// cleanup/validate gpx/kml
110
+		$kml = $this->mediaIdToPath($kml);
111
+		// Logger::debug('helper_plugin_openlayersmap_staticmap::getMap: kml file:',$kml);
112
+		$gpx = $this->mediaIdToPath($gpx);
113
+		// Logger::debug('helper_plugin_openlayersmap_staticmap::getMap: gpx file:',$gpx);
114
+		$geojson = $this->mediaIdToPath($geojson);
115 115
 
116
-        // create map
117
-        require_once DOKU_PLUGIN . 'openlayersmap/StaticMap.php';
118
-        $map = new StaticMap(
119
-            $lat, $lon, $zoom, $width, $height, $maptype,
120
-            $markers, $gpx, $kml, $geojson, $conf['mediadir'], $conf['cachedir'],
121
-            $this->getConf('autoZoomMap'), $apikey
122
-        );
116
+		// create map
117
+		require_once DOKU_PLUGIN . 'openlayersmap/StaticMap.php';
118
+		$map = new StaticMap(
119
+			$lat, $lon, $zoom, $width, $height, $maptype,
120
+			$markers, $gpx, $kml, $geojson, $conf['mediadir'], $conf['cachedir'],
121
+			$this->getConf('autoZoomMap'), $apikey
122
+		);
123 123
 
124
-        // return the media id url
125
-        // $mediaId = str_replace('/', ':', $map->getMap());
126
-        // if($this->startsWith($mediaId,':')) {
127
-        //     $mediaId = substr($mediaId, 1);
128
-        // }
129
-        // return $mediaId;
130
-        return str_replace('/', ':', $map->getMap());
131
-    }
124
+		// return the media id url
125
+		// $mediaId = str_replace('/', ':', $map->getMap());
126
+		// if($this->startsWith($mediaId,':')) {
127
+		//     $mediaId = substr($mediaId, 1);
128
+		// }
129
+		// return $mediaId;
130
+		return str_replace('/', ':', $map->getMap());
131
+	}
132 132
 
133
-    /**
134
-     * Constructs the path to a file.
135
-     * @param string $id the DW media id
136
-     * @return string the path to the file
137
-     */
138
-    private function mediaIdToPath(string $id): string
139
-    {
140
-        global $conf;
141
-        if (empty($id)) {
142
-            return "";
143
-        }
144
-        $id = str_replace(array("[[", "]]"), "", $id);
145
-        if ((strpos($id, ':') === 0)) {
146
-            $id = substr($id, 1);
147
-        }
148
-        $id = str_replace(":", "/", $id);
149
-        return $conf['mediadir'] . '/' . $id;
150
-    }
133
+	/**
134
+	 * Constructs the path to a file.
135
+	 * @param string $id the DW media id
136
+	 * @return string the path to the file
137
+	 */
138
+	private function mediaIdToPath(string $id): string
139
+	{
140
+		global $conf;
141
+		if (empty($id)) {
142
+			return "";
143
+		}
144
+		$id = str_replace(array("[[", "]]"), "", $id);
145
+		if ((strpos($id, ':') === 0)) {
146
+			$id = substr($id, 1);
147
+		}
148
+		$id = str_replace(":", "/", $id);
149
+		return $conf['mediadir'] . '/' . $id;
150
+	}
151 151
 }
Please login to merge, or discard this patch.
conf/metadata.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -22,74 +22,74 @@
 block discarded – undo
22 22
  */
23 23
 
24 24
 $meta['enableOSM']                = array(
25
-    'onoff'
25
+	'onoff'
26 26
 );
27 27
 $meta['enableStamen']             = array(
28
-    'onoff'
28
+	'onoff'
29 29
 );
30 30
 $meta['enableGoogle']             = array(
31
-    'onoff'
31
+	'onoff'
32 32
 );
33 33
 $meta['googleAPIkey']             = array(
34
-    'string'
34
+	'string'
35 35
 );
36 36
 $meta['enableBing']               = array(
37
-    'onoff'
37
+	'onoff'
38 38
 );
39 39
 $meta['bingAPIKey']               = array(
40
-    'string'
40
+	'string'
41 41
 );
42 42
 $meta['tfApiKey']                 = array(
43
-    'string'
43
+	'string'
44 44
 );
45 45
 $meta['iconUrlOverload']          = array(
46
-    'string'
46
+	'string'
47 47
 );
48 48
 $meta['enableA11y']               = array(
49
-    'onoff'
49
+	'onoff'
50 50
 );
51 51
 $meta['optionStaticMapGenerator'] = array(
52
-    'multichoice',
53
-    '_choices' => array('local', 'remote')
52
+	'multichoice',
53
+	'_choices' => array('local', 'remote')
54 54
 );
55 55
 $meta['autoZoomMap']              = array(
56
-    'onoff'
56
+	'onoff'
57 57
 );
58 58
 $meta ['displayformat']           = array(
59
-    'multichoice',
60
-    '_choices' => array('DD', 'DMS')
59
+	'multichoice',
60
+	'_choices' => array('DD', 'DMS')
61 61
 );
62 62
 
63 63
 $meta ['default_width']         = array(
64
-    'string'
64
+	'string'
65 65
 );
66 66
 $meta ['default_height']        = array(
67
-    'string'
67
+	'string'
68 68
 );
69 69
 $meta ['default_zoom']          = array(
70
-    'string'
70
+	'string'
71 71
 );
72 72
 $meta ['default_autozoom']      = array(
73
-    'onoff'
73
+	'onoff'
74 74
 );
75 75
 $meta ['default_statusbar']     = array(
76
-    'onoff'
76
+	'onoff'
77 77
 );
78 78
 $meta ['default_toolbar']       = array(
79
-    'onoff'
79
+	'onoff'
80 80
 );
81 81
 $meta ['default_controls']      = array(
82
-    'onoff'
82
+	'onoff'
83 83
 );
84 84
 $meta ['default_poihoverstyle'] = array(
85
-    'onoff'
85
+	'onoff'
86 86
 );
87 87
 $meta ['default_kmlfile']       = array(
88
-    'string'
88
+	'string'
89 89
 );
90 90
 $meta ['default_gpxfile']       = array(
91
-    'string'
91
+	'string'
92 92
 );
93 93
 $meta ['default_geojsonfile']   = array(
94
-    'string'
94
+	'string'
95 95
 );
Please login to merge, or discard this patch.
admin/purge.php 1 patch
Indentation   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -27,108 +27,108 @@
 block discarded – undo
27 27
  */
28 28
 class admin_plugin_openlayersmap_purge extends DokuWiki_Admin_Plugin
29 29
 {
30
-    /**
31
-     * (non-PHPdoc)
32
-     * @see DokuWiki_Admin_Plugin::getMenuSort()
33
-     */
34
-    public function getMenuSort(): int
35
-    {
36
-        return 800;
37
-    }
30
+	/**
31
+	 * (non-PHPdoc)
32
+	 * @see DokuWiki_Admin_Plugin::getMenuSort()
33
+	 */
34
+	public function getMenuSort(): int
35
+	{
36
+		return 800;
37
+	}
38 38
 
39
-    public function getMenuIcon(): string
40
-    {
41
-        $plugin = $this->getPluginName();
42
-        return DOKU_PLUGIN . $plugin . '/admin/purge.svg';
43
-    }
39
+	public function getMenuIcon(): string
40
+	{
41
+		$plugin = $this->getPluginName();
42
+		return DOKU_PLUGIN . $plugin . '/admin/purge.svg';
43
+	}
44 44
 
45
-    /**
46
-     * (non-PHPdoc)
47
-     * @see DokuWiki_Admin_Plugin::handle()
48
-     */
49
-    public function handle(): void
50
-    {
51
-        global $conf;
52
-        if (!isset($_REQUEST['continue']) || !checkSecurityToken()) {
53
-            return;
54
-        }
55
-        if (isset($_REQUEST['purgetiles'])) {
56
-            $path = $conf['cachedir'] . '/olmaptiles';
57
-            if ($this->rrmdir($path)) {
58
-                msg($this->getLang('admin_purged_tiles'));
59
-            }
60
-        }
61
-        if (isset($_REQUEST['purgemaps'])) {
62
-            $path = $conf['mediadir'] . '/olmapmaps';
63
-            if ($this->rrmdir($path)) {
64
-                msg($this->getLang('admin_purged_maps'));
65
-            }
66
-        }
67
-    }
45
+	/**
46
+	 * (non-PHPdoc)
47
+	 * @see DokuWiki_Admin_Plugin::handle()
48
+	 */
49
+	public function handle(): void
50
+	{
51
+		global $conf;
52
+		if (!isset($_REQUEST['continue']) || !checkSecurityToken()) {
53
+			return;
54
+		}
55
+		if (isset($_REQUEST['purgetiles'])) {
56
+			$path = $conf['cachedir'] . '/olmaptiles';
57
+			if ($this->rrmdir($path)) {
58
+				msg($this->getLang('admin_purged_tiles'));
59
+			}
60
+		}
61
+		if (isset($_REQUEST['purgemaps'])) {
62
+			$path = $conf['mediadir'] . '/olmapmaps';
63
+			if ($this->rrmdir($path)) {
64
+				msg($this->getLang('admin_purged_maps'));
65
+			}
66
+		}
67
+	}
68 68
 
69
-    /**
70
-     * Recursively delete the directory.
71
-     * @param string $sDir directory path
72
-     * @return boolean true when succesful
73
-     */
74
-    private function rrmdir(string $sDir): bool
75
-    {
76
-        if (is_dir($sDir)) {
77
-            Logger::debug('admin_plugin_openlayersmap_purge::rrmdir: recursively removing path: ', $sDir);
78
-            $sDir = rtrim($sDir, '/');
79
-            $oDir = dir($sDir);
80
-            while (($sFile = $oDir->read()) !== false) {
81
-                if ($sFile !== '.' && $sFile !== '..') {
82
-                    (!is_link("$sDir/$sFile") && is_dir("$sDir/$sFile")) ?
83
-                        $this->rrmdir("$sDir/$sFile") : unlink("$sDir/$sFile");
84
-                }
85
-            }
86
-            $oDir->close();
87
-            rmdir($sDir);
88
-            return true;
89
-        }
90
-        return false;
91
-    }
69
+	/**
70
+	 * Recursively delete the directory.
71
+	 * @param string $sDir directory path
72
+	 * @return boolean true when succesful
73
+	 */
74
+	private function rrmdir(string $sDir): bool
75
+	{
76
+		if (is_dir($sDir)) {
77
+			Logger::debug('admin_plugin_openlayersmap_purge::rrmdir: recursively removing path: ', $sDir);
78
+			$sDir = rtrim($sDir, '/');
79
+			$oDir = dir($sDir);
80
+			while (($sFile = $oDir->read()) !== false) {
81
+				if ($sFile !== '.' && $sFile !== '..') {
82
+					(!is_link("$sDir/$sFile") && is_dir("$sDir/$sFile")) ?
83
+						$this->rrmdir("$sDir/$sFile") : unlink("$sDir/$sFile");
84
+				}
85
+			}
86
+			$oDir->close();
87
+			rmdir($sDir);
88
+			return true;
89
+		}
90
+		return false;
91
+	}
92 92
 
93
-    /**
94
-     * (non-PHPdoc)
95
-     * @see DokuWiki_Admin_Plugin::html()
96
-     */
97
-    public function html(): void
98
-    {
99
-        echo $this->locale_xhtml('admin_intro');
100
-        $form = new Doku_Form(array('id' => 'olmap_purgeform', 'method' => 'post'));
101
-        $form->addHidden('continue', 'go');
93
+	/**
94
+	 * (non-PHPdoc)
95
+	 * @see DokuWiki_Admin_Plugin::html()
96
+	 */
97
+	public function html(): void
98
+	{
99
+		echo $this->locale_xhtml('admin_intro');
100
+		$form = new Doku_Form(array('id' => 'olmap_purgeform', 'method' => 'post'));
101
+		$form->addHidden('continue', 'go');
102 102
 
103
-        $form->startFieldset($this->getLang('admin_tiles'));
104
-        $form->addElement('<p>');
105
-        $form->addElement(
106
-            '<input id="purgetiles" name="purgetiles" type="checkbox" value="1" class="checkbox" />'
107
-        );
108
-        $form->addElement(
109
-            '<label for="purgetiles" class="label">' . $this->getLang('admin_purge_tiles')
110
-            . '</label>'
111
-        );
112
-        $form->addElement('</p>');
113
-        $form->endFieldset();
103
+		$form->startFieldset($this->getLang('admin_tiles'));
104
+		$form->addElement('<p>');
105
+		$form->addElement(
106
+			'<input id="purgetiles" name="purgetiles" type="checkbox" value="1" class="checkbox" />'
107
+		);
108
+		$form->addElement(
109
+			'<label for="purgetiles" class="label">' . $this->getLang('admin_purge_tiles')
110
+			. '</label>'
111
+		);
112
+		$form->addElement('</p>');
113
+		$form->endFieldset();
114 114
 
115
-        $form->startFieldset($this->getLang('admin_maps'));
116
-        $form->addElement('<p>');
117
-        $form->addElement('<input id="purgemaps" name="purgemaps" type="checkbox" value="1" class="checkbox" />');
118
-        $form->addElement(
119
-            '<label for="purgemaps" class="label">' . $this->getLang('admin_purge_maps') . '</label>'
120
-        );
121
-        $form->addElement('</p>');
122
-        $form->endFieldset();
115
+		$form->startFieldset($this->getLang('admin_maps'));
116
+		$form->addElement('<p>');
117
+		$form->addElement('<input id="purgemaps" name="purgemaps" type="checkbox" value="1" class="checkbox" />');
118
+		$form->addElement(
119
+			'<label for="purgemaps" class="label">' . $this->getLang('admin_purge_maps') . '</label>'
120
+		);
121
+		$form->addElement('</p>');
122
+		$form->endFieldset();
123 123
 
124
-        $form->addElement(
125
-            form_makeButton(
126
-                'submit',
127
-                'admin',
128
-                $this->getLang('admin_submit'),
129
-                array('accesskey' => 'p', 'title' => $this->getLang('admin_submit'))
130
-            )
131
-        );
132
-        $form->printForm();
133
-    }
124
+		$form->addElement(
125
+			form_makeButton(
126
+				'submit',
127
+				'admin',
128
+				$this->getLang('admin_submit'),
129
+				array('accesskey' => 'p', 'title' => $this->getLang('admin_submit'))
130
+			)
131
+		);
132
+		$form->printForm();
133
+	}
134 134
 }
Please login to merge, or discard this patch.
action.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -25,49 +25,49 @@
 block discarded – undo
25 25
 class action_plugin_openlayersmap extends DokuWiki_Action_Plugin
26 26
 {
27 27
 
28
-    /**
29
-     * plugin should use this method to register its handlers with the DokuWiki's event controller
30
-     *
31
-     * @param    $controller DokuWiki's event controller object. Also available as global $EVENT_HANDLER
32
-     */
33
-    public function register(Doku_Event_Handler $controller)
34
-    {
35
-        $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'insertButton', array());
36
-        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'insertCSSSniffer');
37
-    }
28
+	/**
29
+	 * plugin should use this method to register its handlers with the DokuWiki's event controller
30
+	 *
31
+	 * @param    $controller DokuWiki's event controller object. Also available as global $EVENT_HANDLER
32
+	 */
33
+	public function register(Doku_Event_Handler $controller)
34
+	{
35
+		$controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'insertButton', array());
36
+		$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'insertCSSSniffer');
37
+	}
38 38
 
39
-    /**
40
-     * Inserts the toolbar button.
41
-     * @param Doku_Event $event the DokuWiki event
42
-     */
43
-    public function insertButton(Doku_Event $event, $param)
44
-    {
45
-        $strOpen       = '<olmap id="olMapOne" width="550px" height="450px" lat="50.0" ';
46
-        $strOpen       .= 'lon="5.1" zoom="12" statusbar="1" controls="1" poihoverstyle="0" ';
47
-        $strOpen       .= 'baselyr="OpenStreetMap" gpxfile="" kmlfile="" geojsonfile="" summary="" >\n';
48
-        $strOpen       .= '~~ Plugin olmap help.\n';
49
-        $strOpen       .= '~~ Required in the above tag are values for: id (unique on this page), width, heigth.\n';
50
-        $strOpen       .= '~~ Also you will want to enter zoomlevel and lat, lon values that make sense for where you';
51
-        $strOpen       .= '~~ want the map to start.\n\n';
52
-        $strOpen       .= '~~ Below is an example of a POI, you can add as many as you want. ';
53
-        $strOpen       .= '~~ More examples: https://dokuwiki.org/plugin:openlayersmap \n';
54
-        $event->data[] = array(
55
-            'type'   => 'format',
56
-            'title'  => $this->getLang('openlayersmap'),
57
-            'icon'   => '../../plugins/openlayersmap/toolbar/map.png',
58
-            'open'   => $strOpen,
59
-            'sample' => '50.0117,5.1287,-90,.8,marker-green.png,Pont de Barbouillons; Daverdisse \\\\ external link: 
39
+	/**
40
+	 * Inserts the toolbar button.
41
+	 * @param Doku_Event $event the DokuWiki event
42
+	 */
43
+	public function insertButton(Doku_Event $event, $param)
44
+	{
45
+		$strOpen       = '<olmap id="olMapOne" width="550px" height="450px" lat="50.0" ';
46
+		$strOpen       .= 'lon="5.1" zoom="12" statusbar="1" controls="1" poihoverstyle="0" ';
47
+		$strOpen       .= 'baselyr="OpenStreetMap" gpxfile="" kmlfile="" geojsonfile="" summary="" >\n';
48
+		$strOpen       .= '~~ Plugin olmap help.\n';
49
+		$strOpen       .= '~~ Required in the above tag are values for: id (unique on this page), width, heigth.\n';
50
+		$strOpen       .= '~~ Also you will want to enter zoomlevel and lat, lon values that make sense for where you';
51
+		$strOpen       .= '~~ want the map to start.\n\n';
52
+		$strOpen       .= '~~ Below is an example of a POI, you can add as many as you want. ';
53
+		$strOpen       .= '~~ More examples: https://dokuwiki.org/plugin:openlayersmap \n';
54
+		$event->data[] = array(
55
+			'type'   => 'format',
56
+			'title'  => $this->getLang('openlayersmap'),
57
+			'icon'   => '../../plugins/openlayersmap/toolbar/map.png',
58
+			'open'   => $strOpen,
59
+			'sample' => '50.0117,5.1287,-90,.8,marker-green.png,Pont de Barbouillons; Daverdisse \\\\ external link: 
60 60
                         [[https://test.com|test.com]] \\\\ internal link: [[::start]]\\\\ **DW Formatting** \n',
61
-            'close'  => '</olmap>\n',
62
-        );
63
-    }
61
+			'close'  => '</olmap>\n',
62
+		);
63
+	}
64 64
 
65
-    /** add a snippet of javascript into the head to do a css operation we can check for later on.*/
66
-    public function insertCSSSniffer(Doku_Event $event, $param)
67
-    {
68
-        $event->data["script"][] = array(
69
-            "type"  => "text/javascript",
70
-            "_data" => "document.documentElement.className += ' olCSSsupported';",
71
-        );
72
-    }
65
+	/** add a snippet of javascript into the head to do a css operation we can check for later on.*/
66
+	public function insertCSSSniffer(Doku_Event $event, $param)
67
+	{
68
+		$event->data["script"][] = array(
69
+			"type"  => "text/javascript",
70
+			"_data" => "document.documentElement.className += ' olCSSsupported';",
71
+		);
72
+	}
73 73
 }
Please login to merge, or discard this patch.
_test/general.test.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -25,48 +25,48 @@
 block discarded – undo
25 25
 class general_plugin_openlayersmap_test extends DokuWikiTest
26 26
 {
27 27
 
28
-    protected $pluginsEnabled = array('openlayersmap', 'geophp');
28
+	protected $pluginsEnabled = array('openlayersmap', 'geophp');
29 29
 
30
-    /**
31
-     * Simple test to make sure the plugin.info.txt is in correct format.
32
-     */
33
-    final public function test_plugininfo(): void
34
-    {
35
-        $file = __DIR__ . '/../plugin.info.txt';
36
-        self::assertFileExists($file);
30
+	/**
31
+	 * Simple test to make sure the plugin.info.txt is in correct format.
32
+	 */
33
+	final public function test_plugininfo(): void
34
+	{
35
+		$file = __DIR__ . '/../plugin.info.txt';
36
+		self::assertFileExists($file);
37 37
 
38
-        $info = confToHash($file);
38
+		$info = confToHash($file);
39 39
 
40
-        self::assertArrayHasKey('base', $info);
41
-        self::assertArrayHasKey('author', $info);
42
-        self::assertArrayHasKey('email', $info);
43
-        self::assertArrayHasKey('date', $info);
44
-        self::assertArrayHasKey('name', $info);
45
-        self::assertArrayHasKey('desc', $info);
46
-        self::assertArrayHasKey('url', $info);
40
+		self::assertArrayHasKey('base', $info);
41
+		self::assertArrayHasKey('author', $info);
42
+		self::assertArrayHasKey('email', $info);
43
+		self::assertArrayHasKey('date', $info);
44
+		self::assertArrayHasKey('name', $info);
45
+		self::assertArrayHasKey('desc', $info);
46
+		self::assertArrayHasKey('url', $info);
47 47
 
48
-        self::assertEquals('openlayersmap', $info['base']);
49
-        self::assertRegExp('/^https?:\/\//', $info['url']);
50
-        self::assertTrue(mail_isvalid($info['email']));
51
-        self::assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
52
-        self::assertTrue(false !== strtotime($info['date']));
53
-    }
48
+		self::assertEquals('openlayersmap', $info['base']);
49
+		self::assertRegExp('/^https?:\/\//', $info['url']);
50
+		self::assertTrue(mail_isvalid($info['email']));
51
+		self::assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
52
+		self::assertTrue(false !== strtotime($info['date']));
53
+	}
54 54
 
55
-    /**
56
-     * test if plugin is loaded.
57
-     */
58
-    final public function test_plugin_openlayersmap_isloaded(): void
59
-    {
60
-        global $plugin_controller;
61
-        self::assertContains(
62
-            'geophp',
63
-            $plugin_controller->getList(),
64
-            "geophp plugin is loaded"
65
-        );
66
-        self::assertContains(
67
-            'openlayersmap',
68
-            $plugin_controller->getList(),
69
-            "openlayersmap plugin is loaded"
70
-        );
71
-    }
55
+	/**
56
+	 * test if plugin is loaded.
57
+	 */
58
+	final public function test_plugin_openlayersmap_isloaded(): void
59
+	{
60
+		global $plugin_controller;
61
+		self::assertContains(
62
+			'geophp',
63
+			$plugin_controller->getList(),
64
+			"geophp plugin is loaded"
65
+		);
66
+		self::assertContains(
67
+			'openlayersmap',
68
+			$plugin_controller->getList(),
69
+			"openlayersmap plugin is loaded"
70
+		);
71
+	}
72 72
 }
Please login to merge, or discard this patch.
StaticMap.php 1 patch
Indentation   +899 added lines, -899 removed lines patch added patch discarded remove patch
@@ -34,903 +34,903 @@
 block discarded – undo
34 34
 class StaticMap
35 35
 {
36 36
 
37
-    // the final output
38
-    private $tileSize = 256;
39
-    private $tileInfo = array(
40
-        // OSM sources
41
-        'openstreetmap' => array(
42
-            'txt'  => '(c) OpenStreetMap data/ODbl',
43
-            'logo' => 'osm_logo.png',
44
-            'url'  => 'https://tile.openstreetmap.org/{Z}/{X}/{Y}.png'
45
-        ),
46
-        // OCM sources
47
-        'cycle'         => array(
48
-            'txt'  => '(c) Thunderforest maps',
49
-            'logo' => 'tf_logo.png',
50
-            'url'  => 'https://tile.thunderforest.com/cycle/{Z}/{X}/{Y}.png'
51
-        ),
52
-        'transport'     => array(
53
-            'txt'  => '(c) Thunderforest maps',
54
-            'logo' => 'tf_logo.png',
55
-            'url'  => 'https://tile.thunderforest.com/transport/{Z}/{X}/{Y}.png'
56
-        ),
57
-        'landscape'     => array(
58
-            'txt'  => '(c) Thunderforest maps',
59
-            'logo' => 'tf_logo.png',
60
-            'url'  => 'https://tile.thunderforest.com/landscape/{Z}/{X}/{Y}.png'
61
-        ),
62
-        'outdoors'      => array(
63
-            'txt'  => '(c) Thunderforest maps',
64
-            'logo' => 'tf_logo.png',
65
-            'url'  => 'https://tile.thunderforest.com/outdoors/{Z}/{X}/{Y}.png'
66
-        ),
67
-        'toner-lite'    => array(
68
-            'txt'  => 'Stamen tiles',
69
-            'logo' => 'stamen.png',
70
-            'url'  => 'http://tile.stamen.com/toner-lite/{Z}/{X}/{Y}.png'
71
-        ),
72
-        'terrain'       => array(
73
-            'txt'  => 'Stamen tiles',
74
-            'logo' => 'stamen.png',
75
-            'url'  => 'http://tile.stamen.com/terrain/{Z}/{X}/{Y}.png'
76
-        )
77
-        //,
78
-        // 'piste'=>array(
79
-        // 'txt'=>'OpenPisteMap tiles',
80
-        // 'logo'=>'piste_logo.png',
81
-        // 'url'=>''),
82
-        // 'sea'=>array(
83
-        // 'txt'=>'OpenSeaMap tiles',
84
-        // 'logo'=>'sea_logo.png',
85
-        // 'url'=>''),
86
-        // H&B sources
87
-        //          'hikeandbike' => array (
88
-        //                  'txt' => 'Hike & Bike Map',
89
-        //                  'logo' => 'hnb_logo.png',
90
-        //                  //'url' => 'http://toolserver.org/tiles/hikebike/{Z}/{X}/{Y}.png'
91
-        //                  //moved to: https://www.toolserver.org/tiles/hikebike/12/2105/1388.png
92
-        //                  'url' => 'http://c.tiles.wmflabs.org/hikebike/{Z}/{X}/{Y}.png'
93
-        //          )
94
-    );
95
-    private $tileDefaultSrc = 'openstreetmap';
96
-
97
-    // set up markers
98
-    private $markerPrototypes = array(
99
-        // found at http://www.mapito.net/map-marker-icons.html
100
-        // these are 17x19 px with a pointer at the bottom left
101
-        'lightblue' => array(
102
-            'regex'        => '/^lightblue([0-9]+)$/',
103
-            'extension'    => '.png',
104
-            'shadow'       => false,
105
-            'offsetImage'  => '0,-19',
106
-            'offsetShadow' => false
107
-        ),
108
-        // openlayers std markers are 21x25px with shadow
109
-        'ol-marker' => array(
110
-            'regex'        => '/^marker(|-blue|-gold|-green|-red)+$/',
111
-            'extension'    => '.png',
112
-            'shadow'       => 'marker_shadow.png',
113
-            'offsetImage'  => '-10,-25',
114
-            'offsetShadow' => '-1,-13'
115
-        ),
116
-        // these are 16x16 px
117
-        'ww_icon'   => array(
118
-            'regex'        => '/ww_\S+$/',
119
-            'extension'    => '.png',
120
-            'shadow'       => false,
121
-            'offsetImage'  => '-8,-8',
122
-            'offsetShadow' => false
123
-        ),
124
-        // assume these are 16x16 px
125
-        'rest'      => array(
126
-            'regex'        => '/^(?!lightblue([0-9]+)$)(?!(ww_\S+$))(?!marker(|-blue|-gold|-green|-red)+$)(.*)/',
127
-            'extension'    => '.png',
128
-            'shadow'       => 'marker_shadow.png',
129
-            'offsetImage'  => '-8,-8',
130
-            'offsetShadow' => '-1,-1'
131
-        )
132
-    );
133
-    private $centerX;
134
-    private $centerY;
135
-    private $offsetX;
136
-    private $offsetY;
137
-    private $image;
138
-    private $zoom;
139
-    private $lat;
140
-    private $lon;
141
-    private $width;
142
-    private $height;
143
-    private $markers;
144
-    private $maptype;
145
-    private $kmlFileName;
146
-    private $gpxFileName;
147
-    private $geojsonFileName;
148
-    private $autoZoomExtent;
149
-    private $apikey;
150
-    private $tileCacheBaseDir;
151
-    private $mapCacheBaseDir;
152
-    private $mediaBaseDir;
153
-    private $useTileCache;
154
-    private $mapCacheID = '';
155
-    private $mapCacheFile = '';
156
-    private $mapCacheExtension = 'png';
157
-
158
-    /**
159
-     * Constructor.
160
-     *
161
-     * @param float  $lat
162
-     *            Latitude (x) of center of map
163
-     * @param float  $lon
164
-     *            Longitude (y) of center of map
165
-     * @param int    $zoom
166
-     *            Zoomlevel
167
-     * @param int    $width
168
-     *            Width in pixels
169
-     * @param int    $height
170
-     *            Height in pixels
171
-     * @param string $maptype
172
-     *            Name of the map
173
-     * @param array  $markers
174
-     *            array of markers
175
-     * @param string $gpx
176
-     *            GPX filename
177
-     * @param string $kml
178
-     *            KML filename
179
-     * @param string $geojson
180
-     * @param string $mediaDir
181
-     *            Directory to store/cache maps
182
-     * @param string $tileCacheBaseDir
183
-     *            Directory to cache map tiles
184
-     * @param bool   $autoZoomExtent
185
-     *            Wheter or not to override zoom/lat/lon and zoom to the extent of gpx/kml and markers
186
-     * @param string $apikey
187
-     */
188
-    public function __construct(
189
-        float $lat,
190
-        float $lon,
191
-        int $zoom,
192
-        int $width,
193
-        int $height,
194
-        string $maptype,
195
-        array $markers,
196
-        string $gpx,
197
-        string $kml,
198
-        string $geojson,
199
-        string $mediaDir,
200
-        string $tileCacheBaseDir,
201
-        bool $autoZoomExtent = true,
202
-        string $apikey = ''
203
-    ) {
204
-        $this->zoom   = $zoom;
205
-        $this->lat    = $lat;
206
-        $this->lon    = $lon;
207
-        $this->width  = $width;
208
-        $this->height = $height;
209
-        // validate + set maptype
210
-        $this->maptype = $this->tileDefaultSrc;
211
-        if (array_key_exists($maptype, $this->tileInfo)) {
212
-            $this->maptype = $maptype;
213
-        }
214
-        $this->markers          = $markers;
215
-        $this->kmlFileName      = $kml;
216
-        $this->gpxFileName      = $gpx;
217
-        $this->geojsonFileName  = $geojson;
218
-        $this->mediaBaseDir     = $mediaDir;
219
-        $this->tileCacheBaseDir = $tileCacheBaseDir . '/olmaptiles';
220
-        $this->useTileCache     = $this->tileCacheBaseDir !== '';
221
-        $this->mapCacheBaseDir  = $mediaDir . '/olmapmaps';
222
-        $this->autoZoomExtent   = $autoZoomExtent;
223
-        $this->apikey           = $apikey;
224
-    }
225
-
226
-    /**
227
-     * get the map, this may return a reference to a cached copy.
228
-     *
229
-     * @return string url relative to media dir
230
-     */
231
-    public function getMap(): string
232
-    {
233
-        try {
234
-            if ($this->autoZoomExtent) {
235
-                $this->autoZoom();
236
-            }
237
-        } catch (Exception $e) {
238
-            Logger::debug($e);
239
-        }
240
-
241
-        // use map cache, so check cache for map
242
-        if (!$this->checkMapCache()) {
243
-            // map is not in cache, needs to be build
244
-            $this->makeMap();
245
-            $this->mkdirRecursive(dirname($this->mapCacheIDToFilename()), 0777);
246
-            imagepng($this->image, $this->mapCacheIDToFilename(), 9);
247
-        }
248
-        $doc = $this->mapCacheIDToFilename();
249
-        // make url relative to media dir
250
-        return str_replace($this->mediaBaseDir, '', $doc);
251
-    }
252
-
253
-    /**
254
-     * Calculate the lat/lon/zoom values to make sure that all of the markers and gpx/kml are on the map.
255
-     * can throw an error like
256
-     * "Fatal error: Uncaught Exception: Cannot create a collection with non-geometries in
257
-     * D:\www\wild-water.nl\www\dokuwiki\lib\plugins\geophp\geoPHP\lib\geometry\Collection.class.php:29"
258
-     *
259
-     * @param float $paddingFactor
260
-     *            buffer constant to enlarge (>1.0) the zoom level
261
-     * @throws Exception
262
-     */
263
-    private function autoZoom(float $paddingFactor = 1.0): void
264
-    {
265
-        $geoms    = array();
266
-        $geoms [] = new Point ($this->lon, $this->lat);
267
-        if (!empty ($this->markers)) {
268
-            foreach ($this->markers as $marker) {
269
-                $geoms [] = new Point ($marker ['lon'], $marker ['lat']);
270
-            }
271
-        }
272
-        if (file_exists($this->kmlFileName)) {
273
-            $g = geoPHP::load(file_get_contents($this->kmlFileName), 'kml');
274
-            if ($g !== false) {
275
-                $geoms [] = $g;
276
-            }
277
-        }
278
-        if (file_exists($this->gpxFileName)) {
279
-            $g = geoPHP::load(file_get_contents($this->gpxFileName), 'gpx');
280
-            if ($g !== false) {
281
-                $geoms [] = $g;
282
-            }
283
-        }
284
-        if (file_exists($this->geojsonFileName)) {
285
-            $g = geoPHP::load(file_get_contents($this->geojsonFileName), 'geojson');
286
-            if ($g !== false) {
287
-                $geoms [] = $g;
288
-            }
289
-        }
290
-
291
-        if (count($geoms) <= 1) {
292
-            Logger::debug("StaticMap::autoZoom: Skip setting autozoom options", $geoms);
293
-            return;
294
-        }
295
-
296
-        $geom     = new GeometryCollection ($geoms);
297
-        $centroid = $geom->centroid();
298
-        $bbox     = $geom->getBBox();
299
-
300
-        // determine vertical resolution, this depends on the distance from the equator
301
-        // $vy00 = log(tan(M_PI*(0.25 + $centroid->getY()/360)));
302
-        $vy0 = log(tan(M_PI * (0.25 + $bbox ['miny'] / 360)));
303
-        $vy1 = log(tan(M_PI * (0.25 + $bbox ['maxy'] / 360)));
304
-        Logger::debug("StaticMap::autoZoom: vertical resolution: $vy0, $vy1");
305
-        $zoomFactorPowered  = ($this->height / 2) / (40.7436654315252 * ($vy1 - $vy0));
306
-        $resolutionVertical = 360 / ($zoomFactorPowered * $this->tileSize);
307
-        // determine horizontal resolution
308
-        $resolutionHorizontal = ($bbox ['maxx'] - $bbox ['minx']) / $this->width;
309
-        $resolution           = max($resolutionHorizontal, $resolutionVertical) * $paddingFactor;
310
-        $zoom                 = log(360 / ($resolution * $this->tileSize), 2);
311
-
312
-        if (is_finite($zoom) && $zoom < 15 && $zoom > 2) {
313
-            $this->zoom = floor($zoom);
314
-        }
315
-        $this->lon = $centroid->getX();
316
-        $this->lat = $centroid->getY();
317
-        Logger::debug("StaticMap::autoZoom: Set autozoom options to: z: $this->zoom, lon: $this->lon, lat: $this->lat");
318
-    }
319
-
320
-    public function checkMapCache(): bool
321
-    {
322
-        // side effect: set the mapCacheID
323
-        $this->mapCacheID = md5($this->serializeParams());
324
-        $filename         = $this->mapCacheIDToFilename();
325
-        return file_exists($filename);
326
-    }
327
-
328
-    public function serializeParams(): string
329
-    {
330
-        return join(
331
-            "&",
332
-            array(
333
-                $this->zoom,
334
-                $this->lat,
335
-                $this->lon,
336
-                $this->width,
337
-                $this->height,
338
-                serialize($this->markers),
339
-                $this->maptype,
340
-                $this->kmlFileName,
341
-                $this->gpxFileName,
342
-                $this->geojsonFileName
343
-            )
344
-        );
345
-    }
346
-
347
-    public function mapCacheIDToFilename(): string
348
-    {
349
-        if (!$this->mapCacheFile) {
350
-            $this->mapCacheFile = $this->mapCacheBaseDir . "/" . $this->maptype . "/" . $this->zoom . "/cache_"
351
-                . substr($this->mapCacheID, 0, 2) . "/" . substr($this->mapCacheID, 2, 2)
352
-                . "/" . substr($this->mapCacheID, 4);
353
-        }
354
-        return $this->mapCacheFile . "." . $this->mapCacheExtension;
355
-    }
356
-
357
-    /**
358
-     * make the map.
359
-     */
360
-    public function makeMap(): void
361
-    {
362
-        $this->initCoords();
363
-        $this->createBaseMap();
364
-        if (!empty ($this->markers)) {
365
-            $this->placeMarkers();
366
-        }
367
-        if (file_exists($this->kmlFileName)) {
368
-            try {
369
-                $this->drawKML();
370
-            } catch (exception $e) {
371
-                Logger::error('failed to load KML file', $e);
372
-            }
373
-        }
374
-        if (file_exists($this->gpxFileName)) {
375
-            try {
376
-                $this->drawGPX();
377
-            } catch (exception $e) {
378
-                Logger::error('failed to load GPX file', $e);
379
-            }
380
-        }
381
-        if (file_exists($this->geojsonFileName)) {
382
-            try {
383
-                $this->drawGeojson();
384
-            } catch (exception $e) {
385
-                Logger::error('failed to load GeoJSON file', $e);
386
-            }
387
-        }
388
-
389
-        $this->drawCopyright();
390
-    }
391
-
392
-    /**
393
-     */
394
-    public function initCoords(): void
395
-    {
396
-        $this->centerX = $this->lonToTile($this->lon, $this->zoom);
397
-        $this->centerY = $this->latToTile($this->lat, $this->zoom);
398
-        $this->offsetX = floor((floor($this->centerX) - $this->centerX) * $this->tileSize);
399
-        $this->offsetY = floor((floor($this->centerY) - $this->centerY) * $this->tileSize);
400
-    }
401
-
402
-    /**
403
-     *
404
-     * @param float $long
405
-     * @param int   $zoom
406
-     * @return float|int
407
-     */
408
-    public function lonToTile(float $long, int $zoom)
409
-    {
410
-        return (($long + 180) / 360) * pow(2, $zoom);
411
-    }
412
-
413
-    /**
414
-     *
415
-     * @param float $lat
416
-     * @param int   $zoom
417
-     * @return float|int
418
-     */
419
-    public function latToTile(float $lat, int $zoom)
420
-    {
421
-        return (1 - log(tan($lat * pi() / 180) + 1 / cos($lat * M_PI / 180)) / M_PI) / 2 * pow(2, $zoom);
422
-    }
423
-
424
-    /**
425
-     * make basemap image.
426
-     */
427
-    public function createBaseMap(): void
428
-    {
429
-        $this->image   = imagecreatetruecolor($this->width, $this->height);
430
-        $startX        = floor($this->centerX - ($this->width / $this->tileSize) / 2);
431
-        $startY        = floor($this->centerY - ($this->height / $this->tileSize) / 2);
432
-        $endX          = ceil($this->centerX + ($this->width / $this->tileSize) / 2);
433
-        $endY          = ceil($this->centerY + ($this->height / $this->tileSize) / 2);
434
-        $this->offsetX = -floor(($this->centerX - floor($this->centerX)) * $this->tileSize);
435
-        $this->offsetY = -floor(($this->centerY - floor($this->centerY)) * $this->tileSize);
436
-        $this->offsetX += floor($this->width / 2);
437
-        $this->offsetY += floor($this->height / 2);
438
-        $this->offsetX += floor($startX - floor($this->centerX)) * $this->tileSize;
439
-        $this->offsetY += floor($startY - floor($this->centerY)) * $this->tileSize;
440
-
441
-        for ($x = $startX; $x <= $endX; $x++) {
442
-            for ($y = $startY; $y <= $endY; $y++) {
443
-                $url = str_replace(
444
-                    array(
445
-                        '{Z}',
446
-                        '{X}',
447
-                        '{Y}'
448
-                    ),
449
-                    array(
450
-                        $this->zoom,
451
-                        $x,
452
-                        $y
453
-                    ),
454
-                    $this->tileInfo [$this->maptype] ['url']
455
-                );
456
-
457
-                $tileData = $this->fetchTile($url);
458
-                if ($tileData) {
459
-                    $tileImage = imagecreatefromstring($tileData);
460
-                } else {
461
-                    $tileImage = imagecreate($this->tileSize, $this->tileSize);
462
-                    $color     = imagecolorallocate($tileImage, 255, 255, 255);
463
-                    @imagestring($tileImage, 1, 127, 127, 'err', $color);
464
-                }
465
-                $destX = ($x - $startX) * $this->tileSize + $this->offsetX;
466
-                $destY = ($y - $startY) * $this->tileSize + $this->offsetY;
467
-                Logger::debug("imagecopy tile into image: $destX, $destY", $this->tileSize);
468
-                imagecopy(
469
-                    $this->image,
470
-                    $tileImage,
471
-                    $destX,
472
-                    $destY,
473
-                    0,
474
-                    0,
475
-                    $this->tileSize,
476
-                    $this->tileSize
477
-                );
478
-            }
479
-        }
480
-    }
481
-
482
-    /**
483
-     * Fetch a tile and (if configured) store it in the cache.
484
-     * @param string $url
485
-     * @return bool|string
486
-     * @todo refactor this to use dokuwiki\HTTP\HTTPClient or dokuwiki\HTTP\DokuHTTPClient
487
-     *          for better proxy handling...
488
-     */
489
-    public function fetchTile(string $url)
490
-    {
491
-        if ($this->useTileCache && ($cached = $this->checkTileCache($url))) {
492
-            return $cached;
493
-        }
494
-
495
-        $_UA = 'Mozilla/4.0 (compatible; DokuWikiSpatial HTTP Client; ' . PHP_OS . ')';
496
-        if (function_exists("curl_init")) {
497
-            // use cUrl
498
-            $ch = curl_init();
499
-            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
500
-            curl_setopt($ch, CURLOPT_USERAGENT, $_UA);
501
-            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
502
-            curl_setopt($ch, CURLOPT_URL, $url . $this->apikey);
503
-            Logger::debug("StaticMap::fetchTile: getting: $url using curl_exec");
504
-            $tile = curl_exec($ch);
505
-            curl_close($ch);
506
-        } else {
507
-            // use file_get_contents
508
-            global $conf;
509
-            $opts = array(
510
-                'http' => array(
511
-                    'method'          => "GET",
512
-                    'header'          => "Accept-language: en\r\n" . "User-Agent: $_UA\r\n" . "accept: image/png\r\n",
513
-                    'request_fulluri' => true
514
-                )
515
-            );
516
-            if (isset($conf['proxy']['host'], $conf['proxy']['port'])
517
-                && $conf['proxy']['host'] !== ''
518
-                && $conf['proxy']['port'] !== '') {
519
-                $opts['http'] += ['proxy' => "tcp://" . $conf['proxy']['host'] . ":" . $conf['proxy']['port']];
520
-            }
521
-
522
-            $context = stream_context_create($opts);
523
-            Logger::debug(
524
-                "StaticMap::fetchTile: getting: $url . $this->apikey using file_get_contents and options $opts"
525
-            );
526
-            $tile = file_get_contents($url . $this->apikey, false, $context);
527
-        }
528
-        if ($tile && $this->useTileCache) {
529
-            $this->writeTileToCache($url, $tile);
530
-        }
531
-        return $tile;
532
-    }
533
-
534
-    /**
535
-     *
536
-     * @param string $url
537
-     * @return string|false
538
-     */
539
-    public function checkTileCache(string $url)
540
-    {
541
-        $filename = $this->tileUrlToFilename($url);
542
-        if (file_exists($filename)) {
543
-            return file_get_contents($filename);
544
-        }
545
-        return false;
546
-    }
547
-
548
-    /**
549
-     *
550
-     * @param string $url
551
-     * @return string
552
-     */
553
-    public function tileUrlToFilename(string $url): string
554
-    {
555
-        return $this->tileCacheBaseDir . "/" . substr($url, strpos($url, '/') + 1);
556
-    }
557
-
558
-    /**
559
-     * Write a tile into the cache.
560
-     *
561
-     * @param string $url
562
-     * @param mixed  $data
563
-     */
564
-    public function writeTileToCache(string $url, $data): void
565
-    {
566
-        $filename = $this->tileUrlToFilename($url);
567
-        $this->mkdirRecursive(dirname($filename), 0777);
568
-        file_put_contents($filename, $data);
569
-    }
570
-
571
-    /**
572
-     * Recursively create the directory.
573
-     *
574
-     * @param string $pathname
575
-     *            The directory path.
576
-     * @param int    $mode
577
-     *            File access mode. For more information on modes, read the details on the chmod manpage.
578
-     */
579
-    public function mkdirRecursive(string $pathname, int $mode): bool
580
-    {
581
-        is_dir(dirname($pathname)) || $this->mkdirRecursive(dirname($pathname), $mode);
582
-        return is_dir($pathname) || mkdir($pathname, $mode) || is_dir($pathname);
583
-    }
584
-
585
-    /**
586
-     * Place markers on the map and number them in the same order as they are listed in the html.
587
-     */
588
-    public function placeMarkers(): void
589
-    {
590
-        $count               = 0;
591
-        $color               = imagecolorallocate($this->image, 0, 0, 0);
592
-        $bgcolor             = imagecolorallocate($this->image, 200, 200, 200);
593
-        $markerBaseDir       = __DIR__ . '/icons';
594
-        $markerImageOffsetX  = 0;
595
-        $markerImageOffsetY  = 0;
596
-        $markerShadowOffsetX = 0;
597
-        $markerShadowOffsetY = 0;
598
-        $markerShadowImg     = null;
599
-        // loop thru marker array
600
-        foreach ($this->markers as $marker) {
601
-            // set some local variables
602
-            $markerLat  = $marker ['lat'];
603
-            $markerLon  = $marker ['lon'];
604
-            $markerType = $marker ['type'];
605
-            // clear variables from previous loops
606
-            $markerFilename = '';
607
-            $markerShadow   = '';
608
-            $matches        = false;
609
-            // check for marker type, get settings from markerPrototypes
610
-            if ($markerType) {
611
-                foreach ($this->markerPrototypes as $markerPrototype) {
612
-                    if (preg_match($markerPrototype ['regex'], $markerType, $matches)) {
613
-                        $markerFilename = $matches [0] . $markerPrototype ['extension'];
614
-                        if ($markerPrototype ['offsetImage']) {
615
-                            list ($markerImageOffsetX, $markerImageOffsetY) = explode(
616
-                                ",",
617
-                                $markerPrototype ['offsetImage']
618
-                            );
619
-                        }
620
-                        $markerShadow = $markerPrototype ['shadow'];
621
-                        if ($markerShadow) {
622
-                            list ($markerShadowOffsetX, $markerShadowOffsetY) = explode(
623
-                                ",",
624
-                                $markerPrototype ['offsetShadow']
625
-                            );
626
-                        }
627
-                    }
628
-                }
629
-            }
630
-            // create img resource
631
-            if (file_exists($markerBaseDir . '/' . $markerFilename)) {
632
-                $markerImg = imagecreatefrompng($markerBaseDir . '/' . $markerFilename);
633
-            } else {
634
-                $markerImg = imagecreatefrompng($markerBaseDir . '/marker.png');
635
-            }
636
-            // check for shadow + create shadow recource
637
-            if ($markerShadow && file_exists($markerBaseDir . '/' . $markerShadow)) {
638
-                $markerShadowImg = imagecreatefrompng($markerBaseDir . '/' . $markerShadow);
639
-            }
640
-            // calc position
641
-            $destX = floor(
642
-                ($this->width / 2) -
643
-                $this->tileSize * ($this->centerX - $this->lonToTile($markerLon, $this->zoom))
644
-            );
645
-            $destY = floor(
646
-                ($this->height / 2) -
647
-                $this->tileSize * ($this->centerY - $this->latToTile($markerLat, $this->zoom))
648
-            );
649
-            // copy shadow on basemap
650
-            if ($markerShadow && $markerShadowImg) {
651
-                imagecopy(
652
-                    $this->image,
653
-                    $markerShadowImg,
654
-                    $destX + (int)$markerShadowOffsetX,
655
-                    $destY + (int)$markerShadowOffsetY,
656
-                    0,
657
-                    0,
658
-                    imagesx($markerShadowImg),
659
-                    imagesy($markerShadowImg)
660
-                );
661
-            }
662
-            // copy marker on basemap above shadow
663
-            imagecopy(
664
-                $this->image,
665
-                $markerImg,
666
-                $destX + (int)$markerImageOffsetX,
667
-                $destY + (int)$markerImageOffsetY,
668
-                0,
669
-                0,
670
-                imagesx($markerImg),
671
-                imagesy($markerImg)
672
-            );
673
-            // add label
674
-            imagestring(
675
-                $this->image,
676
-                3,
677
-                $destX - imagesx($markerImg) + 1,
678
-                $destY + (int)$markerImageOffsetY + 1,
679
-                ++$count,
680
-                $bgcolor
681
-            );
682
-            imagestring(
683
-                $this->image,
684
-                3,
685
-                $destX - imagesx($markerImg),
686
-                $destY + (int)$markerImageOffsetY,
687
-                $count,
688
-                $color
689
-            );
690
-        }
691
-    }
692
-
693
-    /**
694
-     * Draw kml trace on the map.
695
-     * @throws exception if loading the specified KML fails
696
-     */
697
-    public function drawKML(): void
698
-    {
699
-        // TODO get colour from kml node (not currently supported in geoPHP)
700
-        $col     = imagecolorallocatealpha($this->image, 255, 0, 0, .4 * 127);
701
-        $kmlgeom = geoPHP::load(file_get_contents($this->kmlFileName), 'kml');
702
-        $this->drawGeometry($kmlgeom, $col);
703
-    }
704
-
705
-    /**
706
-     * Draw geometry or geometry collection on the map.
707
-     *
708
-     * @param Geometry|GeometryCollection|MultiPolygon|MultiLineString|MultiPoint|Polygon|LineString|Point $geom
709
-     * @param int                                                                                          $colour
710
-     *            drawing colour
711
-     */
712
-    private function drawGeometry(Geometry $geom, int $colour): void
713
-    {
714
-        if (empty($geom)) {
715
-            return;
716
-        }
717
-
718
-        switch ($geom->geometryType()) {
719
-            case 'GeometryCollection' :
720
-                // recursively draw part of the collection
721
-                for ($i = 1; $i < $geom->numGeometries() + 1; $i++) {
722
-                    $_geom = $geom->geometryN($i);
723
-                    $this->drawGeometry($_geom, $colour);
724
-                }
725
-                break;
726
-            case 'MultiPolygon' :
727
-            case 'MultiLineString' :
728
-            case 'MultiPoint' :
729
-                // TODO implement / do nothing
730
-                break;
731
-            case 'Polygon' :
732
-                $this->drawPolygon($geom, $colour);
733
-                break;
734
-            case 'LineString' :
735
-                $this->drawLineString($geom, $colour);
736
-                break;
737
-            case 'Point' :
738
-                $this->drawPoint($geom, $colour);
739
-                break;
740
-            default :
741
-                // draw nothing
742
-                break;
743
-        }
744
-    }
745
-
746
-    /**
747
-     * Draw a polygon on the map.
748
-     *
749
-     * @param Polygon $polygon
750
-     * @param int     $colour
751
-     *            drawing colour
752
-     */
753
-    private function drawPolygon(Polygon $polygon, int $colour)
754
-    {
755
-        // TODO implementation of drawing holes,
756
-        // maybe draw the polygon to an in-memory image and use imagecopy, draw polygon in col., draw holes in bgcol?
757
-
758
-        // print_r('Polygon:<br />');
759
-        // print_r($polygon);
760
-        $extPoints = array();
761
-        // extring is a linestring actually..
762
-        $extRing = $polygon->exteriorRing();
763
-
764
-        for ($i = 1; $i < $extRing->numGeometries(); $i++) {
765
-            $p1           = $extRing->geometryN($i);
766
-            $x            = floor(
767
-                ($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($p1->x(), $this->zoom))
768
-            );
769
-            $y            = floor(
770
-                ($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($p1->y(), $this->zoom))
771
-            );
772
-            $extPoints [] = $x;
773
-            $extPoints [] = $y;
774
-        }
775
-        // print_r('points:('.($i-1).')<br />');
776
-        // print_r($extPoints);
777
-        // imagepolygon ($this->image, $extPoints, $i-1, $colour );
778
-        imagefilledpolygon($this->image, $extPoints, $i - 1, $colour);
779
-    }
780
-
781
-    /**
782
-     * Draw a line on the map.
783
-     *
784
-     * @param LineString $line
785
-     * @param int        $colour
786
-     *            drawing colour
787
-     */
788
-    private function drawLineString(LineString $line, int $colour)
789
-    {
790
-        imagesetthickness($this->image, 2);
791
-        for ($p = 1; $p < $line->numGeometries(); $p++) {
792
-            // get first pair of points
793
-            $p1 = $line->geometryN($p);
794
-            $p2 = $line->geometryN($p + 1);
795
-            // translate to paper space
796
-            $x1 = floor(
797
-                ($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($p1->x(), $this->zoom))
798
-            );
799
-            $y1 = floor(
800
-                ($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($p1->y(), $this->zoom))
801
-            );
802
-            $x2 = floor(
803
-                ($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($p2->x(), $this->zoom))
804
-            );
805
-            $y2 = floor(
806
-                ($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($p2->y(), $this->zoom))
807
-            );
808
-            // draw to image
809
-            imageline($this->image, $x1, $y1, $x2, $y2, $colour);
810
-        }
811
-        imagesetthickness($this->image, 1);
812
-    }
813
-
814
-    /**
815
-     * Draw a point on the map.
816
-     *
817
-     * @param Point $point
818
-     * @param int   $colour
819
-     *            drawing colour
820
-     */
821
-    private function drawPoint(Point $point, int $colour)
822
-    {
823
-        imagesetthickness($this->image, 2);
824
-        // translate to paper space
825
-        $cx = floor(
826
-            ($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($point->x(), $this->zoom))
827
-        );
828
-        $cy = floor(
829
-            ($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($point->y(), $this->zoom))
830
-        );
831
-        $r  = 5;
832
-        // draw to image
833
-        // imageellipse($this->image, $cx, $cy,$r, $r, $colour);
834
-        imagefilledellipse($this->image, $cx, $cy, $r, $r, $colour);
835
-        // don't use imageellipse because the imagesetthickness function has
836
-        // no effect. So the better workaround is to use imagearc.
837
-        imagearc($this->image, $cx, $cy, $r, $r, 0, 359, $colour);
838
-        imagesetthickness($this->image, 1);
839
-    }
840
-
841
-    /**
842
-     * Draw gpx trace on the map.
843
-     * @throws exception if loading the specified GPX fails
844
-     */
845
-    public function drawGPX()
846
-    {
847
-        $col     = imagecolorallocatealpha($this->image, 0, 0, 255, .4 * 127);
848
-        $gpxgeom = geoPHP::load(file_get_contents($this->gpxFileName), 'gpx');
849
-        $this->drawGeometry($gpxgeom, $col);
850
-    }
851
-
852
-    /**
853
-     * Draw geojson on the map.
854
-     * @throws exception if loading the specified GeoJSON fails
855
-     */
856
-    public function drawGeojson()
857
-    {
858
-        $col     = imagecolorallocatealpha($this->image, 255, 0, 255, .4 * 127);
859
-        $gpxgeom = geoPHP::load(file_get_contents($this->geojsonFileName), 'json');
860
-        $this->drawGeometry($gpxgeom, $col);
861
-    }
862
-
863
-    /**
864
-     * add copyright and origin notice and icons to the map.
865
-     */
866
-    public function drawCopyright()
867
-    {
868
-        $logoBaseDir = dirname(__FILE__) . '/' . 'logo/';
869
-        $logoImg     = imagecreatefrompng($logoBaseDir . $this->tileInfo ['openstreetmap'] ['logo']);
870
-        $textcolor   = imagecolorallocate($this->image, 0, 0, 0);
871
-        $bgcolor     = imagecolorallocate($this->image, 200, 200, 200);
872
-
873
-        imagecopy(
874
-            $this->image,
875
-            $logoImg,
876
-            0,
877
-            imagesy($this->image) - imagesy($logoImg),
878
-            0,
879
-            0,
880
-            imagesx($logoImg),
881
-            imagesy($logoImg)
882
-        );
883
-        imagestring(
884
-            $this->image,
885
-            1,
886
-            imagesx($logoImg) + 2,
887
-            imagesy($this->image) - imagesy($logoImg) + 1,
888
-            $this->tileInfo ['openstreetmap'] ['txt'],
889
-            $bgcolor
890
-        );
891
-        imagestring(
892
-            $this->image,
893
-            1,
894
-            imagesx($logoImg) + 1,
895
-            imagesy($this->image) - imagesy($logoImg),
896
-            $this->tileInfo ['openstreetmap'] ['txt'],
897
-            $textcolor
898
-        );
899
-
900
-        // additional tile source info, ie. who created/hosted the tiles
901
-        $xIconOffset = 0;
902
-        if ($this->maptype === 'openstreetmap') {
903
-            $mapAuthor = "(c) OpenStreetMap maps/CC BY-SA";
904
-        } else {
905
-            $mapAuthor   = $this->tileInfo [$this->maptype] ['txt'];
906
-            $iconImg     = imagecreatefrompng($logoBaseDir . $this->tileInfo [$this->maptype] ['logo']);
907
-            $xIconOffset = imagesx($iconImg);
908
-            imagecopy(
909
-                $this->image,
910
-                $iconImg,
911
-                imagesx($logoImg) + 1,
912
-                imagesy($this->image) - imagesy($iconImg),
913
-                0,
914
-                0,
915
-                imagesx($iconImg),
916
-                imagesy($iconImg)
917
-            );
918
-        }
919
-        imagestring(
920
-            $this->image,
921
-            1,
922
-            imagesx($logoImg) + $xIconOffset + 4,
923
-            imagesy($this->image) - ceil(imagesy($logoImg) / 2) + 1,
924
-            $mapAuthor,
925
-            $bgcolor
926
-        );
927
-        imagestring(
928
-            $this->image,
929
-            1,
930
-            imagesx($logoImg) + $xIconOffset + 3,
931
-            imagesy($this->image) - ceil(imagesy($logoImg) / 2),
932
-            $mapAuthor,
933
-            $textcolor
934
-        );
935
-    }
37
+	// the final output
38
+	private $tileSize = 256;
39
+	private $tileInfo = array(
40
+		// OSM sources
41
+		'openstreetmap' => array(
42
+			'txt'  => '(c) OpenStreetMap data/ODbl',
43
+			'logo' => 'osm_logo.png',
44
+			'url'  => 'https://tile.openstreetmap.org/{Z}/{X}/{Y}.png'
45
+		),
46
+		// OCM sources
47
+		'cycle'         => array(
48
+			'txt'  => '(c) Thunderforest maps',
49
+			'logo' => 'tf_logo.png',
50
+			'url'  => 'https://tile.thunderforest.com/cycle/{Z}/{X}/{Y}.png'
51
+		),
52
+		'transport'     => array(
53
+			'txt'  => '(c) Thunderforest maps',
54
+			'logo' => 'tf_logo.png',
55
+			'url'  => 'https://tile.thunderforest.com/transport/{Z}/{X}/{Y}.png'
56
+		),
57
+		'landscape'     => array(
58
+			'txt'  => '(c) Thunderforest maps',
59
+			'logo' => 'tf_logo.png',
60
+			'url'  => 'https://tile.thunderforest.com/landscape/{Z}/{X}/{Y}.png'
61
+		),
62
+		'outdoors'      => array(
63
+			'txt'  => '(c) Thunderforest maps',
64
+			'logo' => 'tf_logo.png',
65
+			'url'  => 'https://tile.thunderforest.com/outdoors/{Z}/{X}/{Y}.png'
66
+		),
67
+		'toner-lite'    => array(
68
+			'txt'  => 'Stamen tiles',
69
+			'logo' => 'stamen.png',
70
+			'url'  => 'http://tile.stamen.com/toner-lite/{Z}/{X}/{Y}.png'
71
+		),
72
+		'terrain'       => array(
73
+			'txt'  => 'Stamen tiles',
74
+			'logo' => 'stamen.png',
75
+			'url'  => 'http://tile.stamen.com/terrain/{Z}/{X}/{Y}.png'
76
+		)
77
+		//,
78
+		// 'piste'=>array(
79
+		// 'txt'=>'OpenPisteMap tiles',
80
+		// 'logo'=>'piste_logo.png',
81
+		// 'url'=>''),
82
+		// 'sea'=>array(
83
+		// 'txt'=>'OpenSeaMap tiles',
84
+		// 'logo'=>'sea_logo.png',
85
+		// 'url'=>''),
86
+		// H&B sources
87
+		//          'hikeandbike' => array (
88
+		//                  'txt' => 'Hike & Bike Map',
89
+		//                  'logo' => 'hnb_logo.png',
90
+		//                  //'url' => 'http://toolserver.org/tiles/hikebike/{Z}/{X}/{Y}.png'
91
+		//                  //moved to: https://www.toolserver.org/tiles/hikebike/12/2105/1388.png
92
+		//                  'url' => 'http://c.tiles.wmflabs.org/hikebike/{Z}/{X}/{Y}.png'
93
+		//          )
94
+	);
95
+	private $tileDefaultSrc = 'openstreetmap';
96
+
97
+	// set up markers
98
+	private $markerPrototypes = array(
99
+		// found at http://www.mapito.net/map-marker-icons.html
100
+		// these are 17x19 px with a pointer at the bottom left
101
+		'lightblue' => array(
102
+			'regex'        => '/^lightblue([0-9]+)$/',
103
+			'extension'    => '.png',
104
+			'shadow'       => false,
105
+			'offsetImage'  => '0,-19',
106
+			'offsetShadow' => false
107
+		),
108
+		// openlayers std markers are 21x25px with shadow
109
+		'ol-marker' => array(
110
+			'regex'        => '/^marker(|-blue|-gold|-green|-red)+$/',
111
+			'extension'    => '.png',
112
+			'shadow'       => 'marker_shadow.png',
113
+			'offsetImage'  => '-10,-25',
114
+			'offsetShadow' => '-1,-13'
115
+		),
116
+		// these are 16x16 px
117
+		'ww_icon'   => array(
118
+			'regex'        => '/ww_\S+$/',
119
+			'extension'    => '.png',
120
+			'shadow'       => false,
121
+			'offsetImage'  => '-8,-8',
122
+			'offsetShadow' => false
123
+		),
124
+		// assume these are 16x16 px
125
+		'rest'      => array(
126
+			'regex'        => '/^(?!lightblue([0-9]+)$)(?!(ww_\S+$))(?!marker(|-blue|-gold|-green|-red)+$)(.*)/',
127
+			'extension'    => '.png',
128
+			'shadow'       => 'marker_shadow.png',
129
+			'offsetImage'  => '-8,-8',
130
+			'offsetShadow' => '-1,-1'
131
+		)
132
+	);
133
+	private $centerX;
134
+	private $centerY;
135
+	private $offsetX;
136
+	private $offsetY;
137
+	private $image;
138
+	private $zoom;
139
+	private $lat;
140
+	private $lon;
141
+	private $width;
142
+	private $height;
143
+	private $markers;
144
+	private $maptype;
145
+	private $kmlFileName;
146
+	private $gpxFileName;
147
+	private $geojsonFileName;
148
+	private $autoZoomExtent;
149
+	private $apikey;
150
+	private $tileCacheBaseDir;
151
+	private $mapCacheBaseDir;
152
+	private $mediaBaseDir;
153
+	private $useTileCache;
154
+	private $mapCacheID = '';
155
+	private $mapCacheFile = '';
156
+	private $mapCacheExtension = 'png';
157
+
158
+	/**
159
+	 * Constructor.
160
+	 *
161
+	 * @param float  $lat
162
+	 *            Latitude (x) of center of map
163
+	 * @param float  $lon
164
+	 *            Longitude (y) of center of map
165
+	 * @param int    $zoom
166
+	 *            Zoomlevel
167
+	 * @param int    $width
168
+	 *            Width in pixels
169
+	 * @param int    $height
170
+	 *            Height in pixels
171
+	 * @param string $maptype
172
+	 *            Name of the map
173
+	 * @param array  $markers
174
+	 *            array of markers
175
+	 * @param string $gpx
176
+	 *            GPX filename
177
+	 * @param string $kml
178
+	 *            KML filename
179
+	 * @param string $geojson
180
+	 * @param string $mediaDir
181
+	 *            Directory to store/cache maps
182
+	 * @param string $tileCacheBaseDir
183
+	 *            Directory to cache map tiles
184
+	 * @param bool   $autoZoomExtent
185
+	 *            Wheter or not to override zoom/lat/lon and zoom to the extent of gpx/kml and markers
186
+	 * @param string $apikey
187
+	 */
188
+	public function __construct(
189
+		float $lat,
190
+		float $lon,
191
+		int $zoom,
192
+		int $width,
193
+		int $height,
194
+		string $maptype,
195
+		array $markers,
196
+		string $gpx,
197
+		string $kml,
198
+		string $geojson,
199
+		string $mediaDir,
200
+		string $tileCacheBaseDir,
201
+		bool $autoZoomExtent = true,
202
+		string $apikey = ''
203
+	) {
204
+		$this->zoom   = $zoom;
205
+		$this->lat    = $lat;
206
+		$this->lon    = $lon;
207
+		$this->width  = $width;
208
+		$this->height = $height;
209
+		// validate + set maptype
210
+		$this->maptype = $this->tileDefaultSrc;
211
+		if (array_key_exists($maptype, $this->tileInfo)) {
212
+			$this->maptype = $maptype;
213
+		}
214
+		$this->markers          = $markers;
215
+		$this->kmlFileName      = $kml;
216
+		$this->gpxFileName      = $gpx;
217
+		$this->geojsonFileName  = $geojson;
218
+		$this->mediaBaseDir     = $mediaDir;
219
+		$this->tileCacheBaseDir = $tileCacheBaseDir . '/olmaptiles';
220
+		$this->useTileCache     = $this->tileCacheBaseDir !== '';
221
+		$this->mapCacheBaseDir  = $mediaDir . '/olmapmaps';
222
+		$this->autoZoomExtent   = $autoZoomExtent;
223
+		$this->apikey           = $apikey;
224
+	}
225
+
226
+	/**
227
+	 * get the map, this may return a reference to a cached copy.
228
+	 *
229
+	 * @return string url relative to media dir
230
+	 */
231
+	public function getMap(): string
232
+	{
233
+		try {
234
+			if ($this->autoZoomExtent) {
235
+				$this->autoZoom();
236
+			}
237
+		} catch (Exception $e) {
238
+			Logger::debug($e);
239
+		}
240
+
241
+		// use map cache, so check cache for map
242
+		if (!$this->checkMapCache()) {
243
+			// map is not in cache, needs to be build
244
+			$this->makeMap();
245
+			$this->mkdirRecursive(dirname($this->mapCacheIDToFilename()), 0777);
246
+			imagepng($this->image, $this->mapCacheIDToFilename(), 9);
247
+		}
248
+		$doc = $this->mapCacheIDToFilename();
249
+		// make url relative to media dir
250
+		return str_replace($this->mediaBaseDir, '', $doc);
251
+	}
252
+
253
+	/**
254
+	 * Calculate the lat/lon/zoom values to make sure that all of the markers and gpx/kml are on the map.
255
+	 * can throw an error like
256
+	 * "Fatal error: Uncaught Exception: Cannot create a collection with non-geometries in
257
+	 * D:\www\wild-water.nl\www\dokuwiki\lib\plugins\geophp\geoPHP\lib\geometry\Collection.class.php:29"
258
+	 *
259
+	 * @param float $paddingFactor
260
+	 *            buffer constant to enlarge (>1.0) the zoom level
261
+	 * @throws Exception
262
+	 */
263
+	private function autoZoom(float $paddingFactor = 1.0): void
264
+	{
265
+		$geoms    = array();
266
+		$geoms [] = new Point ($this->lon, $this->lat);
267
+		if (!empty ($this->markers)) {
268
+			foreach ($this->markers as $marker) {
269
+				$geoms [] = new Point ($marker ['lon'], $marker ['lat']);
270
+			}
271
+		}
272
+		if (file_exists($this->kmlFileName)) {
273
+			$g = geoPHP::load(file_get_contents($this->kmlFileName), 'kml');
274
+			if ($g !== false) {
275
+				$geoms [] = $g;
276
+			}
277
+		}
278
+		if (file_exists($this->gpxFileName)) {
279
+			$g = geoPHP::load(file_get_contents($this->gpxFileName), 'gpx');
280
+			if ($g !== false) {
281
+				$geoms [] = $g;
282
+			}
283
+		}
284
+		if (file_exists($this->geojsonFileName)) {
285
+			$g = geoPHP::load(file_get_contents($this->geojsonFileName), 'geojson');
286
+			if ($g !== false) {
287
+				$geoms [] = $g;
288
+			}
289
+		}
290
+
291
+		if (count($geoms) <= 1) {
292
+			Logger::debug("StaticMap::autoZoom: Skip setting autozoom options", $geoms);
293
+			return;
294
+		}
295
+
296
+		$geom     = new GeometryCollection ($geoms);
297
+		$centroid = $geom->centroid();
298
+		$bbox     = $geom->getBBox();
299
+
300
+		// determine vertical resolution, this depends on the distance from the equator
301
+		// $vy00 = log(tan(M_PI*(0.25 + $centroid->getY()/360)));
302
+		$vy0 = log(tan(M_PI * (0.25 + $bbox ['miny'] / 360)));
303
+		$vy1 = log(tan(M_PI * (0.25 + $bbox ['maxy'] / 360)));
304
+		Logger::debug("StaticMap::autoZoom: vertical resolution: $vy0, $vy1");
305
+		$zoomFactorPowered  = ($this->height / 2) / (40.7436654315252 * ($vy1 - $vy0));
306
+		$resolutionVertical = 360 / ($zoomFactorPowered * $this->tileSize);
307
+		// determine horizontal resolution
308
+		$resolutionHorizontal = ($bbox ['maxx'] - $bbox ['minx']) / $this->width;
309
+		$resolution           = max($resolutionHorizontal, $resolutionVertical) * $paddingFactor;
310
+		$zoom                 = log(360 / ($resolution * $this->tileSize), 2);
311
+
312
+		if (is_finite($zoom) && $zoom < 15 && $zoom > 2) {
313
+			$this->zoom = floor($zoom);
314
+		}
315
+		$this->lon = $centroid->getX();
316
+		$this->lat = $centroid->getY();
317
+		Logger::debug("StaticMap::autoZoom: Set autozoom options to: z: $this->zoom, lon: $this->lon, lat: $this->lat");
318
+	}
319
+
320
+	public function checkMapCache(): bool
321
+	{
322
+		// side effect: set the mapCacheID
323
+		$this->mapCacheID = md5($this->serializeParams());
324
+		$filename         = $this->mapCacheIDToFilename();
325
+		return file_exists($filename);
326
+	}
327
+
328
+	public function serializeParams(): string
329
+	{
330
+		return join(
331
+			"&",
332
+			array(
333
+				$this->zoom,
334
+				$this->lat,
335
+				$this->lon,
336
+				$this->width,
337
+				$this->height,
338
+				serialize($this->markers),
339
+				$this->maptype,
340
+				$this->kmlFileName,
341
+				$this->gpxFileName,
342
+				$this->geojsonFileName
343
+			)
344
+		);
345
+	}
346
+
347
+	public function mapCacheIDToFilename(): string
348
+	{
349
+		if (!$this->mapCacheFile) {
350
+			$this->mapCacheFile = $this->mapCacheBaseDir . "/" . $this->maptype . "/" . $this->zoom . "/cache_"
351
+				. substr($this->mapCacheID, 0, 2) . "/" . substr($this->mapCacheID, 2, 2)
352
+				. "/" . substr($this->mapCacheID, 4);
353
+		}
354
+		return $this->mapCacheFile . "." . $this->mapCacheExtension;
355
+	}
356
+
357
+	/**
358
+	 * make the map.
359
+	 */
360
+	public function makeMap(): void
361
+	{
362
+		$this->initCoords();
363
+		$this->createBaseMap();
364
+		if (!empty ($this->markers)) {
365
+			$this->placeMarkers();
366
+		}
367
+		if (file_exists($this->kmlFileName)) {
368
+			try {
369
+				$this->drawKML();
370
+			} catch (exception $e) {
371
+				Logger::error('failed to load KML file', $e);
372
+			}
373
+		}
374
+		if (file_exists($this->gpxFileName)) {
375
+			try {
376
+				$this->drawGPX();
377
+			} catch (exception $e) {
378
+				Logger::error('failed to load GPX file', $e);
379
+			}
380
+		}
381
+		if (file_exists($this->geojsonFileName)) {
382
+			try {
383
+				$this->drawGeojson();
384
+			} catch (exception $e) {
385
+				Logger::error('failed to load GeoJSON file', $e);
386
+			}
387
+		}
388
+
389
+		$this->drawCopyright();
390
+	}
391
+
392
+	/**
393
+	 */
394
+	public function initCoords(): void
395
+	{
396
+		$this->centerX = $this->lonToTile($this->lon, $this->zoom);
397
+		$this->centerY = $this->latToTile($this->lat, $this->zoom);
398
+		$this->offsetX = floor((floor($this->centerX) - $this->centerX) * $this->tileSize);
399
+		$this->offsetY = floor((floor($this->centerY) - $this->centerY) * $this->tileSize);
400
+	}
401
+
402
+	/**
403
+	 *
404
+	 * @param float $long
405
+	 * @param int   $zoom
406
+	 * @return float|int
407
+	 */
408
+	public function lonToTile(float $long, int $zoom)
409
+	{
410
+		return (($long + 180) / 360) * pow(2, $zoom);
411
+	}
412
+
413
+	/**
414
+	 *
415
+	 * @param float $lat
416
+	 * @param int   $zoom
417
+	 * @return float|int
418
+	 */
419
+	public function latToTile(float $lat, int $zoom)
420
+	{
421
+		return (1 - log(tan($lat * pi() / 180) + 1 / cos($lat * M_PI / 180)) / M_PI) / 2 * pow(2, $zoom);
422
+	}
423
+
424
+	/**
425
+	 * make basemap image.
426
+	 */
427
+	public function createBaseMap(): void
428
+	{
429
+		$this->image   = imagecreatetruecolor($this->width, $this->height);
430
+		$startX        = floor($this->centerX - ($this->width / $this->tileSize) / 2);
431
+		$startY        = floor($this->centerY - ($this->height / $this->tileSize) / 2);
432
+		$endX          = ceil($this->centerX + ($this->width / $this->tileSize) / 2);
433
+		$endY          = ceil($this->centerY + ($this->height / $this->tileSize) / 2);
434
+		$this->offsetX = -floor(($this->centerX - floor($this->centerX)) * $this->tileSize);
435
+		$this->offsetY = -floor(($this->centerY - floor($this->centerY)) * $this->tileSize);
436
+		$this->offsetX += floor($this->width / 2);
437
+		$this->offsetY += floor($this->height / 2);
438
+		$this->offsetX += floor($startX - floor($this->centerX)) * $this->tileSize;
439
+		$this->offsetY += floor($startY - floor($this->centerY)) * $this->tileSize;
440
+
441
+		for ($x = $startX; $x <= $endX; $x++) {
442
+			for ($y = $startY; $y <= $endY; $y++) {
443
+				$url = str_replace(
444
+					array(
445
+						'{Z}',
446
+						'{X}',
447
+						'{Y}'
448
+					),
449
+					array(
450
+						$this->zoom,
451
+						$x,
452
+						$y
453
+					),
454
+					$this->tileInfo [$this->maptype] ['url']
455
+				);
456
+
457
+				$tileData = $this->fetchTile($url);
458
+				if ($tileData) {
459
+					$tileImage = imagecreatefromstring($tileData);
460
+				} else {
461
+					$tileImage = imagecreate($this->tileSize, $this->tileSize);
462
+					$color     = imagecolorallocate($tileImage, 255, 255, 255);
463
+					@imagestring($tileImage, 1, 127, 127, 'err', $color);
464
+				}
465
+				$destX = ($x - $startX) * $this->tileSize + $this->offsetX;
466
+				$destY = ($y - $startY) * $this->tileSize + $this->offsetY;
467
+				Logger::debug("imagecopy tile into image: $destX, $destY", $this->tileSize);
468
+				imagecopy(
469
+					$this->image,
470
+					$tileImage,
471
+					$destX,
472
+					$destY,
473
+					0,
474
+					0,
475
+					$this->tileSize,
476
+					$this->tileSize
477
+				);
478
+			}
479
+		}
480
+	}
481
+
482
+	/**
483
+	 * Fetch a tile and (if configured) store it in the cache.
484
+	 * @param string $url
485
+	 * @return bool|string
486
+	 * @todo refactor this to use dokuwiki\HTTP\HTTPClient or dokuwiki\HTTP\DokuHTTPClient
487
+	 *          for better proxy handling...
488
+	 */
489
+	public function fetchTile(string $url)
490
+	{
491
+		if ($this->useTileCache && ($cached = $this->checkTileCache($url))) {
492
+			return $cached;
493
+		}
494
+
495
+		$_UA = 'Mozilla/4.0 (compatible; DokuWikiSpatial HTTP Client; ' . PHP_OS . ')';
496
+		if (function_exists("curl_init")) {
497
+			// use cUrl
498
+			$ch = curl_init();
499
+			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
500
+			curl_setopt($ch, CURLOPT_USERAGENT, $_UA);
501
+			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
502
+			curl_setopt($ch, CURLOPT_URL, $url . $this->apikey);
503
+			Logger::debug("StaticMap::fetchTile: getting: $url using curl_exec");
504
+			$tile = curl_exec($ch);
505
+			curl_close($ch);
506
+		} else {
507
+			// use file_get_contents
508
+			global $conf;
509
+			$opts = array(
510
+				'http' => array(
511
+					'method'          => "GET",
512
+					'header'          => "Accept-language: en\r\n" . "User-Agent: $_UA\r\n" . "accept: image/png\r\n",
513
+					'request_fulluri' => true
514
+				)
515
+			);
516
+			if (isset($conf['proxy']['host'], $conf['proxy']['port'])
517
+				&& $conf['proxy']['host'] !== ''
518
+				&& $conf['proxy']['port'] !== '') {
519
+				$opts['http'] += ['proxy' => "tcp://" . $conf['proxy']['host'] . ":" . $conf['proxy']['port']];
520
+			}
521
+
522
+			$context = stream_context_create($opts);
523
+			Logger::debug(
524
+				"StaticMap::fetchTile: getting: $url . $this->apikey using file_get_contents and options $opts"
525
+			);
526
+			$tile = file_get_contents($url . $this->apikey, false, $context);
527
+		}
528
+		if ($tile && $this->useTileCache) {
529
+			$this->writeTileToCache($url, $tile);
530
+		}
531
+		return $tile;
532
+	}
533
+
534
+	/**
535
+	 *
536
+	 * @param string $url
537
+	 * @return string|false
538
+	 */
539
+	public function checkTileCache(string $url)
540
+	{
541
+		$filename = $this->tileUrlToFilename($url);
542
+		if (file_exists($filename)) {
543
+			return file_get_contents($filename);
544
+		}
545
+		return false;
546
+	}
547
+
548
+	/**
549
+	 *
550
+	 * @param string $url
551
+	 * @return string
552
+	 */
553
+	public function tileUrlToFilename(string $url): string
554
+	{
555
+		return $this->tileCacheBaseDir . "/" . substr($url, strpos($url, '/') + 1);
556
+	}
557
+
558
+	/**
559
+	 * Write a tile into the cache.
560
+	 *
561
+	 * @param string $url
562
+	 * @param mixed  $data
563
+	 */
564
+	public function writeTileToCache(string $url, $data): void
565
+	{
566
+		$filename = $this->tileUrlToFilename($url);
567
+		$this->mkdirRecursive(dirname($filename), 0777);
568
+		file_put_contents($filename, $data);
569
+	}
570
+
571
+	/**
572
+	 * Recursively create the directory.
573
+	 *
574
+	 * @param string $pathname
575
+	 *            The directory path.
576
+	 * @param int    $mode
577
+	 *            File access mode. For more information on modes, read the details on the chmod manpage.
578
+	 */
579
+	public function mkdirRecursive(string $pathname, int $mode): bool
580
+	{
581
+		is_dir(dirname($pathname)) || $this->mkdirRecursive(dirname($pathname), $mode);
582
+		return is_dir($pathname) || mkdir($pathname, $mode) || is_dir($pathname);
583
+	}
584
+
585
+	/**
586
+	 * Place markers on the map and number them in the same order as they are listed in the html.
587
+	 */
588
+	public function placeMarkers(): void
589
+	{
590
+		$count               = 0;
591
+		$color               = imagecolorallocate($this->image, 0, 0, 0);
592
+		$bgcolor             = imagecolorallocate($this->image, 200, 200, 200);
593
+		$markerBaseDir       = __DIR__ . '/icons';
594
+		$markerImageOffsetX  = 0;
595
+		$markerImageOffsetY  = 0;
596
+		$markerShadowOffsetX = 0;
597
+		$markerShadowOffsetY = 0;
598
+		$markerShadowImg     = null;
599
+		// loop thru marker array
600
+		foreach ($this->markers as $marker) {
601
+			// set some local variables
602
+			$markerLat  = $marker ['lat'];
603
+			$markerLon  = $marker ['lon'];
604
+			$markerType = $marker ['type'];
605
+			// clear variables from previous loops
606
+			$markerFilename = '';
607
+			$markerShadow   = '';
608
+			$matches        = false;
609
+			// check for marker type, get settings from markerPrototypes
610
+			if ($markerType) {
611
+				foreach ($this->markerPrototypes as $markerPrototype) {
612
+					if (preg_match($markerPrototype ['regex'], $markerType, $matches)) {
613
+						$markerFilename = $matches [0] . $markerPrototype ['extension'];
614
+						if ($markerPrototype ['offsetImage']) {
615
+							list ($markerImageOffsetX, $markerImageOffsetY) = explode(
616
+								",",
617
+								$markerPrototype ['offsetImage']
618
+							);
619
+						}
620
+						$markerShadow = $markerPrototype ['shadow'];
621
+						if ($markerShadow) {
622
+							list ($markerShadowOffsetX, $markerShadowOffsetY) = explode(
623
+								",",
624
+								$markerPrototype ['offsetShadow']
625
+							);
626
+						}
627
+					}
628
+				}
629
+			}
630
+			// create img resource
631
+			if (file_exists($markerBaseDir . '/' . $markerFilename)) {
632
+				$markerImg = imagecreatefrompng($markerBaseDir . '/' . $markerFilename);
633
+			} else {
634
+				$markerImg = imagecreatefrompng($markerBaseDir . '/marker.png');
635
+			}
636
+			// check for shadow + create shadow recource
637
+			if ($markerShadow && file_exists($markerBaseDir . '/' . $markerShadow)) {
638
+				$markerShadowImg = imagecreatefrompng($markerBaseDir . '/' . $markerShadow);
639
+			}
640
+			// calc position
641
+			$destX = floor(
642
+				($this->width / 2) -
643
+				$this->tileSize * ($this->centerX - $this->lonToTile($markerLon, $this->zoom))
644
+			);
645
+			$destY = floor(
646
+				($this->height / 2) -
647
+				$this->tileSize * ($this->centerY - $this->latToTile($markerLat, $this->zoom))
648
+			);
649
+			// copy shadow on basemap
650
+			if ($markerShadow && $markerShadowImg) {
651
+				imagecopy(
652
+					$this->image,
653
+					$markerShadowImg,
654
+					$destX + (int)$markerShadowOffsetX,
655
+					$destY + (int)$markerShadowOffsetY,
656
+					0,
657
+					0,
658
+					imagesx($markerShadowImg),
659
+					imagesy($markerShadowImg)
660
+				);
661
+			}
662
+			// copy marker on basemap above shadow
663
+			imagecopy(
664
+				$this->image,
665
+				$markerImg,
666
+				$destX + (int)$markerImageOffsetX,
667
+				$destY + (int)$markerImageOffsetY,
668
+				0,
669
+				0,
670
+				imagesx($markerImg),
671
+				imagesy($markerImg)
672
+			);
673
+			// add label
674
+			imagestring(
675
+				$this->image,
676
+				3,
677
+				$destX - imagesx($markerImg) + 1,
678
+				$destY + (int)$markerImageOffsetY + 1,
679
+				++$count,
680
+				$bgcolor
681
+			);
682
+			imagestring(
683
+				$this->image,
684
+				3,
685
+				$destX - imagesx($markerImg),
686
+				$destY + (int)$markerImageOffsetY,
687
+				$count,
688
+				$color
689
+			);
690
+		}
691
+	}
692
+
693
+	/**
694
+	 * Draw kml trace on the map.
695
+	 * @throws exception if loading the specified KML fails
696
+	 */
697
+	public function drawKML(): void
698
+	{
699
+		// TODO get colour from kml node (not currently supported in geoPHP)
700
+		$col     = imagecolorallocatealpha($this->image, 255, 0, 0, .4 * 127);
701
+		$kmlgeom = geoPHP::load(file_get_contents($this->kmlFileName), 'kml');
702
+		$this->drawGeometry($kmlgeom, $col);
703
+	}
704
+
705
+	/**
706
+	 * Draw geometry or geometry collection on the map.
707
+	 *
708
+	 * @param Geometry|GeometryCollection|MultiPolygon|MultiLineString|MultiPoint|Polygon|LineString|Point $geom
709
+	 * @param int                                                                                          $colour
710
+	 *            drawing colour
711
+	 */
712
+	private function drawGeometry(Geometry $geom, int $colour): void
713
+	{
714
+		if (empty($geom)) {
715
+			return;
716
+		}
717
+
718
+		switch ($geom->geometryType()) {
719
+			case 'GeometryCollection' :
720
+				// recursively draw part of the collection
721
+				for ($i = 1; $i < $geom->numGeometries() + 1; $i++) {
722
+					$_geom = $geom->geometryN($i);
723
+					$this->drawGeometry($_geom, $colour);
724
+				}
725
+				break;
726
+			case 'MultiPolygon' :
727
+			case 'MultiLineString' :
728
+			case 'MultiPoint' :
729
+				// TODO implement / do nothing
730
+				break;
731
+			case 'Polygon' :
732
+				$this->drawPolygon($geom, $colour);
733
+				break;
734
+			case 'LineString' :
735
+				$this->drawLineString($geom, $colour);
736
+				break;
737
+			case 'Point' :
738
+				$this->drawPoint($geom, $colour);
739
+				break;
740
+			default :
741
+				// draw nothing
742
+				break;
743
+		}
744
+	}
745
+
746
+	/**
747
+	 * Draw a polygon on the map.
748
+	 *
749
+	 * @param Polygon $polygon
750
+	 * @param int     $colour
751
+	 *            drawing colour
752
+	 */
753
+	private function drawPolygon(Polygon $polygon, int $colour)
754
+	{
755
+		// TODO implementation of drawing holes,
756
+		// maybe draw the polygon to an in-memory image and use imagecopy, draw polygon in col., draw holes in bgcol?
757
+
758
+		// print_r('Polygon:<br />');
759
+		// print_r($polygon);
760
+		$extPoints = array();
761
+		// extring is a linestring actually..
762
+		$extRing = $polygon->exteriorRing();
763
+
764
+		for ($i = 1; $i < $extRing->numGeometries(); $i++) {
765
+			$p1           = $extRing->geometryN($i);
766
+			$x            = floor(
767
+				($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($p1->x(), $this->zoom))
768
+			);
769
+			$y            = floor(
770
+				($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($p1->y(), $this->zoom))
771
+			);
772
+			$extPoints [] = $x;
773
+			$extPoints [] = $y;
774
+		}
775
+		// print_r('points:('.($i-1).')<br />');
776
+		// print_r($extPoints);
777
+		// imagepolygon ($this->image, $extPoints, $i-1, $colour );
778
+		imagefilledpolygon($this->image, $extPoints, $i - 1, $colour);
779
+	}
780
+
781
+	/**
782
+	 * Draw a line on the map.
783
+	 *
784
+	 * @param LineString $line
785
+	 * @param int        $colour
786
+	 *            drawing colour
787
+	 */
788
+	private function drawLineString(LineString $line, int $colour)
789
+	{
790
+		imagesetthickness($this->image, 2);
791
+		for ($p = 1; $p < $line->numGeometries(); $p++) {
792
+			// get first pair of points
793
+			$p1 = $line->geometryN($p);
794
+			$p2 = $line->geometryN($p + 1);
795
+			// translate to paper space
796
+			$x1 = floor(
797
+				($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($p1->x(), $this->zoom))
798
+			);
799
+			$y1 = floor(
800
+				($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($p1->y(), $this->zoom))
801
+			);
802
+			$x2 = floor(
803
+				($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($p2->x(), $this->zoom))
804
+			);
805
+			$y2 = floor(
806
+				($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($p2->y(), $this->zoom))
807
+			);
808
+			// draw to image
809
+			imageline($this->image, $x1, $y1, $x2, $y2, $colour);
810
+		}
811
+		imagesetthickness($this->image, 1);
812
+	}
813
+
814
+	/**
815
+	 * Draw a point on the map.
816
+	 *
817
+	 * @param Point $point
818
+	 * @param int   $colour
819
+	 *            drawing colour
820
+	 */
821
+	private function drawPoint(Point $point, int $colour)
822
+	{
823
+		imagesetthickness($this->image, 2);
824
+		// translate to paper space
825
+		$cx = floor(
826
+			($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($point->x(), $this->zoom))
827
+		);
828
+		$cy = floor(
829
+			($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($point->y(), $this->zoom))
830
+		);
831
+		$r  = 5;
832
+		// draw to image
833
+		// imageellipse($this->image, $cx, $cy,$r, $r, $colour);
834
+		imagefilledellipse($this->image, $cx, $cy, $r, $r, $colour);
835
+		// don't use imageellipse because the imagesetthickness function has
836
+		// no effect. So the better workaround is to use imagearc.
837
+		imagearc($this->image, $cx, $cy, $r, $r, 0, 359, $colour);
838
+		imagesetthickness($this->image, 1);
839
+	}
840
+
841
+	/**
842
+	 * Draw gpx trace on the map.
843
+	 * @throws exception if loading the specified GPX fails
844
+	 */
845
+	public function drawGPX()
846
+	{
847
+		$col     = imagecolorallocatealpha($this->image, 0, 0, 255, .4 * 127);
848
+		$gpxgeom = geoPHP::load(file_get_contents($this->gpxFileName), 'gpx');
849
+		$this->drawGeometry($gpxgeom, $col);
850
+	}
851
+
852
+	/**
853
+	 * Draw geojson on the map.
854
+	 * @throws exception if loading the specified GeoJSON fails
855
+	 */
856
+	public function drawGeojson()
857
+	{
858
+		$col     = imagecolorallocatealpha($this->image, 255, 0, 255, .4 * 127);
859
+		$gpxgeom = geoPHP::load(file_get_contents($this->geojsonFileName), 'json');
860
+		$this->drawGeometry($gpxgeom, $col);
861
+	}
862
+
863
+	/**
864
+	 * add copyright and origin notice and icons to the map.
865
+	 */
866
+	public function drawCopyright()
867
+	{
868
+		$logoBaseDir = dirname(__FILE__) . '/' . 'logo/';
869
+		$logoImg     = imagecreatefrompng($logoBaseDir . $this->tileInfo ['openstreetmap'] ['logo']);
870
+		$textcolor   = imagecolorallocate($this->image, 0, 0, 0);
871
+		$bgcolor     = imagecolorallocate($this->image, 200, 200, 200);
872
+
873
+		imagecopy(
874
+			$this->image,
875
+			$logoImg,
876
+			0,
877
+			imagesy($this->image) - imagesy($logoImg),
878
+			0,
879
+			0,
880
+			imagesx($logoImg),
881
+			imagesy($logoImg)
882
+		);
883
+		imagestring(
884
+			$this->image,
885
+			1,
886
+			imagesx($logoImg) + 2,
887
+			imagesy($this->image) - imagesy($logoImg) + 1,
888
+			$this->tileInfo ['openstreetmap'] ['txt'],
889
+			$bgcolor
890
+		);
891
+		imagestring(
892
+			$this->image,
893
+			1,
894
+			imagesx($logoImg) + 1,
895
+			imagesy($this->image) - imagesy($logoImg),
896
+			$this->tileInfo ['openstreetmap'] ['txt'],
897
+			$textcolor
898
+		);
899
+
900
+		// additional tile source info, ie. who created/hosted the tiles
901
+		$xIconOffset = 0;
902
+		if ($this->maptype === 'openstreetmap') {
903
+			$mapAuthor = "(c) OpenStreetMap maps/CC BY-SA";
904
+		} else {
905
+			$mapAuthor   = $this->tileInfo [$this->maptype] ['txt'];
906
+			$iconImg     = imagecreatefrompng($logoBaseDir . $this->tileInfo [$this->maptype] ['logo']);
907
+			$xIconOffset = imagesx($iconImg);
908
+			imagecopy(
909
+				$this->image,
910
+				$iconImg,
911
+				imagesx($logoImg) + 1,
912
+				imagesy($this->image) - imagesy($iconImg),
913
+				0,
914
+				0,
915
+				imagesx($iconImg),
916
+				imagesy($iconImg)
917
+			);
918
+		}
919
+		imagestring(
920
+			$this->image,
921
+			1,
922
+			imagesx($logoImg) + $xIconOffset + 4,
923
+			imagesy($this->image) - ceil(imagesy($logoImg) / 2) + 1,
924
+			$mapAuthor,
925
+			$bgcolor
926
+		);
927
+		imagestring(
928
+			$this->image,
929
+			1,
930
+			imagesx($logoImg) + $xIconOffset + 3,
931
+			imagesy($this->image) - ceil(imagesy($logoImg) / 2),
932
+			$mapAuthor,
933
+			$textcolor
934
+		);
935
+	}
936 936
 }
Please login to merge, or discard this patch.
syntax/olmap.php 1 patch
Indentation   +759 added lines, -759 removed lines patch added patch discarded remove patch
@@ -28,114 +28,114 @@  discard block
 block discarded – undo
28 28
 class syntax_plugin_openlayersmap_olmap extends DokuWiki_Syntax_Plugin
29 29
 {
30 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
-        'statusbar'     => true,
43
-        'toolbar'       => true,
44
-        'controls'      => true,
45
-        'poihoverstyle' => false,
46
-        'baselyr'       => 'OpenStreetMap',
47
-        'gpxfile'       => '',
48
-        'kmlfile'       => '',
49
-        'geojsonfile'   => '',
50
-        'summary'       => ''
51
-    );
52
-
53
-    /**
54
-     *
55
-     * @see DokuWiki_Syntax_Plugin::getType()
56
-     */
57
-    public function getType(): string
58
-    {
59
-        return 'substition';
60
-    }
61
-
62
-    /**
63
-     *
64
-     * @see DokuWiki_Syntax_Plugin::getPType()
65
-     */
66
-    public function getPType(): string
67
-    {
68
-        return 'block';
69
-    }
70
-
71
-    /**
72
-     *
73
-     * @see Doku_Parser_Mode::getSort()
74
-     */
75
-    public function getSort(): int
76
-    {
77
-        return 901;
78
-    }
79
-
80
-    /**
81
-     *
82
-     * @see Doku_Parser_Mode::connectTo()
83
-     */
84
-    public function connectTo($mode)
85
-    {
86
-        $this->Lexer->addSpecialPattern(
87
-            '<olmap ?[^>\n]*>.*?</olmap>',
88
-            $mode,
89
-            'plugin_openlayersmap_olmap'
90
-        );
91
-    }
92
-
93
-    /**
94
-     *
95
-     * @see DokuWiki_Syntax_Plugin::handle()
96
-     */
97
-    public function handle($match, $state, $pos, Doku_Handler $handler): array
98
-    {
99
-        // break matched cdata into its components
100
-        list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
101
-        // get the lat/lon for adding them to the metadata (used by geotag)
102
-        preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat);
103
-        preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon);
104
-        $mainLat = substr($mainLat [0], 5, -1);
105
-        $mainLon = substr($mainLon [0], 5, -1);
106
-        if (!is_numeric($mainLat)) {
107
-            $mainLat = $this->dflt ['lat'];
108
-        }
109
-        if (!is_numeric($mainLon)) {
110
-            $mainLon = $this->dflt ['lon'];
111
-        }
112
-
113
-        $gmap          = $this->extractParams($str_params);
114
-        $overlay       = $this->extractPoints($str_points);
115
-        $_firstimageID = '';
116
-
117
-        $_nocache = false;
118
-        // choose maptype based on the specified tag
119
-        $imgUrl = "{{";
120
-        if (stripos($gmap ['baselyr'], 'google') !== false) {
121
-            // Google
122
-            $imgUrl .= $this->getGoogle($gmap, $overlay);
123
-            $imgUrl .= "&.png";
124
-        } elseif (stripos($gmap ['baselyr'], 'bing') !== false) {
125
-            // Bing
126
-            if (!$this->getConf('bingAPIKey')) {
127
-                // in case there is no Bing api key we'll use OSM
128
-                $_firstimageID = $this->getStaticOSM($gmap, $overlay);
129
-                $imgUrl        .= $_firstimageID;
130
-                if ($this->getConf('optionStaticMapGenerator') == 'remote') {
131
-                    $imgUrl .= "&.png";
132
-                }
133
-            } else {
134
-                // seems that Bing doesn't like the DW client, turn off caching
135
-                $_nocache = true;
136
-                $imgUrl   .= $this->getBing($gmap, $overlay) . "&.png";
137
-            }
138
-        } /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) {
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
+		'statusbar'     => true,
43
+		'toolbar'       => true,
44
+		'controls'      => true,
45
+		'poihoverstyle' => false,
46
+		'baselyr'       => 'OpenStreetMap',
47
+		'gpxfile'       => '',
48
+		'kmlfile'       => '',
49
+		'geojsonfile'   => '',
50
+		'summary'       => ''
51
+	);
52
+
53
+	/**
54
+	 *
55
+	 * @see DokuWiki_Syntax_Plugin::getType()
56
+	 */
57
+	public function getType(): string
58
+	{
59
+		return 'substition';
60
+	}
61
+
62
+	/**
63
+	 *
64
+	 * @see DokuWiki_Syntax_Plugin::getPType()
65
+	 */
66
+	public function getPType(): string
67
+	{
68
+		return 'block';
69
+	}
70
+
71
+	/**
72
+	 *
73
+	 * @see Doku_Parser_Mode::getSort()
74
+	 */
75
+	public function getSort(): int
76
+	{
77
+		return 901;
78
+	}
79
+
80
+	/**
81
+	 *
82
+	 * @see Doku_Parser_Mode::connectTo()
83
+	 */
84
+	public function connectTo($mode)
85
+	{
86
+		$this->Lexer->addSpecialPattern(
87
+			'<olmap ?[^>\n]*>.*?</olmap>',
88
+			$mode,
89
+			'plugin_openlayersmap_olmap'
90
+		);
91
+	}
92
+
93
+	/**
94
+	 *
95
+	 * @see DokuWiki_Syntax_Plugin::handle()
96
+	 */
97
+	public function handle($match, $state, $pos, Doku_Handler $handler): array
98
+	{
99
+		// break matched cdata into its components
100
+		list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
101
+		// get the lat/lon for adding them to the metadata (used by geotag)
102
+		preg_match('(lat[:|=]\"-?\d*\.?\d*\")', $match, $mainLat);
103
+		preg_match('(lon[:|=]\"-?\d*\.?\d*\")', $match, $mainLon);
104
+		$mainLat = substr($mainLat [0], 5, -1);
105
+		$mainLon = substr($mainLon [0], 5, -1);
106
+		if (!is_numeric($mainLat)) {
107
+			$mainLat = $this->dflt ['lat'];
108
+		}
109
+		if (!is_numeric($mainLon)) {
110
+			$mainLon = $this->dflt ['lon'];
111
+		}
112
+
113
+		$gmap          = $this->extractParams($str_params);
114
+		$overlay       = $this->extractPoints($str_points);
115
+		$_firstimageID = '';
116
+
117
+		$_nocache = false;
118
+		// choose maptype based on the specified tag
119
+		$imgUrl = "{{";
120
+		if (stripos($gmap ['baselyr'], 'google') !== false) {
121
+			// Google
122
+			$imgUrl .= $this->getGoogle($gmap, $overlay);
123
+			$imgUrl .= "&.png";
124
+		} elseif (stripos($gmap ['baselyr'], 'bing') !== false) {
125
+			// Bing
126
+			if (!$this->getConf('bingAPIKey')) {
127
+				// in case there is no Bing api key we'll use OSM
128
+				$_firstimageID = $this->getStaticOSM($gmap, $overlay);
129
+				$imgUrl        .= $_firstimageID;
130
+				if ($this->getConf('optionStaticMapGenerator') == 'remote') {
131
+					$imgUrl .= "&.png";
132
+				}
133
+			} else {
134
+				// seems that Bing doesn't like the DW client, turn off caching
135
+				$_nocache = true;
136
+				$imgUrl   .= $this->getBing($gmap, $overlay) . "&.png";
137
+			}
138
+		} /* elseif (stripos ( $gmap ['baselyr'], 'mapquest' ) !== false) {
139 139
             // MapQuest
140 140
             if (! $this->getConf ( 'mapquestAPIKey' )) {
141 141
                 // no API key for MapQuest, use OSM
@@ -149,171 +149,171 @@  discard block
 block discarded – undo
149 149
                 $imgUrl .= "&.png";
150 150
             }
151 151
         } */ else {
152
-            // default OSM
153
-            $_firstimageID = $this->getStaticOSM($gmap, $overlay);
154
-            $imgUrl        .= $_firstimageID;
155
-            if ($this->getConf('optionStaticMapGenerator') == 'remote') {
156
-                $imgUrl .= "&.png";
157
-            }
158
-        }
159
-
160
-        // append dw p_render specific params and render
161
-        $imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x"
162
-            . str_replace("px", "", $gmap ['height']);
163
-        $imgUrl .= "&nolink";
164
-
165
-        // add nocache option for selected services
166
-        if ($_nocache) {
167
-            $imgUrl .= "&nocache";
168
-        }
169
-
170
-        $imgUrl .= " |" . $gmap ['summary'] . " }}";
171
-
172
-        // Logger::debug("complete image tags is:",$imgUrl);
173
-
174
-        $mapid = $gmap ['id'];
175
-        // create a javascript parameter string for the map
176
-        $param = '';
177
-        foreach ($gmap as $key => $val) {
178
-            $param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
179
-        }
180
-        if (!empty ($param)) {
181
-            $param = substr($param, 0, -2);
182
-        }
183
-        unset ($gmap ['id']);
184
-
185
-        // create a javascript serialisation of the point data
186
-        $poi      = '';
187
-        $poitable = '';
188
-        $rowId    = 0;
189
-        if (!empty ($overlay)) {
190
-            foreach ($overlay as $data) {
191
-                list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
192
-                $rowId++;
193
-                $poi .= ", {lat:$lat,lon:$lon,txt:'$text',angle:$angle,opacity:$opacity,img:'$img',rowId: $rowId}";
194
-
195
-                if ($this->getConf('displayformat') === 'DMS') {
196
-                    $lat = $this->convertLat($lat);
197
-                    $lon = $this->convertLon($lon);
198
-                } else {
199
-                    $lat .= 'º';
200
-                    $lon .= 'º';
201
-                }
202
-
203
-                $poitable .= '
152
+			// default OSM
153
+			$_firstimageID = $this->getStaticOSM($gmap, $overlay);
154
+			$imgUrl        .= $_firstimageID;
155
+			if ($this->getConf('optionStaticMapGenerator') == 'remote') {
156
+				$imgUrl .= "&.png";
157
+			}
158
+		}
159
+
160
+		// append dw p_render specific params and render
161
+		$imgUrl .= "?" . str_replace("px", "", $gmap ['width']) . "x"
162
+			. str_replace("px", "", $gmap ['height']);
163
+		$imgUrl .= "&nolink";
164
+
165
+		// add nocache option for selected services
166
+		if ($_nocache) {
167
+			$imgUrl .= "&nocache";
168
+		}
169
+
170
+		$imgUrl .= " |" . $gmap ['summary'] . " }}";
171
+
172
+		// Logger::debug("complete image tags is:",$imgUrl);
173
+
174
+		$mapid = $gmap ['id'];
175
+		// create a javascript parameter string for the map
176
+		$param = '';
177
+		foreach ($gmap as $key => $val) {
178
+			$param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
179
+		}
180
+		if (!empty ($param)) {
181
+			$param = substr($param, 0, -2);
182
+		}
183
+		unset ($gmap ['id']);
184
+
185
+		// create a javascript serialisation of the point data
186
+		$poi      = '';
187
+		$poitable = '';
188
+		$rowId    = 0;
189
+		if (!empty ($overlay)) {
190
+			foreach ($overlay as $data) {
191
+				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
192
+				$rowId++;
193
+				$poi .= ", {lat:$lat,lon:$lon,txt:'$text',angle:$angle,opacity:$opacity,img:'$img',rowId: $rowId}";
194
+
195
+				if ($this->getConf('displayformat') === 'DMS') {
196
+					$lat = $this->convertLat($lat);
197
+					$lon = $this->convertLon($lon);
198
+				} else {
199
+					$lat .= 'º';
200
+					$lon .= 'º';
201
+				}
202
+
203
+				$poitable .= '
204 204
                     <tr>
205 205
                     <td class="rowId">' . $rowId . '</td>
206 206
                     <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/icons/' . $img . '" alt="'
207
-                    . substr($img, 0, -4) . $this->getlang('alt_legend_poi') . '" /></td>
207
+					. substr($img, 0, -4) . $this->getlang('alt_legend_poi') . '" /></td>
208 208
                     <td class="lat" title="' . $this->getLang('olmapPOIlatTitle') . '">' . $lat . '</td>
209 209
                     <td class="lon" title="' . $this->getLang('olmapPOIlonTitle') . '">' . $lon . '</td>
210 210
                     <td class="txt">' . $text . '</td>
211 211
                     </tr>';
212
-            }
213
-            $poi = substr($poi, 2);
214
-        }
215
-        if (!empty ($gmap ['kmlfile'])) {
216
-            $poitable .= '
212
+			}
213
+			$poi = substr($poi, 2);
214
+		}
215
+		if (!empty ($gmap ['kmlfile'])) {
216
+			$poitable .= '
217 217
                     <tr>
218 218
                     <td class="rowId"><img src="' . DOKU_BASE
219
-                . 'lib/plugins/openlayersmap/toolbar/kml_file.png" alt="KML file" /></td>
219
+				. 'lib/plugins/openlayersmap/toolbar/kml_file.png" alt="KML file" /></td>
220 220
                     <td class="icon"><img src="' . DOKU_BASE . 'lib/plugins/openlayersmap/toolbar/kml_line.png" alt="'
221
-                . $this->getlang('alt_legend_kml') . '" /></td>
221
+				. $this->getlang('alt_legend_kml') . '" /></td>
222 222
                     <td class="txt" colspan="3">KML track: ' . $this->getFileName($gmap ['kmlfile']) . '</td>
223 223
                     </tr>';
224
-        }
225
-        if (!empty ($gmap ['gpxfile'])) {
226
-            $poitable .= '
224
+		}
225
+		if (!empty ($gmap ['gpxfile'])) {
226
+			$poitable .= '
227 227
                     <tr>
228 228
                     <td class="rowId"><img src="' . DOKU_BASE
229
-                . 'lib/plugins/openlayersmap/toolbar/gpx_file.png" alt="GPX file" /></td>
229
+				. 'lib/plugins/openlayersmap/toolbar/gpx_file.png" alt="GPX file" /></td>
230 230
                     <td class="icon"><img src="' . DOKU_BASE
231
-                . 'lib/plugins/openlayersmap/toolbar/gpx_line.png" alt="'
232
-                . $this->getlang('alt_legend_gpx') . '" /></td>
231
+				. 'lib/plugins/openlayersmap/toolbar/gpx_line.png" alt="'
232
+				. $this->getlang('alt_legend_gpx') . '" /></td>
233 233
                     <td class="txt" colspan="3">GPX track: ' . $this->getFileName($gmap ['gpxfile']) . '</td>
234 234
                     </tr>';
235
-        }
236
-        if (!empty ($gmap ['geojsonfile'])) {
237
-            $poitable .= '
235
+		}
236
+		if (!empty ($gmap ['geojsonfile'])) {
237
+			$poitable .= '
238 238
                     <tr>
239 239
                     <td class="rowId"><img src="' . DOKU_BASE
240
-                . 'lib/plugins/openlayersmap/toolbar/geojson_file.png" alt="GeoJSON file" /></td>
240
+				. 'lib/plugins/openlayersmap/toolbar/geojson_file.png" alt="GeoJSON file" /></td>
241 241
                     <td class="icon"><img src="' . DOKU_BASE
242
-                . 'lib/plugins/openlayersmap/toolbar/geojson_line.png" alt="'
243
-                . $this->getlang('alt_legend_geojson') . '" /></td>
242
+				. 'lib/plugins/openlayersmap/toolbar/geojson_line.png" alt="'
243
+				. $this->getlang('alt_legend_geojson') . '" /></td>
244 244
                     <td class="txt" colspan="3">GeoJSON track: ' . $this->getFileName($gmap ['geojsonfile']) . '</td>
245 245
                     </tr>';
246
-        }
247
-
248
-        $autozoom = empty ($gmap ['autozoom']) ? $this->getConf('autoZoomMap') : $gmap ['autozoom'];
249
-        $js       = "{mapOpts: {" . $param . ", displayformat: '" . $this->getConf('displayformat')
250
-            . "', autozoom: " . $autozoom . "}, poi: [$poi]};";
251
-        // unescape the json
252
-        $poitable = stripslashes($poitable);
253
-
254
-        return array(
255
-            $mapid,
256
-            $js,
257
-            $mainLat,
258
-            $mainLon,
259
-            $poitable,
260
-            $gmap ['summary'],
261
-            $imgUrl,
262
-            $_firstimageID
263
-        );
264
-    }
265
-
266
-    /**
267
-     * extract parameters for the map from the parameter string
268
-     *
269
-     * @param string $str_params
270
-     *            string of key="value" pairs
271
-     * @return array associative array of parameters key=>value
272
-     */
273
-    private function extractParams(string $str_params): array
274
-    {
275
-        $param = array();
276
-        preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
277
-        // parse match for instructions, break into key value pairs
278
-        $gmap = $this->dflt;
279
-        foreach ($gmap as $key => &$value) {
280
-            $defval = $this->getConf('default_' . $key);
281
-            if ($defval !== '') {
282
-                $value = $defval;
283
-            }
284
-        }
285
-        unset ($value);
286
-        foreach ($param as $kvpair) {
287
-            list ($match, $key, $val) = $kvpair;
288
-            $key = strtolower($key);
289
-            if (isset ($gmap [$key])) {
290
-                if ($key == 'summary') {
291
-                    // preserve case for summary field
292
-                    $gmap [$key] = $val;
293
-                } elseif ($key == 'id') {
294
-                    // preserve case for id field
295
-                    $gmap [$key] = $val;
296
-                } else {
297
-                    $gmap [$key] = strtolower($val);
298
-                }
299
-            }
300
-        }
301
-        return $gmap;
302
-    }
303
-
304
-    /**
305
-     * extract overlay points for the map from the wiki syntax data
306
-     *
307
-     * @param string $str_points
308
-     *            multi-line string of lat,lon,text triplets
309
-     * @return array multi-dimensional array of lat,lon,text triplets
310
-     */
311
-    private function extractPoints(string $str_points): array
312
-    {
313
-        $point = array();
314
-        // preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um',
315
-        //      $str_points, $point, PREG_SET_ORDER);
316
-        /*
246
+		}
247
+
248
+		$autozoom = empty ($gmap ['autozoom']) ? $this->getConf('autoZoomMap') : $gmap ['autozoom'];
249
+		$js       = "{mapOpts: {" . $param . ", displayformat: '" . $this->getConf('displayformat')
250
+			. "', autozoom: " . $autozoom . "}, poi: [$poi]};";
251
+		// unescape the json
252
+		$poitable = stripslashes($poitable);
253
+
254
+		return array(
255
+			$mapid,
256
+			$js,
257
+			$mainLat,
258
+			$mainLon,
259
+			$poitable,
260
+			$gmap ['summary'],
261
+			$imgUrl,
262
+			$_firstimageID
263
+		);
264
+	}
265
+
266
+	/**
267
+	 * extract parameters for the map from the parameter string
268
+	 *
269
+	 * @param string $str_params
270
+	 *            string of key="value" pairs
271
+	 * @return array associative array of parameters key=>value
272
+	 */
273
+	private function extractParams(string $str_params): array
274
+	{
275
+		$param = array();
276
+		preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
277
+		// parse match for instructions, break into key value pairs
278
+		$gmap = $this->dflt;
279
+		foreach ($gmap as $key => &$value) {
280
+			$defval = $this->getConf('default_' . $key);
281
+			if ($defval !== '') {
282
+				$value = $defval;
283
+			}
284
+		}
285
+		unset ($value);
286
+		foreach ($param as $kvpair) {
287
+			list ($match, $key, $val) = $kvpair;
288
+			$key = strtolower($key);
289
+			if (isset ($gmap [$key])) {
290
+				if ($key == 'summary') {
291
+					// preserve case for summary field
292
+					$gmap [$key] = $val;
293
+				} elseif ($key == 'id') {
294
+					// preserve case for id field
295
+					$gmap [$key] = $val;
296
+				} else {
297
+					$gmap [$key] = strtolower($val);
298
+				}
299
+			}
300
+		}
301
+		return $gmap;
302
+	}
303
+
304
+	/**
305
+	 * extract overlay points for the map from the wiki syntax data
306
+	 *
307
+	 * @param string $str_points
308
+	 *            multi-line string of lat,lon,text triplets
309
+	 * @return array multi-dimensional array of lat,lon,text triplets
310
+	 */
311
+	private function extractPoints(string $str_points): array
312
+	{
313
+		$point = array();
314
+		// preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um',
315
+		//      $str_points, $point, PREG_SET_ORDER);
316
+		/*
317 317
          * group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
318 318
          * group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
319 319
          * group 3: (.*?)
@@ -321,107 +321,107 @@  discard block
 block discarded – undo
321 321
          * group 5: (.*?)
322 322
          * group 6: (.*)
323 323
          */
324
-        preg_match_all(
325
-            '/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um',
326
-            $str_points,
327
-            $point,
328
-            PREG_SET_ORDER
329
-        );
330
-        // create poi array
331
-        $overlay = array();
332
-        foreach ($point as $pt) {
333
-            list ($match, $lat, $lon, $angle, $opacity, $img, $text) = $pt;
334
-            $lat     = is_numeric($lat) ? $lat : 0;
335
-            $lon     = is_numeric($lon) ? $lon : 0;
336
-            $angle   = is_numeric($angle) ? $angle : 0;
337
-            $opacity = is_numeric($opacity) ? $opacity : 0.8;
338
-            // TODO validate using exist & set up default img?
339
-            $img  = trim($img);
340
-            $text = p_get_instructions($text);
341
-            // dbg ( $text );
342
-            $text = p_render("xhtml", $text, $info);
343
-            // dbg ( $text );
344
-            $text       = addslashes(str_replace("\n", "", $text));
345
-            $overlay [] = array(
346
-                $lat,
347
-                $lon,
348
-                $text,
349
-                $angle,
350
-                $opacity,
351
-                $img
352
-            );
353
-        }
354
-        return $overlay;
355
-    }
356
-
357
-    /**
358
-     * Create a Google maps static image url w/ the poi.
359
-     *
360
-     * @param array $gmap
361
-     * @param array $overlay
362
-     * @return string
363
-     */
364
-    private function getGoogle(array $gmap, array $overlay): string
365
-    {
366
-        $sUrl = $this->getConf('iconUrlOverload');
367
-        if (!$sUrl) {
368
-            $sUrl = DOKU_URL;
369
-        }
370
-        switch ($gmap ['baselyr']) {
371
-            case 'google hybrid' :
372
-                $maptype = 'hybrid';
373
-                break;
374
-            case 'google sat' :
375
-                $maptype = 'satellite';
376
-                break;
377
-            case 'terrain' :
378
-            case 'google relief' :
379
-                $maptype = 'terrain';
380
-                break;
381
-            case 'google road' :
382
-            default :
383
-                $maptype = 'roadmap';
384
-                break;
385
-        }
386
-        // TODO maybe use viewport / visible instead of center/zoom,
387
-        // see: https://developers.google.com/maps/documentation/staticmaps/index#Viewports
388
-        // 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
389
-        $imgUrl = "https://maps.googleapis.com/maps/api/staticmap?";
390
-        $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
391
-            . str_replace("px", "", $gmap ['height']);
392
-        //if (!$this->getConf( 'autoZoomMap')) { // no need for center & zoom params }
393
-        $imgUrl .= "&center=" . $gmap ['lat'] . "," . $gmap ['lon'];
394
-        // max is 21 (== building scale), but that's overkill..
395
-        if ($gmap ['zoom'] > 17) {
396
-            $imgUrl .= "&zoom=17";
397
-        } else {
398
-            $imgUrl .= "&zoom=" . $gmap ['zoom'];
399
-        }
400
-        if (!empty ($overlay)) {
401
-            $rowId = 0;
402
-            foreach ($overlay as $data) {
403
-                list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
404
-                $imgUrl .= "&markers=icon%3a" . $sUrl . "lib/plugins/openlayersmap/icons/" . $img . "%7c"
405
-                    . $lat . "," . $lon . "%7clabel%3a" . ++$rowId;
406
-            }
407
-        }
408
-        $imgUrl .= "&format=png&maptype=" . $maptype;
409
-        global $conf;
410
-        $imgUrl .= "&language=" . $conf ['lang'];
411
-        if ($this->getConf('googleAPIkey')) {
412
-            $imgUrl .= "&key=" . $this->getConf('googleAPIkey');
413
-        }
414
-        // Logger::debug('syntax_plugin_openlayersmap_olmap::getGoogle: Google image url is:',$imgUrl);
415
-        return $imgUrl;
416
-    }
417
-
418
-    /**
419
-     * Create a MapQuest static map API image url.
420
-     *
421
-     * @param array $gmap
422
-     * @param array $overlay
423
-     */
424
-    /*
324
+		preg_match_all(
325
+			'/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um',
326
+			$str_points,
327
+			$point,
328
+			PREG_SET_ORDER
329
+		);
330
+		// create poi array
331
+		$overlay = array();
332
+		foreach ($point as $pt) {
333
+			list ($match, $lat, $lon, $angle, $opacity, $img, $text) = $pt;
334
+			$lat     = is_numeric($lat) ? $lat : 0;
335
+			$lon     = is_numeric($lon) ? $lon : 0;
336
+			$angle   = is_numeric($angle) ? $angle : 0;
337
+			$opacity = is_numeric($opacity) ? $opacity : 0.8;
338
+			// TODO validate using exist & set up default img?
339
+			$img  = trim($img);
340
+			$text = p_get_instructions($text);
341
+			// dbg ( $text );
342
+			$text = p_render("xhtml", $text, $info);
343
+			// dbg ( $text );
344
+			$text       = addslashes(str_replace("\n", "", $text));
345
+			$overlay [] = array(
346
+				$lat,
347
+				$lon,
348
+				$text,
349
+				$angle,
350
+				$opacity,
351
+				$img
352
+			);
353
+		}
354
+		return $overlay;
355
+	}
356
+
357
+	/**
358
+	 * Create a Google maps static image url w/ the poi.
359
+	 *
360
+	 * @param array $gmap
361
+	 * @param array $overlay
362
+	 * @return string
363
+	 */
364
+	private function getGoogle(array $gmap, array $overlay): string
365
+	{
366
+		$sUrl = $this->getConf('iconUrlOverload');
367
+		if (!$sUrl) {
368
+			$sUrl = DOKU_URL;
369
+		}
370
+		switch ($gmap ['baselyr']) {
371
+			case 'google hybrid' :
372
+				$maptype = 'hybrid';
373
+				break;
374
+			case 'google sat' :
375
+				$maptype = 'satellite';
376
+				break;
377
+			case 'terrain' :
378
+			case 'google relief' :
379
+				$maptype = 'terrain';
380
+				break;
381
+			case 'google road' :
382
+			default :
383
+				$maptype = 'roadmap';
384
+				break;
385
+		}
386
+		// TODO maybe use viewport / visible instead of center/zoom,
387
+		// see: https://developers.google.com/maps/documentation/staticmaps/index#Viewports
388
+		// 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
389
+		$imgUrl = "https://maps.googleapis.com/maps/api/staticmap?";
390
+		$imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
391
+			. str_replace("px", "", $gmap ['height']);
392
+		//if (!$this->getConf( 'autoZoomMap')) { // no need for center & zoom params }
393
+		$imgUrl .= "&center=" . $gmap ['lat'] . "," . $gmap ['lon'];
394
+		// max is 21 (== building scale), but that's overkill..
395
+		if ($gmap ['zoom'] > 17) {
396
+			$imgUrl .= "&zoom=17";
397
+		} else {
398
+			$imgUrl .= "&zoom=" . $gmap ['zoom'];
399
+		}
400
+		if (!empty ($overlay)) {
401
+			$rowId = 0;
402
+			foreach ($overlay as $data) {
403
+				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
404
+				$imgUrl .= "&markers=icon%3a" . $sUrl . "lib/plugins/openlayersmap/icons/" . $img . "%7c"
405
+					. $lat . "," . $lon . "%7clabel%3a" . ++$rowId;
406
+			}
407
+		}
408
+		$imgUrl .= "&format=png&maptype=" . $maptype;
409
+		global $conf;
410
+		$imgUrl .= "&language=" . $conf ['lang'];
411
+		if ($this->getConf('googleAPIkey')) {
412
+			$imgUrl .= "&key=" . $this->getConf('googleAPIkey');
413
+		}
414
+		// Logger::debug('syntax_plugin_openlayersmap_olmap::getGoogle: Google image url is:',$imgUrl);
415
+		return $imgUrl;
416
+	}
417
+
418
+	/**
419
+	 * Create a MapQuest static map API image url.
420
+	 *
421
+	 * @param array $gmap
422
+	 * @param array $overlay
423
+	 */
424
+	/*
425 425
    private function _getMapQuest($gmap, $overlay) {
426 426
        $sUrl = $this->getConf ( 'iconUrlOverload' );
427 427
        if (! $sUrl) {
@@ -479,358 +479,358 @@  discard block
 block discarded – undo
479 479
    }
480 480
    */
481 481
 
482
-    /**
483
-     * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
484
-     * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
485
-     *
486
-     * @param array $gmap
487
-     * @param array $overlay
488
-     *
489
-     * @return false|string
490
-     * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
491
-     */
492
-    private function getStaticOSM(array $gmap, array $overlay)
493
-    {
494
-        if ($this->getConf('optionStaticMapGenerator') == 'local') {
495
-            // using local basemap composer
496
-            if (!$myMap = plugin_load('helper', 'openlayersmap_staticmap')) {
497
-                Logger::error(
498
-                    'openlayersmap_staticmap plugin is not available for use.',
499
-                    $myMap
500
-                );
501
-            }
502
-            if (!$geophp = plugin_load('helper', 'geophp')) {
503
-                Logger::debug('geophp plugin is not available for use.', $geophp);
504
-            }
505
-            $size = str_replace("px", "", $gmap ['width']) . "x"
506
-                . str_replace("px", "", $gmap ['height']);
507
-
508
-            $markers = array();
509
-            if (!empty ($overlay)) {
510
-                foreach ($overlay as $data) {
511
-                    list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
512
-                    $iconStyle  = substr($img, 0, strlen($img) - 4);
513
-                    $markers [] = array(
514
-                        'lat'  => $lat,
515
-                        'lon'  => $lon,
516
-                        'type' => $iconStyle
517
-                    );
518
-                }
519
-            }
520
-
521
-            $apikey = '';
522
-            switch ($gmap ['baselyr']) {
523
-                case 'mapnik' :
524
-                case 'openstreetmap' :
525
-                    $maptype = 'openstreetmap';
526
-                    break;
527
-                case 'transport' :
528
-                    $maptype = 'transport';
529
-                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
530
-                    break;
531
-                case 'landscape' :
532
-                    $maptype = 'landscape';
533
-                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
534
-                    break;
535
-                case 'outdoors' :
536
-                    $maptype = 'outdoors';
537
-                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
538
-                    break;
539
-                case 'cycle map' :
540
-                    $maptype = 'cycle';
541
-                    $apikey  = '?apikey=' . $this->getConf('tfApiKey');
542
-                    break;
543
-                case 'hike and bike map' :
544
-                    $maptype = 'hikeandbike';
545
-                    break;
546
-                case 'mapquest hybrid' :
547
-                case 'mapquest road' :
548
-                case 'mapquest sat' :
549
-                    $maptype = 'mapquest';
550
-                    break;
551
-                default :
552
-                    $maptype = '';
553
-                    break;
554
-            }
555
-
556
-            $result = $myMap->getMap(
557
-                $gmap ['lat'],
558
-                $gmap ['lon'],
559
-                $gmap ['zoom'],
560
-                $size,
561
-                $maptype,
562
-                $markers,
563
-                $gmap ['gpxfile'],
564
-                $gmap ['kmlfile'],
565
-                $gmap ['geojsonfile'],
566
-                $apikey
567
-            );
568
-        } else {
569
-            // using external basemap composer
570
-
571
-            // https://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10
572
-            //.117187497601&zoom=5&size=500x350
573
-            // &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,
574
-            //  lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,
575
-            //  ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,
576
-            //  ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
577
-            $imgUrl = "https://staticmap.openstreetmap.de/staticmap.php";
578
-            $imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
579
-            $imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
580
-                . str_replace("px", "", $gmap ['height']);
581
-
582
-            if ($gmap ['zoom'] > 16) {
583
-                // actually this could even be 18, but that seems overkill
584
-                $imgUrl .= "&zoom=16";
585
-            } else {
586
-                $imgUrl .= "&zoom=" . $gmap ['zoom'];
587
-            }
588
-
589
-            if (!empty ($overlay)) {
590
-                $rowId  = 0;
591
-                $imgUrl .= "&markers=";
592
-                foreach ($overlay as $data) {
593
-                    list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
594
-                    $rowId++;
595
-                    $iconStyle = "lightblue$rowId";
596
-                    $imgUrl    .= "$lat,$lon,$iconStyle%7c";
597
-                }
598
-                $imgUrl = substr($imgUrl, 0, -3);
599
-            }
600
-
601
-            $result = $imgUrl;
602
-        }
603
-        // Logger::debug('syntax_plugin_openlayersmap_olmap::getStaticOSM: osm image url is:',$result);
604
-        return $result;
605
-    }
606
-
607
-    /**
608
-     * Create a Bing maps static image url w/ the poi.
609
-     *
610
-     * @param array $gmap
611
-     * @param array $overlay
612
-     * @return string
613
-     */
614
-    private function getBing(array $gmap, array $overlay): string
615
-    {
616
-        switch ($gmap ['baselyr']) {
617
-            case 've hybrid' :
618
-            case 'bing hybrid' :
619
-                $maptype = 'AerialWithLabels';
620
-                break;
621
-            case 've sat' :
622
-            case 'bing sat' :
623
-                $maptype = 'Aerial';
624
-                break;
625
-            case 've normal' :
626
-            case 've road' :
627
-            case 've' :
628
-            case 'bing road' :
629
-            default :
630
-                $maptype = 'Road';
631
-                break;
632
-        }
633
-        $imgUrl = "https://dev.virtualearth.net/REST/v1/Imagery/Map/" . $maptype;// . "/";
634
-        if ($this->getConf('autoZoomMap')) {
635
-            $bbox = $this->calcBBOX($overlay, $gmap ['lat'], $gmap ['lon']);
636
-            //$imgUrl .= "?ma=" . $bbox ['minlat'] . "," . $bbox ['minlon'] . ","
637
-            //          . $bbox ['maxlat'] . "," . $bbox ['maxlon'];
638
-            $imgUrl .= "?ma=" . $bbox ['minlat'] . "%2C" . $bbox ['minlon'] . "%2C" . $bbox ['maxlat']
639
-                . "%2C" . $bbox ['maxlon'];
640
-            $imgUrl .= "&dcl=1";
641
-        }
642
-        if (strpos($imgUrl, "?") === false) {
643
-            $imgUrl .= "?";
644
-        }
645
-
646
-        //$imgUrl .= "&ms=" . str_replace ( "px", "", $gmap ['width'] ) . ","
647
-        //          . str_replace ( "px", "", $gmap ['height'] );
648
-        $imgUrl .= "&ms=" . str_replace("px", "", $gmap ['width']) . "%2C"
649
-            . str_replace("px", "", $gmap ['height']);
650
-        $imgUrl .= "&key=" . $this->getConf('bingAPIKey');
651
-        if (!empty ($overlay)) {
652
-            $rowId = 0;
653
-            foreach ($overlay as $data) {
654
-                list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
655
-                // TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
656
-                $iconStyle = 32;
657
-                $rowId++;
658
-                // NOTE: the max number of pushpins is 18! or we have to use POST
659
-                //  (http://msdn.microsoft.com/en-us/library/ff701724.aspx)
660
-                if ($rowId == 18) {
661
-                    break;
662
-                }
663
-                //$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
664
-                $imgUrl .= "&pp=$lat%2C$lon%3B$iconStyle%3B$rowId";
665
-            }
666
-        }
667
-        global $conf;
668
-        $imgUrl .= "&fmt=png";
669
-        $imgUrl .= "&c=" . $conf ['lang'];
670
-        // Logger::debug('syntax_plugin_openlayersmap_olmap::getBing: bing image url is:',$imgUrl);
671
-        return $imgUrl;
672
-    }
673
-
674
-    /**
675
-     * Calculate the minimum bbox for a start location + poi.
676
-     *
677
-     * @param array $overlay
678
-     *            multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
679
-     * @param float $lat
680
-     *            latitude for map center
681
-     * @param float $lon
682
-     *            longitude for map center
683
-     * @return array :float array describing the mbr and center point
684
-     */
685
-    private function calcBBOX(array $overlay, float $lat, float $lon): array
686
-    {
687
-        $lats = array($lat);
688
-        $lons = array($lon);
689
-        foreach ($overlay as $data) {
690
-            list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
691
-            $lats [] = $lat;
692
-            $lons [] = $lon;
693
-        }
694
-        sort($lats);
695
-        sort($lons);
696
-        // TODO: make edge/wrap around cases work
697
-        $centerlat = $lats [0] + ($lats [count($lats) - 1] - $lats [0]);
698
-        $centerlon = $lons [0] + ($lons [count($lats) - 1] - $lons [0]);
699
-        return array(
700
-            'minlat'    => $lats [0],
701
-            'minlon'    => $lons [0],
702
-            'maxlat'    => $lats [count($lats) - 1],
703
-            'maxlon'    => $lons [count($lats) - 1],
704
-            'centerlat' => $centerlat,
705
-            'centerlon' => $centerlon
706
-        );
707
-    }
708
-
709
-    /**
710
-     * convert latitude in decimal degrees to DMS+hemisphere.
711
-     *
712
-     * @param float $decimaldegrees
713
-     * @return string
714
-     * @todo move this into a shared library
715
-     */
716
-    private function convertLat(float $decimaldegrees): string
717
-    {
718
-        if (strpos($decimaldegrees, '-') !== false) {
719
-            $latPos = "S";
720
-        } else {
721
-            $latPos = "N";
722
-        }
723
-        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
724
-        return hsc($dms . $latPos);
725
-    }
726
-
727
-    /**
728
-     * Convert decimal degrees to degrees, minutes, seconds format
729
-     *
730
-     * @param float $decimaldegrees
731
-     * @return string dms
732
-     * @todo move this into a shared library
733
-     */
734
-    private function convertDDtoDMS(float $decimaldegrees): string
735
-    {
736
-        $dms  = floor($decimaldegrees);
737
-        $secs = ($decimaldegrees - $dms) * 3600;
738
-        $min  = floor($secs / 60);
739
-        $sec  = round($secs - ($min * 60), 3);
740
-        $dms  .= 'º' . $min . '\'' . $sec . '"';
741
-        return $dms;
742
-    }
743
-
744
-    /**
745
-     * convert longitude in decimal degrees to DMS+hemisphere.
746
-     *
747
-     * @param float $decimaldegrees
748
-     * @return string
749
-     * @todo move this into a shared library
750
-     */
751
-    private function convertLon(float $decimaldegrees): string
752
-    {
753
-        if (strpos($decimaldegrees, '-') !== false) {
754
-            $lonPos = "W";
755
-        } else {
756
-            $lonPos = "E";
757
-        }
758
-        $dms = $this->convertDDtoDMS(abs($decimaldegrees));
759
-        return hsc($dms . $lonPos);
760
-    }
761
-
762
-    /**
763
-     * Figures out the base filename of a media path.
764
-     *
765
-     * @param string $mediaLink
766
-     * @return string
767
-     */
768
-    private function getFileName(string $mediaLink): string
769
-    {
770
-        $mediaLink = str_replace('[[', '', $mediaLink);
771
-        $mediaLink = str_replace(']]', '', $mediaLink);
772
-        $mediaLink = substr($mediaLink, 0, -4);
773
-        $parts     = explode(':', $mediaLink);
774
-        $mediaLink = end($parts);
775
-        return str_replace('_', ' ', $mediaLink);
776
-    }
777
-
778
-    /**
779
-     *
780
-     * @see DokuWiki_Syntax_Plugin::render()
781
-     */
782
-    public function render($format, Doku_Renderer $renderer, $data): bool
783
-    {
784
-        // set to true after external scripts tags are written
785
-        static $initialised = false;
786
-        // incremented for each map tag in the page source so we can keep track of each map in this page
787
-        static $mapnumber = 0;
788
-
789
-        // Logger::debug('olmap::render() data.',$data);
790
-        list ($mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage) = $data;
791
-
792
-        if ($format == 'xhtml') {
793
-            $olscript     = '';
794
-            $olEnable     = false;
795
-            $gscript      = '';
796
-            $gEnable      = $this->getConf('enableGoogle');
797
-            $stamenEnable = $this->getConf('enableStamen');
798
-            $osmEnable    = $this->getConf('enableOSM');
799
-            $enableBing   = $this->getConf('enableBing');
800
-
801
-            $scriptEnable = '';
802
-            if (!$initialised) {
803
-                $initialised = true;
804
-                // render necessary script tags
805
-                if ($gEnable) {
806
-                    $gscript = '<script defer="defer" src="//maps.google.com/maps/api/js?v=3.29&amp;key='
807
-                        . $this->getConf('googleAPIkey') . '"></script>';
808
-                }
809
-                $olscript = '<script defer="defer" src="' . DOKU_BASE
810
-                    . 'lib/plugins/openlayersmap/lib/OpenLayers.js"></script>';
811
-
812
-                $scriptEnable = '<script defer="defer" src="data:text/javascript;base64,';
813
-                $scriptSrc    = $olscript ? 'olEnable = true;' : 'olEnable = false;';
814
-                $scriptSrc    .= 'gEnable = ' . ($gEnable ? 'true' : 'false') . ';';
815
-                $scriptSrc    .= 'osmEnable = ' . ($osmEnable ? 'true' : 'false') . ';';
816
-                $scriptSrc    .= 'stamenEnable = ' . ($stamenEnable ? 'true' : 'false') . ';';
817
-                $scriptSrc    .= 'bEnable = ' . ($enableBing ? 'true' : 'false') . ';';
818
-                $scriptSrc    .= 'bApiKey="' . $this->getConf('bingAPIKey') . '";';
819
-                $scriptSrc    .= 'tfApiKey="' . $this->getConf('tfApiKey') . '";';
820
-                $scriptSrc    .= 'gApiKey="' . $this->getConf('googleAPIkey') . '";';
821
-                $scriptEnable .= base64_encode($scriptSrc);
822
-                $scriptEnable .= '"></script>';
823
-            }
824
-            $renderer->doc .= "$gscript\n$olscript\n$scriptEnable";
825
-            $renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>';
826
-            if ($this->getConf('enableA11y')) {
827
-                $renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">'
828
-                    . p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
829
-            }
830
-            $renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p>&nbsp;</p></div>';
831
-            if ($this->getConf('enableA11y')) {
832
-                // render a table of the POI for the print and a11y presentation, it is hidden using javascript
833
-                $renderer->doc .= '<div class="olPOItableSpan" id="' . $mapid . '-table-span">
482
+	/**
483
+	 * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
484
+	 * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
485
+	 *
486
+	 * @param array $gmap
487
+	 * @param array $overlay
488
+	 *
489
+	 * @return false|string
490
+	 * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
491
+	 */
492
+	private function getStaticOSM(array $gmap, array $overlay)
493
+	{
494
+		if ($this->getConf('optionStaticMapGenerator') == 'local') {
495
+			// using local basemap composer
496
+			if (!$myMap = plugin_load('helper', 'openlayersmap_staticmap')) {
497
+				Logger::error(
498
+					'openlayersmap_staticmap plugin is not available for use.',
499
+					$myMap
500
+				);
501
+			}
502
+			if (!$geophp = plugin_load('helper', 'geophp')) {
503
+				Logger::debug('geophp plugin is not available for use.', $geophp);
504
+			}
505
+			$size = str_replace("px", "", $gmap ['width']) . "x"
506
+				. str_replace("px", "", $gmap ['height']);
507
+
508
+			$markers = array();
509
+			if (!empty ($overlay)) {
510
+				foreach ($overlay as $data) {
511
+					list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
512
+					$iconStyle  = substr($img, 0, strlen($img) - 4);
513
+					$markers [] = array(
514
+						'lat'  => $lat,
515
+						'lon'  => $lon,
516
+						'type' => $iconStyle
517
+					);
518
+				}
519
+			}
520
+
521
+			$apikey = '';
522
+			switch ($gmap ['baselyr']) {
523
+				case 'mapnik' :
524
+				case 'openstreetmap' :
525
+					$maptype = 'openstreetmap';
526
+					break;
527
+				case 'transport' :
528
+					$maptype = 'transport';
529
+					$apikey  = '?apikey=' . $this->getConf('tfApiKey');
530
+					break;
531
+				case 'landscape' :
532
+					$maptype = 'landscape';
533
+					$apikey  = '?apikey=' . $this->getConf('tfApiKey');
534
+					break;
535
+				case 'outdoors' :
536
+					$maptype = 'outdoors';
537
+					$apikey  = '?apikey=' . $this->getConf('tfApiKey');
538
+					break;
539
+				case 'cycle map' :
540
+					$maptype = 'cycle';
541
+					$apikey  = '?apikey=' . $this->getConf('tfApiKey');
542
+					break;
543
+				case 'hike and bike map' :
544
+					$maptype = 'hikeandbike';
545
+					break;
546
+				case 'mapquest hybrid' :
547
+				case 'mapquest road' :
548
+				case 'mapquest sat' :
549
+					$maptype = 'mapquest';
550
+					break;
551
+				default :
552
+					$maptype = '';
553
+					break;
554
+			}
555
+
556
+			$result = $myMap->getMap(
557
+				$gmap ['lat'],
558
+				$gmap ['lon'],
559
+				$gmap ['zoom'],
560
+				$size,
561
+				$maptype,
562
+				$markers,
563
+				$gmap ['gpxfile'],
564
+				$gmap ['kmlfile'],
565
+				$gmap ['geojsonfile'],
566
+				$apikey
567
+			);
568
+		} else {
569
+			// using external basemap composer
570
+
571
+			// https://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10
572
+			//.117187497601&zoom=5&size=500x350
573
+			// &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,
574
+			//  lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,
575
+			//  ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,
576
+			//  ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
577
+			$imgUrl = "https://staticmap.openstreetmap.de/staticmap.php";
578
+			$imgUrl .= "?center=" . $gmap ['lat'] . "," . $gmap ['lon'];
579
+			$imgUrl .= "&size=" . str_replace("px", "", $gmap ['width']) . "x"
580
+				. str_replace("px", "", $gmap ['height']);
581
+
582
+			if ($gmap ['zoom'] > 16) {
583
+				// actually this could even be 18, but that seems overkill
584
+				$imgUrl .= "&zoom=16";
585
+			} else {
586
+				$imgUrl .= "&zoom=" . $gmap ['zoom'];
587
+			}
588
+
589
+			if (!empty ($overlay)) {
590
+				$rowId  = 0;
591
+				$imgUrl .= "&markers=";
592
+				foreach ($overlay as $data) {
593
+					list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
594
+					$rowId++;
595
+					$iconStyle = "lightblue$rowId";
596
+					$imgUrl    .= "$lat,$lon,$iconStyle%7c";
597
+				}
598
+				$imgUrl = substr($imgUrl, 0, -3);
599
+			}
600
+
601
+			$result = $imgUrl;
602
+		}
603
+		// Logger::debug('syntax_plugin_openlayersmap_olmap::getStaticOSM: osm image url is:',$result);
604
+		return $result;
605
+	}
606
+
607
+	/**
608
+	 * Create a Bing maps static image url w/ the poi.
609
+	 *
610
+	 * @param array $gmap
611
+	 * @param array $overlay
612
+	 * @return string
613
+	 */
614
+	private function getBing(array $gmap, array $overlay): string
615
+	{
616
+		switch ($gmap ['baselyr']) {
617
+			case 've hybrid' :
618
+			case 'bing hybrid' :
619
+				$maptype = 'AerialWithLabels';
620
+				break;
621
+			case 've sat' :
622
+			case 'bing sat' :
623
+				$maptype = 'Aerial';
624
+				break;
625
+			case 've normal' :
626
+			case 've road' :
627
+			case 've' :
628
+			case 'bing road' :
629
+			default :
630
+				$maptype = 'Road';
631
+				break;
632
+		}
633
+		$imgUrl = "https://dev.virtualearth.net/REST/v1/Imagery/Map/" . $maptype;// . "/";
634
+		if ($this->getConf('autoZoomMap')) {
635
+			$bbox = $this->calcBBOX($overlay, $gmap ['lat'], $gmap ['lon']);
636
+			//$imgUrl .= "?ma=" . $bbox ['minlat'] . "," . $bbox ['minlon'] . ","
637
+			//          . $bbox ['maxlat'] . "," . $bbox ['maxlon'];
638
+			$imgUrl .= "?ma=" . $bbox ['minlat'] . "%2C" . $bbox ['minlon'] . "%2C" . $bbox ['maxlat']
639
+				. "%2C" . $bbox ['maxlon'];
640
+			$imgUrl .= "&dcl=1";
641
+		}
642
+		if (strpos($imgUrl, "?") === false) {
643
+			$imgUrl .= "?";
644
+		}
645
+
646
+		//$imgUrl .= "&ms=" . str_replace ( "px", "", $gmap ['width'] ) . ","
647
+		//          . str_replace ( "px", "", $gmap ['height'] );
648
+		$imgUrl .= "&ms=" . str_replace("px", "", $gmap ['width']) . "%2C"
649
+			. str_replace("px", "", $gmap ['height']);
650
+		$imgUrl .= "&key=" . $this->getConf('bingAPIKey');
651
+		if (!empty ($overlay)) {
652
+			$rowId = 0;
653
+			foreach ($overlay as $data) {
654
+				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
655
+				// TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
656
+				$iconStyle = 32;
657
+				$rowId++;
658
+				// NOTE: the max number of pushpins is 18! or we have to use POST
659
+				//  (http://msdn.microsoft.com/en-us/library/ff701724.aspx)
660
+				if ($rowId == 18) {
661
+					break;
662
+				}
663
+				//$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
664
+				$imgUrl .= "&pp=$lat%2C$lon%3B$iconStyle%3B$rowId";
665
+			}
666
+		}
667
+		global $conf;
668
+		$imgUrl .= "&fmt=png";
669
+		$imgUrl .= "&c=" . $conf ['lang'];
670
+		// Logger::debug('syntax_plugin_openlayersmap_olmap::getBing: bing image url is:',$imgUrl);
671
+		return $imgUrl;
672
+	}
673
+
674
+	/**
675
+	 * Calculate the minimum bbox for a start location + poi.
676
+	 *
677
+	 * @param array $overlay
678
+	 *            multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
679
+	 * @param float $lat
680
+	 *            latitude for map center
681
+	 * @param float $lon
682
+	 *            longitude for map center
683
+	 * @return array :float array describing the mbr and center point
684
+	 */
685
+	private function calcBBOX(array $overlay, float $lat, float $lon): array
686
+	{
687
+		$lats = array($lat);
688
+		$lons = array($lon);
689
+		foreach ($overlay as $data) {
690
+			list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
691
+			$lats [] = $lat;
692
+			$lons [] = $lon;
693
+		}
694
+		sort($lats);
695
+		sort($lons);
696
+		// TODO: make edge/wrap around cases work
697
+		$centerlat = $lats [0] + ($lats [count($lats) - 1] - $lats [0]);
698
+		$centerlon = $lons [0] + ($lons [count($lats) - 1] - $lons [0]);
699
+		return array(
700
+			'minlat'    => $lats [0],
701
+			'minlon'    => $lons [0],
702
+			'maxlat'    => $lats [count($lats) - 1],
703
+			'maxlon'    => $lons [count($lats) - 1],
704
+			'centerlat' => $centerlat,
705
+			'centerlon' => $centerlon
706
+		);
707
+	}
708
+
709
+	/**
710
+	 * convert latitude in decimal degrees to DMS+hemisphere.
711
+	 *
712
+	 * @param float $decimaldegrees
713
+	 * @return string
714
+	 * @todo move this into a shared library
715
+	 */
716
+	private function convertLat(float $decimaldegrees): string
717
+	{
718
+		if (strpos($decimaldegrees, '-') !== false) {
719
+			$latPos = "S";
720
+		} else {
721
+			$latPos = "N";
722
+		}
723
+		$dms = $this->convertDDtoDMS(abs($decimaldegrees));
724
+		return hsc($dms . $latPos);
725
+	}
726
+
727
+	/**
728
+	 * Convert decimal degrees to degrees, minutes, seconds format
729
+	 *
730
+	 * @param float $decimaldegrees
731
+	 * @return string dms
732
+	 * @todo move this into a shared library
733
+	 */
734
+	private function convertDDtoDMS(float $decimaldegrees): string
735
+	{
736
+		$dms  = floor($decimaldegrees);
737
+		$secs = ($decimaldegrees - $dms) * 3600;
738
+		$min  = floor($secs / 60);
739
+		$sec  = round($secs - ($min * 60), 3);
740
+		$dms  .= 'º' . $min . '\'' . $sec . '"';
741
+		return $dms;
742
+	}
743
+
744
+	/**
745
+	 * convert longitude in decimal degrees to DMS+hemisphere.
746
+	 *
747
+	 * @param float $decimaldegrees
748
+	 * @return string
749
+	 * @todo move this into a shared library
750
+	 */
751
+	private function convertLon(float $decimaldegrees): string
752
+	{
753
+		if (strpos($decimaldegrees, '-') !== false) {
754
+			$lonPos = "W";
755
+		} else {
756
+			$lonPos = "E";
757
+		}
758
+		$dms = $this->convertDDtoDMS(abs($decimaldegrees));
759
+		return hsc($dms . $lonPos);
760
+	}
761
+
762
+	/**
763
+	 * Figures out the base filename of a media path.
764
+	 *
765
+	 * @param string $mediaLink
766
+	 * @return string
767
+	 */
768
+	private function getFileName(string $mediaLink): string
769
+	{
770
+		$mediaLink = str_replace('[[', '', $mediaLink);
771
+		$mediaLink = str_replace(']]', '', $mediaLink);
772
+		$mediaLink = substr($mediaLink, 0, -4);
773
+		$parts     = explode(':', $mediaLink);
774
+		$mediaLink = end($parts);
775
+		return str_replace('_', ' ', $mediaLink);
776
+	}
777
+
778
+	/**
779
+	 *
780
+	 * @see DokuWiki_Syntax_Plugin::render()
781
+	 */
782
+	public function render($format, Doku_Renderer $renderer, $data): bool
783
+	{
784
+		// set to true after external scripts tags are written
785
+		static $initialised = false;
786
+		// incremented for each map tag in the page source so we can keep track of each map in this page
787
+		static $mapnumber = 0;
788
+
789
+		// Logger::debug('olmap::render() data.',$data);
790
+		list ($mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl, $_firstimage) = $data;
791
+
792
+		if ($format == 'xhtml') {
793
+			$olscript     = '';
794
+			$olEnable     = false;
795
+			$gscript      = '';
796
+			$gEnable      = $this->getConf('enableGoogle');
797
+			$stamenEnable = $this->getConf('enableStamen');
798
+			$osmEnable    = $this->getConf('enableOSM');
799
+			$enableBing   = $this->getConf('enableBing');
800
+
801
+			$scriptEnable = '';
802
+			if (!$initialised) {
803
+				$initialised = true;
804
+				// render necessary script tags
805
+				if ($gEnable) {
806
+					$gscript = '<script defer="defer" src="//maps.google.com/maps/api/js?v=3.29&amp;key='
807
+						. $this->getConf('googleAPIkey') . '"></script>';
808
+				}
809
+				$olscript = '<script defer="defer" src="' . DOKU_BASE
810
+					. 'lib/plugins/openlayersmap/lib/OpenLayers.js"></script>';
811
+
812
+				$scriptEnable = '<script defer="defer" src="data:text/javascript;base64,';
813
+				$scriptSrc    = $olscript ? 'olEnable = true;' : 'olEnable = false;';
814
+				$scriptSrc    .= 'gEnable = ' . ($gEnable ? 'true' : 'false') . ';';
815
+				$scriptSrc    .= 'osmEnable = ' . ($osmEnable ? 'true' : 'false') . ';';
816
+				$scriptSrc    .= 'stamenEnable = ' . ($stamenEnable ? 'true' : 'false') . ';';
817
+				$scriptSrc    .= 'bEnable = ' . ($enableBing ? 'true' : 'false') . ';';
818
+				$scriptSrc    .= 'bApiKey="' . $this->getConf('bingAPIKey') . '";';
819
+				$scriptSrc    .= 'tfApiKey="' . $this->getConf('tfApiKey') . '";';
820
+				$scriptSrc    .= 'gApiKey="' . $this->getConf('googleAPIkey') . '";';
821
+				$scriptEnable .= base64_encode($scriptSrc);
822
+				$scriptEnable .= '"></script>';
823
+			}
824
+			$renderer->doc .= "$gscript\n$olscript\n$scriptEnable";
825
+			$renderer->doc .= '<div class="olMapHelp">' . $this->locale_xhtml("help") . '</div>';
826
+			if ($this->getConf('enableA11y')) {
827
+				$renderer->doc .= '<div id="' . $mapid . '-static" class="olStaticMap">'
828
+					. p_render($format, p_get_instructions($staticImgUrl), $info) . '</div>';
829
+			}
830
+			$renderer->doc .= '<div id="' . $mapid . '-clearer" class="clearer"><p>&nbsp;</p></div>';
831
+			if ($this->getConf('enableA11y')) {
832
+				// render a table of the POI for the print and a11y presentation, it is hidden using javascript
833
+				$renderer->doc .= '<div class="olPOItableSpan" id="' . $mapid . '-table-span">
834 834
                     <table class="olPOItable" id="' . $mapid . '-table">
835 835
                     <caption class="olPOITblCaption">' . $this->getLang('olmapPOItitle') . '</caption>
836 836
                     <thead class="olPOITblHeader">
@@ -838,64 +838,64 @@  discard block
 block discarded – undo
838 838
                     <th class="rowId" scope="col">id</th>
839 839
                     <th class="icon" scope="col">' . $this->getLang('olmapPOIicon') . '</th>
840 840
                     <th class="lat" scope="col" title="' . $this->getLang('olmapPOIlatTitle') . '">'
841
-                    . $this->getLang('olmapPOIlat') . '</th>
841
+					. $this->getLang('olmapPOIlat') . '</th>
842 842
                     <th class="lon" scope="col" title="' . $this->getLang('olmapPOIlonTitle') . '">'
843
-                    . $this->getLang('olmapPOIlon') . '</th>
843
+					. $this->getLang('olmapPOIlon') . '</th>
844 844
                     <th class="txt" scope="col">' . $this->getLang('olmapPOItxt') . '</th>
845 845
                     </tr>
846 846
                     </thead>';
847
-                if ($poitabledesc != '') {
848
-                    $renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc
849
-                        . '</td></tr></tfoot>';
850
-                }
851
-                $renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody>
847
+				if ($poitabledesc != '') {
848
+					$renderer->doc .= '<tfoot class="olPOITblFooter"><tr><td colspan="5">' . $poitabledesc
849
+						. '</td></tr></tfoot>';
850
+				}
851
+				$renderer->doc .= '<tbody class="olPOITblBody">' . $poitable . '</tbody>
852 852
                     </table></div>';
853
-            }
854
-            // render inline mapscript parts
855
-            $renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,';
856
-            $renderer->doc .= base64_encode("olMapData[$mapnumber] = $param");
857
-            $renderer->doc .= '"></script>';
858
-            $mapnumber++;
859
-            return true;
860
-        } elseif ($format == 'metadata') {
861
-            if (!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) {
862
-                // render geo metadata, unless they are the default
863
-                $renderer->meta ['geo'] ['lat'] = $mainLat;
864
-                $renderer->meta ['geo'] ['lon'] = $mainLon;
865
-                if ($geophp = plugin_load('helper', 'geophp')) {
866
-                    // if we have the geoPHP helper, add the geohash
867
-                    try {
868
-                        $renderer->meta['geo']['geohash'] = (new Point($mainLon, $mainLat))->out('geohash');
869
-                    } catch (Exception $e) {
870
-                        Logger::error("Failed to create geohash for: $mainLat, $mainLon");
871
-                    }
872
-                }
873
-            }
874
-
875
-            if (($this->getConf('enableA11y')) && (!empty ($_firstimage))) {
876
-                // add map local image into relation/firstimage if not already filled and when it is a local image
877
-
878
-                global $ID;
879
-                $rel = p_get_metadata($ID, 'relation');
880
-                $img = $rel ['firstimage'];
881
-                if (empty ($img) /* || $img == $_firstimage*/) {
882
-                    //Logger::debug(
883
-                    // 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.',
884
-                    // $_firstimage);
885
-
886
-                    // This seems to never work; the firstimage entry in the .meta file is empty
887
-                    // $renderer->meta['relation']['firstimage'] = $_firstimage;
888
-
889
-                    // ... and neither does this; the firstimage entry in the .meta file is empty
890
-                    // $relation = array('relation'=>array('firstimage'=>$_firstimage));
891
-                    // p_set_metadata($ID, $relation, false, false);
892
-
893
-                    // ... this works
894
-                    $renderer->internalmedia($_firstimage, $poitabledesc);
895
-                }
896
-            }
897
-            return true;
898
-        }
899
-        return false;
900
-    }
853
+			}
854
+			// render inline mapscript parts
855
+			$renderer->doc .= '<script defer="defer" src="data:text/javascript;base64,';
856
+			$renderer->doc .= base64_encode("olMapData[$mapnumber] = $param");
857
+			$renderer->doc .= '"></script>';
858
+			$mapnumber++;
859
+			return true;
860
+		} elseif ($format == 'metadata') {
861
+			if (!(($this->dflt ['lat'] == $mainLat) && ($this->dflt ['lon'] == $mainLon))) {
862
+				// render geo metadata, unless they are the default
863
+				$renderer->meta ['geo'] ['lat'] = $mainLat;
864
+				$renderer->meta ['geo'] ['lon'] = $mainLon;
865
+				if ($geophp = plugin_load('helper', 'geophp')) {
866
+					// if we have the geoPHP helper, add the geohash
867
+					try {
868
+						$renderer->meta['geo']['geohash'] = (new Point($mainLon, $mainLat))->out('geohash');
869
+					} catch (Exception $e) {
870
+						Logger::error("Failed to create geohash for: $mainLat, $mainLon");
871
+					}
872
+				}
873
+			}
874
+
875
+			if (($this->getConf('enableA11y')) && (!empty ($_firstimage))) {
876
+				// add map local image into relation/firstimage if not already filled and when it is a local image
877
+
878
+				global $ID;
879
+				$rel = p_get_metadata($ID, 'relation');
880
+				$img = $rel ['firstimage'];
881
+				if (empty ($img) /* || $img == $_firstimage*/) {
882
+					//Logger::debug(
883
+					// 'olmap::render#rendering image relation metadata for _firstimage as $img was empty or same.',
884
+					// $_firstimage);
885
+
886
+					// This seems to never work; the firstimage entry in the .meta file is empty
887
+					// $renderer->meta['relation']['firstimage'] = $_firstimage;
888
+
889
+					// ... and neither does this; the firstimage entry in the .meta file is empty
890
+					// $relation = array('relation'=>array('firstimage'=>$_firstimage));
891
+					// p_set_metadata($ID, $relation, false, false);
892
+
893
+					// ... this works
894
+					$renderer->internalmedia($_firstimage, $poitabledesc);
895
+				}
896
+			}
897
+			return true;
898
+		}
899
+		return false;
900
+	}
901 901
 }
Please login to merge, or discard this patch.