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