1<?php 2/** 3 * DokuWiki Plugin acknowledge (Helper Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Andreas Gohr, Anna Dabrowska <dokuwiki@cosmocode.de> 7 */ 8 9 10class helper_plugin_acknowledge extends DokuWiki_Plugin 11{ 12 13 /** 14 * @return helper_plugin_sqlite|null 15 */ 16 public function getDB() 17 { 18 /** @var \helper_plugin_sqlite $sqlite */ 19 $sqlite = plugin_load('helper', 'sqlite'); 20 if ($sqlite === null) { 21 msg($this->getLang('error sqlite plugin missing'), -1); 22 return null; 23 } 24 if (!$sqlite->init('acknowledgement', __DIR__ . '/db')) { 25 return null; 26 } 27 28 $this->registerUDF($sqlite); 29 30 return $sqlite; 31 } 32 33 /** 34 * Register user defined functions 35 * 36 * @param helper_plugin_sqlite $sqlite 37 */ 38 protected function registerUDF($sqlite) 39 { 40 $sqlite->create_function('AUTH_ISMEMBER', [$this, 'auth_isMember'], -1); 41 } 42 43 /** 44 * Wrapper function for auth_isMember which accepts groups as string 45 * 46 * @param string $memberList 47 * @param string $user 48 * @param string $groups 49 * @return bool 50 */ 51 public function auth_isMember($memberList, $user, $groups) 52 { 53 return auth_isMember($memberList, $user, explode('///', $groups)); 54 } 55 56 /** 57 * Delete a page 58 * 59 * Cascades to delete all assigned data, etc. 60 * 61 * @param string $page Page ID 62 */ 63 public function removePage($page) 64 { 65 $sqlite = $this->getDB(); 66 if (!$sqlite) return; 67 68 $sql = "DELETE FROM pages WHERE page = ?"; 69 $sqlite->query($sql, $page); 70 } 71 72 /** 73 * Update last modified date of page if content has changed 74 * 75 * @param string $page Page ID 76 * @param int $lastmod timestamp of last non-minor change 77 */ 78 public function storePageDate($page, $lastmod, $newContent) 79 { 80 $sqlite = $this->getDB(); 81 if (!$sqlite) return; 82 83 $identical = true; 84 $changelog = new \dokuwiki\ChangeLog\PageChangeLog($page); 85 86 $revs = $changelog->getRevisions(1, 20); 87 88 foreach ($revs as $rev) { 89 $info = $changelog->getRevisionInfo($rev); 90 if ($info['type'] !== DOKU_CHANGE_TYPE_MINOR_EDIT) { 91 // compare content 92 $oldContent = str_replace(NL, '', io_readFile(wikiFN($page, $rev))); 93 $newContent = str_replace(NL, '', $newContent); 94 if ($oldContent !== $newContent) $identical = false; 95 break; 96 } 97 } 98 99 if ($identical) return; 100 101 $sql = "REPLACE INTO pages (page, lastmod) VALUES (?,?)"; 102 $sqlite->query($sql, $page, $lastmod); 103 } 104 105 /** 106 * @param string $page Page ID 107 * @param string $assignees comma separated list of users and groups 108 */ 109 public function setAssignees($page, $assignees) 110 { 111 $sqlite = $this->getDB(); 112 if (!$sqlite) return; 113 114 $sql = "REPLACE INTO assignments ('page', 'assignee') VALUES (?,?)"; 115 $sqlite->query($sql, $page, $assignees); 116 } 117 118 /** 119 * Clears assignments for a page 120 * 121 * @param string $page Page ID 122 */ 123 public function clearAssignments($page) 124 { 125 $sqlite = $this->getDB(); 126 if (!$sqlite) return; 127 128 $sql = "DELETE FROM assignments WHERE page = ?"; 129 $sqlite->query($sql, $page); 130 } 131 132 133 /** 134 * Is the given user one of the assignees for this page 135 * 136 * @param string $page Page ID 137 * @param string $user user name to check 138 * @param string[] $groups groups this user is in 139 * @return bool 140 */ 141 public function isUserAssigned($page, $user, $groups) 142 { 143 $sqlite = $this->getDB(); 144 if (!$sqlite) return false; 145 146 147 $sql = "SELECT assignee FROM assignments WHERE page = ?"; 148 $result = $sqlite->query($sql, $page); 149 $assignees = (string)$sqlite->res2single($result); 150 $sqlite->res_close($result); 151 152 return auth_isMember($assignees, $user, $groups); 153 } 154 155 /** 156 * Has the given user acknowledged the given page? 157 * 158 * @param string $page 159 * @param string $user 160 * @return bool|int timestamp of acknowledgement or false 161 */ 162 public function hasUserAcknowledged($page, $user) 163 { 164 $sqlite = $this->getDB(); 165 if (!$sqlite) return false; 166 167 $sql = "SELECT ack 168 FROM acks A, pages B 169 WHERE A.page = B.page 170 AND A.page = ? 171 AND A.user = ? 172 AND A.ack >= B.lastmod"; 173 174 $result = $sqlite->query($sql, $page, $user); 175 $acktime = $sqlite->res2single($result); 176 $sqlite->res_close($result); 177 178 return $acktime ? (int)$acktime : false; 179 } 180 181 /** 182 * Save user's acknowledgement for a given page 183 * 184 * @param string $page 185 * @param string $user 186 * @return bool 187 */ 188 public function saveAcknowledgement($page, $user) 189 { 190 $sqlite = $this->getDB(); 191 if (!$sqlite) return false; 192 193 $sql = "INSERT INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))"; 194 195 $result = $sqlite->query($sql, $page, $user); 196 $sqlite->res_close($result); 197 return true; 198 199 } 200 201 /** 202 * Fetch all assignments for a given user, with additional page information, 203 * filtering already granted acknowledgements. 204 * 205 * @param string $user 206 * @param array $groups 207 * @return array|bool 208 */ 209 public function getUserAssignments($user, $groups) 210 { 211 $sqlite = $this->getDB(); 212 if (!$sqlite) return false; 213 214 $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, C.ack FROM assignments A 215 JOIN pages B 216 ON A.page = B.page 217 LEFT JOIN acks C 218 ON A.page = C.page AND ( (C.user = ? AND C.ack > B.lastmod) ) 219 WHERE AUTH_ISMEMBER(A.assignee, ? , ?) 220 AND ack IS NULL"; 221 222 $result = $sqlite->query($sql, $user, $user, implode('///', $groups)); 223 $assignments = $sqlite->res2arr($result); 224 $sqlite->res_close($result); 225 226 return $assignments; 227 } 228 229 /** 230 * Returns all acknowledgements 231 * 232 * @return array|bool 233 */ 234 public function getAcknowledgements() 235 { 236 $sqlite = $this->getDB(); 237 if (!$sqlite) return false; 238 239 $sql = 'SELECT page, user, max(ack) AS ack FROM acks GROUP BY user,page ORDER BY ack DESC'; 240 $result = $sqlite->query($sql); 241 $acknowledgements = $sqlite->res2arr($result); 242 $sqlite->res_close($result); 243 244 return $acknowledgements; 245 } 246} 247 248