Passed
Push — development ( 2c0f7a...866d79 )
by Thomas
01:59
created

htdocs/util2/cron/modules/geokrety.class.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/***************************************************************************
3
 *  For license information see doc/license.txt
4
 *  Import new data from geokrety.org.
5
 *  See util2/geokrety for check and repair functions.
6
 *  See discussion in http://redmine.opencaching.de/issues/18.
7
 ***************************************************************************/
8
9
checkJob(new Geokrety());
10
11
class Geokrety
12
{
13
    public $name = 'geokrety';
14
    public $interval = 900;
15
16
    public function run()
17
    {
18
        global $opt;
19
20
        if ($opt['cron']['geokrety']['run']) {
21
            $xmlfile = $this->loadXML();
22
            if ($xmlfile === false) {
23
                return;
24
            }
25
26
            $this->importXML($xmlfile);
27
            if (!$opt['cron']['geokrety']['xml_archive']) {
28
                $this->removeXML($xmlfile);
29
            }
30
        }
31
    }
32
33
    /* get file from XML interface
34
     * and return path of saved xml
35
     * or false on error
36
     */
37
    public function loadXML()
38
    {
39
        global $opt;
40
41
        if (!@mkdir(__DIR__ . '/../../../var/cache2/geokrety')) {
42
            // die('can\'t create geogrety cache dir');
43
        }
44
        $path = __DIR__ . '/../../../var/cache2/geokrety/import-' . date('Ymd-His') . '.xml';
45
46
        // Changed default-value for getSysConfig() from '2005-01-01 00:00:00' to 'NOW - 9d 12h'
47
        // to safely stay in api-limit, even when client and server are in different time zones.
48
        $modifiedSince = strtotime(
49
            getSysConfig('geokrety_lastupdate', date($opt['db']['dateformat'], time() - 60 * 60 * 24 * 9.5))
50
        );
51
        if (!@copy('https://geokrety.org/export.php?modifiedsince=' . date('YmdHis', $modifiedSince - 1), $path)) {
52
            return false;
53
        }
54
55
        return $path;
56
    }
57
58
    /**
59
     * @param string $file
60
     */
61
    public function removeXML($file)
62
    {
63
        @unlink($file);
64
    }
65
66
    /**
67
     * @param string $file
68
     */
69
    public function importXML($file)
70
    {
71
        global $opt;
72
73
        $xr = new XMLReader();
74
        if (!$xr->open($file)) {
75
            $xr->close();
76
77
            return;
78
        }
79
80
        $xr->read();
81
        if ($xr->nodeType != XMLReader::ELEMENT) {
82
            echo 'error: First element expected, aborted' . "\n";
83
84
            return;
85
        }
86
        if ($xr->name != 'gkxml') {
87
            echo 'error: First element not valid, aborted' . "\n";
88
89
            return;
90
        }
91
92
        $startUpdate = $xr->getAttribute('date');
93
        if ($startUpdate === '') {
94
            echo 'error: Date attribute not valid, aborted' . "\n";
95
96
            return;
97
        }
98
//      is probably noot needed
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
99
//        while ($xr->read() && !($xr->name == 'geokret' || $xr->name == 'moves')) {}
100
101
        $nRecordsCount = 0;
102
        do {
103
            if ($xr->nodeType == XMLReader::ELEMENT) {
104
                $element = $xr->expand();
105
                switch ($xr->name) {
106
                    case 'geokret':
107
                        $this->importGeoKret($element);
108
                        break;
109
                    case 'moves':
110
                        $this->importMove($element);
111
                        break;
112
                }
113
114
                $nRecordsCount++;
115
            }
116
        } while ($xr->next());
117
118
        $xr->close();
119
120
        setSysConfig('geokrety_lastupdate', date($opt['db']['dateformat'], strtotime($startUpdate)));
121
    }
122
123
    /**
124
     * @param DOMNode $element
125
     */
126
    public function importGeoKret($element)
127
    {
128
        global $opt;
129
130
        $id = $element->getAttribute('id');
131
132
        $name = html_entity_decode($this->getNodeValue($element, 'name'));
133
        if ($name === '') {
134
            return;
135
        }
136
137
        $userId = $this->getNodeAttribute($element, 'owner', 'id') + 0;
138
        $username = $this->getNodeValue($element, 'owner');
139
        $this->checkUser($userId, $username);
140
141
        $typeId = $this->getNodeAttribute($element, 'type', 'id') + 0;
142
        $typename = $this->getNodeValue($element, 'type');
143
        $this->checkGeoKretType($typeId, $typename);
144
145
        $description = html_entity_decode($this->getNodeValue($element, 'description'));
146
        $dateCreated = strtotime($this->getNodeValue($element, 'datecreated'));
147
148
        $distanceTravelled = $this->getNodeValue($element, 'distancetravelled') + 0;
149
        $state = $this->getNodeValue($element, 'state') + 0;
150
151
        $longitude = $this->getNodeAttribute($element, 'position', 'longitude') + 0;
152
        $latitude = $this->getNodeAttribute($element, 'position', 'latitude') + 0;
153
154
        sql(
155
            "INSERT INTO `gk_item`
156
                    (`id`, `name`, `description`, `userid`, `datecreated`,
157
                    `distancetravelled`, `latitude`, `longitude`, `typeid`, `stateid`)
158
            VALUES ('&1', '&2', '&3', '&4', '&5', '&6', '&7', '&8', '&9', '&10')
159
            ON DUPLICATE KEY UPDATE
160
            `name`='&2', `description`='&3', `userid`='&4', `datecreated`='&5', `distancetravelled`='&6',
161
            `latitude`='&7', `longitude`='&8', `typeid`='&9', `stateid`='&10'",
162
            $id,
163
            $name,
164
            $description,
165
            $userId,
166
            date($opt['db']['dateformat'], $dateCreated),
167
            $distanceTravelled,
168
            $latitude,
169
            $longitude,
170
            $typeId,
171
            $state
172
        );
173
174
        // Deleting and inserting item-waypoints if they have not changed will
175
        // update caches.meta_last_modified -> caches.okapi_syncbase and thus trigger
176
        // OKAPI changelog actions. This probably can be ignored as OKAPI will verify
177
        // if data has really changed.
178
179
        // update associated waypoints
180
        /**
181
         * This does not work properly, because geokret.waypoints does NOT contain the
182
         * current location of the Kret but something like the last cache where it was logged.
183
         * Evaluating the 'state' fielt might help, but for now, we import waypoint data
184
         * from the moves instead.
185
         * sql("DELETE FROM `gk_item_waypoint` WHERE id='&1'", $id);
186
         * $waypoints = $element->getElementsByTagName('waypoints');
187
         * if ($waypoints->length > 0)
188
         * {
189
         * $wpItems = $waypoints->item(0)->getElementsByTagName('waypoint');
190
         * for ($i = 0; $i < $wpItems->length; $i++)
191
         * {
192
         * $wp = $wpItems->item($i)->nodeValue;
193
         * if ($wp != '')
194
         * sql("INSERT INTO `gk_item_waypoint`
195
         * (`id`, `wp`)
196
         * VALUES
197
         * ('&1', '&2')",
198
         * $id, $wp);
199
         * }
200
         * }
201
         */
202
    }
203
204
    /**
205
     * @param DOMNode $element
206
     */
207
    public function importMove($element)
208
    {
209
        global $opt;
210
211
        $id = $element->getAttribute('id') + 0;
212
213
        $gkId = $this->getNodeAttribute($element, 'geokret', 'id') + 0;
214
        if (sql_value("SELECT COUNT(*) FROM `gk_item` WHERE `id`='&1'", 0, $gkId) == 0) {
215
            return;
216
        }
217
218
        $latitude = $this->getNodeAttribute($element, 'position', 'latitude') + 0;
219
        $longitude = $this->getNodeAttribute($element, 'position', 'longitude') + 0;
220
221
        $dateLogged = strtotime($this->getNodeAttribute($element, 'date', 'logged'));
222
        $dateMoved = strtotime($this->getNodeAttribute($element, 'date', 'moved'));
223
        $userId = $this->getNodeAttribute($element, 'user', 'id') + 0;
224
        $username = $this->getNodeValue($element, 'user');
225
        $this->checkUser($userId, $username);
226
227
        $comment = html_entity_decode($this->getNodeValue($element, 'comment'));
228
        $logTypeId = $this->getNodeAttribute($element, 'logtype', 'id') + 0;
229
        $logTypeName = $this->getNodeValue($element, 'logtype');
230
        $this->checkMoveType($logTypeId, $logTypeName);
231
232
        sql(
233
            "INSERT INTO `gk_move`
234
                (`id`, `itemid`, `latitude`, `longitude`, `datemoved`, `datelogged`, `userid`, `comment`, `logtypeid`)
235
            VALUES ('&1', '&2', '&3', '&4', '&5', '&6', '&7', '&8', '&9')
236
            ON DUPLICATE KEY UPDATE
237
                `itemid`='&2', `latitude`='&3', `longitude`='&4', `datemoved`='&5',
238
                `datelogged`='&6', `userid`='&7', `comment`='&8', `logtypeid`='&9'",
239
            $id,
240
            $gkId,
241
            $latitude,
242
            $longitude,
243
            date($opt['db']['dateformat'], $dateMoved),
244
            date($opt['db']['dateformat'], $dateLogged),
245
            $userId,
246
            $comment,
247
            $logTypeId
248
        );
249
250
        sql("DELETE FROM `gk_move_waypoint` WHERE id='&1'", $id);
251
252
        // update associated waypoints
253
        $waypoints = $element->getElementsByTagName('waypoints');
254
        if ($waypoints->length > 0) {
255
            $wpItems = $waypoints->item(0)->getElementsByTagName('waypoint');
256
            for ($i = 0; $i < $wpItems->length; $i++) {
257
                $wp = mb_trim($wpItems->item($i)->nodeValue);
258
                if ($wp != '') {
259
                    sql("INSERT INTO `gk_move_waypoint` (`id`, `wp`) VALUES ('&1', '&2')", $id, $wp);
260
                }
261
            }
262
        }
263
264
        // update the current gk-waypoints based on the last move
265
        sql("DELETE FROM `gk_item_waypoint` WHERE `id`='&1'", $gkId);
266
        $rs = sql(
267
            "
268
                SELECT `id`,`logtypeid` FROM `gk_move`
269
                WHERE `itemid`='&1' AND `logtypeid`!=2
270
                ORDER BY `datemoved` DESC LIMIT 1",
271
            $gkId
272
        );
273
        $r = sql_fetch_assoc($rs);
274
        sql_free_result($rs);
275
        if ($r === false) {
276
            return;
277
        }
278
279
        if ($r['logtypeid'] == 0 /* dropped */ || $r['logtypeid'] == 3 /* seen in */) {
280
            sql(
281
                "
282
                INSERT INTO `gk_item_waypoint` (`id`, `wp`)
283
                SELECT '&1' AS `id`, `wp`
284
                FROM `gk_move_waypoint`
285
                WHERE `id`='&2' AND `wp`!=''",
286
                $gkId,
287
                $r['id']
288
            ); // "late log" bugfix: replaced $id parameter by $r['id']
289
        }
290
    }
291
292
293
    /**
294
     * @param integer $id
295
     * @param $name
296
     */
297
    public function checkGeoKretType($id, $name)
298
    {
299
        sql(
300
            "INSERT INTO `gk_item_type` (`id`, `name`) VALUES ('&1', '&2') ON DUPLICATE KEY UPDATE `name`='&2'",
301
            $id,
302
            $name
303
        );
304
    }
305
306
307
    /**
308
     * @param integer $id
309
     * @param $name
310
     */
311
    public function checkUser($id, $name)
312
    {
313
        if ($id === 0) {
314
            return;
315
        }
316
317
        sql("INSERT INTO `gk_user` (`id`, `name`) VALUES ('&1', '&2') ON DUPLICATE KEY UPDATE `name`='&2'", $id, $name);
318
    }
319
320
321
    /**
322
     * @param integer $id
323
     * @param $name
324
     */
325
    public function checkMoveType($id, $name)
326
    {
327
        sql(
328
            "INSERT INTO `gk_move_type` (`id`, `name`) VALUES ('&1', '&2') ON DUPLICATE KEY UPDATE `name`='&2'",
329
            $id,
330
            $name
331
        );
332
    }
333
334
335
    /**
336
     * @param $domNode
337
     * @param string $element
338
     * @return string
339
     */
340
    public function getNodeValue(&$domNode, $element)
341
    {
342
        $subNode = $domNode->getElementsByTagName($element);
343
        if ($subNode->length < 1) {
344
            return '';
345
        } else {
346
            return $subNode->item(0)->nodeValue;
347
        }
348
    }
349
350
351
    /**
352
     * @param string $element
353
     * @param string $attr
354
     * @return string
355
     */
356
    public function getNodeAttribute(&$domNode, $element, $attr)
357
    {
358
        $subNode = $domNode->getElementsByTagName($element);
359
        if ($subNode->length < 1) {
360
            return '';
361
        } else {
362
            return $subNode->item(0)->getAttribute($attr);
363
        }
364
    }
365
}
366