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 3302c45c98SMark C. Prins // TODO add configurable namespace, NOTE if $mediaID is namespaced the directory may need to be created 3402c45c98SMark C. Prins private $media_kml = ':sitemap.kml'; 3502c45c98SMark C. Prins private $media_georss = ':sitemap.georss'; 3602c45c98SMark C. Prins 37bd120a73SMark C. Prins /** 38bd120a73SMark C. Prins * Register for events. 39bd120a73SMark C. Prins * 40a9441f7dSMark C. Prins * @param Doku_Event_Handler $controller 41a9441f7dSMark C. Prins * DokuWiki's event controller object. Also available as global $EVENT_HANDLER 42bd120a73SMark C. Prins */ 43bd120a73SMark C. Prins public function register(Doku_Event_Handler &$controller) { 447c452997SMark C. Prins // listen for page add / delete events 45bd120a73SMark C. Prins // http://www.dokuwiki.org/devel:event:indexer_page_add 4602c45c98SMark C. Prins $controller->register_hook ( 'INDEXER_PAGE_ADD', 'BEFORE', $this, 'handle_indexer_page_add' ); 4734fb1e15SMark C. Prins $controller->register_hook ( 'IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_removeFromIndex' ); 48a9441f7dSMark C. Prins 49bd120a73SMark C. Prins // http://www.dokuwiki.org/devel:event:sitemap_generate 5002c45c98SMark C. Prins $controller->register_hook ( 'SITEMAP_GENERATE', 'BEFORE', $this, 'handle_sitemap_generate_before' ); 517c452997SMark C. Prins // using after will only trigger us if a sitemap was actually created 5202c45c98SMark C. Prins $controller->register_hook ( 'SITEMAP_GENERATE', 'AFTER', $this, 'handle_sitemap_generate_after' ); 537c452997SMark C. Prins 54a9441f7dSMark C. Prins // handle actions we know of 5502c45c98SMark C. Prins $controller->register_hook ( 'ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_preprocess', array () ); 563e83b370SMark C. Prins $controller->register_hook ( 'TPL_ACT_UNKNOWN', 'BEFORE', $this, '_findnearby', array ( 573e83b370SMark C. Prins 'format' => 'HTML' 583e83b370SMark C. Prins ) ); 593e83b370SMark C. Prins 603e83b370SMark C. Prins $controller->register_hook ( 'AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_findnearby', array ( 613e83b370SMark C. Prins 'format' => 'JSON' 623e83b370SMark C. Prins ) ); 637c452997SMark C. Prins 64a9441f7dSMark C. Prins // listen for media uploads and deletes 65a9441f7dSMark C. Prins $controller->register_hook ( 'MEDIA_UPLOAD_FINISH', 'BEFORE', $this, '_handle_media_uploaded', array () ); 66a9441f7dSMark C. Prins $controller->register_hook ( 'MEDIA_DELETE_FILE', 'BEFORE', $this, '_handle_media_deleted', array () ); 6702c45c98SMark C. Prins 6802c45c98SMark C. Prins $controller->register_hook ( 'TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handle_metaheader_output' ); 69bd120a73SMark C. Prins } 70bd120a73SMark C. Prins 71bd120a73SMark C. Prins /** 72bd120a73SMark C. Prins * Update the spatial index for the page. 73a9441f7dSMark C. Prins * 74a9441f7dSMark C. Prins * @param Doku_Event $event 75a9441f7dSMark C. Prins * event object by reference 76a9441f7dSMark C. Prins * @param object $param 77a9441f7dSMark C. Prins * the parameters passed to register_hook when this handler was registered 78bd120a73SMark C. Prins */ 7902c45c98SMark C. Prins function handle_indexer_page_add(Doku_Event &$event, $param) { 807c452997SMark C. Prins // $event→data['page'] – the page id 817c452997SMark C. Prins // $event→data['body'] – empty, can be filled by additional content to index by your plugin 827c452997SMark 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. 839af1cdd4SMark C. Prins $id = $event->data ['page']; 8402c45c98SMark C. Prins $indexer = & plugin_load ( 'helper', 'spatialhelper_index' ); 85bd120a73SMark C. Prins $entries = $indexer->updateSpatialIndex ( $id ); 86bd120a73SMark C. Prins } 87bd120a73SMark C. Prins 88bd120a73SMark C. Prins /** 8934fb1e15SMark C. Prins * Update the spatial index, removing the page. 90a9441f7dSMark C. Prins * 91a9441f7dSMark C. Prins * @param Doku_Event $event 92a9441f7dSMark C. Prins * event object by reference 93a9441f7dSMark C. Prins * @param object $param 94a9441f7dSMark C. Prins * the parameters passed to register_hook when this handler was registered 9534fb1e15SMark C. Prins */ 9634fb1e15SMark C. Prins function _removeFromIndex(Doku_Event &$event, $param) { 977c452997SMark C. Prins // event data: 987c452997SMark C. Prins // $data[0] – The raw arguments for io_saveFile as an array. Do not change file path. 997c452997SMark C. Prins // $data[0][0] – the file path. 1007c452997SMark C. Prins // $data[0][1] – the content to be saved, and may be modified. 1017c452997SMark C. Prins // $data[1] – ns: The colon separated namespace path minus the trailing page name. (false if root ns) 1027c452997SMark C. Prins // $data[2] – page_name: The wiki page name. 1037c452997SMark C. Prins // $data[3] – rev: The page revision, false for current wiki pages. 1047c452997SMark C. Prins 10502c45c98SMark C. Prins // dbglog ( $event->data, "Event data in _removeFromIndex." ); 10634fb1e15SMark C. Prins if (@file_exists ( $event->data [0] [0] )) { 10734fb1e15SMark C. Prins // file not new 10834fb1e15SMark C. Prins if (! $event->data [0] [1]) { 10934fb1e15SMark C. Prins // file is empty, page is being deleted 11034fb1e15SMark C. Prins if (empty ( $event->data [1] )) { 11134fb1e15SMark C. Prins // root namespace 11234fb1e15SMark C. Prins $id = $event->data [2]; 11334fb1e15SMark C. Prins } else { 11434fb1e15SMark C. Prins $id = $event->data [1] . ":" . $event->data [2]; 11534fb1e15SMark C. Prins } 11602c45c98SMark C. Prins $indexer = & plugin_load ( 'helper', 'spatialhelper_index' ); 11734fb1e15SMark C. Prins if ($indexer) { 11834fb1e15SMark C. Prins $indexer->deleteFromIndex ( $id ); 11934fb1e15SMark C. Prins } 12034fb1e15SMark C. Prins } 12134fb1e15SMark C. Prins } 12234fb1e15SMark C. Prins } 12334fb1e15SMark C. Prins 12434fb1e15SMark C. Prins /** 12502c45c98SMark C. Prins * Add a new SitemapItem object that points to the KML of public geocoded pages. 12602c45c98SMark C. Prins * 12702c45c98SMark C. Prins * @param Doku_Event $event 12802c45c98SMark C. Prins * @param unknown $param 12902c45c98SMark C. Prins */ 13002c45c98SMark C. Prins function handle_sitemap_generate_before(Doku_Event &$event, $param) { 13102c45c98SMark C. Prins $path = mediaFN ( $this->media_kml ); 13202c45c98SMark C. Prins $lastmod = @filemtime ( $path ); 13302c45c98SMark C. Prins $event->data ['items'] [] = new SitemapItem ( ml ( $this->media_kml, '', true, '&', true ), $lastmod ); 13402c45c98SMark C. Prins // dbglog ( $event->data ['items'], "Added a new SitemapItem object that points to the KML of public geocoded pages." ); 13502c45c98SMark C. Prins } 13602c45c98SMark C. Prins 13702c45c98SMark C. Prins /** 138a9441f7dSMark C. Prins * Create a spatial sitemap or attach the geo/kml map to the sitemap. 139a9441f7dSMark C. Prins * 140a9441f7dSMark C. Prins * @param Doku_Event $event 1413e83b370SMark C. Prins * event object by reference, not used 142a9441f7dSMark C. Prins * @param mixed $param 1433e83b370SMark C. Prins * parameter array, not used 144bd120a73SMark C. Prins */ 14502c45c98SMark C. Prins function handle_sitemap_generate_after(Doku_Event &$event, $param) { 1467c452997SMark C. Prins // $event→data['items']: Array of SitemapItem instances, the array of sitemap items that already contains all public pages of the wiki 1477c452997SMark C. Prins // $event→data['sitemap']: The path of the file the sitemap will be saved to. 14802c45c98SMark C. Prins 14902c45c98SMark C. Prins // dbglog ($event->data['items'], "createSpatialSitemap loading helper" ); 15002c45c98SMark C. Prins if ($helper = & plugin_load ( 'helper', 'spatialhelper_sitemap' )) { 15102c45c98SMark C. Prins // dbglog ( $helper, "createSpatialSitemap loaded helper." ); 15202c45c98SMark C. Prins 153*f2601b07SMark C. Prins $kml = $helper->createKMLSitemap ( $this->getConf('media_kml') ); 154*f2601b07SMark C. Prins $rss = $helper->createGeoRSSSitemap ( $this->getConf('media_georss') ); 15502c45c98SMark C. Prins 15602c45c98SMark C. Prins return $kml && $rss; 15702c45c98SMark C. Prins } else { 15802c45c98SMark C. Prins // dbglog ( $helper, "createSpatialSitemap NOT loaded helper." ); 15902c45c98SMark C. Prins } 1609af1cdd4SMark C. Prins } 1619af1cdd4SMark C. Prins 1629af1cdd4SMark C. Prins /** 1639af1cdd4SMark C. Prins * trap findnearby action. 16402c45c98SMark C. Prins * This addional handler is required as described at: https://www.dokuwiki.org/devel:event:tpl_act_unknown 165a9441f7dSMark C. Prins * 166a9441f7dSMark C. Prins * @param Doku_Event $event 167a9441f7dSMark C. Prins * event object by reference 168a9441f7dSMark C. Prins * @param mixed $param 169a9441f7dSMark C. Prins * not used 1709af1cdd4SMark C. Prins */ 17102c45c98SMark C. Prins function handle_action_act_preprocess(Doku_Event &$event, $param) { 172a9441f7dSMark C. Prins if ($event->data != 'findnearby') 173a9441f7dSMark C. Prins return; 1749af1cdd4SMark C. Prins $event->preventDefault (); 1759af1cdd4SMark C. Prins } 1769af1cdd4SMark C. Prins 1779af1cdd4SMark C. Prins /** 1789af1cdd4SMark C. Prins * handle findnearby action. 179a9441f7dSMark C. Prins * 180a9441f7dSMark C. Prins * @param Doku_Event $event 181a9441f7dSMark C. Prins * event object by reference 182a9441f7dSMark C. Prins * @param mixed $param 1833e83b370SMark C. Prins * 'format'=> 1849af1cdd4SMark C. Prins */ 185a9441f7dSMark C. Prins function _findnearby(Doku_Event &$event, $param) { 186a9441f7dSMark C. Prins if ($event->data != 'findnearby') 187a9441f7dSMark C. Prins return; 1889af1cdd4SMark C. Prins $event->preventDefault (); 1899af1cdd4SMark C. Prins 1907c452997SMark C. Prins global $INPUT; 1917c452997SMark C. Prins $dist_prefix = ''; 1929af1cdd4SMark C. Prins if ($helper = & plugin_load ( 'helper', 'spatialhelper_search' )) { 1937c452997SMark C. Prins if ($INPUT->has ( 'geohash' )) { 1947c452997SMark C. Prins $results = $helper->findNearby ( $INPUT->str ( 'geohash' ) ); 1957c452997SMark C. Prins $dist_prefix = hsc ( $this->getLang ( 'result_distance_prefix' ) ) . ' '; 1967c452997SMark C. Prins } elseif ($INPUT->has ( 'lat' ) && $INPUT->has ( 'lon' )) { 1977c452997SMark C. Prins $results = $helper->findNearbyLatLon ( $INPUT->param ( 'lat' ), $INPUT->param ( 'lon' ) ); 1987c452997SMark C. Prins } else { 1993e83b370SMark C. Prins $results = array ( 2003e83b370SMark C. Prins 'error' => hsc ( $this->getLang ( 'invalidinput' ) ) 2013e83b370SMark C. Prins ); 2029af1cdd4SMark C. Prins } 2039af1cdd4SMark C. Prins } 2049af1cdd4SMark C. Prins 2053e83b370SMark C. Prins $showMedia = $INPUT->bool ( 'showMedia', true ); 2063e83b370SMark C. Prins 2073e83b370SMark C. Prins switch ($param ['format']) { 2083e83b370SMark C. Prins case 'JSON' : 2093e83b370SMark C. Prins $this->printJSON ( $results ); 2103e83b370SMark C. Prins break; 2113e83b370SMark C. Prins case 'HTML' : 2123e83b370SMark C. Prins default : 2133e83b370SMark C. Prins $this->printHTML ( $results, $showMedia ); 2143e83b370SMark C. Prins break; 2153e83b370SMark C. Prins } 2163e83b370SMark C. Prins } 2173e83b370SMark C. Prins 2183e83b370SMark C. Prins /** 2193e83b370SMark C. Prins * Print seachresults as HTML lists. 2203e83b370SMark C. Prins * 2213e83b370SMark C. Prins * @param array $searchresults 2223e83b370SMark C. Prins */ 2233e83b370SMark C. Prins private function printJSON($searchresults) { 2243e83b370SMark C. Prins require_once DOKU_INC . 'inc/JSON.php'; 2253e83b370SMark C. Prins $json = new JSON (); 2263e83b370SMark C. Prins 2273e83b370SMark C. Prins header ( 'Content-Type: application/json' ); 2283e83b370SMark C. Prins print $json->encode ( $searchresults ); 2293e83b370SMark C. Prins } 2303e83b370SMark C. Prins 2313e83b370SMark C. Prins /** 2323e83b370SMark C. Prins * Print seachresults as HTML lists. 2333e83b370SMark C. Prins * 2343e83b370SMark C. Prins * @param array $searchresults 2353e83b370SMark C. Prins * @param boolean $showMedia 2363e83b370SMark C. Prins */ 2373e83b370SMark C. Prins private function printHTML($searchresults, $showMedia = true) { 2383e83b370SMark C. Prins $pages = ( array ) ($searchresults ['pages']); 2393e83b370SMark C. Prins $media = ( array ) $searchresults ['media']; 2403e83b370SMark C. Prins $location = ( string ) $searchresults ['latlon']; 2413e83b370SMark C. Prins $geohash = ( string ) $searchresults ['geohash']; 2423e83b370SMark C. Prins 2433e83b370SMark C. Prins if (isset ( $searchresults ['error'] )) { 2443e83b370SMark C. Prins print '<div class="level1"><p>' . hsc ( $results ['error'] ) . '</p></div>'; 2453e83b370SMark C. Prins return; 2463e83b370SMark C. Prins } 2473e83b370SMark C. Prins 2483e83b370SMark C. Prins // print a HTML list 2497c452997SMark C. Prins print '<h1>' . $this->getLang ( 'results_header' ) . '</h1>' . DOKU_LF; 2509af1cdd4SMark C. Prins print '<div class="level1">' . DOKU_LF; 2517c452997SMark C. Prins if (! empty ( $pages )) { 2527c452997SMark C. Prins $pagelist = '<ol>' . DOKU_LF; 2537c452997SMark C. Prins foreach ( $pages as $page ) { 2547c452997SMark C. Prins $pagelist .= '<li>' . html_wikilink ( ':' . $page ['id'], useHeading ( 'navigation' ) ? null : noNS ( $page ['id'] ) ) . ' (' . $dist_prefix . $page ['distance'] . 'm) ' . $page ['description'] . '</li>' . DOKU_LF; 2557c452997SMark C. Prins } 2567c452997SMark C. Prins $pagelist .= '</ol>' . DOKU_LF; 2577c452997SMark C. Prins 2587c452997SMark C. Prins print '<h2>' . $this->getLang ( 'results_pages' ) . hsc ( ' lat,lon: ' . $location . ' (geohash: ' . $geohash . ')' ) . '</h2>'; 2597c452997SMark C. Prins print '<div class="level2">' . DOKU_LF; 2607c452997SMark C. Prins print $pagelist; 2613e83b370SMark C. Prins print '<p>Precision: ' . $searchresults ['precision'] . ' m</p>' . DOKU_LF; 2629af1cdd4SMark C. Prins print '</div>' . DOKU_LF; 2639af1cdd4SMark C. Prins } else { 2647c452997SMark C. Prins print '<p>' . hsc ( $this->getLang ( 'nothingfound' ) ) . '</p>'; 2659af1cdd4SMark C. Prins } 2663e83b370SMark C. Prins 2673e83b370SMark C. Prins if (! empty ( $media ) && $showMedia) { 2687c452997SMark C. Prins $pagelist = '<ol>' . DOKU_LF; 2697c452997SMark C. Prins foreach ( $media as $m ) { 2707c452997SMark C. Prins $opts = array (); 2717c452997SMark C. Prins $link = ml ( $m ['id'], $opts, false, '&', false ); 2727c452997SMark C. Prins $opts ['w'] = '100px'; 2737c452997SMark C. Prins $src = ml ( $m ['id'], $opts ); 2747c452997SMark C. Prins $pagelist .= '<li><a href="' . $link . '"><img src="' . $src . '"></a> (' . $dist_prefix . $page ['distance'] . 'm) </li>' . DOKU_LF; 275bd120a73SMark C. Prins } 2767c452997SMark C. Prins $pagelist .= '</ol>' . DOKU_LF; 2777c452997SMark C. Prins 2787c452997SMark C. Prins print '<h2>' . $this->getLang ( 'results_media' ) . hsc ( ' lat,lon: ' . $location . ' (geohash: ' . $geohash . ')' ) . '</h2>' . DOKU_LF; 2797c452997SMark C. Prins print '<div class="level2">' . DOKU_LF; 2807c452997SMark C. Prins print $pagelist; 2813e83b370SMark C. Prins print '<p>Precision: ' . $searchresults ['precision'] . ' m</p>' . DOKU_LF; 2827c452997SMark C. Prins print '</div>' . DOKU_LF; 2837c452997SMark C. Prins } 2847c452997SMark C. Prins print '</div>' . DOKU_LF; 2857c452997SMark C. Prins } 2863e83b370SMark C. Prins 2877c452997SMark C. Prins /** 2887c452997SMark C. Prins * add media to spatial index. 2897c452997SMark C. Prins * 2907c452997SMark C. Prins * @param Doku_Event $event 2917c452997SMark C. Prins * event object by reference 2927c452997SMark C. Prins * @param unknown $param 293a9441f7dSMark C. Prins */ 2947c452997SMark C. Prins function _handle_media_uploaded(Doku_Event &$event, $param) { 2957c452997SMark C. Prins // data[0] temporary file name (read from $_FILES) 2967c452997SMark C. Prins // data[1] file name of the file being uploaded 2977c452997SMark C. Prins // data[2] future directory id of the file being uploaded 2987c452997SMark C. Prins // data[3] the mime type of the file being uploaded 2997c452997SMark C. Prins // data[4] true if the uploaded file exists already 3007c452997SMark C. Prins // data[5] (since 2011-02-06) the PHP function used to move the file to the correct location 30102c45c98SMark C. Prins 30202c45c98SMark C. Prins // dbglog ( $event->data, "_handle_media_uploaded::event data" ); 303a9441f7dSMark C. Prins 304a9441f7dSMark C. Prins // check the list of mimetypes 305a9441f7dSMark C. Prins // if it's a supported type call appropriate index function 3067c452997SMark C. Prins if (substr_compare ( $event->data [3], 'image/jpeg', 0 )) { 307a9441f7dSMark C. Prins $indexer = plugin_load ( 'helper', 'spatialhelper_index' ); 308a9441f7dSMark C. Prins if ($indexer) { 309a9441f7dSMark C. Prins $indexer->indexImage ( $event->data [2], $event->data [1] ); 310a9441f7dSMark C. Prins } 311a9441f7dSMark C. Prins } 3127c452997SMark C. Prins // TODO add image/tiff 313a9441f7dSMark C. Prins // TODO kml, gpx, geojson... 314a9441f7dSMark C. Prins } 315a9441f7dSMark C. Prins 316a9441f7dSMark C. Prins /** 317a9441f7dSMark C. Prins * removes the media from the index. 318a9441f7dSMark C. Prins */ 319a9441f7dSMark C. Prins function _handle_media_deleted(Doku_Event &$event, $param) { 3207c452997SMark C. Prins // data['id'] ID data['unl'] unlink return code 3217c452997SMark C. Prins // data['del'] Namespace directory unlink return code 3227c452997SMark C. Prins // data['name'] file name data['path'] full path to the file 3237c452997SMark C. Prins // data['size'] file size 32402c45c98SMark C. Prins 32502c45c98SMark C. Prins // dbglog ( $event->data, "_handle_media_deleted::event data" ); 3267c452997SMark C. Prins 3277c452997SMark C. Prins // remove the media id from the index 32802c45c98SMark C. Prins $indexer = & plugin_load ( 'helper', 'spatialhelper_index' ); 329a9441f7dSMark C. Prins if ($indexer) { 3307c452997SMark C. Prins $indexer->deleteFromIndex ( 'media__' . $event->data ['id'] ); 331a9441f7dSMark C. Prins } 332a9441f7dSMark C. Prins } 3337c452997SMark C. Prins 3347c452997SMark C. Prins /** 33502c45c98SMark C. Prins * add a link to the spatial sitemap files in the header. 33602c45c98SMark C. Prins * 33702c45c98SMark C. Prins * @param Doku_Event $event 33802c45c98SMark C. Prins * the DokuWiki event. $event->data is a two-dimensional 33902c45c98SMark C. Prins * array of all meta headers. The keys are meta, link and script. 34002c45c98SMark C. Prins * @param unknown_type $param 34102c45c98SMark C. Prins * 34202c45c98SMark C. Prins * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output 34302c45c98SMark C. Prins */ 34402c45c98SMark C. Prins public function handle_metaheader_output(Doku_Event &$event, $param) { 34502c45c98SMark C. Prins // TODO maybe test for exist 34602c45c98SMark C. Prins $event->data ["link"] [] = array ( 34702c45c98SMark C. Prins "type" => "application/atom+xml", 34802c45c98SMark C. Prins "rel" => "alternate", 34902c45c98SMark C. Prins "href" => ml ( $this->media_georss ), 35002c45c98SMark C. Prins "title" => "Spatial ATOM Feed" 35102c45c98SMark C. Prins ); 35202c45c98SMark C. Prins $event->data ["link"] [] = array ( 35302c45c98SMark C. Prins "type" => "application/vnd.google-earth.kml+xml", 35402c45c98SMark C. Prins "rel" => "alternate", 35502c45c98SMark C. Prins "href" => ml ( $this->media_kml ), 35602c45c98SMark C. Prins "title" => "KML Sitemap" 35702c45c98SMark C. Prins ); 35802c45c98SMark C. Prins } 35902c45c98SMark C. Prins 36002c45c98SMark C. Prins /** 3617c452997SMark C. Prins * Calculate a new coordinate based on start, distance and bearing 3627c452997SMark C. Prins * 3637c452997SMark C. Prins * @param $start array 3647c452997SMark C. Prins * - start coordinate as decimal lat/lon pair 3657c452997SMark C. Prins * @param $dist float 3667c452997SMark C. Prins * - distance in kilometers 3677c452997SMark C. Prins * @param $brng float 3687c452997SMark C. Prins * - bearing in degrees (compass direction) 3697c452997SMark C. Prins */ 3707c452997SMark C. Prins private function _geo_destination($start, $dist, $brng) { 3717c452997SMark C. Prins $lat1 = _toRad ( $start [0] ); 3727c452997SMark C. Prins $lon1 = _toRad ( $start [1] ); 3737c452997SMark C. Prins // http://en.wikipedia.org/wiki/Earth_radius 3747c452997SMark C. Prins // average earth radius in km 3757c452997SMark C. Prins $dist = $dist / 6371.01; 3767c452997SMark C. Prins $brng = _toRad ( $brng ); 3777c452997SMark C. Prins 3787c452997SMark C. Prins $lon2 = $lon1 + atan2 ( sin ( $brng ) * sin ( $dist ) * cos ( $lat1 ), cos ( $dist ) - sin ( $lat1 ) * sin ( $lat2 ) ); 3797c452997SMark C. Prins $lon2 = fmod ( ($lon2 + 3 * pi ()), (2 * pi ()) ) - pi (); 3807c452997SMark C. Prins 3817c452997SMark C. Prins return array ( 3827c452997SMark C. Prins _toDeg ( $lat2 ), 3837c452997SMark C. Prins _toDeg ( $lon2 ) 3847c452997SMark C. Prins ); 3857c452997SMark C. Prins } 3867c452997SMark C. Prins private function _toRad($deg) { 3877c452997SMark C. Prins return $deg * pi () / 180; 3887c452997SMark C. Prins } 3897c452997SMark C. Prins private function _toDeg($rad) { 3907c452997SMark C. Prins return $rad * 180 / pi (); 3917c452997SMark C. Prins } 392bd120a73SMark C. Prins}