Completed
Push — master ( 097360...16d695 )
by Mark
02:46
created

action_plugin_spatialhelper::_toRad()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/*
3
 * Copyright (c) 2011-2016 Mark C. Prins <[email protected]>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
if (!defined('DOKU_INC')) {
18
	die ();
19
}
20
if (!defined('DOKU_PLUGIN')) {
21
	define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
22
}
23
if (!defined('DOKU_LF')) {
24
	define('DOKU_LF', "\n");
25
}
26
require_once (DOKU_PLUGIN . 'action.php');
27
28
/**
29
 * DokuWiki Plugin dokuwikispatial (Action Component).
30
 *
31
 * @license BSD license
32
 * @author Mark C. Prins <[email protected]>
33
 */
34
class action_plugin_spatialhelper extends DokuWiki_Action_Plugin {
35
36
	/**
37
	 * Register for events.
38
	 *
39
	 * @param Doku_Event_Handler $controller
40
	 *        	DokuWiki's event controller object. Also available as global $EVENT_HANDLER
41
	 */
42
	public function register(Doku_Event_Handler $controller) {
43
		// listen for page add / delete events
44
		// http://www.dokuwiki.org/devel:event:indexer_page_add
45
		$controller->register_hook('INDEXER_PAGE_ADD', 'BEFORE', $this, 'handle_indexer_page_add');
46
		$controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_removeFromIndex');
47
48
		// http://www.dokuwiki.org/devel:event:sitemap_generate
49
		$controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handle_sitemap_generate_before');
50
		// using after will only trigger us if a sitemap was actually created
51
		$controller->register_hook('SITEMAP_GENERATE', 'AFTER', $this, 'handle_sitemap_generate_after');
52
53
		// handle actions we know of
54
		$controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_preprocess', array());
55
		// handle HTML eg. /dokuwiki/doku.php?id=start&do=findnearby&geohash=u15vk4
56
		$controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, '_findnearby', array(
57
				'format' => 'HTML'
58
		));
59
		// handles AJAX/json eg: jQuery.post("/dokuwiki/lib/exe/ajax.php?id=start&call=findnearby&geohash=u15vk4");
60
		$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_findnearby', array(
61
				'format' => 'JSON'
62
		));
63
64
		// listen for media uploads and deletes
65
		$controller->register_hook('MEDIA_UPLOAD_FINISH', 'BEFORE', $this, '_handle_media_uploaded', array());
66
		$controller->register_hook('MEDIA_DELETE_FILE', 'BEFORE', $this, '_handle_media_deleted', array());
67
68
		$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handle_metaheader_output');
69
	}
70
71
	/**
72
	 * Update the spatial index for the page.
73
	 *
74
	 * @param Doku_Event $event
75
	 *        	event object by reference
76
	 * @param object $param
77
	 *        	the parameters passed to register_hook when this handler was registered
78
	 */
79
	public function handle_indexer_page_add(Doku_Event $event, $param) {
80
		// $event→data['page'] – the page id
81
		// $event→data['body'] – empty, can be filled by additional content to index by your plugin
82
		// $event→data['metadata'] – the metadata that shall be indexed. This is an array where the keys are the metadata indexes and the value a string or an array of strings with the values. title and relation_references will already be set.
83
		$id = $event->data ['page'];
84
		$indexer = & plugin_load('helper', 'spatialhelper_index');
85
		$entries = $indexer->updateSpatialIndex($id);
0 ignored issues
show
Unused Code introduced by
$entries is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
86
	}
87
88
	/**
89
	 * Update the spatial index, removing the page.
90
	 *
91
	 * @param Doku_Event $event
92
	 *        	event object by reference
93
	 * @param object $param
94
	 *        	the parameters passed to register_hook when this handler was registered
95
	 */
