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