1bd120a73SMark C. Prins<?php 2bd120a73SMark C. Prins/* 3e48b49c1SMark Prins * Copyright (c) 2011-2020 Mark C. Prins <mprins@users.sf.net> 4bd120a73SMark C. Prins * 5bd120a73SMark C. Prins * Permission to use, copy, modify, and distribute this software for any 6bd120a73SMark C. Prins * purpose with or without fee is hereby granted, provided that the above 7bd120a73SMark C. Prins * copyright notice and this permission notice appear in all copies. 8bd120a73SMark C. Prins * 9bd120a73SMark C. Prins * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10bd120a73SMark C. Prins * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11bd120a73SMark C. Prins * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12bd120a73SMark C. Prins * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13bd120a73SMark C. Prins * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14bd120a73SMark C. Prins * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15bd120a73SMark C. Prins * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16bd120a73SMark C. Prins */ 17e48b49c1SMark Prins 18e48b49c1SMark Prinsuse dokuwiki\Sitemap\Item; 19bd120a73SMark C. Prins 20a9441f7dSMark C. Prins/** 21a9441f7dSMark C. Prins * DokuWiki Plugin dokuwikispatial (Action Component). 22a9441f7dSMark C. Prins * 23a9441f7dSMark C. Prins * @license BSD license 24a9441f7dSMark C. Prins * @author Mark C. Prins <mprins@users.sf.net> 25a9441f7dSMark C. Prins */ 26bd120a73SMark C. Prinsclass action_plugin_spatialhelper extends DokuWiki_Action_Plugin { 27bd120a73SMark C. Prins 28bd120a73SMark C. Prins /** 29bd120a73SMark C. Prins * Register for events. 30bd120a73SMark C. Prins * 31a9441f7dSMark C. Prins * @param Doku_Event_Handler $controller 32a9441f7dSMark C. Prins * DokuWiki's event controller object. Also available as global $EVENT_HANDLER 33bd120a73SMark C. Prins */ 3436e7539bSMark C. Prins public function register(Doku_Event_Handler $controller) { 357c452997SMark C. Prins // listen for page add / delete events 36bd120a73SMark C. Prins // http://www.dokuwiki.org/devel:event:indexer_page_add 37*817f8be5SMark Prins $controller->register_hook('INDEXER_PAGE_ADD', 'BEFORE', $this, 'handleIndexerPageAdd'); 38*817f8be5SMark Prins $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'removeFromIndex'); 39a9441f7dSMark C. Prins 40bd120a73SMark C. Prins // http://www.dokuwiki.org/devel:event:sitemap_generate 41*817f8be5SMark Prins $controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handleSitemapGenerateBefore'); 427c452997SMark C. Prins // using after will only trigger us if a sitemap was actually created 43*817f8be5SMark Prins $controller->register_hook('SITEMAP_GENERATE', 'AFTER', $this, 'handleSitemapGenerateAfter'); 447c452997SMark C. Prins 45a9441f7dSMark C. Prins // handle actions we know of 46*817f8be5SMark Prins $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleActionActPreprocess', array()); 47f8fde0daSMark C. Prins // handle HTML eg. /dokuwiki/doku.php?id=start&do=findnearby&geohash=u15vk4 48*817f8be5SMark Prins $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'findnearby', array( 493e83b370SMark C. Prins 'format' => 'HTML' 503e83b370SMark C. Prins )); 51f8fde0daSMark C. Prins // handles AJAX/json eg: jQuery.post("/dokuwiki/lib/exe/ajax.php?id=start&call=findnearby&geohash=u15vk4"); 52*817f8be5SMark Prins $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'findnearby', array( 533e83b370SMark C. Prins 'format' => 'JSON' 543e83b370SMark C. Prins )); 557c452997SMark C. Prins 56a9441f7dSMark C. Prins // listen for media uploads and deletes 57*817f8be5SMark Prins $controller->register_hook('MEDIA_UPLOAD_FINISH', 'BEFORE', $this, 'handleMediaUploaded', array()); 58*817f8be5SMark Prins $controller->register_hook('MEDIA_DELETE_FILE', 'BEFORE', $this, 'handleMediaDeleted', array()); 5902c45c98SMark C. Prins 60*817f8be5SMark Prins $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleMetaheaderOutput'); 61bd120a73SMark C. Prins } 62bd120a73SMark C. Prins 63bd120a73SMark C. Prins /** 64bd120a73SMark C. Prins * Update the spatial index for the page. 65a9441f7dSMark C. Prins * 66a9441f7dSMark C. Prins * @param Doku_Event $event 67a9441f7dSMark C. Prins * event object by reference 68a9441f7dSMark C. Prins * @param object $param 69a9441f7dSMark C. Prins * the parameters passed to register_hook when this handler was registered 70bd120a73SMark C. Prins */ 71*817f8be5SMark Prins public function handleIndexerPageAdd(Doku_Event $event, $param) { 727c452997SMark C. Prins // $event→data['page'] – the page id 737c452997SMark C. Prins // $event→data['body'] – empty, can be filled by additional content to index by your plugin 74*817f8be5SMark Prins // $event→data['metadata'] – the metadata that shall be indexed. This is an array where the keys are the 75*817f8be5SMark Prins // metadata indexes and the value a string or an array of strings with the values. 76*817f8be5SMark Prins // title and relation_references will already be set. 779af1cdd4SMark C. Prins $id = $event->data ['page']; 7802c45c98SMark C. Prins $indexer = & plugin_load('helper', 'spatialhelper_index'); 79bd120a73SMark C. Prins $entries = $indexer->updateSpatialIndex($id); 80bd120a73SMark C. Prins } 81bd120a73SMark C. Prins 82bd120a73SMark C. Prins /** 8334fb1e15SMark C. Prins * Update the spatial index, removing the page. 84a9441f7dSMark C. Prins * 85a9441f7dSMark C. Prins * @param Doku_Event $event 86a9441f7dSMark C. Prins * event object by reference 87a9441f7dSMark C. Prins * @param object $param 88a9441f7dSMark C. Prins * the parameters passed to register_hook when this handler was registered 8934fb1e15SMark C. Prins */ 90*817f8be5SMark Prins public function removeFromIndex(Doku_Event & $event, $param) { 917c452997SMark C. Prins // event data: 927c452997SMark C. Prins // $data[0] – The raw arguments for io_saveFile as an array. Do not change file path. 937c452997SMark C. Prins // $data[0][0] – the file path. 947c452997SMark C. Prins // $data[0][1] – the content to be saved, and may be modified. 957c452997SMark C. Prins // $data[1] – ns: The colon separated namespace path minus the trailing page name. (false if root ns) 967c452997SMark C. Prins // $data[2] – page_name: The wiki page name. 977c452997SMark C. Prins // $data[3] – rev: The page revision, false for current wiki pages. 987c452997SMark C. Prins 99*817f8be5SMark Prins dbglog($event->data, "Event data in removeFromIndex."); 10034fb1e15SMark C. Prins if (@file_exists($event->data [0] [0])) { 10134fb1e15SMark C. Prins // file not new 10234fb1e15SMark C. Prins if (!$event->data [0] [1]) { 10334fb1e15SMark C. Prins // file is empty, page is being deleted 10434fb1e15SMark C. Prins if (empty ($event->data [1])) { 10534fb1e15SMark C. Prins // root namespace 10634fb1e15SMark C. Prins $id = $event->data [2]; 10734fb1e15SMark C. Prins } else { 10834fb1e15SMark C. Prins $id = $event->data [1] . ":" . $event->data [2]; 10934fb1e15SMark C. Prins } 11002c45c98SMark C. Prins $indexer = & plugin_load('helper', 'spatialhelper_index'); 11134fb1e15SMark C. Prins if ($indexer) { 11234fb1e15SMark C. Prins $indexer->deleteFromIndex($id); 11334fb1e15SMark C. Prins } 11434fb1e15SMark C. Prins } 11534fb1e15SMark C. Prins } 11634fb1e15SMark C. Prins } 11734fb1e15SMark C. Prins 11834fb1e15SMark C. Prins /** 11902c45c98SMark C. Prins * Add a new SitemapItem object that points to the KML of public geocoded pages. 12002c45c98SMark C. Prins * 12102c45c98SMark C. Prins * @param Doku_Event $event 12202c45c98SMark C. Prins * @param unknown $param 12302c45c98SMark C. Prins */ 124*817f8be5SMark Prins public function handleSitemapGenerateBefore(Doku_Event $event, $param) { 12500e20e07SMark C. Prins $path = mediaFN($this->getConf('media_kml')); 12602c45c98SMark C. Prins $lastmod = @filemtime($path); 127e48b49c1SMark Prins $event->data ['items'] [] = new Item(ml($this->getConf('media_kml'), '', true, '&', true), $lastmod); 128*817f8be5SMark Prins //dbglog($event->data ['items'], 129*817f8be5SMark Prins // "Added a new SitemapItem object that points to the KML of public geocoded pages."); 13002c45c98SMark C. Prins } 13102c45c98SMark C. Prins 13202c45c98SMark C. Prins /** 133a9441f7dSMark C. Prins * Create a spatial sitemap or attach the geo/kml map to the sitemap. 134a9441f7dSMark C. Prins * 135a9441f7dSMark C. Prins * @param Doku_Event $event 1363e83b370SMark C. Prins * event object by reference, not used 137a9441f7dSMark C. Prins * @param mixed $param 1383e83b370SMark C. Prins * parameter array, not used 139bd120a73SMark C. Prins */ 140*817f8be5SMark Prins public function handleSitemapGenerateAfter(Doku_Event $event, $param) { 141*817f8be5SMark Prins // $event→data['items']: Array of SitemapItem instances, the array of sitemap items that already 142*817f8be5SMark Prins // contains all public pages of the wiki 1437c452997SMark C. Prins // $event→data['sitemap']: The path of the file the sitemap will be saved to. 14402c45c98SMark C. Prins if ($helper = & plugin_load('helper', 'spatialhelper_sitemap')) { 14596c9e758SMark Prins // dbglog($helper, "createSpatialSitemap loaded helper."); 14602c45c98SMark C. Prins 147f2601b07SMark C. Prins $kml = $helper->createKMLSitemap($this->getConf('media_kml')); 148f2601b07SMark C. Prins $rss = $helper->createGeoRSSSitemap($this->getConf('media_georss')); 14902c45c98SMark C. Prins 15096c9e758SMark Prins if (!empty ($this->getConf('sitemap_namespaces'))) { 15196c9e758SMark Prins $namespaces = array_map('trim', explode("\n", $this->getConf('sitemap_namespaces'))); 15296c9e758SMark Prins foreach ($namespaces as $namespace) { 15396c9e758SMark Prins $kmlN = $helper->createKMLSitemap($namespace . $this->getConf('media_kml')); 15496c9e758SMark Prins $rssN = $helper->createGeoRSSSitemap($namespace . $this->getConf('media_georss')); 155*817f8be5SMark Prins dbglog( 156*817f8be5SMark Prins $kmlN && $rssN, 157*817f8be5SMark Prins "handleSitemapGenerateAfter, created KML / GeoRSS sitemap in $namespace, succes: " 158*817f8be5SMark Prins ); 15996c9e758SMark Prins } 16096c9e758SMark Prins } 16102c45c98SMark C. Prins return $kml && $rss; 16202c45c98SMark C. Prins } else { 16316d69598SMark Prins dbglog($helper, "createSpatialSitemap NOT loaded helper."); 16402c45c98SMark C. Prins } 1659af1cdd4SMark C. Prins } 1669af1cdd4SMark C. Prins 1679af1cdd4SMark C. Prins /** 1689af1cdd4SMark C. Prins * trap findnearby action. 16902c45c98SMark C. Prins * This addional handler is required as described at: https://www.dokuwiki.org/devel:event:tpl_act_unknown 170a9441f7dSMark C. Prins * 171a9441f7dSMark C. Prins * @param Doku_Event $event 172a9441f7dSMark C. Prins * event object by reference 173a9441f7dSMark C. Prins * @param mixed $param 174a9441f7dSMark C. Prins * not used 1759af1cdd4SMark C. Prins */ 176*817f8be5SMark Prins public function handleActionActPreprocess(Doku_Event $event, $param) { 1775fe9bc3cSScrutinizer Auto-Fixer if ($event->data != 'findnearby') { 178a9441f7dSMark C. Prins return; 1795fe9bc3cSScrutinizer Auto-Fixer } 1809af1cdd4SMark C. Prins $event->preventDefault(); 1819af1cdd4SMark C. Prins } 1829af1cdd4SMark C. Prins 1839af1cdd4SMark C. Prins /** 1849af1cdd4SMark C. Prins * handle findnearby action. 185a9441f7dSMark C. Prins * 186a9441f7dSMark C. Prins * @param Doku_Event $event 187a9441f7dSMark C. Prins * event object by reference 188e4020312SMark C. Prins * @param mixed $param 189e4020312SMark C. Prins * associative array with keys 1909bb9b388SMark C. Prins * 'format'=> HTML | JSON 1919af1cdd4SMark C. Prins */ 192*817f8be5SMark Prins public function findnearby(Doku_Event & $event, $param) { 1935fe9bc3cSScrutinizer Auto-Fixer if ($event->data != 'findnearby') { 194a9441f7dSMark C. Prins return; 1955fe9bc3cSScrutinizer Auto-Fixer } 1969af1cdd4SMark C. Prins $event->preventDefault(); 1979af1cdd4SMark C. Prins 1987c452997SMark C. Prins global $INPUT; 1999af1cdd4SMark C. Prins if ($helper = & plugin_load('helper', 'spatialhelper_search')) { 200fd140697SMark C. Prins if ($INPUT->has('lat') && $INPUT->has('lon')) { 2017c452997SMark C. Prins $results = $helper->findNearbyLatLon($INPUT->param('lat'), $INPUT->param('lon')); 202fd140697SMark C. Prins } elseif ($INPUT->has('geohash')) { 203fd140697SMark C. Prins $results = $helper->findNearby($INPUT->str('geohash')); 2047c452997SMark C. Prins } else { 2053e83b370SMark C. Prins $results = array( 2063e83b370SMark C. Prins 'error' => hsc($this->getLang('invalidinput')) 2073e83b370SMark C. Prins ); 2089af1cdd4SMark C. Prins } 2099af1cdd4SMark C. Prins } 2109af1cdd4SMark C. Prins 2113e83b370SMark C. Prins $showMedia = $INPUT->bool('showMedia', true); 2123e83b370SMark C. Prins 213f8fde0daSMark C. Prins switch ($param['format']) { 2143e83b370SMark C. Prins case 'JSON' : 2153e83b370SMark C. Prins $this->printJSON($results); 2163e83b370SMark C. Prins break; 2173e83b370SMark C. Prins case 'HTML' : 2189892789dSMark C. Prins // fall through to default 2193e83b370SMark C. Prins default : 2203e83b370SMark C. Prins $this->printHTML($results, $showMedia); 2213e83b370SMark C. Prins break; 2223e83b370SMark C. Prins } 2233e83b370SMark C. Prins } 2243e83b370SMark C. Prins 2253e83b370SMark C. Prins /** 2263e83b370SMark C. Prins * Print seachresults as HTML lists. 2273e83b370SMark C. Prins * 2283e83b370SMark C. Prins * @param array $searchresults 2293e83b370SMark C. Prins */ 2303e83b370SMark C. Prins private function printJSON($searchresults) { 2313e83b370SMark C. Prins require_once DOKU_INC . 'inc/JSON.php'; 2323e83b370SMark C. Prins $json = new JSON(); 2333e83b370SMark C. Prins header('Content-Type: application/json'); 2343e83b370SMark C. Prins print $json->encode($searchresults); 2353e83b370SMark C. Prins } 2363e83b370SMark C. Prins 2373e83b370SMark C. Prins /** 2383e83b370SMark C. Prins * Print seachresults as HTML lists. 2393e83b370SMark C. Prins * 2403e83b370SMark C. Prins * @param array $searchresults 2413e83b370SMark C. Prins * @param boolean $showMedia 2423e83b370SMark C. Prins */ 2433e83b370SMark C. Prins private function printHTML($searchresults, $showMedia = true) { 2443e83b370SMark C. Prins $pages = (array) ($searchresults ['pages']); 2453e83b370SMark C. Prins $media = (array) $searchresults ['media']; 246594a0ef1SMark C. Prins $lat = (float) $searchresults ['lat']; 247594a0ef1SMark C. Prins $lon = (float) $searchresults ['lon']; 2483e83b370SMark C. Prins $geohash = (string) $searchresults ['geohash']; 2493e83b370SMark C. Prins 2503e83b370SMark C. Prins if (isset ($searchresults ['error'])) { 2513e83b370SMark C. Prins print '<div class="level1"><p>' . hsc($results ['error']) . '</p></div>'; 2523e83b370SMark C. Prins return; 2533e83b370SMark C. Prins } 2543e83b370SMark C. Prins 2553e83b370SMark C. Prins // print a HTML list 2567c452997SMark C. Prins print '<h1>' . $this->getLang('results_header') . '</h1>' . DOKU_LF; 2579af1cdd4SMark C. Prins print '<div class="level1">' . DOKU_LF; 2587c452997SMark C. Prins if (!empty ($pages)) { 2597c452997SMark C. Prins $pagelist = '<ol>' . DOKU_LF; 2607c452997SMark C. Prins foreach ($pages as $page) { 261*817f8be5SMark Prins $pagelist .= '<li>' . html_wikilink(':' . $page ['id'], useHeading('navigation') ? null : 262*817f8be5SMark Prins noNS($page ['id'])) . ' (' . $this->getLang('results_distance_prefix') 263*817f8be5SMark Prins . $page ['distance'] . ' m) ' . $page ['description'] . '</li>' . DOKU_LF; 2647c452997SMark C. Prins } 2657c452997SMark C. Prins $pagelist .= '</ol>' . DOKU_LF; 2667c452997SMark C. Prins 267*817f8be5SMark Prins print '<h2>' . $this->getLang('results_pages') . hsc(' lat;lon: ' . $lat . ';' . $lon 268*817f8be5SMark Prins . ' (geohash: ' . $geohash . ')') . '</h2>'; 2697c452997SMark C. Prins print '<div class="level2">' . DOKU_LF; 2707c452997SMark C. Prins print $pagelist; 2719af1cdd4SMark C. Prins print '</div>' . DOKU_LF; 2729af1cdd4SMark C. Prins } else { 2737c452997SMark C. Prins print '<p>' . hsc($this->getLang('nothingfound')) . '</p>'; 2749af1cdd4SMark C. Prins } 275e4020312SMark C. Prins 2763e83b370SMark C. Prins if (!empty ($media) && $showMedia) { 2777c452997SMark C. Prins $pagelist = '<ol>' . DOKU_LF; 2787c452997SMark C. Prins foreach ($media as $m) { 2797c452997SMark C. Prins $opts = array(); 2807c452997SMark C. Prins $link = ml($m ['id'], $opts, false, '&', false); 2819bb9b388SMark C. Prins $opts ['w'] = '100'; 2827c452997SMark C. Prins $src = ml($m ['id'], $opts); 283*817f8be5SMark Prins $pagelist .= '<li><a href="' . $link . '"><img src="' . $src . '"></a> (' 284*817f8be5SMark Prins . $this->getLang('results_distance_prefix') . $page ['distance'] . ' m) ' . hsc($desc) 285*817f8be5SMark Prins . '</li>' . DOKU_LF; 286bd120a73SMark C. Prins } 2877c452997SMark C. Prins $pagelist .= '</ol>' . DOKU_LF; 2887c452997SMark C. Prins 289*817f8be5SMark Prins print '<h2>' . $this->getLang('results_media') . hsc(' lat;lon: ' . $lat . ';' . $lon 290*817f8be5SMark Prins . ' (geohash: ' . $geohash . ')') . '</h2>' . DOKU_LF; 2917c452997SMark C. Prins print '<div class="level2">' . DOKU_LF; 2927c452997SMark C. Prins print $pagelist; 2937c452997SMark C. Prins print '</div>' . DOKU_LF; 2947c452997SMark C. Prins } 295594a0ef1SMark C. Prins print '<p>' . $this->getLang('results_precision') . $searchresults ['precision'] . ' m. '; 296594a0ef1SMark C. Prins if (strlen($geohash) > 1) { 297594a0ef1SMark C. Prins $url = wl(getID(), array( 298594a0ef1SMark C. Prins 'do' => 'findnearby', 299594a0ef1SMark C. Prins 'geohash' => substr($geohash, 0, - 1) 3009892789dSMark C. Prins )); 301*817f8be5SMark Prins print '<a href="' . $url . '" class="findnearby">' . $this->getLang('search_largerarea') . '</a>.</p>' 302*817f8be5SMark Prins . DOKU_LF; 303594a0ef1SMark C. Prins } 3047c452997SMark C. Prins print '</div>' . DOKU_LF; 3057c452997SMark C. Prins } 3063e83b370SMark C. Prins 3077c452997SMark C. Prins /** 3087c452997SMark C. Prins * add media to spatial index. 3097c452997SMark C. Prins * 3107c452997SMark C. Prins * @param Doku_Event $event 3117c452997SMark C. Prins * event object by reference 3127c452997SMark C. Prins * @param unknown $param 313a9441f7dSMark C. Prins */ 314*817f8be5SMark Prins public function handleMediaUploaded(Doku_Event & $event, $param) { 3157c452997SMark C. Prins // data[0] temporary file name (read from $_FILES) 3167c452997SMark C. Prins // data[1] file name of the file being uploaded 3177c452997SMark C. Prins // data[2] future directory id of the file being uploaded 3187c452997SMark C. Prins // data[3] the mime type of the file being uploaded 3197c452997SMark C. Prins // data[4] true if the uploaded file exists already 3207c452997SMark C. Prins // data[5] (since 2011-02-06) the PHP function used to move the file to the correct location 32102c45c98SMark C. Prins 322*817f8be5SMark Prins dbglog($event->data, "handleMediaUploaded::event data"); 323a9441f7dSMark C. Prins 324a9441f7dSMark C. Prins // check the list of mimetypes 325a9441f7dSMark C. Prins // if it's a supported type call appropriate index function 3267c452997SMark C. Prins if (substr_compare($event->data [3], 'image/jpeg', 0)) { 327a9441f7dSMark C. Prins $indexer = plugin_load('helper', 'spatialhelper_index'); 328a9441f7dSMark C. Prins if ($indexer) { 329a9441f7dSMark C. Prins $indexer->indexImage($event->data [2], $event->data [1]); 330a9441f7dSMark C. Prins } 331a9441f7dSMark C. Prins } 3327c452997SMark C. Prins // TODO add image/tiff 333a9441f7dSMark C. Prins // TODO kml, gpx, geojson... 334a9441f7dSMark C. Prins } 335a9441f7dSMark C. Prins 336a9441f7dSMark C. Prins /** 337a9441f7dSMark C. Prins * removes the media from the index. 338a9441f7dSMark C. Prins */ 339*817f8be5SMark Prins public function handleMediaDeleted(Doku_Event & $event, $param) { 3407c452997SMark C. Prins // data['id'] ID data['unl'] unlink return code 3417c452997SMark C. Prins // data['del'] Namespace directory unlink return code 3427c452997SMark C. Prins // data['name'] file name data['path'] full path to the file 3437c452997SMark C. Prins // data['size'] file size 34402c45c98SMark C. Prins 345*817f8be5SMark Prins dbglog($event->data, "handleMediaDeleted::event data"); 3467c452997SMark C. Prins 3477c452997SMark C. Prins // remove the media id from the index 34802c45c98SMark C. Prins $indexer = & plugin_load('helper', 'spatialhelper_index'); 349a9441f7dSMark C. Prins if ($indexer) { 3507c452997SMark C. Prins $indexer->deleteFromIndex('media__' . $event->data ['id']); 351a9441f7dSMark C. Prins } 352a9441f7dSMark C. Prins } 3537c452997SMark C. Prins 3547c452997SMark C. Prins /** 35502c45c98SMark C. Prins * add a link to the spatial sitemap files in the header. 35602c45c98SMark C. Prins * 35702c45c98SMark C. Prins * @param Doku_Event $event 35802c45c98SMark C. Prins * the DokuWiki event. $event->data is a two-dimensional 35902c45c98SMark C. Prins * array of all meta headers. The keys are meta, link and script. 36002c45c98SMark C. Prins * @param unknown_type $param 36102c45c98SMark C. Prins * 36202c45c98SMark C. Prins * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output 36302c45c98SMark C. Prins */ 364*817f8be5SMark Prins public function handleMetaheaderOutput(Doku_Event $event, $param) { 36502c45c98SMark C. Prins // TODO maybe test for exist 36602c45c98SMark C. Prins $event->data ["link"] [] = array( 36702c45c98SMark C. Prins "type" => "application/atom+xml", 36802c45c98SMark C. Prins "rel" => "alternate", 36900e20e07SMark C. Prins "href" => ml($this->getConf('media_georss')), 37002c45c98SMark C. Prins "title" => "Spatial ATOM Feed" 37102c45c98SMark C. Prins ); 37202c45c98SMark C. Prins $event->data ["link"] [] = array( 37302c45c98SMark C. Prins "type" => "application/vnd.google-earth.kml+xml", 37402c45c98SMark C. Prins "rel" => "alternate", 37500e20e07SMark C. Prins "href" => ml($this->getConf('media_kml')), 37602c45c98SMark C. Prins "title" => "KML Sitemap" 37702c45c98SMark C. Prins ); 37802c45c98SMark C. Prins } 37902c45c98SMark C. Prins 38002c45c98SMark C. Prins /** 3817c452997SMark C. Prins * Calculate a new coordinate based on start, distance and bearing 3827c452997SMark C. Prins * 3837c452997SMark C. Prins * @param $start array 3847c452997SMark C. Prins * - start coordinate as decimal lat/lon pair 3857c452997SMark C. Prins * @param $dist float 3867c452997SMark C. Prins * - distance in kilometers 3877c452997SMark C. Prins * @param $brng float 3887c452997SMark C. Prins * - bearing in degrees (compass direction) 3897c452997SMark C. Prins */ 390*817f8be5SMark Prins private function geoDestination($start, $dist, $brng) { 391*817f8be5SMark Prins $lat1 = toRad($start [0]); 392*817f8be5SMark Prins $lon1 = toRad($start [1]); 3937c452997SMark C. Prins // http://en.wikipedia.org/wiki/Earth_radius 3947c452997SMark C. Prins // average earth radius in km 3957c452997SMark C. Prins $dist = $dist / 6371.01; 396*817f8be5SMark Prins $brng = toRad($brng); 3977c452997SMark C. Prins 3987c452997SMark C. Prins $lon2 = $lon1 + atan2(sin($brng) * sin($dist) * cos($lat1), cos($dist) - sin($lat1) * sin($lat2)); 3997c452997SMark C. Prins $lon2 = fmod(($lon2 + 3 * pi()), (2 * pi())) - pi(); 4007c452997SMark C. Prins 4017c452997SMark C. Prins return array( 402*817f8be5SMark Prins toDeg($lat2), 403*817f8be5SMark Prins toDeg($lon2) 4047c452997SMark C. Prins ); 4057c452997SMark C. Prins } 406*817f8be5SMark Prins private function toRad($deg) { 4077c452997SMark C. Prins return $deg * pi() / 180; 4087c452997SMark C. Prins } 409*817f8be5SMark Prins private function toDeg($rad) { 4107c452997SMark C. Prins return $rad * 180 / pi(); 4117c452997SMark C. Prins } 412bd120a73SMark C. Prins} 413