1bd120a73SMark C. Prins<?php 2bd120a73SMark C. Prins/* 3a9441f7dSMark C. Prins * Copyright (c) 2011-2014 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 */ 17a9441f7dSMark C. Prinsif (! defined ( 'DOKU_INC' )) 18a9441f7dSMark C. Prins die (); 19a9441f7dSMark C. Prinsif (! defined ( 'DOKU_PLUGIN' )) 20a9441f7dSMark C. Prins define ( 'DOKU_PLUGIN', DOKU_INC . 'lib/plugins/' ); 217c452997SMark C. Prinsif (! defined ( 'DOKU_LF' )) 227c452997SMark C. Prins define ( 'DOKU_LF', "\n" ); 23bd120a73SMark C. Prinsrequire_once (DOKU_PLUGIN . 'action.php'); 24bd120a73SMark C. Prins 25a9441f7dSMark C. Prins/** 26a9441f7dSMark C. Prins * DokuWiki Plugin dokuwikispatial (Action Component). 27a9441f7dSMark C. Prins * 28a9441f7dSMark C. Prins * @license BSD license 29a9441f7dSMark C. Prins * @author Mark C. Prins <mprins@users.sf.net> 30a9441f7dSMark C. Prins */ 31bd120a73SMark C. Prinsclass action_plugin_spatialhelper extends DokuWiki_Action_Plugin { 32bd120a73SMark C. Prins 33bd120a73SMark C. Prins /** 34bd120a73SMark C. Prins * Register for events. 35bd120a73SMark C. Prins * 36a9441f7dSMark C. Prins * @param Doku_Event_Handler $controller 37a9441f7dSMark C. Prins * DokuWiki's event controller object. Also available as global $EVENT_HANDLER 38bd120a73SMark C. Prins */ 39bd120a73SMark C. Prins public function register(Doku_Event_Handler &$controller) { 407c452997SMark C. Prins // listen for page add / delete events 41bd120a73SMark C. Prins // http://www.dokuwiki.org/devel:event:indexer_page_add 4202c45c98SMark C. Prins $controller->register_hook ( 'INDEXER_PAGE_ADD', 'BEFORE', $this, 'handle_indexer_page_add' ); 4334fb1e15SMark C. Prins $controller->register_hook ( 'IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_removeFromIndex' ); 44a9441f7dSMark C. Prins 45bd120a73SMark C. Prins // http://www.dokuwiki.org/devel:event:sitemap_generate 4602c45c98SMark C. Prins $controller->register_hook ( 'SITEMAP_GENERATE', 'BEFORE', $this, 'handle_sitemap_generate_before' ); 477c452997SMark C. Prins // using after will only trigger us if a sitemap was actually created 4802c45c98SMark C. Prins $controller->register_hook ( 'SITEMAP_GENERATE', 'AFTER', $this, 'handle_sitemap_generate_after' ); 497c452997SMark C. Prins 50a9441f7dSMark C. Prins // handle actions we know of 5102c45c98SMark C. Prins $controller->register_hook ( 'ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_preprocess', array () ); 523e83b370SMark C. Prins $controller->register_hook ( 'TPL_ACT_UNKNOWN', 'BEFORE', $this, '_findnearby', array ( 533e83b370SMark C. Prins 'format' => 'HTML' 543e83b370SMark C. Prins ) ); 553e83b370SMark C. Prins 563e83b370SMark C. Prins $controller->register_hook ( 'AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_findnearby', array ( 573e83b370SMark C. Prins 'format' => 'JSON' 583e83b370SMark C. Prins ) ); 597c452997SMark C. Prins 60a9441f7dSMark C. Prins // listen for media uploads and deletes 61a9441f7dSMark C. Prins $controller->register_hook ( 'MEDIA_UPLOAD_FINISH', 'BEFORE', $this, '_handle_media_uploaded', array () ); 62a9441f7dSMark C. Prins $controller->register_hook ( 'MEDIA_DELETE_FILE', 'BEFORE', $this, '_handle_media_deleted', array () ); 6302c45c98SMark C. Prins 6402c45c98SMark C. Prins $controller->register_hook ( 'TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handle_metaheader_output' ); 65bd120a73SMark C. Prins } 66bd120a73SMark C. Prins 67bd120a73SMark C. Prins /** 68bd120a73SMark C. Prins * Update the spatial index for the page. 69a9441f7dSMark C. Prins * 70a9441f7dSMark C. Prins * @param Doku_Event $event 71a9441f7dSMark C. Prins * event object by reference 72a9441f7dSMark C. Prins * @param object $param 73a9441f7dSMark C. Prins * the parameters passed to register_hook when this handler was registered 74bd120a73SMark C. Prins */ 7502c45c98SMark C. Prins function handle_indexer_page_add(Doku_Event &$event, $param) { 767c452997SMark C. Prins // $event→data['page'] – the page id 777c452997SMark C. Prins // $event→data['body'] – empty, can be filled by additional content to index by your plugin 787c452997SMark C. Prins // $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. 799af1cdd4SMark C. Prins $id = $event->data ['page']; 8002c45c98SMark C. Prins $indexer = & plugin_load ( 'helper', 'spatialhelper_index' ); 81bd120a73SMark C. Prins $entries = $indexer->updateSpatialIndex ( $id ); 82bd120a73SMark C. Prins } 83bd120a73SMark C. Prins 84bd120a73SMark C. Prins /** 8534fb1e15SMark C. Prins * Update the spatial index, removing the page. 86a9441f7dSMark C. Prins * 87a9441f7dSMark C. Prins * @param Doku_Event $event 88a9441f7dSMark C. Prins * event object by reference 89a9441f7dSMark C. Prins * @param object $param 90a9441f7dSMark C. Prins * the parameters passed to register_hook when this handler was registered 9134fb1e15SMark C. Prins */ 9234fb1e15SMark C. Prins function _removeFromIndex(Doku_Event &$event, $param) { 937c452997SMark C. Prins // event data: 947c452997SMark C. Prins // $data[0] – The raw arguments for io_saveFile as an array. Do not change file path. 957c452997SMark C. Prins // $data[0][0] – the file path. 967c452997SMark C. Prins // $data[0][1] – the content to be saved, and may be modified. 977c452997SMark C. Prins // $data[1] – ns: The colon separated namespace path minus the trailing page name. (false if root ns) 987c452997SMark C. Prins // $data[2] – page_name: The wiki page name. 997c452997SMark C. Prins // $data[3] – rev: The page revision, false for current wiki pages. 1007c452997SMark C. Prins 10102c45c98SMark C. Prins // dbglog ( $event->data, "Event data in _removeFromIndex." ); 10234fb1e15SMark C. Prins if (@file_exists ( $event->data [0] [0] )) { 10334fb1e15SMark C. Prins // file not new 10434fb1e15SMark C. Prins if (! $event->data [0] [1]) { 10534fb1e15SMark C. Prins // file is empty, page is being deleted 10634fb1e15SMark C. Prins if (empty ( $event->data [1] )) { 10734fb1e15SMark C. Prins // root namespace 10834fb1e15SMark C. Prins $id = $event->data [2]; 10934fb1e15SMark C. Prins } else { 11034fb1e15SMark C. Prins $id = $event->data [1] . ":" . $event->data [2]; 11134fb1e15SMark C. Prins } 11202c45c98SMark C. Prins $indexer = & plugin_load ( 'helper', 'spatialhelper_index' ); 11334fb1e15SMark C. Prins if ($indexer) { 11434fb1e15SMark C. Prins $indexer->deleteFromIndex ( $id ); 11534fb1e15SMark C. Prins } 11634fb1e15SMark C. Prins } 11734fb1e15SMark C. Prins } 11834fb1e15SMark C. Prins } 11934fb1e15SMark C. Prins 12034fb1e15SMark C. Prins /** 12102c45c98SMark C. Prins * Add a new SitemapItem object that points to the KML of public geocoded pages. 12202c45c98SMark C. Prins * 12302c45c98SMark C. Prins * @param Doku_Event $event 12402c45c98SMark C. Prins * @param unknown $param 12502c45c98SMark C. Prins */ 12602c45c98SMark C. Prins function handle_sitemap_generate_before(Doku_Event &$event, $param) { 12700e20e07SMark C. Prins $path = mediaFN ( $this->getConf ( 'media_kml' ) ); 12802c45c98SMark C. Prins $lastmod = @filemtime ( $path ); 12900e20e07SMark C. Prins $event->data ['items'] [] = new SitemapItem ( ml ( $this->getConf ( 'media_kml' ), '', true, '&', true ), $lastmod ); 13002c45c98SMark C. Prins // dbglog ( $event->data ['items'], "Added a new SitemapItem object that points to the KML of public geocoded pages." ); 13102c45c98SMark C. Prins } 13202c45c98SMark C. Prins 13302c45c98SMark C. Prins /** 134a9441f7dSMark C. Prins * Create a spatial sitemap or attach the geo/kml map to the sitemap. 135a9441f7dSMark C. Prins * 136a9441f7dSMark C. Prins * @param Doku_Event $event 1373e83b370SMark C. Prins * event object by reference, not used 138a9441f7dSMark C. Prins * @param mixed $param 1393e83b370SMark C. Prins * parameter array, not used 140bd120a73SMark C. Prins */ 14102c45c98SMark C. Prins function handle_sitemap_generate_after(Doku_Event &$event, $param) { 1427c452997SMark C. Prins // $event→data['items']: Array of SitemapItem instances, the array of sitemap items that already 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 14502c45c98SMark C. Prins // dbglog ($event->data['items'], "createSpatialSitemap loading helper" ); 14602c45c98SMark C. Prins if ($helper = & plugin_load ( 'helper', 'spatialhelper_sitemap' )) { 14702c45c98SMark C. Prins // dbglog ( $helper, "createSpatialSitemap loaded helper." ); 14802c45c98SMark C. Prins 149f2601b07SMark C. Prins $kml = $helper->createKMLSitemap ( $this->getConf ( 'media_kml' ) ); 150f2601b07SMark C. Prins $rss = $helper->createGeoRSSSitemap ( $this->getConf ( 'media_georss' ) ); 15102c45c98SMark C. Prins 15202c45c98SMark C. Prins return $kml && $rss; 15302c45c98SMark C. Prins } else { 15402c45c98SMark C. Prins // dbglog ( $helper, "createSpatialSitemap NOT loaded helper." ); 15502c45c98SMark C. Prins } 1569af1cdd4SMark C. Prins } 1579af1cdd4SMark C. Prins 1589af1cdd4SMark C. Prins /** 1599af1cdd4SMark C. Prins * trap findnearby action. 16002c45c98SMark C. Prins * This addional handler is required as described at: https://www.dokuwiki.org/devel:event:tpl_act_unknown 161a9441f7dSMark C. Prins * 162a9441f7dSMark C. Prins * @param Doku_Event $event 163a9441f7dSMark C. Prins * event object by reference 164a9441f7dSMark C. Prins * @param mixed $param 165a9441f7dSMark C. Prins * not used 1669af1cdd4SMark C. Prins */ 16702c45c98SMark C. Prins function handle_action_act_preprocess(Doku_Event &$event, $param) { 168a9441f7dSMark C. Prins if ($event->data != 'findnearby') 169a9441f7dSMark C. Prins return; 1709af1cdd4SMark C. Prins $event->preventDefault (); 1719af1cdd4SMark C. Prins } 1729af1cdd4SMark C. Prins 1739af1cdd4SMark C. Prins /** 1749af1cdd4SMark C. Prins * handle findnearby action. 175a9441f7dSMark C. Prins * 176a9441f7dSMark C. Prins * @param Doku_Event $event 177a9441f7dSMark C. Prins * event object by reference 178*e4020312SMark C. Prins * @param mixed $param 179*e4020312SMark C. Prins * associative array with keys 1809bb9b388SMark C. Prins * 'format'=> HTML | JSON 1819af1cdd4SMark C. Prins */ 182a9441f7dSMark C. Prins function _findnearby(Doku_Event &$event, $param) { 183a9441f7dSMark C. Prins if ($event->data != 'findnearby') 184a9441f7dSMark C. Prins return; 1859af1cdd4SMark C. Prins $event->preventDefault (); 1869af1cdd4SMark C. Prins 1877c452997SMark C. Prins global $INPUT; 1887c452997SMark C. Prins $dist_prefix = ''; 1899af1cdd4SMark C. Prins if ($helper = & plugin_load ( 'helper', 'spatialhelper_search' )) { 1907c452997SMark C. Prins if ($INPUT->has ( 'geohash' )) { 1917c452997SMark C. Prins $results = $helper->findNearby ( $INPUT->str ( 'geohash' ) ); 1927c452997SMark C. Prins $dist_prefix = hsc ( $this->getLang ( 'result_distance_prefix' ) ) . ' '; 1937c452997SMark C. Prins } elseif ($INPUT->has ( 'lat' ) && $INPUT->has ( 'lon' )) { 1947c452997SMark C. Prins $results = $helper->findNearbyLatLon ( $INPUT->param ( 'lat' ), $INPUT->param ( 'lon' ) ); 1957c452997SMark C. Prins } else { 1963e83b370SMark C. Prins $results = array ( 1973e83b370SMark C. Prins 'error' => hsc ( $this->getLang ( 'invalidinput' ) ) 1983e83b370SMark C. Prins ); 1999af1cdd4SMark C. Prins } 2009af1cdd4SMark C. Prins } 2019af1cdd4SMark C. Prins 2023e83b370SMark C. Prins $showMedia = $INPUT->bool ( 'showMedia', true ); 2033e83b370SMark C. Prins 2043e83b370SMark C. Prins switch ($param ['format']) { 2053e83b370SMark C. Prins case 'JSON' : 2063e83b370SMark C. Prins $this->printJSON ( $results ); 2073e83b370SMark C. Prins break; 2083e83b370SMark C. Prins case 'HTML' : 2093e83b370SMark C. Prins default : 2103e83b370SMark C. Prins $this->printHTML ( $results, $showMedia ); 2113e83b370SMark C. Prins break; 2123e83b370SMark C. Prins } 2133e83b370SMark C. Prins } 2143e83b370SMark C. Prins 2153e83b370SMark C. Prins /** 2163e83b370SMark C. Prins * Print seachresults as HTML lists. 2173e83b370SMark C. Prins * 2183e83b370SMark C. Prins * @param array $searchresults 2193e83b370SMark C. Prins */ 2203e83b370SMark C. Prins private function printJSON($searchresults) { 2213e83b370SMark C. Prins require_once DOKU_INC . 'inc/JSON.php'; 2223e83b370SMark C. Prins $json = new JSON (); 2233e83b370SMark C. Prins 2243e83b370SMark C. Prins header ( 'Content-Type: application/json' ); 2253e83b370SMark C. Prins print $json->encode ( $searchresults ); 2263e83b370SMark C. Prins } 2273e83b370SMark C. Prins 2283e83b370SMark C. Prins /** 2293e83b370SMark C. Prins * Print seachresults as HTML lists. 2303e83b370SMark C. Prins * 2313e83b370SMark C. Prins * @param array $searchresults 2323e83b370SMark C. Prins * @param boolean $showMedia 2333e83b370SMark C. Prins */ 2343e83b370SMark C. Prins private function printHTML($searchresults, $showMedia = true) { 2353e83b370SMark C. Prins $pages = ( array ) ($searchresults ['pages']); 2363e83b370SMark C. Prins $media = ( array ) $searchresults ['media']; 2373e83b370SMark C. Prins $location = ( string ) $searchresults ['latlon']; 2383e83b370SMark C. Prins $geohash = ( string ) $searchresults ['geohash']; 2393e83b370SMark C. Prins 2403e83b370SMark C. Prins if (isset ( $searchresults ['error'] )) { 2413e83b370SMark C. Prins print '<div class="level1"><p>' . hsc ( $results ['error'] ) . '</p></div>'; 2423e83b370SMark C. Prins return; 2433e83b370SMark C. Prins } 2443e83b370SMark C. Prins 2453e83b370SMark C. Prins // print a HTML list 2467c452997SMark C. Prins print '<h1>' . $this->getLang ( 'results_header' ) . '</h1>' . DOKU_LF; 2479af1cdd4SMark C. Prins print '<div class="level1">' . DOKU_LF; 2487c452997SMark C. Prins if (! empty ( $pages )) { 2497c452997SMark C. Prins $pagelist = '<ol>' . DOKU_LF; 2507c452997SMark C. Prins foreach ( $pages as $page ) { 251*e4020312SMark C. Prins $pagelist .= '<li>' . html_wikilink ( ':' . $page ['id'], useHeading ( 'navigation' ) ? null : noNS ( $page ['id'] ) ) . ' (' . $this->getLang ( 'results_distance_prefix' ) . $page ['distance'] . 'm) ' . $page ['description'] . '</li>' . DOKU_LF; 2527c452997SMark C. Prins } 2537c452997SMark C. Prins $pagelist .= '</ol>' . DOKU_LF; 2547c452997SMark C. Prins 2557c452997SMark C. Prins print '<h2>' . $this->getLang ( 'results_pages' ) . hsc ( ' lat,lon: ' . $location . ' (geohash: ' . $geohash . ')' ) . '</h2>'; 2567c452997SMark C. Prins print '<div class="level2">' . DOKU_LF; 2577c452997SMark C. Prins print $pagelist; 2583e83b370SMark C. Prins print '<p>Precision: ' . $searchresults ['precision'] . ' m</p>' . DOKU_LF; 2599af1cdd4SMark C. Prins print '</div>' . DOKU_LF; 2609af1cdd4SMark C. Prins } else { 2617c452997SMark C. Prins print '<p>' . hsc ( $this->getLang ( 'nothingfound' ) ) . '</p>'; 2629af1cdd4SMark C. Prins } 263*e4020312SMark C. Prins 2643e83b370SMark C. Prins if (! empty ( $media ) && $showMedia) { 2657c452997SMark C. Prins $pagelist = '<ol>' . DOKU_LF; 2667c452997SMark C. Prins foreach ( $media as $m ) { 2677c452997SMark C. Prins $opts = array (); 2687c452997SMark C. Prins $link = ml ( $m ['id'], $opts, false, '&', false ); 2699bb9b388SMark C. Prins $opts ['w'] = '100'; 2707c452997SMark C. Prins $src = ml ( $m ['id'], $opts ); 271*e4020312SMark C. Prins $pagelist .= '<li><a href="' . $link . '"><img src="' . $src . '"></a> (' . $this->getLang ( 'results_distance_prefix' ) . $page ['distance'] . 'm) ' . hsc ( $desc ) . '</li>' . DOKU_LF; 272bd120a73SMark C. Prins } 2737c452997SMark C. Prins $pagelist .= '</ol>' . DOKU_LF; 2747c452997SMark C. Prins 2757c452997SMark C. Prins print '<h2>' . $this->getLang ( 'results_media' ) . hsc ( ' lat,lon: ' . $location . ' (geohash: ' . $geohash . ')' ) . '</h2>' . DOKU_LF; 2767c452997SMark C. Prins print '<div class="level2">' . DOKU_LF; 2777c452997SMark C. Prins print $pagelist; 2783e83b370SMark C. Prins print '<p>Precision: ' . $searchresults ['precision'] . ' m</p>' . DOKU_LF; 2797c452997SMark C. Prins print '</div>' . DOKU_LF; 2807c452997SMark C. Prins } 2817c452997SMark C. Prins print '</div>' . DOKU_LF; 2827c452997SMark C. Prins } 2833e83b370SMark C. Prins 2847c452997SMark C. Prins /** 2857c452997SMark C. Prins * add media to spatial index. 2867c452997SMark C. Prins * 2877c452997SMark C. Prins * @param Doku_Event $event 2887c452997SMark C. Prins * event object by reference 2897c452997SMark C. Prins * @param unknown $param 290a9441f7dSMark C. Prins */ 2917c452997SMark C. Prins function _handle_media_uploaded(Doku_Event &$event, $param) { 2927c452997SMark C. Prins // data[0] temporary file name (read from $_FILES) 2937c452997SMark C. Prins // data[1] file name of the file being uploaded 2947c452997SMark C. Prins // data[2] future directory id of the file being uploaded 2957c452997SMark C. Prins // data[3] the mime type of the file being uploaded 2967c452997SMark C. Prins // data[4] true if the uploaded file exists already 2977c452997SMark C. Prins // data[5] (since 2011-02-06) the PHP function used to move the file to the correct location 29802c45c98SMark C. Prins 29902c45c98SMark C. Prins // dbglog ( $event->data, "_handle_media_uploaded::event data" ); 300a9441f7dSMark C. Prins 301a9441f7dSMark C. Prins // check the list of mimetypes 302a9441f7dSMark C. Prins // if it's a supported type call appropriate index function 3037c452997SMark C. Prins if (substr_compare ( $event->data [3], 'image/jpeg', 0 )) { 304a9441f7dSMark C. Prins $indexer = plugin_load ( 'helper', 'spatialhelper_index' ); 305a9441f7dSMark C. Prins if ($indexer) { 306a9441f7dSMark C. Prins $indexer->indexImage ( $event->data [2], $event->data [1] ); 307a9441f7dSMark C. Prins } 308a9441f7dSMark C. Prins } 3097c452997SMark C. Prins // TODO add image/tiff 310a9441f7dSMark C. Prins // TODO kml, gpx, geojson... 311a9441f7dSMark C. Prins } 312a9441f7dSMark C. Prins 313a9441f7dSMark C. Prins /** 314a9441f7dSMark C. Prins * removes the media from the index. 315a9441f7dSMark C. Prins */ 316a9441f7dSMark C. Prins function _handle_media_deleted(Doku_Event &$event, $param) { 3177c452997SMark C. Prins // data['id'] ID data['unl'] unlink return code 3187c452997SMark C. Prins // data['del'] Namespace directory unlink return code 3197c452997SMark C. Prins // data['name'] file name data['path'] full path to the file 3207c452997SMark C. Prins // data['size'] file size 32102c45c98SMark C. Prins 32202c45c98SMark C. Prins // dbglog ( $event->data, "_handle_media_deleted::event data" ); 3237c452997SMark C. Prins 3247c452997SMark C. Prins // remove the media id from the index 32502c45c98SMark C. Prins $indexer = & plugin_load ( 'helper', 'spatialhelper_index' ); 326a9441f7dSMark C. Prins if ($indexer) { 3277c452997SMark C. Prins $indexer->deleteFromIndex ( 'media__' . $event->data ['id'] ); 328a9441f7dSMark C. Prins } 329a9441f7dSMark C. Prins } 3307c452997SMark C. Prins 3317c452997SMark C. Prins /** 33202c45c98SMark C. Prins * add a link to the spatial sitemap files in the header. 33302c45c98SMark C. Prins * 33402c45c98SMark C. Prins * @param Doku_Event $event 33502c45c98SMark C. Prins * the DokuWiki event. $event->data is a two-dimensional 33602c45c98SMark C. Prins * array of all meta headers. The keys are meta, link and script. 33702c45c98SMark C. Prins * @param unknown_type $param 33802c45c98SMark C. Prins * 33902c45c98SMark C. Prins * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output 34002c45c98SMark C. Prins */ 34102c45c98SMark C. Prins public function handle_metaheader_output(Doku_Event &$event, $param) { 34202c45c98SMark C. Prins // TODO maybe test for exist 34302c45c98SMark C. Prins $event->data ["link"] [] = array ( 34402c45c98SMark C. Prins "type" => "application/atom+xml", 34502c45c98SMark C. Prins "rel" => "alternate", 34600e20e07SMark C. Prins "href" => ml ( $this->getConf ( 'media_georss' ) ), 34702c45c98SMark C. Prins "title" => "Spatial ATOM Feed" 34802c45c98SMark C. Prins ); 34902c45c98SMark C. Prins $event->data ["link"] [] = array ( 35002c45c98SMark C. Prins "type" => "application/vnd.google-earth.kml+xml", 35102c45c98SMark C. Prins "rel" => "alternate", 35200e20e07SMark C. Prins "href" => ml ( $this->getConf ( 'media_kml' ) ), 35302c45c98SMark C. Prins "title" => "KML Sitemap" 35402c45c98SMark C. Prins ); 35502c45c98SMark C. Prins } 35602c45c98SMark C. Prins 35702c45c98SMark C. Prins /** 3587c452997SMark C. Prins * Calculate a new coordinate based on start, distance and bearing 3597c452997SMark C. Prins * 3607c452997SMark C. Prins * @param $start array 3617c452997SMark C. Prins * - start coordinate as decimal lat/lon pair 3627c452997SMark C. Prins * @param $dist float 3637c452997SMark C. Prins * - distance in kilometers 3647c452997SMark C. Prins * @param $brng float 3657c452997SMark C. Prins * - bearing in degrees (compass direction) 3667c452997SMark C. Prins */ 3677c452997SMark C. Prins private function _geo_destination($start, $dist, $brng) { 3687c452997SMark C. Prins $lat1 = _toRad ( $start [0] ); 3697c452997SMark C. Prins $lon1 = _toRad ( $start [1] ); 3707c452997SMark C. Prins // http://en.wikipedia.org/wiki/Earth_radius 3717c452997SMark C. Prins // average earth radius in km 3727c452997SMark C. Prins $dist = $dist / 6371.01; 3737c452997SMark C. Prins $brng = _toRad ( $brng ); 3747c452997SMark C. Prins 3757c452997SMark C. Prins $lon2 = $lon1 + atan2 ( sin ( $brng ) * sin ( $dist ) * cos ( $lat1 ), cos ( $dist ) - sin ( $lat1 ) * sin ( $lat2 ) ); 3767c452997SMark C. Prins $lon2 = fmod ( ($lon2 + 3 * pi ()), (2 * pi ()) ) - pi (); 3777c452997SMark C. Prins 3787c452997SMark C. Prins return array ( 3797c452997SMark C. Prins _toDeg ( $lat2 ), 3807c452997SMark C. Prins _toDeg ( $lon2 ) 3817c452997SMark C. Prins ); 3827c452997SMark C. Prins } 3837c452997SMark C. Prins private function _toRad($deg) { 3847c452997SMark C. Prins return $deg * pi () / 180; 3857c452997SMark C. Prins } 3867c452997SMark C. Prins private function _toDeg($rad) { 3877c452997SMark C. Prins return $rad * 180 / pi (); 3887c452997SMark C. Prins } 389bd120a73SMark C. Prins}