1<?php
2/**
3 * DokuWiki Plugin rating (Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <gohr@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class helper_plugin_rating extends DokuWiki_Plugin {
13
14    /** @var helper_plugin_sqlite */
15    protected $sqlite = null;
16
17    /**
18     * initializes the DB connection
19     *
20     * @return helper_plugin_sqlite|null
21     */
22    public function getDBHelper() {
23        if(!is_null($this->sqlite)) return $this->sqlite;
24
25        $this->sqlite = plugin_load('helper', 'sqlite');
26        if(!$this->sqlite) {
27            msg('The rating plugin requires the sqlite plugin', -1);
28            $this->sqlite = null;
29            return null;
30        }
31
32        $ok = $this->sqlite->init('rating', __DIR__ . '/db');
33        if(!$ok) {
34            msg('rating plugin sqlite initialization failed', -1);
35            $this->sqlite = null;
36            return null;
37        }
38
39        return $this->sqlite;
40    }
41
42    /**
43     * Current user identifier
44     *
45     * @return string
46     */
47    public function userID() {
48        if(isset($_SERVER['REMOTE_USER'])) return $_SERVER['REMOTE_USER'];
49        return clientIP(true);
50    }
51
52    /**
53     * Display the rating tool in a template
54     *
55     * @param bool $inner used for AJAX updates
56     */
57    public function tpl($inner = false) {
58        global $ID;
59
60        $sqlite = $this->getDBHelper();
61        if(!$sqlite) return;
62
63        $sql     = "SELECT sum(value) FROM ratings WHERE page = ?";
64        $res     = $sqlite->query($sql, $ID);
65        $current = (int) $sqlite->res2single($res);
66        $sqlite->res_close($res);
67
68        $sql  = "SELECT value FROM ratings WHERE page = ? AND rater = ?";
69        $res  = $sqlite->query($sql, $ID, $this->userID());
70        $self = (int) $sqlite->res2single($res);
71        $sqlite->res_close($res);
72
73        if(!$inner) echo '<div class="plugin_rating">';
74        echo '<span class="intro">' . $this->getLang('intro') . '</span>';
75
76        $class = ($self == -1) ? 'act' : '';
77        echo '<a href="' . wl($ID, array('rating' => -1)) . '" class="plugin_rating_down ' . $class . ' plugin_feedback" data-rating="-1">-1</a>';
78        echo '<span class="current">' . $current . '</span>';
79
80        $class = ($self == 1) ? 'act' : '';
81        echo '<a href="' . wl($ID, array('rating' => +1)) . '" class="plugin_rating_up ' . $class . '" data-rating="1">+1</a>';
82
83        if(!$inner) echo '</div>';
84    }
85
86    /**
87     * Removes all entries for a page
88     *
89     * @param $page
90     */
91    public function remove($page) {
92        $sqlite = $this->getDBHelper();
93        if(!$sqlite) return;
94
95        $sql = "DELETE FROM ratings WHERE page = ?";
96        $res  = $sqlite->query($sql, $page);
97        $sqlite->res_close($res);
98    }
99
100    /**
101     * Get the best voted pages
102     *
103     * @param int $num
104     * @return array
105     */
106    public function best($lang, $startdate, $num = 10) {
107        $sqlite = $this->getDBHelper();
108        if(!$sqlite) return array();
109
110        $sqlbegin  = "SELECT sum(value) as val, page, lang FROM ratings ";
111        $sqlend = "GROUP BY page ORDER BY sum(value) DESC LIMIT ?";
112        if ($lang === null && $startdate === null){
113            $sql = $sqlbegin . $sqlend;
114            $res  = $sqlite->query($sql, $num);
115        } else if ($lang !== null && $startdate === null) {
116            $sql = $sqlbegin . "WHERE lang = ? " . $sqlend;
117            $res  = $sqlite->query($sql, $lang, $num);
118        } else if ($lang === null && $startdate !== null){
119            $sql = $sqlbegin . "WHERE date >= ? " . $sqlend;
120            $res  = $sqlite->query($sql, $startdate, $num);
121        } else {
122            $sql = $sqlbegin . "WHERE lang = ? AND date >= ? " . $sqlend;
123            $res  = $sqlite->query($sql, $lang, $startdate, $num);
124        }
125        $list = $sqlite->res2arr($res);
126        $sqlite->res_close($res);
127        return $list;
128    }
129
130    /**
131     * Store a rating
132     *
133     * @param int $rate either -1 or +1
134     * @param string $page page to rate
135     */
136    public function rate($rate, $page) {
137        if($rate < -1) $rate = -1;
138        if($rate > 1) $rate = 1;
139
140        $sqlite = $this->getDBHelper();
141        if(!$sqlite) return;
142
143        // ignore any bot accesses
144        if(!class_exists('Jaybizzle\CrawlerDetect\CrawlerDetect')){
145            require (__DIR__ . '/CrawlerDetect.php');
146        }
147        $CrawlerDetect = new Jaybizzle\CrawlerDetect\CrawlerDetect();
148        if($CrawlerDetect->isCrawler()) return;
149
150        $translation = plugin_load('helper', 'translation');
151        if (!$translation) {
152            $lang = '';
153        } else {
154            $lang = $translation->getLangPart($page);
155        }
156
157        $date = date('Y-m-d');
158
159        $sql = "INSERT OR REPLACE INTO ratings (page, rater, lang, date, value) VALUES (?, ?, ?, ?, ?)";
160        $sqlite->query($sql, $page, $this->userID(), $lang, $date, $rate);
161    }
162}
163
164// vim:ts=4:sw=4:et:
165