96
	public function _removeFromIndex(Doku_Event & $event, $param) {
97
		// event data:
98
		// $data[0] – The raw arguments for io_saveFile as an array. Do not change file path.
99
		// $data[0][0] – the file path.
100
		// $data[0][1] – the content to be saved, and may be modified.
101
		// $data[1] – ns: The colon separated namespace path minus the trailing page name. (false if root ns)
102
		// $data[2] – page_name: The wiki page name.
103
		// $data[3] – rev: The page revision, false for current wiki pages.
104
105
		dbglog($event->data, "Event data in _removeFromIndex.");
106
		if (@file_exists($event->data [0] [0])) {
107
			// file not new
108
			if (!$event->data [0] [1]) {
109
				// file is empty, page is being deleted
110
				if (empty ($event->data [1])) {
111
					// root namespace
112
					$id = $event->data [2];
113
				} else {
114
					$id = $event->data [1] . ":" . $event->data [2];
115
				}
116
				$indexer = & plugin_load('helper', 'spatialhelper_index');
117
				if ($indexer) {
118
					$indexer->deleteFromIndex($id);
119
				}
120
			}
121
		}
122
	}
123
124
	/**
125
	 * Add a new SitemapItem object that points to the KML of public geocoded pages.
126
	 *
127
	 * @param Doku_Event $event
128
	 * @param unknown $param
129
	 */
130
	public function handle_sitemap_generate_before(Doku_Event $event, $param) {
131
		$path = mediaFN($this->getConf('media_kml'));
132
		$lastmod = @filemtime($path);
133
		$event->data ['items'] [] = new SitemapItem(ml($this->getConf('media_kml'), '', true, '&amp;', true), $lastmod);
134
		dbglog($event->data ['items'], "Added a new SitemapItem object that points to the KML of public geocoded pages.");
135
	}
136
137
	/**
138
	 * Create a spatial sitemap or attach the geo/kml map to the sitemap.
139
	 *
140
	 * @param Doku_Event $event
141
	 *        	event object by reference, not used
142
	 * @param mixed $param
143
	 *        	parameter array, not used
144
	 */
145
	public function handle_sitemap_generate_after(Doku_Event $event, $param) {
146
		// $event→data['items']: Array of SitemapItem instances, the array of sitemap items that already contains all public pages of the wiki
147
		// $event→data['sitemap']: The path of the file the sitemap will be saved to.
148
149
		dbglog($event->data['items'], "createSpatialSitemap loading helper");
150
		if ($helper = & plugin_load('helper', 'spatialhelper_sitemap')) {
151
			dbglog($helper, "createSpatialSitemap loaded helper.");
152
153
			$kml = $helper->createKMLSitemap($this->getConf('media_kml'));
154
			$rss = $helper->createGeoRSSSitemap($this->getConf('media_georss'));
155
156
			return $kml && $rss;
157
		} else {
158
			dbglog($helper, "createSpatialSitemap NOT loaded helper.");
159
		}
160
	}
161
162
	/**
163
	 * trap findnearby action.
164
	 * This addional handler is required as described at: https://www.dokuwiki.org/devel:event:tpl_act_unknown
165
	 *
166
	 * @param Doku_Event $event
167
	 *        	event object by reference
168
	 * @param mixed $param
169
	 *        	not used
170
	 */
171
	public function handle_action_act_preprocess(Doku_Event $event, $param) {
172
		if ($event->data != 'findnearby') {
173
					return;
174
		}
175
		$event->preventDefault();
176
	}
177
178
	/**
179
	 * handle findnearby action.
180
	 *
181
	 * @param Doku_Event $event
182
	 *        	event object by reference
183
	 * @param mixed $param
184
	 *        	associative array with keys
185
	 *        	'format'=> HTML | JSON
186
	 */
187
	public function _findnearby(Doku_Event & $event, $param) {
188
		if ($event->data != 'findnearby') {
189
					return;
190
		}
191
		$event->preventDefault();
192
193
		global $INPUT;
194
		if ($helper = & plugin_load('helper', 'spatialhelper_search')) {
195
			if ($INPUT->has('lat') && $INPUT->has('lon')) {
196
				$results = $helper->findNearbyLatLon($INPUT->param('lat'), $INPUT->param('lon'));
197
			} elseif ($INPUT->has('geohash')) {
198
				$results = $helper->findNearby($INPUT->str('geohash'));
199
			} else {
200
				$results = array(
201
						'error' => hsc($this->getLang('invalidinput'))
202
				);
203
			}
204
		}
205
206
		$showMedia = $INPUT->bool('showMedia', true);
207
208
		switch ($param['format']) {
209
			case 'JSON' :
210
				$this->printJSON($results);
0 ignored issues
show
Bug introduced by
The variable $results does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
211
				break;
212
			case 'HTML' :
213
			// fall through to default
214
			default :
215
				$this->printHTML($results, $showMedia);
216
				break;
217
		}
218
	}
