xref: /plugin/acknowledge/helper.php (revision 9c3eae1e3c610e8434228ea1685aff223b6828aa)
1<?php
2/**
3 * DokuWiki Plugin acknowledge (Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr, Anna Dabrowska <dokuwiki@cosmocode.de>
7 */
8
9
10class helper_plugin_acknowledge extends DokuWiki_Plugin
11{
12
13    /**
14     * @return helper_plugin_sqlite|null
15     */
16    public function getDB()
17    {
18        /** @var \helper_plugin_sqlite $sqlite */
19        $sqlite = plugin_load('helper', 'sqlite');
20        if ($sqlite === null) {
21            msg($this->getLang('error sqlite plugin missing'), -1);
22            return null;
23        }
24        if (!$sqlite->init('acknowledgement', __DIR__ . '/db')) {
25            return null;
26        }
27
28        $this->registerUDF($sqlite);
29
30        return $sqlite;
31    }
32
33    /**
34     * Register user defined functions
35     *
36     * @param helper_plugin_sqlite $sqlite
37     */
38    protected function registerUDF($sqlite)
39    {
40        $sqlite->create_function('AUTH_ISMEMBER', [$this, 'auth_isMember'], -1);
41    }
42
43    /**
44     * Wrapper function for auth_isMember which accepts groups as string
45     *
46     * @param string $memberList
47     * @param string $user
48     * @param string $groups
49     * @return bool
50     */
51    public function auth_isMember($memberList, $user, $groups)
52    {
53        $a = 1;
54        return auth_isMember($memberList, $user, explode(',', $groups));
55    }
56
57    /**
58     * Delete a page
59     *
60     * Cascades to delete all assigned data, etc.
61     *
62     * @param string $page Page ID
63     */
64    public function removePage($page)
65    {
66        $sqlite = $this->getDB();
67        if (!$sqlite) return;
68
69        $sql = "DELETE FROM pages WHERE page = ?";
70        $sqlite->query($sql, $page);
71    }
72
73    /**
74     * Update last modified date of page
75     *
76     * @param string $page Page ID
77     * @param int $lastmod timestamp of last non-minor change
78     */
79    public function storePageDate($page, $lastmod)
80    {
81        $sqlite = $this->getDB();
82        if (!$sqlite) return;
83
84        $sql = "REPLACE INTO pages (page, lastmod) VALUES (?,?)";
85        $sqlite->query($sql, $page, $lastmod);
86    }
87
88    /**
89     * @param string $page Page ID
90     * @param string $assignees comma separated list of users and groups
91     */
92    public function setAssignees($page, $assignees)
93    {
94        $sqlite = $this->getDB();
95        if (!$sqlite) return;
96
97        $sql = "REPLACE INTO assignments ('page', 'assignee') VALUES (?,?)";
98        $sqlite->query($sql, $page, $assignees);
99    }
100
101    /**
102     * Clears assignments for a page
103     *
104     * @param string $page Page ID
105     */
106    public function clearAssignments($page)
107    {
108        $sqlite = $this->getDB();
109        if (!$sqlite) return;
110
111        $sql = "DELETE FROM assignments WHERE page = ?";
112        $sqlite->query($sql, $page);
113    }
114
115
116    /**
117     * Is the given user one of the assignees for this page
118     *
119     * @param string $page Page ID
120     * @param string $user user name to check
121     * @param string[] $groups groups this user is in
122     * @return bool
123     */
124    public function isUserAssigned($page, $user, $groups)
125    {
126        $sqlite = $this->getDB();
127        if (!$sqlite) return false;
128
129
130        $sql = "SELECT assignee FROM assignments WHERE page = ?";
131        $result = $sqlite->query($sql, $page);
132        $assignees = (string)$sqlite->res2single($result);
133        $sqlite->res_close($result);
134
135        return auth_isMember($assignees, $user, $groups);
136    }
137
138    /**
139     * Has the given user acknowledged the given page?
140     *
141     * @param string $page
142     * @param string $user
143     * @return bool|int timestamp of acknowledgement or false
144     */
145    public function hasUserAcknowledged($page, $user)
146    {
147        $sqlite = $this->getDB();
148        if (!$sqlite) return false;
149
150        $sql = "SELECT ack
151                  FROM acks A, pages B
152                 WHERE A.page = B.page
153                   AND A.page = ?
154                   AND A.user = ?
155                   AND A.ack >= B.lastmod";
156
157        $result = $sqlite->query($sql, $page, $user);
158        $acktime = $sqlite->res2single($result);
159        $sqlite->res_close($result);
160
161        return $acktime ? (int)$acktime : false;
162    }
163
164    /**
165     * Save user's acknowledgement for a given page
166     *
167     * @param string $page
168     * @param string $user
169     * @return bool
170     */
171    public function saveAcknowledgement($page, $user)
172    {
173        $sqlite = $this->getDB();
174        if (!$sqlite) return false;
175
176        $sql = "REPLACE INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))";
177
178        $result = $sqlite->query($sql, $page, $user);
179        $sqlite->res_close($result);
180        return true;
181
182    }
183
184    /**
185     * Fetch all assignments for a given user, with additional page information.
186     *
187     * @param string $user
188     * @return array|bool
189     */
190    public function getUserAssignments($user)
191    {
192        $sqlite = $this->getDB();
193        if (!$sqlite) return false;
194
195        global $USERINFO;
196        $groups = $USERINFO['grps'];
197
198        $sql = "SELECT * FROM assignments A
199                JOIN pages B
200                ON A.page = B.page
201                WHERE AUTH_ISMEMBER(A.assignee, ? , ?)";
202
203        $result = $sqlite->query($sql, $user, implode(',', $groups));
204        $assignments = $sqlite->res2arr($result);
205        $sqlite->res_close($result);
206
207        return $assignments;
208    }
209
210    /**
211     * Compare user's assignments with their past acknowledgements and return only pages
212     * without or with outdated acknowledgements
213     *
214     * @param string $user
215     * @param array $assignments
216     * @return array|bool
217     */
218    public function filterAcknowledged($user, $assignments)
219    {
220        $sqlite = $this->getDB();
221        if (!$sqlite) return false;
222
223        $sql = 'SELECT * FROM acks WHERE user = ?';
224        $result = $sqlite->query($sql, $user);
225        $acknowledgements = $sqlite->res2arr($result);
226        $sqlite->res_close($result);
227
228        $listing = [];
229        $pageAcks = array_column($acknowledgements, 'ack', 'page');
230        foreach ($assignments as $assignment) {
231            if (
232                !in_array($assignment['page'], array_keys($pageAcks))
233                || (int)$assignment['lastmod'] > (int)$pageAcks[$assignment['page']]
234            ) {
235                $listing[] = $assignment;
236            }
237        }
238
239        return $listing;
240    }
241
242    /**
243     * Returns all acknowledgements
244     *
245     * @return array|bool
246     */
247    public function getAcknowledgements()
248    {
249        $sqlite = $this->getDB();
250        if (!$sqlite) return false;
251
252        $sql = 'SELECT * FROM acks ORDER BY ack DESC';
253        $result = $sqlite->query($sql);
254        $acknowledgements = $sqlite->res2arr($result);
255        $sqlite->res_close($result);
256
257        return $acknowledgements;
258    }
259}
260
261