xref: /plugin/acknowledge/helper.php (revision 5dee13f7d920ae9e0a6a090da0b562e80a26e818)
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 Gohr
104d6d17d0SAndreas Gohrclass helper_plugin_acknowledge extends DokuWiki_Plugin
114d6d17d0SAndreas Gohr{
124d6d17d0SAndreas Gohr
13cabb51d3SAndreas Gohr    /**
14cabb51d3SAndreas Gohr     * @return helper_plugin_sqlite|null
15cabb51d3SAndreas Gohr     */
16cabb51d3SAndreas Gohr    public function getDB()
17cabb51d3SAndreas Gohr    {
18cabb51d3SAndreas Gohr        /** @var \helper_plugin_sqlite $sqlite */
19cabb51d3SAndreas Gohr        $sqlite = plugin_load('helper', 'sqlite');
20cabb51d3SAndreas Gohr        if ($sqlite === null) {
21cabb51d3SAndreas Gohr            msg($this->getLang('error sqlite plugin missing'), -1);
22cabb51d3SAndreas Gohr            return null;
23cabb51d3SAndreas Gohr        }
24cabb51d3SAndreas Gohr        if (!$sqlite->init('acknowledgement', __DIR__ . '/db')) {
25cabb51d3SAndreas Gohr            return null;
26cabb51d3SAndreas Gohr        }
27cabb51d3SAndreas Gohr
289c3eae1eSAnna Dabrowska        $this->registerUDF($sqlite);
299c3eae1eSAnna Dabrowska
30cabb51d3SAndreas Gohr        return $sqlite;
31cabb51d3SAndreas Gohr    }
32cabb51d3SAndreas Gohr
33cabb51d3SAndreas Gohr    /**
349c3eae1eSAnna Dabrowska     * Register user defined functions
359c3eae1eSAnna Dabrowska     *
369c3eae1eSAnna Dabrowska     * @param helper_plugin_sqlite $sqlite
379c3eae1eSAnna Dabrowska     */
389c3eae1eSAnna Dabrowska    protected function registerUDF($sqlite)
399c3eae1eSAnna Dabrowska    {
409c3eae1eSAnna Dabrowska        $sqlite->create_function('AUTH_ISMEMBER', [$this, 'auth_isMember'], -1);
419c3eae1eSAnna Dabrowska    }
429c3eae1eSAnna Dabrowska
439c3eae1eSAnna Dabrowska    /**
449c3eae1eSAnna Dabrowska     * Wrapper function for auth_isMember which accepts groups as string
459c3eae1eSAnna Dabrowska     *
469c3eae1eSAnna Dabrowska     * @param string $memberList
479c3eae1eSAnna Dabrowska     * @param string $user
489c3eae1eSAnna Dabrowska     * @param string $groups
499c3eae1eSAnna Dabrowska     * @return bool
509c3eae1eSAnna Dabrowska     */
519c3eae1eSAnna Dabrowska    public function auth_isMember($memberList, $user, $groups)
529c3eae1eSAnna Dabrowska    {
5395113ed8SAnna Dabrowska        return auth_isMember($memberList, $user, explode('///', $groups));
549c3eae1eSAnna Dabrowska    }
559c3eae1eSAnna Dabrowska
569c3eae1eSAnna Dabrowska    /**
57ef3ab392SAndreas Gohr     * Delete a page
58ef3ab392SAndreas Gohr     *
59ef3ab392SAndreas Gohr     * Cascades to delete all assigned data, etc.
60ef3ab392SAndreas Gohr     *
61ef3ab392SAndreas Gohr     * @param string $page Page ID
62ef3ab392SAndreas Gohr     */
63ef3ab392SAndreas Gohr    public function removePage($page)
64ef3ab392SAndreas Gohr    {
65ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
66ef3ab392SAndreas Gohr        if (!$sqlite) return;
67ef3ab392SAndreas Gohr
68ef3ab392SAndreas Gohr        $sql = "DELETE FROM pages WHERE page = ?";
69ef3ab392SAndreas Gohr        $sqlite->query($sql, $page);
70ef3ab392SAndreas Gohr    }
71ef3ab392SAndreas Gohr
72ef3ab392SAndreas Gohr    /**
73*5dee13f7SAnna Dabrowska     * Update last modified date of page if content has changed
74ef3ab392SAndreas Gohr     *
75ef3ab392SAndreas Gohr     * @param string $page Page ID
76ef3ab392SAndreas Gohr     * @param int $lastmod timestamp of last non-minor change
77ef3ab392SAndreas Gohr     */
78*5dee13f7SAnna Dabrowska    public function storePageDate($page, $lastmod, $newContent)
79ef3ab392SAndreas Gohr    {
80ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
81ef3ab392SAndreas Gohr        if (!$sqlite) return;
82ef3ab392SAndreas Gohr
83*5dee13f7SAnna Dabrowska        $identical = true;
84*5dee13f7SAnna Dabrowska        $changelog = new \dokuwiki\ChangeLog\PageChangeLog($page);
85*5dee13f7SAnna Dabrowska
86*5dee13f7SAnna Dabrowska        $revs = $changelog->getRevisions(1, 20);
87*5dee13f7SAnna Dabrowska
88*5dee13f7SAnna Dabrowska        foreach ($revs as $rev) {
89*5dee13f7SAnna Dabrowska            $info = $changelog->getRevisionInfo($rev);
90*5dee13f7SAnna Dabrowska            if ($info['type'] !== DOKU_CHANGE_TYPE_MINOR_EDIT) {
91*5dee13f7SAnna Dabrowska                // compare content
92*5dee13f7SAnna Dabrowska                $oldContent = str_replace(NL, '', io_readFile(wikiFN($page, $rev)));
93*5dee13f7SAnna Dabrowska                $newContent = str_replace(NL, '', $newContent);
94*5dee13f7SAnna Dabrowska                if ($oldContent !== $newContent) $identical = false;
95*5dee13f7SAnna Dabrowska                break;
96*5dee13f7SAnna Dabrowska            }
97*5dee13f7SAnna Dabrowska        }
98*5dee13f7SAnna Dabrowska
99*5dee13f7SAnna Dabrowska        if ($identical) return;
100*5dee13f7SAnna Dabrowska
101ef3ab392SAndreas Gohr        $sql = "REPLACE INTO pages (page, lastmod) VALUES (?,?)";
102ef3ab392SAndreas Gohr        $sqlite->query($sql, $page, $lastmod);
103ef3ab392SAndreas Gohr    }
104ef3ab392SAndreas Gohr
105ef3ab392SAndreas Gohr    /**
106cabb51d3SAndreas Gohr     * @param string $page Page ID
107cabb51d3SAndreas Gohr     * @param string $assignees comma separated list of users and groups
108cabb51d3SAndreas Gohr     */
109cabb51d3SAndreas Gohr    public function setAssignees($page, $assignees)
110cabb51d3SAndreas Gohr    {
111cabb51d3SAndreas Gohr        $sqlite = $this->getDB();
112cabb51d3SAndreas Gohr        if (!$sqlite) return;
113cabb51d3SAndreas Gohr
114cabb51d3SAndreas Gohr        $sql = "REPLACE INTO assignments ('page', 'assignee') VALUES (?,?)";
115cabb51d3SAndreas Gohr        $sqlite->query($sql, $page, $assignees);
116cabb51d3SAndreas Gohr    }
117cabb51d3SAndreas Gohr
118ef3ab392SAndreas Gohr    /**
1195773dd37SAnna Dabrowska     * Clears assignments for a page
120ef3ab392SAndreas Gohr     *
121ef3ab392SAndreas Gohr     * @param string $page Page ID
122ef3ab392SAndreas Gohr     */
123ef3ab392SAndreas Gohr    public function clearAssignments($page)
124ef3ab392SAndreas Gohr    {
125ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
126ef3ab392SAndreas Gohr        if (!$sqlite) return;
127cabb51d3SAndreas Gohr
128ef3ab392SAndreas Gohr        $sql = "DELETE FROM assignments WHERE page = ?";
129ef3ab392SAndreas Gohr        $sqlite->query($sql, $page);
130ef3ab392SAndreas Gohr    }
131ef3ab392SAndreas Gohr
132ef3ab392SAndreas Gohr
133ef3ab392SAndreas Gohr    /**
134ef3ab392SAndreas Gohr     * Is the given user one of the assignees for this page
135ef3ab392SAndreas Gohr     *
136ef3ab392SAndreas Gohr     * @param string $page Page ID
137ef3ab392SAndreas Gohr     * @param string $user user name to check
138ef3ab392SAndreas Gohr     * @param string[] $groups groups this user is in
139ef3ab392SAndreas Gohr     * @return bool
140ef3ab392SAndreas Gohr     */
141ef3ab392SAndreas Gohr    public function isUserAssigned($page, $user, $groups)
142ef3ab392SAndreas Gohr    {
143ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
144ef3ab392SAndreas Gohr        if (!$sqlite) return false;
145ef3ab392SAndreas Gohr
146ef3ab392SAndreas Gohr
147ef3ab392SAndreas Gohr        $sql = "SELECT assignee FROM assignments WHERE page = ?";
148ef3ab392SAndreas Gohr        $result = $sqlite->query($sql, $page);
149ef3ab392SAndreas Gohr        $assignees = (string)$sqlite->res2single($result);
150ef3ab392SAndreas Gohr        $sqlite->res_close($result);
151ef3ab392SAndreas Gohr
152ef3ab392SAndreas Gohr        return auth_isMember($assignees, $user, $groups);
153ef3ab392SAndreas Gohr    }
154ef3ab392SAndreas Gohr
155ef3ab392SAndreas Gohr    /**
156ef3ab392SAndreas Gohr     * Has the given user acknowledged the given page?
157ef3ab392SAndreas Gohr     *
158ef3ab392SAndreas Gohr     * @param string $page
159ef3ab392SAndreas Gohr     * @param string $user
1605773dd37SAnna Dabrowska     * @return bool|int timestamp of acknowledgement or false
161ef3ab392SAndreas Gohr     */
162ef3ab392SAndreas Gohr    public function hasUserAcknowledged($page, $user)
163ef3ab392SAndreas Gohr    {
164ef3ab392SAndreas Gohr        $sqlite = $this->getDB();
165ef3ab392SAndreas Gohr        if (!$sqlite) return false;
166ef3ab392SAndreas Gohr
167ef3ab392SAndreas Gohr        $sql = "SELECT ack
168ef3ab392SAndreas Gohr                  FROM acks A, pages B
169ef3ab392SAndreas Gohr                 WHERE A.page = B.page
1705773dd37SAnna Dabrowska                   AND A.page = ?
1715773dd37SAnna Dabrowska                   AND A.user = ?
172ef3ab392SAndreas Gohr                   AND A.ack >= B.lastmod";
173ef3ab392SAndreas Gohr
174ef3ab392SAndreas Gohr        $result = $sqlite->query($sql, $page, $user);
175ef3ab392SAndreas Gohr        $acktime = $sqlite->res2single($result);
176ef3ab392SAndreas Gohr        $sqlite->res_close($result);
177ef3ab392SAndreas Gohr
178ef3ab392SAndreas Gohr        return $acktime ? (int)$acktime : false;
179ef3ab392SAndreas Gohr    }
1805773dd37SAnna Dabrowska
1815773dd37SAnna Dabrowska    /**
1825773dd37SAnna Dabrowska     * Save user's acknowledgement for a given page
1835773dd37SAnna Dabrowska     *
1845773dd37SAnna Dabrowska     * @param string $page
1855773dd37SAnna Dabrowska     * @param string $user
1865773dd37SAnna Dabrowska     * @return bool
1875773dd37SAnna Dabrowska     */
1885773dd37SAnna Dabrowska    public function saveAcknowledgement($page, $user)
1895773dd37SAnna Dabrowska    {
1905773dd37SAnna Dabrowska        $sqlite = $this->getDB();
1915773dd37SAnna Dabrowska        if (!$sqlite) return false;
1925773dd37SAnna Dabrowska
1938e55e483SAnna Dabrowska        $sql = "INSERT INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))";
1945773dd37SAnna Dabrowska
1955773dd37SAnna Dabrowska        $result = $sqlite->query($sql, $page, $user);
1965773dd37SAnna Dabrowska        $sqlite->res_close($result);
1975773dd37SAnna Dabrowska        return true;
1985773dd37SAnna Dabrowska
1995773dd37SAnna Dabrowska    }
20074126d4bSAnna Dabrowska
20174126d4bSAnna Dabrowska    /**
20260ed3784SAnna Dabrowska     * Fetch all assignments for a given user, with additional page information,
20360ed3784SAnna Dabrowska     * filtering already granted acknowledgements.
20474126d4bSAnna Dabrowska     *
20574126d4bSAnna Dabrowska     * @param string $user
2068c50976eSAnna Dabrowska     * @param array $groups
20774126d4bSAnna Dabrowska     * @return array|bool
20874126d4bSAnna Dabrowska     */
2098c50976eSAnna Dabrowska    public function getUserAssignments($user, $groups)
21074126d4bSAnna Dabrowska    {
21174126d4bSAnna Dabrowska        $sqlite = $this->getDB();
21274126d4bSAnna Dabrowska        if (!$sqlite) return false;
21374126d4bSAnna Dabrowska
21460ed3784SAnna Dabrowska        $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, C.ack FROM assignments A
21574126d4bSAnna Dabrowska                JOIN pages B
21674126d4bSAnna Dabrowska                ON A.page = B.page
21760ed3784SAnna Dabrowska                LEFT JOIN acks C
2182541208bSAnna Dabrowska                ON A.page = C.page AND ( (C.user = ? AND C.ack > B.lastmod) )
21960ed3784SAnna Dabrowska                WHERE AUTH_ISMEMBER(A.assignee, ? , ?)
2208e55e483SAnna Dabrowska                AND ack IS NULL";
22174126d4bSAnna Dabrowska
2222541208bSAnna Dabrowska        $result = $sqlite->query($sql, $user, $user, implode('///', $groups));
22374126d4bSAnna Dabrowska        $assignments = $sqlite->res2arr($result);
22474126d4bSAnna Dabrowska        $sqlite->res_close($result);
22574126d4bSAnna Dabrowska
22674126d4bSAnna Dabrowska        return $assignments;
22774126d4bSAnna Dabrowska    }
22874126d4bSAnna Dabrowska
22974126d4bSAnna Dabrowska    /**
230d6011abdSAnna Dabrowska     * Returns all acknowledgements
231d6011abdSAnna Dabrowska     *
232d6011abdSAnna Dabrowska     * @return array|bool
233d6011abdSAnna Dabrowska     */
234d6011abdSAnna Dabrowska    public function getAcknowledgements()
235d6011abdSAnna Dabrowska    {
236d6011abdSAnna Dabrowska        $sqlite = $this->getDB();
237d6011abdSAnna Dabrowska        if (!$sqlite) return false;
238d6011abdSAnna Dabrowska
2398e55e483SAnna Dabrowska        $sql = 'SELECT page, user, max(ack) AS ack FROM acks GROUP BY user,page ORDER BY ack DESC';
240d6011abdSAnna Dabrowska        $result = $sqlite->query($sql);
241d6011abdSAnna Dabrowska        $acknowledgements = $sqlite->res2arr($result);
242d6011abdSAnna Dabrowska        $sqlite->res_close($result);
243d6011abdSAnna Dabrowska
244d6011abdSAnna Dabrowska        return $acknowledgements;
245d6011abdSAnna Dabrowska    }
2464d6d17d0SAndreas Gohr}
2474d6d17d0SAndreas Gohr
248