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