219
220
	/**
221
	 * Print seachresults as HTML lists.
222
	 *
223
	 * @param array $searchresults
224
	 */
225
	private function printJSON($searchresults) {
226
		require_once DOKU_INC . 'inc/JSON.php';
227
		$json = new JSON();
228
		header('Content-Type: application/json');
229
		print $json->encode($searchresults);
230
	}
231
232
	/**
233
	 * Print seachresults as HTML lists.
234
	 *
235
	 * @param array $searchresults
236
	 * @param boolean $showMedia
237
	 */
238
	private function printHTML($searchresults, $showMedia = true) {
239
		$pages = ( array ) ($searchresults ['pages']);
240
		$media = ( array ) $searchresults ['media'];
241
		$lat = ( float ) $searchresults ['lat'];
242
		$lon = ( float ) $searchresults ['lon'];
243
		$geohash = ( string ) $searchresults ['geohash'];
244
245
		if (isset ($searchresults ['error'])) {
246
			print '<div class="level1"><p>' . hsc($results ['error']) . '</p></div>';
0 ignored issues
show
Bug introduced by
The variable $results does not exist. Did you mean $searchresults?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
247
			return;
248
		}
249
250
		// print a HTML list
251
		print '<h1>' . $this->getLang('results_header') . '</h1>' . DOKU_LF;
252
		print '<div class="level1">' . DOKU_LF;
253
		if (!empty ($pages)) {
254
			$pagelist = '<ol>' . DOKU_LF;
255
			foreach ($pages as $page) {
256
				$pagelist .= '<li>' . html_wikilink(':' . $page ['id'], useHeading('navigation') ? null : noNS($page ['id'])) . ' (' . $this->getLang('results_distance_prefix') . $page ['distance'] . '&nbsp;m) ' . $page ['description'] . '</li>' . DOKU_LF;
257
			}
258
			$pagelist .= '</ol>' . DOKU_LF;
259
260
			print '<h2>' . $this->getLang('results_pages') . hsc(' lat;lon: ' . $lat . ';' . $lon . ' (geohash: ' . $geohash . ')') . '</h2>';
261
			print '<div class="level2">' . DOKU_LF;
262
			print $pagelist;
263
			print '</div>' . DOKU_LF;
264
		} else {
265
			print '<p>' . hsc($this->getLang('nothingfound')) . '</p>';
266
		}
267
268
		if (!empty ($media) && $showMedia) {
269
			$pagelist = '<ol>' . DOKU_LF;
270
			foreach ($media as $m) {
271
				$opts = array();
272
				$link = ml($m ['id'], $opts, false, '&amp;', false);
273
				$opts ['w'] = '100';
274
				$src = ml($m ['id'], $opts);
275
				$pagelist .= '<li><a href="' . $link . '"><img src="' . $src . '"></a> (' . $this->getLang('results_distance_prefix') . $page ['distance'] . '&nbsp;m) ' . hsc($desc) . '</li>' . DOKU_LF;
0 ignored issues
show
Bug introduced by
The variable $page seems to be defined by a foreach iteration on line 255. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
Bug introduced by
The variable $desc does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
276
			}
277
			$pagelist .= '</ol>' . DOKU_LF;
278
279
			print '<h2>' . $this->getLang('results_media') . hsc(' lat;lon: ' . $lat . ';' . $lon . ' (geohash: ' . $geohash . ')') . '</h2>' . DOKU_LF;
280
			print '<div class="level2">' . DOKU_LF;
281
			print $pagelist;
282
			print '</div>' . DOKU_LF;
283
		}
284
		print '<p>' . $this->getLang('results_precision') . $searchresults ['precision'] . ' m. ';
285
		if (strlen($geohash) > 1) {
286
			$url = wl(getID(), array(
287
					'do' => 'findnearby',
288
					'geohash' => substr($geohash, 0, - 1)
289
			));
290
			print '<a href="' . $url . '" class="findnearby">' . $this->getLang('search_largerarea') . '</a>.</p>' . DOKU_LF;
291
		}
292
		print '</div>' . DOKU_LF;
293
	}
