1<?php
2
3use dokuwiki\ErrorHandler;
4use dokuwiki\plugin\sqlite\SQLiteDB;
5
6/**
7 * DokuWiki Plugin starred (Helper Component)
8 *
9 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
10 * @author  Andreas Gohr <dokuwiki@cosmocode.de>
11 */
12class helper_plugin_starred extends DokuWiki_Plugin
13{
14
15    /** @var SQLiteDB */
16    protected $db;
17
18    /**
19     * load the sqlite class
20     *
21     * @return SQLiteDB|null
22     */
23    public function getDB()
24    {
25        if($this->db !== null) return $this->db;
26
27        try {
28            $this->db = new SQLiteDB('starred', __DIR__ . '/db/');
29            return $this->db;
30        } catch (Exception $e) {
31            ErrorHandler::logException($e);
32            msg($this->getLang('e_nosqlite'), -1);
33            return null;
34        }
35    }
36
37    /**
38     * toggle the star for the user and page
39     * @param string|null $user defaults to current user
40     * @param string|null $pageid defaults to current page
41     */
42    public function toggleStar($user = null, $pageid = null)
43    {
44        global $ID;
45        global $INPUT;
46
47        // DB access
48        $db = $this->getDB();
49        if (!$db) return;
50
51        // param defaults
52        if ($pageid === null) $pageid = $ID;
53        if ($user === null) $user = $INPUT->server->str('REMOTE_USER');
54        if (blank($user)) return;
55
56        $on = $this->checkStar($user, $pageid); // currently on?
57
58        if ($on) {
59            //delete
60            $sql = "DELETE FROM stars WHERE pid = ? AND login = ?";
61            $db->exec($sql, [$pageid, $user]);
62        } else {
63            //add
64            $sql = "INSERT OR IGNORE INTO stars (pid,login,stardate) VALUES (?,?,?)";
65            $db->exec($sql, [$pageid, $user, time()]);
66        }
67    }
68
69    /**
70     * check the star for the current user and page
71     *
72     * @param string|null $user defaults to current user
73     * @param string|null $pageid defaults to current page
74     * @return bool|int the time the star was added or false if not
75     */
76    public function checkStar($user = null, $pageid = null)
77    {
78        global $ID;
79        global $INPUT;
80
81        // DB access
82        $db = $this->getDB();
83        if (!$db) return false;
84
85        // param defaults
86        if ($pageid === null) $pageid = $ID;
87        if ($user === null) $user = $INPUT->server->str('REMOTE_USER');
88        if (blank($user)) return false;
89
90        $sql = "SELECT stardate FROM stars WHERE pid = ? AND login = ?";
91        return (int)$db->queryValue($sql, [$pageid, $user]);
92    }
93
94    /**
95     * Load the starred pages of a given user
96     *
97     * @param string|null $user defaults to current user
98     * @param int $limit defaults to all
99     * @return array|bool
100     */
101    public function loadStars($user = null, $limit = 0)
102    {
103        global $INPUT;
104        $result = array();
105
106        $db = $this->getDB();
107        if (!$db) return $result;
108
109        if ($user === null) $user = $INPUT->server->str('REMOTE_USER');
110        if (blank($user)) return $result;
111
112        /** @var DokuWiki_Auth_Plugin $auth */
113        global $auth;
114
115        $sql = "SELECT pid, stardate FROM stars WHERE ";
116
117        if ($auth && !$auth->isCaseSensitive()) {
118            $sql .= 'lower(login) = lower(?)';
119        } else {
120            $sql .= 'login = ?';
121        }
122        $sql .= " ORDER BY stardate DESC";
123        if ($limit) {
124            $sql .= ' LIMIT ' . $limit;
125        }
126
127        return $db->queryKeyValueList($sql, [$user]);
128    }
129
130    /**
131     * Create the html for a star
132     *
133     * @param string $ID The page where the star is supposed to appear.
134     * @param string $pageid The page which the star is supposed to toggle.
135     * @param bool $inneronly
136     * @param bool $setid Must not be true more than once per page
137     * @return string The html for the star
138     */
139    public function starHtml($ID, $pageid, $inneronly = false, $setid = false)
140    {
141        $result = '';
142        $dt = $this->checkStar(null, $pageid);
143        if ($inneronly === false) {
144            $result .= '<a href="' . wl($ID, array('do' => 'startoggle_' . $pageid)) . '" data-pageid="' . $pageid . '" class="plugin__starred"';
145            if ($setid === true) {
146                $result .= ' id="plugin__starred">';
147            } else {
148                $result .= '>';
149            }
150        }
151
152        if ($dt) {
153            $result .= '<span title="' . $this->getLang('star_on') . '" class="starred on">';
154            $result .= inlineSVG(__DIR__ . '/pix/star.svg');
155            $result .= '</span>';
156        } else {
157            $result .= '<span title="' . $this->getLang('star_off') . '" class="starred off">';
158            $result .= inlineSVG(__DIR__ . '/pix/star-outline.svg');
159            $result .= '</span>';
160        }
161        if (!$inneronly) {
162            $result .= '</a>';
163        }
164        return $result;
165    }
166}
167