Completed
Push — master ( 00fa07...61a47e )
by Mark
21s queued 13s
created

helper_plugin_spatialhelper_sitemap   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 0
dl 0
loc 218
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A getMethods() 0 23 1
B createGeoRSSSitemap() 0 69 8
A skipPage() 0 18 5
B createKMLSitemap() 0 70 7
1
<?php
2
/*
3
 * Copyright (c) 2014-2016 Mark C. Prins <[email protected]>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
if(!defined('DOKU_LF')) {
19
    define('DOKU_LF', "\n");
20
}
21
22
/**
23
 * DokuWiki Plugin spatialhelper (sitemap Component).
24
 *
25
 * @license BSD license
26
 * @author  Mark Prins
27
 */
28
class helper_plugin_spatialhelper_sitemap extends DokuWiki_Plugin {
29
    /**
30
     * spatial index.
31
     */
32
    private $spatial_idx;
33
34
    /**
35
     * constructor, load spatial index.
36
     */
37
    public function __construct() {
38
        global $conf;
39
        $idx_dir = $conf['indexdir'];
40
        if(!@file_exists($idx_dir . '/spatial.idx')) {
41
            $indexer = plugin_load('helper', 'spatialhelper_index');
42
            $indexer->generateSpatialIndex();
43
        }
44
        $this->spatial_idx = unserialize(io_readFile($fn = $idx_dir . '/spatial.idx', false));
45
    }
46
47
    public function getMethods() {
48
        $result[] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
49
            'name'   => 'createGeoRSSSitemap',
50
            'desc'   => 'create a spatial sitemap in GeoRSS format.',
51
            'params' => array(
52
                'path' => 'string'
53
            ),
54
            'return' => array(
55
                'success' => 'boolean'
56
            )
57
        );
58
        $result[] = array(
59
            'name'   => 'createKMLSitemap',
60
            'desc'   => 'create a spatial sitemap in KML format.',
61
            'params' => array(
62
                'path' => 'string'
63
            ),
64
            'return' => array(
65
                'success' => 'boolean'
66
            )
67
        );
68
        return $result;
69
    }
70
71
    /**
72
     * Create a GeoRSS Simple sitemap (Atom).
73
     *
74
     * @param $mediaID id
75
     *                 for the GeoRSS file
76
     */
