18
18
die ();
19
19
if (! defined ( 'DOKU_PLUGIN ' ))
20
20
define ( 'DOKU_PLUGIN ' , DOKU_INC . 'lib/plugins/ ' );
21
+ if (! defined ( 'DOKU_LF ' ))
22
+ define ( 'DOKU_LF ' , "\n" );
21
23
require_once (DOKU_PLUGIN . 'action.php ' );
22
24
23
25
/**
@@ -35,18 +37,22 @@ class action_plugin_spatialhelper extends DokuWiki_Action_Plugin {
35
37
* DokuWiki's event controller object. Also available as global $EVENT_HANDLER
36
38
*/
37
39
public function register (Doku_Event_Handler &$ controller ) {
38
- // listen for page add / delete
40
+ // listen for page add / delete events
39
41
// http://www.dokuwiki.org/devel:event:indexer_page_add
40
42
$ controller ->register_hook ( 'INDEXER_PAGE_ADD ' , 'BEFORE ' , $ this , '_updateSpatialIndex ' );
41
43
$ controller ->register_hook ( 'IO_WIKIPAGE_WRITE ' , 'BEFORE ' , $ this , '_removeFromIndex ' );
42
44
43
45
// http://www.dokuwiki.org/devel:event:sitemap_generate
44
- $ controller ->register_hook ( 'SITEMAP_GENERATE ' , 'BEFORE ' , $ this , '_createspatialsitemap ' );
46
+ // using after will only trigger us if a sitemap was actually created
47
+ $ controller ->register_hook ( 'SITEMAP_GENERATE ' , 'AFTER ' , $ this , '_createSpatialSitemap ' );
48
+
45
49
// http://www.dokuwiki.org/devel:event:sitemap_ping
46
50
// $controller->register_hook('SITEMAP_PING', 'AFTER', $this, '_ping');
51
+
47
52
// handle actions we know of
48
53
$ controller ->register_hook ( 'ACTION_ACT_PREPROCESS ' , 'BEFORE ' , $ this , '_trap_action ' , array () );
49
54
$ controller ->register_hook ( 'TPL_ACT_UNKNOWN ' , 'BEFORE ' , $ this , '_findnearby ' , array () );
55
+
50
56
// listen for media uploads and deletes
51
57
$ controller ->register_hook ( 'MEDIA_UPLOAD_FINISH ' , 'BEFORE ' , $ this , '_handle_media_uploaded ' , array () );
52
58
$ controller ->register_hook ( 'MEDIA_DELETE_FILE ' , 'BEFORE ' , $ this , '_handle_media_deleted ' , array () );
@@ -61,28 +67,13 @@ public function register(Doku_Event_Handler &$controller) {
61
67
* the parameters passed to register_hook when this handler was registered
62
68
*/
63
69
function _updateSpatialIndex (Doku_Event &$ event , $ param ) {
64
- // $version = getVersionData();
65
- // dbglog($version, "dokuwiki version data");
66
- $ id = "" ;
67
- // if ($version['date'] < '2011-03-06') {
68
- // /*
69
- // Anteater and previous
70
- // $event→data[0] – the page id
71
- // $event→data[1] – empty, can be filled by additional content to index by your plugin
72
- // */
73
- // $id = $event->data[0];
74
- // } else {
75
- /*
76
- * As of 2011-03-06 the data structure has been changed to:
77
- * $event→data['page'] – the page id
78
- * $event→data['body'] – empty, can be filled by additional content to index by your plugin
79
- * $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.
80
- */
70
+ // $event→data['page'] – the page id
71
+ // $event→data['body'] – empty, can be filled by additional content to index by your plugin
72
+ // $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.
81
73
$ id = $ event ->data ['page ' ];
82
- // }
83
74
dbg ( "start update spatial index for page: $ id " , '--- action_plugin_spatialhelper::_updateSpatialIndex --- ' );
84
- $ indexer = plugin_load ( 'helper ' , 'spatialhelper_index ' );
85
75
76
+ $ indexer = plugin_load ( 'helper ' , 'spatialhelper_index ' );
86
77
if ($ indexer ) {
87
78
$ entries = $ indexer ->updateSpatialIndex ( $ id );
88
79
dbglog ( "Done indexing, entries: $ entries " , '--- action_plugin_spatialhelper::_updateSpatialIndex --- ' );
@@ -100,16 +91,15 @@ function _updateSpatialIndex(Doku_Event &$event, $param) {
100
91
* the parameters passed to register_hook when this handler was registered
101
92
*/
102
93
function _removeFromIndex (Doku_Event &$ event , $ param ) {
103
- /*
104
- * event data:
105
- * $data[0] – The raw arguments for io_saveFile as an array. Do not change file path.
106
- * $data[0][0] – the file path.
107
- * $data[0][1] – the content to be saved, and may be modified.
108
- * $data[1] – ns: The colon separated namespace path minus the trailing page name. (false if root ns)
109
- * $data[2] – page_name: The wiki page name.
110
- * $data[3] – rev: The page revision, false for current wiki pages.
111
- */
112
- // dbglog($event->data,"Event data in _removeFromIndex.");
94
+ // event data:
95
+ // $data[0] – The raw arguments for io_saveFile as an array. Do not change file path.
96
+ // $data[0][0] – the file path.
97
+ // $data[0][1] – the content to be saved, and may be modified.
98
+ // $data[1] – ns: The colon separated namespace path minus the trailing page name. (false if root ns)
99
+ // $data[2] – page_name: The wiki page name.
100
+ // $data[3] – rev: The page revision, false for current wiki pages.
101
+ dbglog ( $ event ->data , "Event data in _removeFromIndex. " );
102
+
113
103
if (@file_exists ( $ event ->data [0 ] [0 ] )) {
114
104
// file not new
115
105
if (! $ event ->data [0 ] [1 ]) {
@@ -122,7 +112,6 @@ function _removeFromIndex(Doku_Event &$event, $param) {
122
112
}
123
113
$ indexer = plugin_load ( 'helper ' , 'spatialhelper_index ' );
124
114
if ($ indexer ) {
125
- dbglog ( "loaded helper spatialhelper_index. Deleting $ id from index " );
126
115
$ indexer ->deleteFromIndex ( $ id );
127
116
}
128
117
}
@@ -137,24 +126,29 @@ function _removeFromIndex(Doku_Event &$event, $param) {
137
126
* @param mixed $param
138
127
* not used
139
128
*/
140
- private function _createspatialsitemap (Doku_Event &$ event , $ param ) {
141
- /*
142
- * $event→data['items']: Array of SitemapItem instances, the array of sitemap items that already contains all public pages of the wiki
143
- * $event→data['sitemap']: The path of the file the sitemap will be saved to.
144
- */
145
- dbglog ( $ event ->data ['items ' ], "Array of SitemapItem instances, the array of sitemap items that already contains all public pages of the wiki " );
146
- dbglog ( $ event ->data ['sitemap ' ], "The path of the file the sitemap will be saved to. " );
129
+ function _createSpatialSitemap (Doku_Event &$ event , $ param ) {
130
+ // $event→data['items']: Array of SitemapItem instances, the array of sitemap items that already contains all public pages of the wiki
131
+ // $event→data['sitemap']: The path of the file the sitemap will be saved to.
132
+ dbglog ( $ event ->data , "_createSpatialSitemap " );
133
+ dbglog ( $ param , "_createSpatialSitemap " );
134
+ // TODO add a new SitemapItem object that point to the KML of public geocoded pages
135
+ // global $conf;
136
+ // $url = $conf['baseurl'].$conf['cachedir'].'/sitemap.kml';
137
+ // $lastmod = @filemtime($conf['cachedir'].'/sitemap.kml);
138
+ // $event->data['items'][] = new SitemapItem($url,$lastmod);
147
139
}
148
140
149
141
/**
150
142
* trap findnearby action.
143
+ * This addional handler is
144
+ * required as described at: https://www.dokuwiki.org/devel:event:tpl_act_unknown
151
145
*
152
146
* @param Doku_Event $event
153
147
* event object by reference
154
148
* @param mixed $param
155
149
* not used
156
150
*/
157
- function _trap_action (&$ event , $ param ) {
151
+ function _trap_action (Doku_Event &$ event , $ param ) {
158
152
if ($ event ->data != 'findnearby ' )
159
153
return ;
160
154
$ event ->preventDefault ();
@@ -169,97 +163,139 @@ function _trap_action(&$event, $param) {
169
163
* not used
170
164
*/
171
165
function _findnearby (Doku_Event &$ event , $ param ) {
172
- global $ lang ;
173
166
if ($ event ->data != 'findnearby ' )
174
167
return ;
175
168
$ event ->preventDefault ();
176
169
177
- $ tagns = $ this ->getConf ( 'namespace ' );
178
- $ flags = explode ( ', ' , trim ( $ this ->getConf ( 'pagelist_flags ' ) ) );
179
-
180
- // TODO findNearbyLatLon()
181
- $ geohash = trim ( str_replace ( $ this ->getConf ( 'namespace ' ) . ': ' , '' , $ _REQUEST ['geohash ' ] ) );
182
-
170
+ global $ INPUT ;
171
+ $ dist_prefix = '' ;
183
172
if ($ helper = &plugin_load ( 'helper ' , 'spatialhelper_search ' )) {
184
- $ results = $ helper -> findNearby ( $ geohash );
185
- $ ids = ( array ) ( $ results [ 0 ] );
186
- $ location = ( string ) ( $ results [ 1 ]) ;
187
- foreach ( $ ids as $ id ) {
188
- $ pages [] = array (
189
- ' id ' => $ id
190
- ) ;
173
+ if ( $ INPUT -> has ( ' geohash ' )) {
174
+ $ results = $ helper -> findNearby ( $ INPUT -> str ( ' geohash ' ) );
175
+ $ dist_prefix = hsc ( $ this -> getLang ( ' result_distance_prefix ' )). ' ' ;
176
+ } elseif ( $ INPUT -> has ( ' lat ' ) && $ INPUT -> has ( ' lon ' ) ) {
177
+ $ results = $ helper -> findNearbyLatLon ( $ INPUT -> param ( ' lat ' ), $ INPUT -> param ( ' lon ' ) );
178
+ } else {
179
+ print ' <div class="level1"><p> ' . hsc ( $ this -> getLang ( ' invalidinput ' ) ) . ' </p></div> ' ;
191
180
}
181
+ $ pages = ( array ) ($ results [0 ]);
182
+ $ media = ( array ) $ results [1 ];
183
+ $ location = ( string ) ($ results [2 ]);
184
+ $ geohash = ( string ) ($ results [3 ]);
185
+ $ precision = $ results [4 ];
192
186
}
193
- // use html_buildlist() instead for media...
194
187
188
+ print '<h1> ' . $ this ->getLang ('results_header ' ) . '</h1> ' . DOKU_LF ;
189
+ print '<div class="level1"> ' . DOKU_LF ;
195
190
if (! empty ( $ pages )) {
196
- // let Pagelist Plugin do the work for us
197
- if (plugin_isdisabled ( 'pagelist ' ) || (! $ pagelist = plugin_load ( 'helper ' , 'pagelist ' ))) {
198
- msg ( $ this ->getLang ( 'missing_pagelistplugin ' ), - 1 );
199
- return false ;
200
- }
201
-
202
- $ pagelist ->setFlags ( $ flags );
203
- $ pagelist ->startList ();
191
+ $ pagelist = '<ol> ' . DOKU_LF ;
204
192
foreach ( $ pages as $ page ) {
205
- $ pagelist-> addPage ( $ page ) ;
193
+ $ pagelist .= ' <li> ' . html_wikilink ( ' : ' . $ page [ ' id ' ], useHeading ( ' navigation ' ) ? null : noNS ( $ page [ ' id ' ] ) ) . ' ( ' . $ dist_prefix . $ page [ ' distance ' ] . ' m) ' . $ page [ ' description ' ] . ' </li> ' . DOKU_LF ;
206
194
}
207
- // TODO convert geohash to lat/lon
208
- print '<h1>Geohash: ' . str_replace ( '_ ' , ' ' , $ _REQUEST ['geohash ' ] ) . ' (lat,lon: ' . $ location . ')</h1> ' . DOKU_LF ;
209
- print '<div class="level1"> ' . DOKU_LF ;
210
- print $ pagelist ->finishList ();
195
+ $ pagelist .= '</ol> ' . DOKU_LF ;
196
+
197
+ print '<h2> ' . $ this ->getLang ('results_pages ' ) . hsc ( ' lat,lon: ' . $ location . ' (geohash: ' . $ geohash . ') ' ) . '</h2> ' ;
198
+ print '<div class="level2"> ' . DOKU_LF ;
199
+ print $ pagelist ;
200
+ print "<p>Precision: $ precision m</p> \n" ;
211
201
print '</div> ' . DOKU_LF ;
212
202
} else {
213
- print '<div class="level1"><p> ' . $ lang ['nothingfound ' ] . '</p></div> ' ;
203
+ print '<p> ' . hsc ( $ this ->getLang ('nothingfound ' ) ) . '</p> ' ;
204
+ }
205
+ if (! empty ( $ media )) {
206
+ $ pagelist = '<ol> ' . DOKU_LF ;
207
+ foreach ( $ media as $ m ) {
208
+ $ opts = array ();
209
+ $ link = ml ( $ m ['id ' ], $ opts , false , '& ' , false );
210
+ $ opts ['w ' ] = '100px ' ;
211
+ $ src = ml ( $ m ['id ' ], $ opts );
212
+ $ pagelist .= '<li><a href=" ' . $ link . '"><img src=" ' . $ src . '"></a> ( ' . $ dist_prefix . $ page ['distance ' ] . 'm) </li> ' . DOKU_LF ;
213
+ }
214
+ $ pagelist .= '</ol> ' . DOKU_LF ;
215
+
216
+ print '<h2> ' . $ this ->getLang ('results_media ' ) . hsc ( ' lat,lon: ' . $ location . ' (geohash: ' . $ geohash . ') ' ) . '</h2> ' . DOKU_LF ;
217
+ print '<div class="level2"> ' . DOKU_LF ;
218
+ print $ pagelist ;
219
+ print "<p>Precision: $ precision m</p> \n" ;
220
+ print '</div> ' . DOKU_LF ;
214
221
}
222
+ print '</div> ' . DOKU_LF ;
215
223
}
224
+ /**
225
+ * add media to spatial index.
226
+ *
227
+ * @param Doku_Event $event
228
+ * event object by reference
229
+ * @param unknown $param
230
+ */
216
231
function _handle_media_uploaded (Doku_Event &$ event , $ param ) {
217
- /*
218
- * data[0] temporary file name (read from $_FILES)
219
- * data[1] file name of the file being uploaded
220
- * data[2] future directory id of the file being uploaded
221
- * data[3] the mime type of the file being uploaded
222
- * data[4] true if the uploaded file exists already
223
- * data[5] (since 2011-02-06) the PHP function used to move the file to the correct location
224
- */
232
+ // data[0] temporary file name (read from $_FILES)
233
+ // data[1] file name of the file being uploaded
234
+ // data[2] future directory id of the file being uploaded
235
+ // data[3] the mime type of the file being uploaded
236
+ // data[4] true if the uploaded file exists already
237
+ // data[5] (since 2011-02-06) the PHP function used to move the file to the correct location
238
+ dbglog ( $ event ->data , "_handle_media_uploaded::event data " );
225
239
226
240
// check the list of mimetypes
227
241
// if it's a supported type call appropriate index function
228
- dbglog ( "checking uploaded media with mimetype " . $ event ->data [3 ] );
229
- dbglog ( $ event ->data , "_handle_media_uploaded::event data " );
230
- // if(stristr('image/',$event->data[3])){
231
- if (substr_compare ( $ event ->data [3 ], 'image/jpeg ' , 0 ))
232
- // TODO add image/tiff
233
- {
234
-
242
+ if (substr_compare ( $ event ->data [3 ], 'image/jpeg ' , 0 )) {
235
243
$ indexer = plugin_load ( 'helper ' , 'spatialhelper_index ' );
236
244
if ($ indexer ) {
237
- dbglog ( "Loaded helper spatialhelper_index. " );
238
245
$ indexer ->indexImage ( $ event ->data [2 ], $ event ->data [1 ] );
239
246
}
240
247
}
248
+ // TODO add image/tiff
241
249
// TODO kml, gpx, geojson...
242
250
}
243
251
244
252
/**
245
253
* removes the media from the index.
246
254
*/
247
255
function _handle_media_deleted (Doku_Event &$ event , $ param ) {
248
- /*
249
- * data['id'] ID
250
- * data['unl'] unlink return code
251
- * data['del'] Namespace directory unlink return code
252
- * data['name'] file name
253
- * data['path'] full path to the file
254
- * data['size'] file size
255
- */
256
+ // data['id'] ID data['unl'] unlink return code
257
+ // data['del'] Namespace directory unlink return code
258
+ // data['name'] file name data['path'] full path to the file
259
+ // data['size'] file size
256
260
dbglog ( $ event ->data , "_handle_media_deleted::event data " );
257
- $ id = $ event -> data [ ' id ' ];
258
- // remove the id from the index
261
+
262
+ // remove the media id from the index
259
263
$ indexer = plugin_load ( 'helper ' , 'spatialhelper_index ' );
260
264
if ($ indexer ) {
261
- dbglog ( "Loaded helper spatialhelper_index. Deleting media $ id from index " );
262
- $ indexer ->deleteFromIndex ( $ id );
265
+ $ indexer ->deleteFromIndex ( 'media__ ' . $ event ->data ['id ' ] );
263
266
}
264
267
}
268
+
269
+ /**
270
+ * Calculate a new coordinate based on start, distance and bearing
271
+ *
272
+ * @param $start array
273
+ * - start coordinate as decimal lat/lon pair
274
+ * @param $dist float
275
+ * - distance in kilometers
276
+ * @param $brng float
277
+ * - bearing in degrees (compass direction)
278
+ */
279
+ private function _geo_destination ($ start , $ dist , $ brng ) {
280
+ $ lat1 = _toRad ( $ start [0 ] );
281
+ $ lon1 = _toRad ( $ start [1 ] );
282
+ // http://en.wikipedia.org/wiki/Earth_radius
283
+ // average earth radius in km
284
+ $ dist = $ dist / 6371.01 ;
285
+ $ brng = _toRad ( $ brng );
286
+
287
+ $ lon2 = $ lon1 + atan2 ( sin ( $ brng ) * sin ( $ dist ) * cos ( $ lat1 ), cos ( $ dist ) - sin ( $ lat1 ) * sin ( $ lat2 ) );
288
+ $ lon2 = fmod ( ($ lon2 + 3 * pi ()), (2 * pi ()) ) - pi ();
289
+
290
+ return array (
291
+ _toDeg ( $ lat2 ),
292
+ _toDeg ( $ lon2 )
293
+ );
294
+ }
295
+ private function _toRad ($ deg ) {
296
+ return $ deg * pi () / 180 ;
297
+ }
298
+ private function _toDeg ($ rad ) {
299
+ return $ rad * 180 / pi ();
300
+ }
265
301
}
0 commit comments