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(1, 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 * Save user's acknowledgement for a given page 173 * 174 * @param string $page 175 * @param string $user 176 * @return bool 177 */ 178 public function saveAcknowledgement($page, $user) 179 { 180 $sqlite = $this->getDB(); 181 if (!$sqlite) return false; 182 183 $sql = "INSERT INTO acks (page, user, ack) VALUES (?,?, strftime('%s','now'))"; 184 185 $result = $sqlite->query($sql, $page, $user); 186 $sqlite->res_close($result); 187 return true; 188 189 } 190 191 /** 192 * Fetch all assignments for a given user, with additional page information, 193 * filtering already granted acknowledgements. 194 * 195 * @param string $user 196 * @param array $groups 197 * @return array|bool 198 */ 199 public function getUserAssignments($user, $groups) 200 { 201 $sqlite = $this->getDB(); 202 if (!$sqlite) return false; 203 204 $sql = "SELECT A.page, A.assignee, B.lastmod, C.user, C.ack FROM assignments A 205 JOIN pages B 206 ON A.page = B.page 207 LEFT JOIN acks C 208 ON A.page = C.page AND ( (C.user = ? AND C.ack > B.lastmod) ) 209 WHERE AUTH_ISMEMBER(A.assignee, ? , ?) 210 AND ack IS NULL"; 211 212 $result = $sqlite->query($sql, $user, $user, implode('///', $groups)); 213 $assignments = $sqlite->res2arr($result); 214 $sqlite->res_close($result); 215 216 return $assignments; 217 } 218 219 /** 220 * Returns all acknowledgements 221 * 222 * @return array|bool 223 */ 224 public function getAcknowledgements() 225 { 226 $sqlite = $this->getDB(); 227 if (!$sqlite) return false; 228 229 $sql = 'SELECT page, user, max(ack) AS ack FROM acks GROUP BY user,page ORDER BY ack DESC'; 230 $result = $sqlite->query($sql); 231 $acknowledgements = $sqlite->res2arr($result); 232 $sqlite->res_close($result); 233 234 return $acknowledgements; 235 } 236} 237 238