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 $approve_helper */ 44 $approve_helper = plugin_load('helper', 'approve'); 45 if ($approve_helper == null) { 46 msg('You must install approve plugin to use ireadit-approve integration.', -1); 47 return null; 48 } 49 50 try { 51 /** @var \helper_plugin_approve_db $db_helper */ 52 $approve_db_helper = plugin_load('helper', 'approve_db'); 53 $approve_sqlite = $approve_db_helper->getDB(); 54 } catch (Exception $e) { 55 msg($e->getMessage(), -1); 56 return null; 57 } 58 59 return $approve_helper->find_last_approved($approve_sqlite, $id); 60 } 61 62 public function use_approve_here($id) { 63 /** @var helper_plugin_approve $approve_helper */ 64 $approve_helper = plugin_load('helper', 'approve'); 65 if ($approve_helper == null) { 66 msg('You must install approve plugin to use ireadit-approve integration.', -1); 67 return null; 68 } 69 70 try { 71 /** @var \helper_plugin_approve_db $db_helper */ 72 $approve_db_helper = plugin_load('helper', 'approve_db'); 73 $approve_sqlite = $approve_db_helper->getDB(); 74 } catch (Exception $e) { 75 msg($e->getMessage(), -1); 76 return null; 77 } 78 79 return $approve_helper->use_approve_here($approve_sqlite, $id); 80 } 81 82 public function get_approved_revs($id) { 83 try { 84 /** @var \helper_plugin_approve_db $db_helper */ 85 $approve_db_helper = plugin_load('helper', 'approve_db'); 86 if ($approve_db_helper == null) { 87 msg('You must install approve plugin to use ireadit-approve integration.', -1); 88 return []; 89 } 90 $approve_sqlite = $approve_db_helper->getDB(); 91 } catch (Exception $e) { 92 msg($e->getMessage(), -1); 93 return []; 94 } 95 96 $res = $approve_sqlite->query('SELECT rev FROM revision WHERE page=? AND approved IS NOT NULL', $id); 97 return array_map(function ($row) { 98 return (int) $row['rev']; 99 }, $approve_sqlite->res2arr($res)); 100 } 101 102 public function use_ireadit_here($id, $rev) { 103 if ($this->getConf('approve_integration') && $this->use_approve_here($id)) { // check if this is newest approve page 104 $last_approved_rev = $this->find_last_approved($id); 105 if ($rev == $last_approved_rev) { // this is last approved version 106 return true; 107 } 108 } elseif ($rev == p_get_metadata($id, 'last_change date')) { // check if it is last page revision 109 return true; 110 } 111 return false; 112 } 113 114 public function user_can_read_page($ireadit_data, $id, $rev, $user) { 115 if (!$this->use_ireadit_here($id, $rev)) return false; 116 117 try { 118 /** @var \helper_plugin_ireadit_db $db_helper */ 119 $db_helper = plugin_load('helper', 'ireadit_db'); 120 $sqlite = $db_helper->getDB(); 121 } catch (Exception $e) { 122 msg($e->getMessage(), -1); 123 return false; 124 } 125 126 $res = $sqlite->query('SELECT user, timestamp FROM ireadit 127 WHERE page = ? 128 AND rev = ? 129 ORDER BY timestamp', $id, $rev); 130 $readers = $sqlite->res2arr($res); 131 $users_set = $this->users_set($ireadit_data); 132 return in_array($user, $users_set) && !in_array($user, array_column($readers, 'user')); 133 } 134 135 /** 136 * @param $user NULL means overview mode 137 * @return array 138 */ 139 public function get_list($user=NULL) { 140 try { 141 /** @var \helper_plugin_ireadit_db $db_helper */ 142 $db_helper = plugin_load('helper', 'ireadit_db'); 143 $sqlite = $db_helper->getDB(); 144 } catch (Exception $e) { 145 msg($e->getMessage(), -1); 146 return []; 147 } 148 149 $indexer = idx_get_indexer(); 150 if ($user) { 151 $current_user_pages = $indexer->lookupKey('ireadit', $user); 152 } else { 153 $current_user_pages = $indexer->getPages('ireadit'); 154 } 155 156 $pages = []; 157 foreach ($current_user_pages as $page) { 158 $current_rev = p_get_metadata($page, 'last_change date'); 159 160 $pages[$page] = [ 161 'current_rev' => $current_rev, 162 'last_read_rev' => NULL, 163 'timestamp' => NULL 164 ]; 165 } 166 if ($user) { 167 $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit WHERE user=? GROUP BY page', 168 $user); 169 } else { 170 $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit GROUP BY page'); 171 } 172 while ($row = $sqlite->res_fetch_assoc($res)) { 173 $page = $row['page']; 174 $rev = (int) $row['rev']; 175 $timestamp = $row['timestamp']; 176 if (isset($pages[$page])) { 177 $pages[$page]['last_read_rev'] = $rev; 178 $pages[$page]['timestamp'] = $timestamp; 179 } 180 } 181 182 if ($this->getConf('approve_integration')) { 183 foreach ($current_user_pages as $page) { 184 if (!$this->use_approve_here($page)) continue; // ignore the pages where approve doesn't apply 185 $approved_revs = $this->get_approved_revs($page); 186 if (count($approved_revs) == 0) { // page was never approved - don't list it 187 unset($pages[$page]); 188 continue; 189 } 190 191 $current_rev = max($approved_revs); 192 if ($user) { 193 $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE user=? AND page=? ORDER BY rev DESC', 194 $user, $page); 195 } else { 196 $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE page=? ORDER BY rev DESC', $page); 197 } 198 $user_reads = $sqlite->res2arr($res); 199 $last_read_rev = NULL; 200 $last_read_timestamp = NULL; 201 foreach ($user_reads as $row) { 202 $rev = (int) $row['rev']; 203 if (in_array($rev, $approved_revs)) { 204 $last_read_rev = $rev; 205 $last_read_timestamp = $row['timestamp']; 206 break; 207 } 208 } 209 210 $pages[$page] = [ 211 'current_rev' => $current_rev, 212 'last_read_rev' => $last_read_rev, 213 'timestamp' => $last_read_timestamp 214 ]; // override default values 215 } 216 } 217 218 // apply states to pages 219 foreach ($pages as &$page) { 220 if ($page['current_rev'] == $page['last_read_rev']) { 221 $page['state'] = 'read'; 222 } elseif ($page['last_read_rev'] == NULL) { 223 $page['state'] = 'unread'; 224 } else { 225 $page['state'] = 'outdated'; 226 } 227 } 228 return $pages; 229 } 230} 231