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 $changelog = new \dokuwiki\ChangeLog\PageChangeLog($page); 81 $revs = $changelog->getRevisions(0, 1); 82 83 // compare content 84 $oldContent = str_replace(NL, '', io_readFile(wikiFN($page, $revs[0]))); 85 $newContent = str_replace(NL, '', $newContent); 86 if ($oldContent === $newContent) return; 87 88 $sqlite = $this->getDB(); 89 if (!$sqlite) return; 90 91 $sql = "REPLACE INTO pages (page, lastmod) VALUES (?,?)"; 92 $sqlite->query($sql, $page, $lastmod); 93 } 94 95 /** 96 * @param string $page Page ID 97 * @param string $assignees comma separated list of users and groups 98 */ 99 public function setAssignees($page, $assignees) 100 { 101 $sqlite = $this->getDB(); 102 if (!$sqlite) return; 103 104 $sql = "REPLACE INTO assignments ('page', 'assignee') VALUES (?,?)"; 105 $sqlite->query($sql, $page, $assignees); 106 } 107 108 /** 109 * Clears assignments for a page 110 * 111 * @param string $page Page ID 112 */ 113 public function clearAssignments($page) 114 { 115 $sqlite = $this->getDB(); 116 if (!$sqlite) return; 117 118 $sql = "DELETE FROM assignments WHERE page = ?"; 119 $sqlite->query($sql, $page); 120 } 121 122 123 /** 124 * Is the given user one of the assignees for this page 125 * 126 * @param string $page Page ID 127 * @param string $user user name to check 128 * @param string[] $groups groups this user is in 129 * @return bool 130 */ 131 public function isUserAssigned($page, $user, $groups) 132 { 133 $sqlite = $this->getDB(); 134 if (!$sqlite) return false; 135 136 137 $sql = "SELECT assignee FROM assignments WHERE page = ?"; 138 $result = $sqlite->query($sql, $page); 139 $assignees = (string)$sqlite->res2single($result); 140 $sqlite->res_close($result); 141 142 return auth_isMember($assignees, $user, $groups); 143 } 144 145 /** 146 * Has the given user acknowledged the given page? 147 * 148 * @param string $page 149 * @param string $user 150 * @return bool|int timestamp of acknowledgement or false 151 */ 152 public function hasUserAcknowledged($page, $user) 153 { 154 $sqlite = $this->getDB(); 155 if (!$sqlite) return false; 156 157 $sql = "SELECT ack 158 FROM acks A, pages B 159 WHERE A.page = B.page 160 AND A.page = ? 161 AND A.user = ? 162 AND A.ack >= B.lastmod"; 163 164 $result = $sqlite->query($sql, $page, $user); 165 $acktime = $sqlite->res2single($result); 166 $sqlite->res_close($result); 167 168 return $acktime ? (int)$acktime : false; 169 } 170 171 /** 172 * Timestamp of the latest acknowledgment of the given page 173 * by the given user 174 * 175 * @param string $page 176 * @param string $user 177 * @return bool|string 178 */ 179 public function getLatestUserAcknowledgement($page, $user) 180 { 181 $sqlite = $this->getDB(); 182 if (!$sqlite) return false; 183 184 $sql = "SELECT MAX(ack) 185 FROM acks 186 WHERE page = ? 187 AND user = ?"; 188 189 $result = $sqlite->query($sql, $page, $user); 190 $latestAck = $sqlite->res2single($result); 191 $sqlite->res_close($result); 192 193 return $latestAck; 194 } 195 196 /** 197 * Save user's acknowledgement for a given page 198 * 199 * @param string $page 200 * @param string $user 201 * @return bool 202 */ 203 public function saveAcknowledgement($page, $user) 204 { 205 $sqlite = $this->getDB(); 206 if (!$sqlite) return false; 207 208 $sql = "INSERT INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))"; 209 210 $result = $sqlite->query($sql, $page, $user); 211 $sqlite->res_close($result); 212 return true; 213 214 } 215 216 /** 217 * Fetch all assignments for a given user, with additional page information, 218 * filtering already granted acknowledgements. 219 * 220 * @param string $user 221 * @param array $groups 222 * @return array|bool 223 */ 224 public function getUserAssignments($user, $groups) 225 { 226 $sqlite = $this->getDB(); 227 if (!$sqlite) return false; 228 229 $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, C.ack FROM assignments A 230 JOIN pages B 231 ON A.page = B.page 232 LEFT JOIN acks C 233 ON A.page = C.page AND ( (C.user = ? AND C.ack > B.lastmod) ) 234 WHERE AUTH_ISMEMBER(A.assignee, ? , ?) 235 AND ack IS NULL"; 236 237 $result = $sqlite->query($sql, $user, $user, implode('///', $groups)); 238 $assignments = $sqlite->res2arr($result); 239 $sqlite->res_close($result); 240 241 return $assignments; 242 } 243 244 /** 245 * Returns all acknowledgements 246 * 247 * @return array|bool 248 */ 249 public function getAcknowledgements() 250 { 251 $sqlite = $this->getDB(); 252 if (!$sqlite) return false; 253 254 $sql = 'SELECT page, user, max(ack) AS ack FROM acks GROUP BY user,page ORDER BY ack DESC'; 255 $result = $sqlite->query($sql); 256 $acknowledgements = $sqlite->res2arr($result); 257 $sqlite->res_close($result); 258 259 return $acknowledgements; 260 } 261} 262 263