xref: /plugin/acknowledge/helper.php (revision 84db77b6273c1455870e5621c11197d2085e25cf)
14d6d17d0SAndreas Gohr<?php
2c6d8c1d9SAndreas Gohr
3c6d8c1d9SAndreas Gohruse dokuwiki\Extension\AuthPlugin;
4c6d8c1d9SAndreas Gohr
54d6d17d0SAndreas Gohr/**
64d6d17d0SAndreas Gohr * DokuWiki Plugin acknowledge (Helper Component)
74d6d17d0SAndreas Gohr *
84d6d17d0SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
94d6d17d0SAndreas Gohr * @author  Andreas Gohr, Anna Dabrowska <dokuwiki@cosmocode.de>
104d6d17d0SAndreas Gohr */
114d6d17d0SAndreas Gohrclass helper_plugin_acknowledge extends DokuWiki_Plugin
124d6d17d0SAndreas Gohr{
134d6d17d0SAndreas Gohr
14cabb51d3SAndreas Gohr    /**
15cabb51d3SAndreas Gohr     * @return helper_plugin_sqlite|null
16cabb51d3SAndreas Gohr     */
17cabb51d3SAndreas Gohr    public function getDB()
18cabb51d3SAndreas Gohr    {
19cabb51d3SAndreas Gohr        /** @var \helper_plugin_sqlite $sqlite */
20cabb51d3SAndreas Gohr        $sqlite = plugin_load('helper', 'sqlite');
21cabb51d3SAndreas Gohr        if ($sqlite === null) {
22cabb51d3SAndreas Gohr            msg($this->getLang('error sqlite plugin missing'), -1);
23cabb51d3SAndreas Gohr            return null;
24cabb51d3SAndreas Gohr        }
25cabb51d3SAndreas Gohr        if (!$sqlite->init('acknowledgement', __DIR__ . '/db')) {
26cabb51d3SAndreas Gohr            return null;
27cabb51d3SAndreas Gohr        }
28cabb51d3SAndreas Gohr
299c3eae1eSAnna Dabrowska        $this->registerUDF($sqlite);
309c3eae1eSAnna Dabrowska
31cabb51d3SAndreas Gohr        return $sqlite;
32cabb51d3SAndreas Gohr    }
33cabb51d3SAndreas Gohr
34cabb51d3SAndreas Gohr    /**
359c3eae1eSAnna Dabrowska     * Register user defined functions
369c3eae1eSAnna Dabrowska     *
379c3eae1eSAnna Dabrowska     * @param helper_plugin_sqlite $sqlite
389c3eae1eSAnna Dabrowska     */
399c3eae1eSAnna Dabrowska    protected function registerUDF($sqlite)
409c3eae1eSAnna Dabrowska    {
419c3eae1eSAnna Dabrowska        $sqlite->create_function('AUTH_ISMEMBER', [$this, 'auth_isMember'], -1);
429c3eae1eSAnna Dabrowska    }
439c3eae1eSAnna Dabrowska
449c3eae1eSAnna Dabrowska    /**
459c3eae1eSAnna Dabrowska     * Wrapper function for auth_isMember which accepts groups as string
469c3eae1eSAnna Dabrowska     *
479c3eae1eSAnna Dabrowska     * @param string $memberList
489c3eae1eSAnna Dabrowska     * @param string $user
499c3eae1eSAnna Dabrowska     * @param string $groups
509c3eae1eSAnna Dabrowska     * @return bool
519c3eae1eSAnna Dabrowska     */
529c3eae1eSAnna Dabrowska    public function auth_isMember($memberList, $user, $groups)
539c3eae1eSAnna Dabrowska    {
5495113ed8SAnna Dabrowska        return auth_isMember($memberList, $user, explode('///', $groups));
559c3eae1eSAnna Dabrowska    }
569c3eae1eSAnna Dabrowska
579c3eae1eSAnna Dabrowska    /**
58ef3ab392SAndreas Gohr     * Delete a page
59ef3ab392SAndreas Gohr     *
60ef3ab392SAndreas Gohr     * Cascades to delete all assigned data, etc.
61ef3ab392SAndreas Gohr     *
62ef3ab392SAndreas Gohr     * @param string $page Page ID
63ef3ab392SAndreas Gohr     */
64ef3ab392SAndreas Gohr    public function removePage($page)
65ef3ab392SAndreas Gohr    {
66ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
67ef3ab392SAndreas Gohr        if (!$sqlite) return;
68ef3ab392SAndreas Gohr
69ef3ab392SAndreas Gohr        $sql = "DELETE FROM pages WHERE page = ?";
70ef3ab392SAndreas Gohr        $sqlite->query($sql, $page);
71ef3ab392SAndreas Gohr    }
72ef3ab392SAndreas Gohr
73ef3ab392SAndreas Gohr    /**
745dee13f7SAnna Dabrowska     * Update last modified date of page if content has changed
75ef3ab392SAndreas Gohr     *
76ef3ab392SAndreas Gohr     * @param string $page Page ID
77ef3ab392SAndreas Gohr     * @param int $lastmod timestamp of last non-minor change
78ef3ab392SAndreas Gohr     */
795dee13f7SAnna Dabrowska    public function storePageDate($page, $lastmod, $newContent)
80ef3ab392SAndreas Gohr    {
81ed4e8871SAnna Dabrowska        $changelog = new \dokuwiki\ChangeLog\PageChangeLog($page);
82789aa26fSAnna Dabrowska        $revs = $changelog->getRevisions(0, 1);
83ed4e8871SAnna Dabrowska
84ed4e8871SAnna Dabrowska        // compare content
85ed4e8871SAnna Dabrowska        $oldContent = str_replace(NL, '', io_readFile(wikiFN($page, $revs[0])));
86ed4e8871SAnna Dabrowska        $newContent = str_replace(NL, '', $newContent);
87ed4e8871SAnna Dabrowska        if ($oldContent === $newContent) return;
88ed4e8871SAnna Dabrowska
89ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
90ef3ab392SAndreas Gohr        if (!$sqlite) return;
91ef3ab392SAndreas Gohr
92ef3ab392SAndreas Gohr        $sql = "REPLACE INTO pages (page, lastmod) VALUES (?,?)";
93ef3ab392SAndreas Gohr        $sqlite->query($sql, $page, $lastmod);
94ef3ab392SAndreas Gohr    }
95ef3ab392SAndreas Gohr
96ef3ab392SAndreas Gohr    /**
97cabb51d3SAndreas Gohr     * @param string $page Page ID
98cabb51d3SAndreas Gohr     * @param string $assignees comma separated list of users and groups
99cabb51d3SAndreas Gohr     */
100cabb51d3SAndreas Gohr    public function setAssignees($page, $assignees)
101cabb51d3SAndreas Gohr    {
102cabb51d3SAndreas Gohr        $sqlite = $this->getDB();
103cabb51d3SAndreas Gohr        if (!$sqlite) return;
104cabb51d3SAndreas Gohr
105cabb51d3SAndreas Gohr        $sql = "REPLACE INTO assignments ('page', 'assignee') VALUES (?,?)";
106cabb51d3SAndreas Gohr        $sqlite->query($sql, $page, $assignees);
107cabb51d3SAndreas Gohr    }
108cabb51d3SAndreas Gohr
109ef3ab392SAndreas Gohr    /**
1105773dd37SAnna Dabrowska     * Clears assignments for a page
111ef3ab392SAndreas Gohr     *
112ef3ab392SAndreas Gohr     * @param string $page Page ID
113ef3ab392SAndreas Gohr     */
114ef3ab392SAndreas Gohr    public function clearAssignments($page)
115ef3ab392SAndreas Gohr    {
116ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
117ef3ab392SAndreas Gohr        if (!$sqlite) return;
118cabb51d3SAndreas Gohr
119ef3ab392SAndreas Gohr        $sql = "DELETE FROM assignments WHERE page = ?";
120ef3ab392SAndreas Gohr        $sqlite->query($sql, $page);
121ef3ab392SAndreas Gohr    }
122ef3ab392SAndreas Gohr
123ef3ab392SAndreas Gohr    /**
124ef3ab392SAndreas Gohr     * Is the given user one of the assignees for this page
125ef3ab392SAndreas Gohr     *
126ef3ab392SAndreas Gohr     * @param string $page Page ID
127ef3ab392SAndreas Gohr     * @param string $user user name to check
128ef3ab392SAndreas Gohr     * @param string[] $groups groups this user is in
129ef3ab392SAndreas Gohr     * @return bool
130ef3ab392SAndreas Gohr     */
131ef3ab392SAndreas Gohr    public function isUserAssigned($page, $user, $groups)
132ef3ab392SAndreas Gohr    {
133ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
134ef3ab392SAndreas Gohr        if (!$sqlite) return false;
135ef3ab392SAndreas Gohr
136ef3ab392SAndreas Gohr        $sql = "SELECT assignee FROM assignments WHERE page = ?";
137ef3ab392SAndreas Gohr        $result = $sqlite->query($sql, $page);
138ef3ab392SAndreas Gohr        $assignees = (string)$sqlite->res2single($result);
139ef3ab392SAndreas Gohr        $sqlite->res_close($result);
140ef3ab392SAndreas Gohr
141ef3ab392SAndreas Gohr        return auth_isMember($assignees, $user, $groups);
142ef3ab392SAndreas Gohr    }
143ef3ab392SAndreas Gohr
144ef3ab392SAndreas Gohr    /**
145ef3ab392SAndreas Gohr     * Has the given user acknowledged the given page?
146ef3ab392SAndreas Gohr     *
147ef3ab392SAndreas Gohr     * @param string $page
148ef3ab392SAndreas Gohr     * @param string $user
1495773dd37SAnna Dabrowska     * @return bool|int timestamp of acknowledgement or false
150ef3ab392SAndreas Gohr     */
151ef3ab392SAndreas Gohr    public function hasUserAcknowledged($page, $user)
152ef3ab392SAndreas Gohr    {
153ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
154ef3ab392SAndreas Gohr        if (!$sqlite) return false;
155ef3ab392SAndreas Gohr
156ef3ab392SAndreas Gohr        $sql = "SELECT ack
157ef3ab392SAndreas Gohr                  FROM acks A, pages B
158ef3ab392SAndreas Gohr                 WHERE A.page = B.page
1595773dd37SAnna Dabrowska                   AND A.page = ?
1605773dd37SAnna Dabrowska                   AND A.user = ?
161ef3ab392SAndreas Gohr                   AND A.ack >= B.lastmod";
162ef3ab392SAndreas Gohr
163ef3ab392SAndreas Gohr        $result = $sqlite->query($sql, $page, $user);
164ef3ab392SAndreas Gohr        $acktime = $sqlite->res2single($result);
165ef3ab392SAndreas Gohr        $sqlite->res_close($result);
166ef3ab392SAndreas Gohr
167ef3ab392SAndreas Gohr        return $acktime ? (int)$acktime : false;
168ef3ab392SAndreas Gohr    }
1695773dd37SAnna Dabrowska
1705773dd37SAnna Dabrowska    /**
171d9a8334dSAnna Dabrowska     * Timestamp of the latest acknowledgment of the given page
172d9a8334dSAnna Dabrowska     * by the given user
173d9a8334dSAnna Dabrowska     *
174d9a8334dSAnna Dabrowska     * @param string $page
175d9a8334dSAnna Dabrowska     * @param string $user
176d9a8334dSAnna Dabrowska     * @return bool|string
177d9a8334dSAnna Dabrowska     */
178d9a8334dSAnna Dabrowska    public function getLatestUserAcknowledgement($page, $user)
179d9a8334dSAnna Dabrowska    {
180d9a8334dSAnna Dabrowska        $sqlite = $this->getDB();
181d9a8334dSAnna Dabrowska        if (!$sqlite) return false;
182d9a8334dSAnna Dabrowska
183d9a8334dSAnna Dabrowska        $sql = "SELECT MAX(ack)
184d9a8334dSAnna Dabrowska                  FROM acks
185d9a8334dSAnna Dabrowska                 WHERE page = ?
186d9a8334dSAnna Dabrowska                   AND user = ?";
187d9a8334dSAnna Dabrowska
188d9a8334dSAnna Dabrowska        $result = $sqlite->query($sql, $page, $user);
189d9a8334dSAnna Dabrowska        $latestAck = $sqlite->res2single($result);
190d9a8334dSAnna Dabrowska        $sqlite->res_close($result);
191d9a8334dSAnna Dabrowska
192d9a8334dSAnna Dabrowska        return $latestAck;
193d9a8334dSAnna Dabrowska    }
194d9a8334dSAnna Dabrowska
195d9a8334dSAnna Dabrowska    /**
1965773dd37SAnna Dabrowska     * Save user's acknowledgement for a given page
1975773dd37SAnna Dabrowska     *
1985773dd37SAnna Dabrowska     * @param string $page
1995773dd37SAnna Dabrowska     * @param string $user
2005773dd37SAnna Dabrowska     * @return bool
2015773dd37SAnna Dabrowska     */
2025773dd37SAnna Dabrowska    public function saveAcknowledgement($page, $user)
2035773dd37SAnna Dabrowska    {
2045773dd37SAnna Dabrowska        $sqlite = $this->getDB();
2055773dd37SAnna Dabrowska        if (!$sqlite) return false;
2065773dd37SAnna Dabrowska
2078e55e483SAnna Dabrowska        $sql = "INSERT INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))";
2085773dd37SAnna Dabrowska
2095773dd37SAnna Dabrowska        $result = $sqlite->query($sql, $page, $user);
2105773dd37SAnna Dabrowska        $sqlite->res_close($result);
2115773dd37SAnna Dabrowska        return true;
2125773dd37SAnna Dabrowska
2135773dd37SAnna Dabrowska    }
21474126d4bSAnna Dabrowska
21574126d4bSAnna Dabrowska    /**
21660ed3784SAnna Dabrowska     * Fetch all assignments for a given user, with additional page information,
21760ed3784SAnna Dabrowska     * filtering already granted acknowledgements.
21874126d4bSAnna Dabrowska     *
21974126d4bSAnna Dabrowska     * @param string $user
2208c50976eSAnna Dabrowska     * @param array $groups
22174126d4bSAnna Dabrowska     * @return array|bool
22274126d4bSAnna Dabrowska     */
2238c50976eSAnna Dabrowska    public function getUserAssignments($user, $groups)
22474126d4bSAnna Dabrowska    {
22574126d4bSAnna Dabrowska        $sqlite = $this->getDB();
22674126d4bSAnna Dabrowska        if (!$sqlite) return false;
22774126d4bSAnna Dabrowska
22860ed3784SAnna Dabrowska        $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, C.ack FROM assignments A
22974126d4bSAnna Dabrowska                JOIN pages B
23074126d4bSAnna Dabrowska                ON A.page = B.page
23160ed3784SAnna Dabrowska                LEFT JOIN acks C
2322541208bSAnna Dabrowska                ON A.page = C.page AND ( (C.user = ? AND C.ack > B.lastmod) )
23360ed3784SAnna Dabrowska                WHERE AUTH_ISMEMBER(A.assignee, ? , ?)
2348e55e483SAnna Dabrowska                AND ack IS NULL";
23574126d4bSAnna Dabrowska
2362541208bSAnna Dabrowska        $result = $sqlite->query($sql, $user, $user, implode('///', $groups));
23774126d4bSAnna Dabrowska        $assignments = $sqlite->res2arr($result);
23874126d4bSAnna Dabrowska        $sqlite->res_close($result);
23974126d4bSAnna Dabrowska
24074126d4bSAnna Dabrowska        return $assignments;
24174126d4bSAnna Dabrowska    }
24274126d4bSAnna Dabrowska
24374126d4bSAnna Dabrowska    /**
244863b6e48SAndreas Gohr     * Get all pages a user needs to acknowledge and the last acknowledge date
245d6011abdSAnna Dabrowska     *
246863b6e48SAndreas Gohr     * @param string $user
247863b6e48SAndreas Gohr     * @param array $groups
248d6011abdSAnna Dabrowska     * @return array|bool
249d6011abdSAnna Dabrowska     */
250863b6e48SAndreas Gohr    public function getUserAcknowledgements($user, $groups)
251d6011abdSAnna Dabrowska    {
252d6011abdSAnna Dabrowska        $sqlite = $this->getDB();
253d6011abdSAnna Dabrowska        if (!$sqlite) return false;
254d6011abdSAnna Dabrowska
255863b6e48SAndreas Gohr        $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, MAX(C.ack) AS ack
256863b6e48SAndreas Gohr                  FROM assignments A
257863b6e48SAndreas Gohr                  JOIN pages B
258863b6e48SAndreas Gohr                    ON A.page = B.page
259863b6e48SAndreas Gohr             LEFT JOIN acks C
260863b6e48SAndreas Gohr                    ON A.page = C.page AND C.user = ?
261863b6e48SAndreas Gohr                 WHERE AUTH_ISMEMBER(A.assignee, ? , ?)
262863b6e48SAndreas Gohr            GROUP BY A.page
263863b6e48SAndreas Gohr            ORDER BY A.page
264863b6e48SAndreas Gohr            ";
265863b6e48SAndreas Gohr
266863b6e48SAndreas Gohr        $result = $sqlite->query($sql, $user, $user, implode('///', $groups));
267863b6e48SAndreas Gohr        $assignments = $sqlite->res2arr($result);
268863b6e48SAndreas Gohr        $sqlite->res_close($result);
269863b6e48SAndreas Gohr
270863b6e48SAndreas Gohr        return $assignments;
271863b6e48SAndreas Gohr    }
272863b6e48SAndreas Gohr
273863b6e48SAndreas Gohr    /**
274c6d8c1d9SAndreas Gohr     * Resolve names of users assigned to a given page
275c6d8c1d9SAndreas Gohr     *
276c6d8c1d9SAndreas Gohr     * This can be slow on huge user bases!
277c6d8c1d9SAndreas Gohr     *
278c6d8c1d9SAndreas Gohr     * @param string $page
279c6d8c1d9SAndreas Gohr     * @return array|false
280c6d8c1d9SAndreas Gohr     */
281c6d8c1d9SAndreas Gohr    public function getPageAssignees($page)
282c6d8c1d9SAndreas Gohr    {
283c6d8c1d9SAndreas Gohr        $sqlite = $this->getDB();
284c6d8c1d9SAndreas Gohr        if (!$sqlite) return false;
285c6d8c1d9SAndreas Gohr        /** @var AuthPlugin $auth */
286c6d8c1d9SAndreas Gohr        global $auth;
287c6d8c1d9SAndreas Gohr
288c6d8c1d9SAndreas Gohr        $sql = "SELECT assignee
289c6d8c1d9SAndreas Gohr                  FROM assignments
290c6d8c1d9SAndreas Gohr                 WHERE page = ?";
291c6d8c1d9SAndreas Gohr        $result = $sqlite->query($sql, $page);
292c6d8c1d9SAndreas Gohr        $assignments = $sqlite->res2single($result);
293c6d8c1d9SAndreas Gohr        $sqlite->res_close($result);
294c6d8c1d9SAndreas Gohr
295c6d8c1d9SAndreas Gohr        $users = [];
296c6d8c1d9SAndreas Gohr        foreach (explode(',', $assignments) as $item) {
297c6d8c1d9SAndreas Gohr            $item = trim($item);
298c6d8c1d9SAndreas Gohr            if ($item === '') continue;
299c6d8c1d9SAndreas Gohr            if ($item[0] == '@') {
300c6d8c1d9SAndreas Gohr                $users = array_merge(
301c6d8c1d9SAndreas Gohr                    $users,
302c6d8c1d9SAndreas Gohr                    array_keys($auth->retrieveUsers(0, 0, ['grps' => substr($item, 1)]))
303c6d8c1d9SAndreas Gohr                );
304c6d8c1d9SAndreas Gohr            } else {
305c6d8c1d9SAndreas Gohr                $users[] = $item;
306c6d8c1d9SAndreas Gohr            }
307c6d8c1d9SAndreas Gohr        }
308c6d8c1d9SAndreas Gohr
309c6d8c1d9SAndreas Gohr        return array_unique($users);
310c6d8c1d9SAndreas Gohr    }
311c6d8c1d9SAndreas Gohr
312c6d8c1d9SAndreas Gohr    /**
313c6d8c1d9SAndreas Gohr     * Get ack status for all assigned users of a given page
314c6d8c1d9SAndreas Gohr     *
315c6d8c1d9SAndreas Gohr     * This can be slow!
316c6d8c1d9SAndreas Gohr     *
317c6d8c1d9SAndreas Gohr     * @param string $page
318c6d8c1d9SAndreas Gohr     * @return array|false
319c6d8c1d9SAndreas Gohr     */
320c6d8c1d9SAndreas Gohr    public function getPageAcknowledgements($page)
321c6d8c1d9SAndreas Gohr    {
322c6d8c1d9SAndreas Gohr        $users = $this->getPageAssignees($page);
323c6d8c1d9SAndreas Gohr        if ($users === false) return false;
324c6d8c1d9SAndreas Gohr        $sqlite = $this->getDB();
325c6d8c1d9SAndreas Gohr        if (!$sqlite) return false;
326c6d8c1d9SAndreas Gohr
327c6d8c1d9SAndreas Gohr        $ulist = $sqlite->quote_and_join($users);
328c6d8c1d9SAndreas Gohr        $sql = "SELECT A.page, A.lastmod, B.user, MAX(B.ack) AS ack
329c6d8c1d9SAndreas Gohr                  FROM pages A
330c6d8c1d9SAndreas Gohr             LEFT JOIN acks B
331c6d8c1d9SAndreas Gohr                    ON A.page = B.page
332c6d8c1d9SAndreas Gohr                   AND B.user IN ($ulist)
333c6d8c1d9SAndreas Gohr                WHERE  A.page = ?
334c6d8c1d9SAndreas Gohr              GROUP BY A.page, B.user
335c6d8c1d9SAndreas Gohr                 ";
336c6d8c1d9SAndreas Gohr        $result = $sqlite->query($sql, $page);
337c6d8c1d9SAndreas Gohr        $acknowledgements = $sqlite->res2arr($result);
338c6d8c1d9SAndreas Gohr        $sqlite->res_close($result);
339c6d8c1d9SAndreas Gohr
340c6d8c1d9SAndreas Gohr        // there should be at least one result, unless the page is unknown
341c6d8c1d9SAndreas Gohr        if (!count($acknowledgements)) return false;
342c6d8c1d9SAndreas Gohr
343c6d8c1d9SAndreas Gohr        $baseinfo = [
344c6d8c1d9SAndreas Gohr            'page' => $acknowledgements[0]['page'],
345c6d8c1d9SAndreas Gohr            'lastmod' => $acknowledgements[0]['lastmod'],
346c6d8c1d9SAndreas Gohr            'user' => null,
347c6d8c1d9SAndreas Gohr            'ack' => null,
348c6d8c1d9SAndreas Gohr        ];
349c6d8c1d9SAndreas Gohr
350c6d8c1d9SAndreas Gohr        // fill up the result with all users that never acknowledged the page
351c6d8c1d9SAndreas Gohr        $combined = [];
352c6d8c1d9SAndreas Gohr        foreach ($acknowledgements as $ack) {
353c6d8c1d9SAndreas Gohr            if ($ack['user'] !== null) {
354c6d8c1d9SAndreas Gohr                $combined[$ack['user']] = $ack;
355c6d8c1d9SAndreas Gohr            }
356c6d8c1d9SAndreas Gohr        }
357c6d8c1d9SAndreas Gohr        foreach ($users as $user) {
358c6d8c1d9SAndreas Gohr            if (!isset($combined[$user])) {
359c6d8c1d9SAndreas Gohr                $combined[$user] = array_merge($baseinfo, ['user' => $user]);
360c6d8c1d9SAndreas Gohr            }
361c6d8c1d9SAndreas Gohr        }
362c6d8c1d9SAndreas Gohr
363c6d8c1d9SAndreas Gohr        ksort($combined);
364c6d8c1d9SAndreas Gohr        return array_values($combined);
365c6d8c1d9SAndreas Gohr    }
366c6d8c1d9SAndreas Gohr
367c6d8c1d9SAndreas Gohr    /**
368863b6e48SAndreas Gohr     * Returns all acknowledgements
369863b6e48SAndreas Gohr     *
370863b6e48SAndreas Gohr     * @param int $limit maximum number of results
371863b6e48SAndreas Gohr     * @return array|bool
372863b6e48SAndreas Gohr     */
373863b6e48SAndreas Gohr    public function getAcknowledgements($limit = 100)
374863b6e48SAndreas Gohr    {
375863b6e48SAndreas Gohr        $sqlite = $this->getDB();
376863b6e48SAndreas Gohr        if (!$sqlite) return false;
377863b6e48SAndreas Gohr
378863b6e48SAndreas Gohr        $sql = '
379*84db77b6SAndreas Gohr            SELECT A.page, A.user, B.lastmod, max(A.ack) AS ack
380*84db77b6SAndreas Gohr              FROM acks A, pages B
381*84db77b6SAndreas Gohr             WHERE A.page = B.page
382*84db77b6SAndreas Gohr          GROUP BY A.user, A.page
383863b6e48SAndreas Gohr          ORDER BY ack DESC
384863b6e48SAndreas Gohr             LIMIT ?
385863b6e48SAndreas Gohr              ';
386863b6e48SAndreas Gohr        $result = $sqlite->query($sql, $limit);
387d6011abdSAnna Dabrowska        $acknowledgements = $sqlite->res2arr($result);
388d6011abdSAnna Dabrowska        $sqlite->res_close($result);
389d6011abdSAnna Dabrowska
390d6011abdSAnna Dabrowska        return $acknowledgements;
391d6011abdSAnna Dabrowska    }
3924d6d17d0SAndreas Gohr}
3934d6d17d0SAndreas Gohr
394