*
* 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);
}
}