294
295
	/**
296
	 * add media to spatial index.
297
	 *
298
	 * @param Doku_Event $event
299
	 *        	event object by reference
300
	 * @param unknown $param
301
	 */
302
	public function _handle_media_uploaded(Doku_Event & $event, $param) {
303
		// data[0] temporary file name (read from $_FILES)
304
		// data[1] file name of the file being uploaded
305
		// data[2] future directory id of the file being uploaded
306
		// data[3] the mime type of the file being uploaded
307
		// data[4] true if the uploaded file exists already
308
		// data[5] (since 2011-02-06) the PHP function used to move the file to the correct location
309
310
		dbglog($event->data, "_handle_media_uploaded::event data");
311
312
		// check the list of mimetypes
313
		// if it's a supported type call appropriate index function
314
		if (substr_compare($event->data [3], 'image/jpeg', 0)) {
315
			$indexer = plugin_load('helper', 'spatialhelper_index');
316
			if ($indexer) {
317
				$indexer->indexImage($event->data [2], $event->data [1]);
318
			}
319
		}
320
		// TODO add image/tiff
321
		// TODO kml, gpx, geojson...
322
	}
323
324
	/**
325
	 * removes the media from the index.
326
	 */
327
	public function _handle_media_deleted(Doku_Event & $event, $param) {
328
		// data['id'] ID data['unl'] unlink return code
329
		// data['del'] Namespace directory unlink return code
330
		// data['name'] file name data['path'] full path to the file
331
		// data['size'] file size
332
333
		dbglog($event->data, "_handle_media_deleted::event data");
334
335
		// remove the media id from the index
336
		$indexer = & plugin_load('helper', 'spatialhelper_index');
337
		if ($indexer) {
338
			$indexer->deleteFromIndex('media__' . $event->data ['id']);
339
		}
340
	}
341
342
	/**
343
	 * add a link to the spatial sitemap files in the header.
344
	 *
345
	 * @param Doku_Event $event
346
	 *        	the DokuWiki event. $event->data is a two-dimensional
347
	 *        	array of all meta headers. The keys are meta, link and script.
348
	 * @param unknown_type $param
349
	 *
350
	 * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output
351
	 */
352
	public function handle_metaheader_output(Doku_Event $event, $param) {
353
		// TODO maybe test for exist
354
		$event->data ["link"] [] = array(
355
				"type" => "application/atom+xml",
356
				"rel" => "alternate",
357
				"href" => ml($this->getConf('media_georss')),
358
				"title" => "Spatial ATOM Feed"
359
		);
360
		$event->data ["link"] [] = array(
361
				"type" => "application/vnd.google-earth.kml+xml",
362
				"rel" => "alternate",
363
				"href" => ml($this->getConf('media_kml')),
364
				"title" => "KML Sitemap"
365
		);
366
	}
367
368
	/**
369
	 * Calculate a new coordinate based on start, distance and bearing
370
	 *
371
	 * @param $start array
372
	 *        	- start coordinate as decimal lat/lon pair
373
	 * @param $dist float
374
	 *        	- distance in kilometers
375
	 * @param $brng float
376
	 *        	- bearing in degrees (compass direction)
377
	 */
378
	private function _geo_destination($start, $dist, $brng) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
379
		$lat1 = _toRad($start [0]);
380
		$lon1 = _toRad($start [1]);
381
		// http://en.wikipedia.org/wiki/Earth_radius
382
		// average earth radius in km
383
		$dist = $dist / 6371.01;
384
		$brng = _toRad($brng);
385
386
		$lon2 = $lon1 + atan2(sin($brng) * sin($dist) * cos($lat1), cos($dist) - sin($lat1) * sin($lat2));
0 ignored issues
show
Bug introduced by
The variable $lat2 does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
387
		$lon2 = fmod(($lon2 + 3 * pi()), (2 * pi())) - pi();
388
389
		return array(
390
				_toDeg($lat2),
391
				_toDeg($lon2)
392
		);
393
	}
394
	private function _toRad($deg) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
395
		return $deg * pi() / 180;
396
	}
397
	private function _toDeg($rad) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
398
		return $rad * 180 / pi();
399
	}
400
}
401