xref: /plugin/acknowledge/helper.php (revision 863b6e48d8bcae5b9535687407c12b2133192a65)
14d6d17d0SAndreas Gohr<?php
24d6d17d0SAndreas Gohr/**
34d6d17d0SAndreas Gohr * DokuWiki Plugin acknowledge (Helper Component)
44d6d17d0SAndreas Gohr *
54d6d17d0SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
64d6d17d0SAndreas Gohr * @author  Andreas Gohr, Anna Dabrowska <dokuwiki@cosmocode.de>
74d6d17d0SAndreas Gohr */
84d6d17d0SAndreas Gohr
94d6d17d0SAndreas Gohrclass helper_plugin_acknowledge extends DokuWiki_Plugin
104d6d17d0SAndreas Gohr{
114d6d17d0SAndreas Gohr
12cabb51d3SAndreas Gohr    /**
13cabb51d3SAndreas Gohr     * @return helper_plugin_sqlite|null
14cabb51d3SAndreas Gohr     */
15cabb51d3SAndreas Gohr    public function getDB()
16cabb51d3SAndreas Gohr    {
17cabb51d3SAndreas Gohr        /** @var \helper_plugin_sqlite $sqlite */
18cabb51d3SAndreas Gohr        $sqlite = plugin_load('helper', 'sqlite');
19cabb51d3SAndreas Gohr        if ($sqlite === null) {
20cabb51d3SAndreas Gohr            msg($this->getLang('error sqlite plugin missing'), -1);
21cabb51d3SAndreas Gohr            return null;
22cabb51d3SAndreas Gohr        }
23cabb51d3SAndreas Gohr        if (!$sqlite->init('acknowledgement', __DIR__ . '/db')) {
24cabb51d3SAndreas Gohr            return null;
25cabb51d3SAndreas Gohr        }
26cabb51d3SAndreas Gohr
279c3eae1eSAnna Dabrowska        $this->registerUDF($sqlite);
289c3eae1eSAnna Dabrowska
29cabb51d3SAndreas Gohr        return $sqlite;
30cabb51d3SAndreas Gohr    }
31cabb51d3SAndreas Gohr
32cabb51d3SAndreas Gohr    /**
339c3eae1eSAnna Dabrowska     * Register user defined functions
349c3eae1eSAnna Dabrowska     *
359c3eae1eSAnna Dabrowska     * @param helper_plugin_sqlite $sqlite
369c3eae1eSAnna Dabrowska     */
379c3eae1eSAnna Dabrowska    protected function registerUDF($sqlite)
389c3eae1eSAnna Dabrowska    {
399c3eae1eSAnna Dabrowska        $sqlite->create_function('AUTH_ISMEMBER', [$this, 'auth_isMember'], -1);
409c3eae1eSAnna Dabrowska    }
419c3eae1eSAnna Dabrowska
429c3eae1eSAnna Dabrowska    /**
439c3eae1eSAnna Dabrowska     * Wrapper function for auth_isMember which accepts groups as string
449c3eae1eSAnna Dabrowska     *
459c3eae1eSAnna Dabrowska     * @param string $memberList
469c3eae1eSAnna Dabrowska     * @param string $user
479c3eae1eSAnna Dabrowska     * @param string $groups
489c3eae1eSAnna Dabrowska     * @return bool
499c3eae1eSAnna Dabrowska     */
509c3eae1eSAnna Dabrowska    public function auth_isMember($memberList, $user, $groups)
519c3eae1eSAnna Dabrowska    {
5295113ed8SAnna Dabrowska        return auth_isMember($memberList, $user, explode('///', $groups));
539c3eae1eSAnna Dabrowska    }
549c3eae1eSAnna Dabrowska
559c3eae1eSAnna Dabrowska    /**
56ef3ab392SAndreas Gohr     * Delete a page
57ef3ab392SAndreas Gohr     *
58ef3ab392SAndreas Gohr     * Cascades to delete all assigned data, etc.
59ef3ab392SAndreas Gohr     *
60ef3ab392SAndreas Gohr     * @param string $page Page ID
61ef3ab392SAndreas Gohr     */
62ef3ab392SAndreas Gohr    public function removePage($page)
63ef3ab392SAndreas Gohr    {
64ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
65ef3ab392SAndreas Gohr        if (!$sqlite) return;
66ef3ab392SAndreas Gohr
67ef3ab392SAndreas Gohr        $sql = "DELETE FROM pages WHERE page = ?";
68ef3ab392SAndreas Gohr        $sqlite->query($sql, $page);
69ef3ab392SAndreas Gohr    }
70ef3ab392SAndreas Gohr
71ef3ab392SAndreas Gohr    /**
725dee13f7SAnna Dabrowska     * Update last modified date of page if content has changed
73ef3ab392SAndreas Gohr     *
74ef3ab392SAndreas Gohr     * @param string $page Page ID
75ef3ab392SAndreas Gohr     * @param int $lastmod timestamp of last non-minor change
76ef3ab392SAndreas Gohr     */
775dee13f7SAnna Dabrowska    public function storePageDate($page, $lastmod, $newContent)
78ef3ab392SAndreas Gohr    {
79ed4e8871SAnna Dabrowska        $changelog = new \dokuwiki\ChangeLog\PageChangeLog($page);
80789aa26fSAnna Dabrowska        $revs = $changelog->getRevisions(0, 1);
81ed4e8871SAnna Dabrowska
82ed4e8871SAnna Dabrowska        // compare content
83ed4e8871SAnna Dabrowska        $oldContent = str_replace(NL, '', io_readFile(wikiFN($page, $revs[0])));
84ed4e8871SAnna Dabrowska        $newContent = str_replace(NL, '', $newContent);
85ed4e8871SAnna Dabrowska        if ($oldContent === $newContent) return;
86ed4e8871SAnna Dabrowska
87ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
88ef3ab392SAndreas Gohr        if (!$sqlite) return;
89ef3ab392SAndreas Gohr
90ef3ab392SAndreas Gohr        $sql = "REPLACE INTO pages (page, lastmod) VALUES (?,?)";
91ef3ab392SAndreas Gohr        $sqlite->query($sql, $page, $lastmod);
92ef3ab392SAndreas Gohr    }
93ef3ab392SAndreas Gohr
94ef3ab392SAndreas Gohr    /**
95cabb51d3SAndreas Gohr     * @param string $page Page ID
96cabb51d3SAndreas Gohr     * @param string $assignees comma separated list of users and groups
97cabb51d3SAndreas Gohr     */
98cabb51d3SAndreas Gohr    public function setAssignees($page, $assignees)
99cabb51d3SAndreas Gohr    {
100cabb51d3SAndreas Gohr        $sqlite = $this->getDB();
101cabb51d3SAndreas Gohr        if (!$sqlite) return;
102cabb51d3SAndreas Gohr
103cabb51d3SAndreas Gohr        $sql = "REPLACE INTO assignments ('page', 'assignee') VALUES (?,?)";
104cabb51d3SAndreas Gohr        $sqlite->query($sql, $page, $assignees);
105cabb51d3SAndreas Gohr    }
106cabb51d3SAndreas Gohr
107ef3ab392SAndreas Gohr    /**
1085773dd37SAnna Dabrowska     * Clears assignments for a page
109ef3ab392SAndreas Gohr     *
110ef3ab392SAndreas Gohr     * @param string $page Page ID
111ef3ab392SAndreas Gohr     */
112ef3ab392SAndreas Gohr    public function clearAssignments($page)
113ef3ab392SAndreas Gohr    {
114ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
115ef3ab392SAndreas Gohr        if (!$sqlite) return;
116cabb51d3SAndreas Gohr
117ef3ab392SAndreas Gohr        $sql = "DELETE FROM assignments WHERE page = ?";
118ef3ab392SAndreas Gohr        $sqlite->query($sql, $page);
119ef3ab392SAndreas Gohr    }
120ef3ab392SAndreas Gohr
121ef3ab392SAndreas Gohr    /**
122ef3ab392SAndreas Gohr     * Is the given user one of the assignees for this page
123ef3ab392SAndreas Gohr     *
124ef3ab392SAndreas Gohr     * @param string $page Page ID
125ef3ab392SAndreas Gohr     * @param string $user user name to check
126ef3ab392SAndreas Gohr     * @param string[] $groups groups this user is in
127ef3ab392SAndreas Gohr     * @return bool
128ef3ab392SAndreas Gohr     */
129ef3ab392SAndreas Gohr    public function isUserAssigned($page, $user, $groups)
130ef3ab392SAndreas Gohr    {
131ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
132ef3ab392SAndreas Gohr        if (!$sqlite) return false;
133ef3ab392SAndreas Gohr
134ef3ab392SAndreas Gohr        $sql = "SELECT assignee FROM assignments WHERE page = ?";
135ef3ab392SAndreas Gohr        $result = $sqlite->query($sql, $page);
136ef3ab392SAndreas Gohr        $assignees = (string)$sqlite->res2single($result);
137ef3ab392SAndreas Gohr        $sqlite->res_close($result);
138ef3ab392SAndreas Gohr
139ef3ab392SAndreas Gohr        return auth_isMember($assignees, $user, $groups);
140ef3ab392SAndreas Gohr    }
141ef3ab392SAndreas Gohr
142ef3ab392SAndreas Gohr    /**
143ef3ab392SAndreas Gohr     * Has the given user acknowledged the given page?
144ef3ab392SAndreas Gohr     *
145ef3ab392SAndreas Gohr     * @param string $page
146ef3ab392SAndreas Gohr     * @param string $user
1475773dd37SAnna Dabrowska     * @return bool|int timestamp of acknowledgement or false
148ef3ab392SAndreas Gohr     */
149ef3ab392SAndreas Gohr    public function hasUserAcknowledged($page, $user)
150ef3ab392SAndreas Gohr    {
151ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
152ef3ab392SAndreas Gohr        if (!$sqlite) return false;
153ef3ab392SAndreas Gohr
154ef3ab392SAndreas Gohr        $sql = "SELECT ack
155ef3ab392SAndreas Gohr                  FROM acks A, pages B
156ef3ab392SAndreas Gohr                 WHERE A.page = B.page
1575773dd37SAnna Dabrowska                   AND A.page = ?
1585773dd37SAnna Dabrowska                   AND A.user = ?
159ef3ab392SAndreas Gohr                   AND A.ack >= B.lastmod";
160ef3ab392SAndreas Gohr
161ef3ab392SAndreas Gohr        $result = $sqlite->query($sql, $page, $user);
162ef3ab392SAndreas Gohr        $acktime = $sqlite->res2single($result);
163ef3ab392SAndreas Gohr        $sqlite->res_close($result);
164ef3ab392SAndreas Gohr
165ef3ab392SAndreas Gohr        return $acktime ? (int)$acktime : false;
166ef3ab392SAndreas Gohr    }
1675773dd37SAnna Dabrowska
1685773dd37SAnna Dabrowska    /**
169d9a8334dSAnna Dabrowska     * Timestamp of the latest acknowledgment of the given page
170d9a8334dSAnna Dabrowska     * by the given user
171d9a8334dSAnna Dabrowska     *
172d9a8334dSAnna Dabrowska     * @param string $page
173d9a8334dSAnna Dabrowska     * @param string $user
174d9a8334dSAnna Dabrowska     * @return bool|string
175d9a8334dSAnna Dabrowska     */
176d9a8334dSAnna Dabrowska    public function getLatestUserAcknowledgement($page, $user)
177d9a8334dSAnna Dabrowska    {
178d9a8334dSAnna Dabrowska        $sqlite = $this->getDB();
179d9a8334dSAnna Dabrowska        if (!$sqlite) return false;
180d9a8334dSAnna Dabrowska
181d9a8334dSAnna Dabrowska        $sql = "SELECT MAX(ack)
182d9a8334dSAnna Dabrowska                  FROM acks
183d9a8334dSAnna Dabrowska                 WHERE page = ?
184d9a8334dSAnna Dabrowska                   AND user = ?";
185d9a8334dSAnna Dabrowska
186d9a8334dSAnna Dabrowska        $result = $sqlite->query($sql, $page, $user);
187d9a8334dSAnna Dabrowska        $latestAck = $sqlite->res2single($result);
188d9a8334dSAnna Dabrowska        $sqlite->res_close($result);
189d9a8334dSAnna Dabrowska
190d9a8334dSAnna Dabrowska        return $latestAck;
191d9a8334dSAnna Dabrowska    }
192d9a8334dSAnna Dabrowska
193d9a8334dSAnna Dabrowska    /**
1945773dd37SAnna Dabrowska     * Save user's acknowledgement for a given page
1955773dd37SAnna Dabrowska     *
1965773dd37SAnna Dabrowska     * @param string $page
1975773dd37SAnna Dabrowska     * @param string $user
1985773dd37SAnna Dabrowska     * @return bool
1995773dd37SAnna Dabrowska     */
2005773dd37SAnna Dabrowska    public function saveAcknowledgement($page, $user)
2015773dd37SAnna Dabrowska    {
2025773dd37SAnna Dabrowska        $sqlite = $this->getDB();
2035773dd37SAnna Dabrowska        if (!$sqlite) return false;
2045773dd37SAnna Dabrowska
2058e55e483SAnna Dabrowska        $sql = "INSERT INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))";
2065773dd37SAnna Dabrowska
2075773dd37SAnna Dabrowska        $result = $sqlite->query($sql, $page, $user);
2085773dd37SAnna Dabrowska        $sqlite->res_close($result);
2095773dd37SAnna Dabrowska        return true;
2105773dd37SAnna Dabrowska
2115773dd37SAnna Dabrowska    }
21274126d4bSAnna Dabrowska
21374126d4bSAnna Dabrowska    /**
21460ed3784SAnna Dabrowska     * Fetch all assignments for a given user, with additional page information,
21560ed3784SAnna Dabrowska     * filtering already granted acknowledgements.
21674126d4bSAnna Dabrowska     *
21774126d4bSAnna Dabrowska     * @param string $user
2188c50976eSAnna Dabrowska     * @param array $groups
21974126d4bSAnna Dabrowska     * @return array|bool
22074126d4bSAnna Dabrowska     */
2218c50976eSAnna Dabrowska    public function getUserAssignments($user, $groups)
22274126d4bSAnna Dabrowska    {
22374126d4bSAnna Dabrowska        $sqlite = $this->getDB();
22474126d4bSAnna Dabrowska        if (!$sqlite) return false;
22574126d4bSAnna Dabrowska
22660ed3784SAnna Dabrowska        $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, C.ack FROM assignments A
22774126d4bSAnna Dabrowska                JOIN pages B
22874126d4bSAnna Dabrowska                ON A.page = B.page
22960ed3784SAnna Dabrowska                LEFT JOIN acks C
2302541208bSAnna Dabrowska                ON A.page = C.page AND ( (C.user = ? AND C.ack > B.lastmod) )
23160ed3784SAnna Dabrowska                WHERE AUTH_ISMEMBER(A.assignee, ? , ?)
2328e55e483SAnna Dabrowska                AND ack IS NULL";
23374126d4bSAnna Dabrowska
2342541208bSAnna Dabrowska        $result = $sqlite->query($sql, $user, $user, implode('///', $groups));
23574126d4bSAnna Dabrowska        $assignments = $sqlite->res2arr($result);
23674126d4bSAnna Dabrowska        $sqlite->res_close($result);
23774126d4bSAnna Dabrowska
23874126d4bSAnna Dabrowska        return $assignments;
23974126d4bSAnna Dabrowska    }
24074126d4bSAnna Dabrowska
24174126d4bSAnna Dabrowska    /**
242*863b6e48SAndreas Gohr     * Get all pages a user needs to acknowledge and the last acknowledge date
243d6011abdSAnna Dabrowska     *
244*863b6e48SAndreas Gohr     * @param string $user
245*863b6e48SAndreas Gohr     * @param array $groups
246d6011abdSAnna Dabrowska     * @return array|bool
247d6011abdSAnna Dabrowska     */
248*863b6e48SAndreas Gohr    public function getUserAcknowledgements($user, $groups)
249d6011abdSAnna Dabrowska    {
250d6011abdSAnna Dabrowska        $sqlite = $this->getDB();
251d6011abdSAnna Dabrowska        if (!$sqlite) return false;
252d6011abdSAnna Dabrowska
253*863b6e48SAndreas Gohr        $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, MAX(C.ack) AS ack
254*863b6e48SAndreas Gohr                  FROM assignments A
255*863b6e48SAndreas Gohr                  JOIN pages B
256*863b6e48SAndreas Gohr                    ON A.page = B.page
257*863b6e48SAndreas Gohr             LEFT JOIN acks C
258*863b6e48SAndreas Gohr                    ON A.page = C.page AND C.user = ?
259*863b6e48SAndreas Gohr                 WHERE AUTH_ISMEMBER(A.assignee, ? , ?)
260*863b6e48SAndreas Gohr            GROUP BY A.page
261*863b6e48SAndreas Gohr            ORDER BY A.page
262*863b6e48SAndreas Gohr            ";
263*863b6e48SAndreas Gohr
264*863b6e48SAndreas Gohr        $result = $sqlite->query($sql, $user, $user, implode('///', $groups));
265*863b6e48SAndreas Gohr        $assignments = $sqlite->res2arr($result);
266*863b6e48SAndreas Gohr        $sqlite->res_close($result);
267*863b6e48SAndreas Gohr
268*863b6e48SAndreas Gohr        return $assignments;
269*863b6e48SAndreas Gohr    }
270*863b6e48SAndreas Gohr
271*863b6e48SAndreas Gohr    /**
272*863b6e48SAndreas Gohr     * Returns all acknowledgements
273*863b6e48SAndreas Gohr     *
274*863b6e48SAndreas Gohr     * @param int $limit maximum number of results
275*863b6e48SAndreas Gohr     * @return array|bool
276*863b6e48SAndreas Gohr     */
277*863b6e48SAndreas Gohr    public function getAcknowledgements($limit = 100)
278*863b6e48SAndreas Gohr    {
279*863b6e48SAndreas Gohr        $sqlite = $this->getDB();
280*863b6e48SAndreas Gohr        if (!$sqlite) return false;
281*863b6e48SAndreas Gohr
282*863b6e48SAndreas Gohr        $sql = '
283*863b6e48SAndreas Gohr            SELECT page, user, max(ack) AS ack
284*863b6e48SAndreas Gohr              FROM acks
285*863b6e48SAndreas Gohr          GROUP BY user,page
286*863b6e48SAndreas Gohr          ORDER BY ack DESC
287*863b6e48SAndreas Gohr             LIMIT ?
288*863b6e48SAndreas Gohr              ';
289*863b6e48SAndreas Gohr        $result = $sqlite->query($sql, $limit);
290d6011abdSAnna Dabrowska        $acknowledgements = $sqlite->res2arr($result);
291d6011abdSAnna Dabrowska        $sqlite->res_close($result);
292d6011abdSAnna Dabrowska
293d6011abdSAnna Dabrowska        return $acknowledgements;
294d6011abdSAnna Dabrowska    }
2954d6d17d0SAndreas Gohr}
2964d6d17d0SAndreas Gohr
297