77
    public function createGeoRSSSitemap($mediaID) {
78
        global $conf;
79
        $namespace = getNS($mediaID);
80
81
        $idTag = 'tag:' . parse_url(DOKU_URL, PHP_URL_HOST) . ',';
82
83
        $RSSstart = '<?xml version="1.0" encoding="UTF-8"?>' . DOKU_LF;
84
        $RSSstart .= '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss" ';
85
        $RSSstart .= 'xmlns:dc="http://purl.org/dc/elements/1.1/">' . DOKU_LF;
86
        $RSSstart .= '<title>' . $conf['title'] . ' spatial feed</title>' . DOKU_LF;
87
        if(!empty($conf['tagline'])) {
88
            $RSSstart .= '<subtitle>' . $conf['tagline'] . '</subtitle>' . DOKU_LF;
89
        }
90
        $RSSstart .= '<dc:publisher>' . $conf['title'] . '</dc:publisher>' . DOKU_LF;
91
        $RSSstart .= '<link href="' . DOKU_URL . '" />' . DOKU_LF;
92
        $RSSstart .= '<link href="' . ml($mediaID, '', true, '&amp;', true) . '" rel="self" />' . DOKU_LF;
93
        $RSSstart .= '<updated>' . date(DATE_ATOM) . '</updated>' . DOKU_LF;
94
        $RSSstart .= '<id>' . $idTag . date("Y-m-d") . ':' . parse_url(ml($mediaID), PHP_URL_PATH)
95
            . '</id>' . DOKU_LF;
96
        $RSSstart .= '<rights>' . $conf['license'] . '</rights>' . DOKU_LF;
97
98
        $RSSend = '</feed>' . DOKU_LF;
99
100
        io_createNamespace($mediaID, 'media');
101
        @touch(mediaFN($mediaID));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
102
        @chmod(mediaFN($mediaID), $conf['fmode']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
103
        $fh = fopen(mediaFN($mediaID), 'w');
104
        fwrite($fh, $RSSstart);
105
106
        foreach($this->spatial_idx as $idxEntry) {
107
            // get list of id's
108
            foreach($idxEntry as $id) {
109
                // for document item in the index
110
                if(strpos($id, 'media__', 0) !== 0) {
111
                    if($this->skipPage($id, $namespace)) {
112
                        continue;
113
                    }
114
115
                    $meta = p_get_metadata($id);
116
117
                    // $desc = p_render('xhtmlsummary', p_get_instructions($meta['description']['abstract']), $info);
118
                    $desc = strip_tags($meta['description']['abstract']);
119
120
                    $entry = '<entry>' . DOKU_LF;
121
                    $entry .= '  <title>' . $meta['title'] . '</title>' . DOKU_LF;
122
                    $entry .= '  <summary>' . $desc . '</summary>' . DOKU_LF;
123
                    $entry .= '  <georss:point>' . $meta['geo']['lat'] . ' ' . $meta['geo']['lon']
124
                        . '</georss:point>' . DOKU_LF;
125
                    if($meta['geo']['alt']) {
126
                        $entry .= '  <georss:elev>' . $meta['geo']['alt'] . '</georss:elev>' . DOKU_LF;
127
                    }
128
                    $entry .= '  <link href="' . wl($id) . '" rel="alternate" type="text/html" />' . DOKU_LF;
129
                    if(empty($meta['creator'])) {
130
                        $meta['creator'] = $conf['title'];
131
                    }
132
                    $entry .= '  <author><name>' . $meta['creator'] . '</name></author>' . DOKU_LF;
133
                    $entry .= '  <updated>' . date_iso8601($meta['date']['modified']) . '</updated>' . DOKU_LF;
134
                    $entry .= '  <published>' . date_iso8601($meta['date']['created']) . '</published>' . DOKU_LF;
135
                    $entry .= '  <id>' . $idTag . date("Y-m-d", $meta['date']['modified']) . ':'
136
                        . parse_url(wl($id), PHP_URL_PATH) . '</id>' . DOKU_LF;
137
                    $entry .= '</entry>' . DOKU_LF;
138
                    fwrite($fh, $entry);
139
                }
140
            }
141
        }
142
143
        fwrite($fh, $RSSend);
144
        return fclose($fh);
145
    }
146
147
    /**
148
     * will return true for non-public or hidden pages or pages that are not below or in the namespace.
149
     */
150
    private function skipPage($id, $namespace) {
151
        dbglog("helper_plugin_spatialhelper_sitemap::skipPage, check for $id in $namespace");
152
        if(isHiddenPage($id)) {
153
            return true;
154
        }
155
        if(auth_aclcheck($id, '', '') < AUTH_READ) {
156
            return true;
157
        }
158
159
        if(!empty($namespace)) {
160
            // only if id is in or below namespace
161
            if(0 !== strpos(getNS($id), $namespace)) {
162
                // dbglog("helper_plugin_spatialhelper_sitemap::skipPage, skipping $id, not in $namespace");
163
                return true;
164
            }
165
        }
166
        return false;
167
    }
168
169
    /**
170
     * Create a KML sitemap.
171
     *
172
     * @param $mediaID id
173
     *                 for the KML file
174
     */
175
    public function createKMLSitemap($mediaID) {
176
        global $conf;
177
        $namespace = getNS($mediaID);
178
179
        $KMLstart = '<?xml version="1.0" encoding="UTF-8"?>' . DOKU_LF;
180
        $KMLstart .= '<kml xmlns="http://www.opengis.net/kml/2.2" ';
181
        $KMLstart .= 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
182
        $KMLstart .= 'xmlns:atom="http://www.w3.org/2005/Atom"';
183
        $KMLstart .= ' xsi:schemaLocation="http://www.opengis.net/kml/2.2 ';
184
        $KMLstart .= 'http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd">' . DOKU_LF;
185
        $KMLstart .= '<Document id="root_doc">' . DOKU_LF;
186
        $KMLstart .= '<name>' . $conf['title'] . ' spatial sitemap</name>' . DOKU_LF;
187
        $KMLstart .= '<atom:link href="' . DOKU_URL . '" rel="related" type="text/html" />' . DOKU_LF;
188
        $KMLstart .= '<!-- atom:updated>' . date(DATE_ATOM) . '</atom:updated -->' . DOKU_LF;
189
        $KMLstart .= '<Style id="icon"><IconStyle><color>ffffffff</color><scale>1</scale>';
190
        $KMLstart .= '<Icon><href>'
191
            . DOKU_BASE . 'lib/plugins/spatialhelper/wikiitem.png</href></Icon></IconStyle></Style>' . DOKU_LF;
192
193
        $KMLend = '</Document>' . DOKU_LF . '</kml>';
194
195
        io_createNamespace($mediaID, 'media');
196
        @touch(mediaFN($mediaID));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
197
        @chmod(mediaFN($mediaID), $conf['fmode']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
198
199
        $fh = fopen(mediaFN($mediaID), 'w');
200
        fwrite($fh, $KMLstart);
201
202
        foreach($this->spatial_idx as $idxEntry) {
203
            // get list of id's
204
            foreach($idxEntry as $id) {
205
                // for document item in the index
206
                if(strpos($id, 'media__', 0) !== 0) {
207
                    if($this->skipPage($id, $namespace)) {
208
                        continue;
209
                    }
210
211
                    $meta = p_get_metadata($id);
212
213
                    // $desc = p_render('xhtmlsummary', p_get_instructions($meta['description']['abstract']), $info);
214
                    $desc = '<p>' . strip_tags($meta['description']['abstract']) . '</p>';
215
                    $desc .= '<p><a href="' . wl($id, '', true) . '">' . $meta['title'] . '</a></p>';
216
217
                    // create an entry and store it
218
                    $plcm = '<Placemark id="crc32-' . hash('crc32', $id) . '">' . DOKU_LF;
219
                    $plcm .= '  <name>' . $meta['title'] . '</name>' . DOKU_LF;
220
                    // TODO escape quotes in: title="' . $meta['title'] . '"
221
                    $plcm .= '  <atom:link href="' . wl($id, '' . true) . '" rel="alternate" type="text/html" />'
222
                        . DOKU_LF;
223
                    if(!empty($meta['creator'])) {
224
                        $entry .= '  <atom:author><atom:name>' . $meta['creator'] . '</atom:name></atom:author>'
0 ignored issues
show
Bug introduced by
The variable $entry does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
225
                            . DOKU_LF;
226
                    }
227
228
                    $plcm .= '  <description><![CDATA[' . $desc . ']]></description>' . DOKU_LF;
229
                    $plcm .= '  <styleUrl>#icon</styleUrl>' . DOKU_LF;
230
231
                    $plcm .= '  <Point><coordinates>' . $meta['geo']['lon'] . ',' . $meta['geo']['lat'];
232
                    if($meta['geo']['alt']) {
233
                        $plcm .= ',' . $meta['geo']['alt'];
234
                    }
235
                    $plcm .= '</coordinates></Point>' . DOKU_LF;
236
                    $plcm .= '</Placemark>' . DOKU_LF;
237
238
                    fwrite($fh, $plcm);
239
                }
240
            }
241
        }
242
        fwrite($fh, $KMLend);
243
        return fclose($fh);
244
    }
245
}
246