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 user_can_read_page($ireadit_data, $id, $rev, $user) { 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 not last approved version 106 return false; 107 } 108 } elseif ($rev != p_get_metadata($id, 'last_change date')) { // check if it is last page revision 109 return false; 110 } 111 112 try { 113 /** @var \helper_plugin_ireadit_db $db_helper */ 114 $db_helper = plugin_load('helper', 'ireadit_db'); 115 $sqlite = $db_helper->getDB(); 116 } catch (Exception $e) { 117 msg($e->getMessage(), -1); 118 return false; 119 } 120 121 $res = $sqlite->query('SELECT user, timestamp FROM ireadit 122 WHERE page = ? 123 AND rev = ? 124 ORDER BY timestamp', $id, $rev); 125 $readers = $sqlite->res2arr($res); 126 $users_set = $this->users_set($ireadit_data); 127 return in_array($user, $users_set) && !in_array($user, array_column($readers, 'user')); 128 } 129 130 /** 131 * @param $user NULL means overview mode 132 * @return array 133 */ 134 public function get_list($user=NULL) { 135 try { 136 /** @var \helper_plugin_ireadit_db $db_helper */ 137 $db_helper = plugin_load('helper', 'ireadit_db'); 138 $sqlite = $db_helper->getDB(); 139 } catch (Exception $e) { 140 msg($e->getMessage(), -1); 141 return []; 142 } 143 144 $indexer = idx_get_indexer(); 145 if ($user) { 146 $current_user_pages = $indexer->lookupKey('ireadit', $user); 147 } else { 148 $current_user_pages = $indexer->getPages('ireadit'); 149 } 150 151 $pages = []; 152 foreach ($current_user_pages as $page) { 153 $current_rev = p_get_metadata($page, 'last_change date'); 154 155 $pages[$page] = [ 156 'current_rev' => $current_rev, 157 'last_read_rev' => NULL, 158 'timestamp' => NULL 159 ]; 160 } 161 if ($user) { 162 $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit WHERE user=? GROUP BY page', 163 $user); 164 } else { 165 $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit GROUP BY page'); 166 } 167 while ($row = $sqlite->res_fetch_assoc($res)) { 168 $page = $row['page']; 169 $rev = (int) $row['rev']; 170 $timestamp = $row['timestamp']; 171 if (isset($pages[$page])) { 172 $pages[$page]['last_read_rev'] = $rev; 173 $pages[$page]['timestamp'] = $timestamp; 174 } 175 } 176 177 if ($this->getConf('approve_integration')) { 178 foreach ($current_user_pages as $page) { 179 if (!$this->use_approve_here($page)) continue; // ignore the pages where approve doesn't apply 180 $approved_revs = $this->get_approved_revs($page); 181 if (count($approved_revs) == 0) unset($pages[$page]); // page was never approved - don't list it 182 183 $current_rev = max($approved_revs); 184 if ($user) { 185 $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE user=? AND page=? ORDER BY rev DESC', 186 $user, $page); 187 } else { 188 $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE page=? ORDER BY rev DESC', $page); 189 } 190 $user_reads = $sqlite->res2arr($res); 191 $last_read_rev = NULL; 192 $last_read_timestamp = NULL; 193 foreach ($user_reads as $row) { 194 $rev = (int) $row['rev']; 195 if (in_array($rev, $approved_revs)) { 196 $last_read_rev = $rev; 197 $last_read_timestamp = $row['timestamp']; 198 break; 199 } 200 } 201 202 $pages[$page] = [ 203 'current_rev' => $current_rev, 204 'last_read_rev' => $last_read_rev, 205 'timestamp' => $last_read_timestamp 206 ]; // override default values 207 } 208 } 209 210 // apply states to pages 211 foreach ($pages as &$page) { 212 if ($page['current_rev'] == $page['last_read_rev']) { 213 $page['state'] = 'read'; 214 } elseif ($page['last_read_rev'] == NULL) { 215 $page['state'] = 'unread'; 216 } else { 217 $page['state'] = 'outdated'; 218 } 219 } 220 return $pages; 221 } 222} 223