1<?php
2/**
3 * DokuWiki Plugin log404 (Helper Component)
4 *
5 * @license GPL 3 http://www.gnu.org/licenses/gpl-3.0.html
6 * @author  Sam Wilson <sam@samwilson.id.au>
7 */
8class helper_plugin_log404 extends DokuWiki_Plugin {
9
10    /** @var array Loaded data */
11    private $data;
12
13    public function getMethods() {
14        $methods = array();
15        $methods[] = array(
16            'name' => 'filename',
17            'desc' => 'Get the filename of the log file used to store 404 data.',
18            'params' => array(),
19            'return' => array('filename' => 'string'),
20        );
21        $methods[] = array(
22            'name' => 'getRecords',
23            'desc' => 'Get a multi-dimensional array of 404 log data.',
24            'params' => array(),
25            'return' => array('records' => 'array'),
26        );
27        return $methods;
28    }
29
30    public function load() {
31        $this->data = array();
32        if (!file_exists($this->filename())) {
33            return;
34        }
35        $log = fopen($this->filename(), 'r');
36        while ($line = fgetcsv($log, 900)) { // Is 900 okay for max line length?
37            if (!isset($this->data[$line[1]])) {
38                $this->data[$line[1]] = array(
39                    'count' => 0,
40                    'hits' => array(),
41                );
42            }
43            $this->data[$line[1]]['count'] ++;
44            if (count($line) === 4) {
45                // Prior to the inclusion of the IP address there were 4 items
46                // in this order: date, page ID, referer, and user agent.
47                $this->data[$line[1]]['hits'][] = array(
48                    'date' => $line[0],
49                    'ip' => '',
50                    'referer' => $line[2],
51                    'user_agent' => $line[3],
52                );
53            } else {
54                // After the inclusion there were 5:
55                // date, page ID, IP address, referer, and user agent.
56                $this->data[$line[1]]['hits'][] = array(
57                    'date' => $line[0],
58                    'ip' => $line[2],
59                    'referer' => $line[3],
60                    'user_agent' => $line[4],
61                );
62            }
63        }
64        fclose($log);
65        uasort($this->data, array($this, 'compareCounts'));
66    }
67
68    public function save($id) {
69        $datetime = date('Y-m-d H:i:s');
70        $page = cleanID($id);
71        $ipAddress = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
72        $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
73        $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
74        $logline = $datetime.','.$page.','.$ipAddress.',"'.$referer.'","'.$agent.'"'.PHP_EOL;
75        if (!io_saveFile($this->filename(), $logline, true)) {
76            msg("Unable to write log404 file.");
77        }
78    }
79
80    public function getRecords() {
81        return $this->data;
82    }
83
84    public function getRecord($id) {
85        return (isset($this->data[$id])) ? $this->data[$id] : false;
86    }
87
88    public function deleteRecord($id) {
89        $tmpFilename = $this->filename().'.temp';
90        $logTemp = fopen($tmpFilename, 'w');
91        $this->load();
92        foreach ($this->getRecords() as $rid=>$rinfo) {
93            if ($rid != $id) {
94                foreach ($rinfo['hits'] as $hit) {
95                    $line = array(
96                        $hit['date'],
97                        $rid,
98                        $hit['ip'],
99                        $hit['referer'],
100                        $hit['user_agent'],
101                    );
102                    fputcsv($logTemp, $line);
103                }
104            }
105        }
106        fclose($logTemp);
107        unlink($this->filename());
108        rename($tmpFilename, $this->filename());
109        $this->load();
110    }
111
112    public function filename() {
113        global $conf;
114        return fullpath($conf['metadir'].DIRECTORY_SEPARATOR.'log404.csv');
115    }
116
117    public function recordCount() {
118        return count($this->getRecords());
119    }
120
121    protected function compareCounts($a, $b) {
122        return $b['count'] - $a['count'];
123    }
124
125}
126
127// vim:ts=4:sw=4:et:
128