* * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * DokuWiki Plugin spatialhelper (sitemap Component). * * @license BSD license * @author Mark Prins */ class helper_plugin_spatialhelper_sitemap extends Plugin { /** * spatial index. */ private $spatial_idx; /** * constructor, load spatial index. */ public function __construct() { global $conf; $idx_dir = $conf['indexdir']; if (!@file_exists($idx_dir . '/spatial.idx')) { $indexer = plugin_load('helper', 'spatialhelper_index'); if ($indexer !== null) { $indexer->generateSpatialIndex(); } } $this->spatial_idx = unserialize( io_readFile($idx_dir . '/spatial.idx', false), ['allowed_classes' => false] ); } final public function getMethods(): array { $result[] = [ 'name' => 'createGeoRSSSitemap', 'desc' => 'create a spatial sitemap in GeoRSS format.', 'params' => ['path' => 'string'], 'return' => ['success' => 'boolean'] ]; $result[] = [ 'name' => 'createKMLSitemap', 'desc' => 'create a spatial sitemap in KML format.', 'params' => ['path' => 'string'], 'return' => ['success' => 'boolean'] ]; return $result; } /** * Create a GeoRSS Simple sitemap (Atom). * * @param string $mediaID id * for the GeoRSS file */ final public function createGeoRSSSitemap(string $mediaID): bool { global $conf; $namespace = getNS($mediaID); $idTag = 'tag:' . parse_url(DOKU_URL, PHP_URL_HOST) . ','; $RSSstart = '' . DOKU_LF; $RSSstart .= '' . DOKU_LF; if (!empty($conf['tagline'])) { $RSSstart .= '' . $conf['tagline'] . '' . DOKU_LF; } $RSSstart .= '' . $conf['title'] . '' . DOKU_LF; $RSSstart .= '' . DOKU_LF; $RSSstart .= '' . DOKU_LF; $RSSstart .= '' . date(DATE_ATOM) . '' . DOKU_LF; $RSSstart .= '' . $idTag . date("Y-m-d") . ':' . parse_url(ml($mediaID), PHP_URL_PATH) . '' . DOKU_LF; $RSSstart .= '' . $conf['license'] . '' . DOKU_LF; $RSSend = '' . DOKU_LF; io_createNamespace($mediaID, 'media'); @touch(mediaFN($mediaID)); @chmod(mediaFN($mediaID), $conf['fmode']); $fh = fopen(mediaFN($mediaID), 'wb'); fwrite($fh, $RSSstart); foreach ($this->spatial_idx as $idxEntry) { // get list of id's foreach ($idxEntry as $id) { // for document item in the index if (strpos($id, 'media__') !== 0) { if ($this->skipPage($id, $namespace)) { continue; } $meta = p_get_metadata($id); // $desc = p_render('xhtmlsummary', p_get_instructions($meta['description']['abstract']), $info); $desc = strip_tags($meta['description']['abstract']); $entry = '' . DOKU_LF; $entry .= ' ' . $meta['title'] . '' . DOKU_LF; $entry .= ' ' . $desc . '' . DOKU_LF; $entry .= ' ' . $meta['geo']['lat'] . ' ' . $meta['geo']['lon'] . '' . DOKU_LF; if (!empty($meta['geo']['alt'])) { $entry .= ' ' . $meta['geo']['alt'] . '' . DOKU_LF; } $entry .= ' ' . DOKU_LF; if (empty($meta['creator'])) { $meta['creator'] = $conf['title']; } $entry .= ' ' . $meta['creator'] . '' . DOKU_LF; $entry .= ' ' . date_iso8601($meta['date']['modified']) . '' . DOKU_LF; $entry .= ' ' . date_iso8601($meta['date']['created']) . '' . DOKU_LF; $entry .= ' ' . $idTag . date("Y-m-d", $meta['date']['modified']) . ':' . parse_url(wl($id), PHP_URL_PATH) . '' . DOKU_LF; $entry .= '' . DOKU_LF; fwrite($fh, $entry); } } } fwrite($fh, $RSSend); return fclose($fh); } /** * will return true for non-public or hidden pages or pages that are not below or in the namespace. */ private function skipPage(string $id, string $namespace): bool { Logger::debug("helper_plugin_spatialhelper_sitemap::skipPage, skipping $id, not in $namespace"); if (isHiddenPage($id)) { return true; } if (auth_aclcheck($id, '', null) < AUTH_READ) { return true; } if (!empty($namespace)) { // only if id is in or below namespace if (0 !== strpos(getNS($id), $namespace)) { return true; } } return false; } /** * Create a KML sitemap. * * @param string $mediaID id for the KML file */ final public function createKMLSitemap(string $mediaID): bool { global $conf; $namespace = getNS($mediaID); $KMLstart = '' . DOKU_LF; $KMLstart .= '' . DOKU_LF; $KMLstart .= '' . DOKU_LF; $KMLstart .= '' . DOKU_LF; $KMLstart .= '' . DOKU_LF; $KMLend = '' . DOKU_LF . ''; io_createNamespace($mediaID, 'media'); @touch(mediaFN($mediaID)); @chmod(mediaFN($mediaID), $conf['fmode']); $fh = fopen(mediaFN($mediaID), 'wb'); fwrite($fh, $KMLstart); foreach ($this->spatial_idx as $idxEntry) { // get list of id's foreach ($idxEntry as $id) { // for document item in the index if (strpos($id, 'media__') !== 0) { if ($this->skipPage($id, $namespace)) { continue; } $meta = p_get_metadata($id); // $desc = p_render('xhtmlsummary', p_get_instructions($meta['description']['abstract']), $info); $desc = '

' . strip_tags($meta['description']['abstract']) . '

'; $desc .= '

' . $meta['title'] . '

'; // create an entry and store it $plcm = '' . DOKU_LF; $plcm .= ' ' . $meta['title'] . '' . DOKU_LF; // TODO escape quotes in: title="' . $meta['title'] . '" $plcm .= ' ' . DOKU_LF; if (!empty($meta['creator'])) { $plcm .= ' ' . $meta['creator'] . '' . DOKU_LF; } $plcm .= ' ' . DOKU_LF; $plcm .= ' #icon' . DOKU_LF; $plcm .= ' ' . $meta['geo']['lon'] . ',' . $meta['geo']['lat']; if (!empty($meta['geo']['alt'])) { $plcm .= ',' . $meta['geo']['alt']; } $plcm .= '' . DOKU_LF; $plcm .= '' . DOKU_LF; fwrite($fh, $plcm); } } } fwrite($fh, $KMLend); return fclose($fh); } }