1<?php 2/** 3 * DokuWiki Plugin struct (Helper Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Szymon Olewniczak <dokuwiki@cosmocode.de> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) { 11 die(); 12} 13 14class helper_plugin_ireadit extends DokuWiki_Plugin 15{ 16 /** 17 * @param array $users 18 * @param array $groups 19 * @return array 20 */ 21 public function users_set($ireadit_data) { 22 global $auth; 23 24 $users = $ireadit_data['users']; 25 $groups = $ireadit_data['groups']; 26 $set = []; 27 if (empty($users) && empty($groups)) { 28 $set = $auth->retrieveUsers(); 29 } else { 30 $all_users = $auth->retrieveUsers(); 31 foreach ($all_users as $user => $info) { 32 if (in_array($user, $users)) { 33 $set[$user] = true; 34 } elseif (array_intersect($groups, $info['grps'])) { 35 $set[$user] = true; 36 } 37 } 38 } 39 return array_keys($set); 40 } 41 42 public function find_last_approved($id) { 43 /** @var helper_plugin_approve_db $approve_db */ 44 $approve_db = plugin_load('helper', 'approve_db'); 45 if ($approve_db == null) { 46 msg('You must install approve plugin to use ireadit-approve integration.', -1); 47 return null; 48 } 49 50 return $approve_db->getLastDbRev($id, 'approved'); 51 } 52 53 public function use_approve_here($id) { 54 /** @var helper_plugin_approve_acl $approve_acl */ 55 $approve_acl = plugin_load('helper', 'approve_acl'); 56 if ($approve_acl == null) { 57 msg('You must install approve plugin to use ireadit-approve integration.', -1); 58 return null; 59 } 60 61 return $approve_acl->useApproveHere($id); 62 } 63 64 public function get_approved_revs($id) { 65 /** @var helper_plugin_approve_db $approve_db */ 66 $approve_db = plugin_load('helper', 'approve_db'); 67 if ($approve_db == null) { 68 msg('You must install approve plugin to use ireadit-approve integration.', -1); 69 return null; 70 } 71 $revs = $approve_db->getPageRevisions($id); 72 $approved_revs = array_filter($revs, function ($rev) { 73 return $rev['status'] == 'approved'; 74 }); 75 return array_map(function ($row) { 76 return (int) $row['rev']; 77 }, $approved_revs); 78 79 try { 80 /** @var \helper_plugin_approve_db $db_helper */ 81 $approve_db_helper = plugin_load('helper', 'approve_db'); 82 if ($approve_db_helper == null) { 83 msg('You must install approve plugin to use ireadit-approve integration.', -1); 84 return []; 85 } 86 $approve_sqlite = $approve_db_helper->getDB(); 87 } catch (Exception $e) { 88 msg($e->getMessage(), -1); 89 return []; 90 } 91 92 $res = $approve_sqlite->query('SELECT rev FROM revision WHERE page=? AND approved IS NOT NULL', $id); 93 return array_map(function ($row) { 94 return (int) $row['rev']; 95 }, $approve_sqlite->res2arr($res)); 96 } 97 98 public function use_ireadit_here($id, $rev) { 99 if ($this->getConf('approve_integration') && $this->use_approve_here($id)) { // check if this is newest approve page 100 $last_approved_rev = $this->find_last_approved($id); 101 if ($rev == $last_approved_rev) { // this is last approved version 102 return true; 103 } 104 } elseif ($rev == p_get_metadata($id, 'last_change date')) { // check if it is last page revision 105 return true; 106 } 107 return false; 108 } 109 110 public function user_can_read_page($ireadit_data, $id, $rev, $user) { 111 if (!$this->use_ireadit_here($id, $rev)) return false; 112 113 try { 114 /** @var \helper_plugin_ireadit_db $db_helper */ 115 $db_helper = plugin_load('helper', 'ireadit_db'); 116 $sqlite = $db_helper->getDB(); 117 } catch (Exception $e) { 118 msg($e->getMessage(), -1); 119 return false; 120 } 121 122 $res = $sqlite->query('SELECT user, timestamp FROM ireadit 123 WHERE page = ? 124 AND rev = ? 125 ORDER BY timestamp', $id, $rev); 126 $readers = $sqlite->res2arr($res); 127 $users_set = $this->users_set($ireadit_data); 128 return in_array($user, $users_set) && !in_array($user, array_column($readers, 'user')); 129 } 130 131 /** 132 * @param $user NULL means overview mode 133 * @return array 134 */ 135 public function get_list($user=NULL) { 136 try { 137 /** @var \helper_plugin_ireadit_db $db_helper */ 138 $db_helper = plugin_load('helper', 'ireadit_db'); 139 $sqlite = $db_helper->getDB(); 140 } catch (Exception $e) { 141 msg($e->getMessage(), -1); 142 return []; 143 } 144 145 $indexer = idx_get_indexer(); 146 if ($user) { 147 $current_user_pages = $indexer->lookupKey('ireadit', $user); 148 } else { 149 $current_user_pages = $indexer->getPages('ireadit'); 150 } 151 152 $pages = []; 153 foreach ($current_user_pages as $page) { 154 $current_rev = p_get_metadata($page, 'last_change date'); 155 156 $pages[$page] = [ 157 'current_rev' => $current_rev, 158 'last_read_rev' => NULL, 159 'timestamp' => NULL 160 ]; 161 } 162 if ($user) { 163 $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit WHERE user=? GROUP BY page', 164 $user); 165 } else { 166 $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit GROUP BY page'); 167 } 168 while ($row = $sqlite->res_fetch_assoc($res)) { 169 $page = $row['page']; 170 $rev = (int) $row['rev']; 171 $timestamp = $row['timestamp']; 172 if (isset($pages[$page])) { 173 $pages[$page]['last_read_rev'] = $rev; 174 $pages[$page]['timestamp'] = $timestamp; 175 } 176 } 177 178 if ($this->getConf('approve_integration')) { 179 foreach ($current_user_pages as $page) { 180 if (!$this->use_approve_here($page)) continue; // ignore the pages where approve doesn't apply 181 $approved_revs = $this->get_approved_revs($page); 182 if (count($approved_revs) == 0) { // page was never approved - don't list it 183 unset($pages[$page]); 184 continue; 185 } 186 187 $current_rev = max($approved_revs); 188 if ($user) { 189 $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE user=? AND page=? ORDER BY rev DESC', 190 $user, $page); 191 } else { 192 $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE page=? ORDER BY rev DESC', $page); 193 } 194 $user_reads = $sqlite->res2arr($res); 195 $last_read_rev = NULL; 196 $last_read_timestamp = NULL; 197 foreach ($user_reads as $row) { 198 $rev = (int) $row['rev']; 199 if (in_array($rev, $approved_revs)) { 200 $last_read_rev = $rev; 201 $last_read_timestamp = $row['timestamp']; 202 break; 203 } 204 } 205 206 $pages[$page] = [ 207 'current_rev' => $current_rev, 208 'last_read_rev' => $last_read_rev, 209 'timestamp' => $last_read_timestamp 210 ]; // override default values 211 } 212 } 213 214 // apply states to pages 215 foreach ($pages as &$page) { 216 if ($page['current_rev'] == $page['last_read_rev']) { 217 $page['state'] = 'read'; 218 } elseif ($page['last_read_rev'] == NULL) { 219 $page['state'] = 'unread'; 220 } else { 221 $page['state'] = 'outdated'; 222 } 223 } 224 return $pages; 225 } 226} 227