1<?php 2/** 3 * DokuWiki Plugin bez (Action Component) 4 * 5 */ 6 7use dokuwiki\Cache\CacheRenderer; 8 9// must be run within Dokuwiki 10 11if (!defined('DOKU_INC')) die(); 12 13/** 14 * Class action_plugin_bez_migration 15 * 16 * Handle migrations that need more than just SQL 17 */ 18class action_plugin_ireadit_migration extends DokuWiki_Action_Plugin 19{ 20 /** 21 * @inheritDoc 22 */ 23 public function register(Doku_Event_Handler $controller) 24 { 25 $controller->register_hook('PLUGIN_SQLITE_DATABASE_UPGRADE', 'AFTER', $this, 'handle_migrations'); 26 } 27 28 /** 29 * Call our custom migrations when defined 30 * 31 * @param Doku_Event $event 32 * @param $param 33 */ 34 public function handle_migrations(Doku_Event $event, $param) 35 { 36 if ($event->data['sqlite']->getAdapter()->getDbname() !== 'ireadit') { 37 return; 38 } 39 $to = $event->data['to']; 40 41 if (is_callable([$this, "migration$to"])) { 42 $event->result = call_user_func([$this, "migration$to"], $event->data); 43 } 44 } 45 46 /** 47 * Convenience function to run an INSERT ... ON CONFLICT IGNORE operation 48 * 49 * The function takes a key-value array with the column names in the key and the actual value in the value, 50 * build the appropriate query and executes it. 51 * 52 * @param string $table the table the entry should be saved to (will not be escaped) 53 * @param array $entry A simple key-value pair array (only values will be escaped) 54 * @return bool|SQLiteResult 55 */ 56 protected function insertOrIgnore(helper_plugin_sqlite $sqlite, $table, $entry) { 57 $keys = join(',', array_keys($entry)); 58 $vals = join(',', array_fill(0,count($entry),'?')); 59 60 $sql = "INSERT OR IGNORE INTO $table ($keys) VALUES ($vals)"; 61 return $sqlite->query($sql, array_values($entry)); 62 } 63 64 protected function migration7($data) 65 { 66 global $conf; 67 $data = array(); 68 search($data, $conf['datadir'], 'search_allpages', array('skipacl' => true)); 69 foreach($data as $val) { 70 //import current data 71 $wikiFN = wikiFN($val['id']); 72 $content = file_get_contents($wikiFN); 73 $status = preg_match('/~~IREADIT.*~~/', $content, $matches); 74 // we use ireadit here 75 if ($status === 1) { 76 $cachefile = new CacheRenderer($val['id'], wikiFN($val['id']), 'metadata'); 77 $cachefile->removeCache(); 78 p_get_metadata($val['id'], 'plugin_ireadit=0.2'); // render metadata 79 idx_addPage($val['id'], false, true); // regenerate index for the plugin 80 } 81 } 82 } 83 84 protected function migration5($data) 85 { 86 /** @var DokuWiki_Auth_Plugin */ 87 global $auth; 88 89 /** @var helper_plugin_sqlite $sqlite */ 90 $sqlite = $data['sqlite']; 91 92 /** @var helper_plugin_ireadit $helper */ 93 $helper = plugin_load('helper', 'ireadit'); 94 95 //remove old rows 96 $sqlite->query('DELETE FROM ireadit WHERE timestamp IS NULL'); 97 98 $res = $sqlite->query('SELECT page,meta FROM meta'); 99 while ($row = $sqlite->res_fetch_assoc($res)) { 100 $page = $row['page']; 101 $meta = json_decode($row['meta'], true); 102 $user_set = $helper->users_set($meta); 103 $last_change_date = p_get_metadata($page, 'last_change date'); 104 105 $users = $auth->retrieveUsers(); 106 foreach ($users as $user => $info) { 107 $res2 = $sqlite->query('SELECT user FROM ireadit WHERE page=? AND rev=? AND user=?', $page, $last_change_date, $user); 108 $existsAlready = $sqlite->res2single($res2); 109 if (!$existsAlready && in_array($user, $user_set)) { 110 $sqlite->storeEntry('ireadit', [ 111 'page' => $page, 112 'rev' => $last_change_date, 113 'user' => $user 114 ]); 115 } 116 } 117 } 118 } 119 120 protected function migration3($data) 121 { 122 global $conf; 123 124 /** @var helper_plugin_sqlite $sqlite */ 125 $sqlite = $data['sqlite']; 126 127 $res = $sqlite->query('SELECT page,meta FROM meta'); 128 while ($row = $sqlite->res_fetch_assoc($res)) { 129 $last_change_date = p_get_metadata($row['page'], 'last_change date'); 130 $sqlite->storeEntry('meta2', [ 131 'page' => $row['page'], 132 'meta' => $row['meta'], 133 'last_change_date' => $last_change_date 134 ]); 135 } 136 $sqlite->query('DROP TABLE meta'); 137 $sqlite->query('ALTER TABLE meta2 RENAME TO meta'); 138 } 139 140 protected function migration2($data) 141 { 142 global $conf; 143 144 /** @var helper_plugin_sqlite $sqlite */ 145 $sqlite = $data['sqlite']; 146 $db = $sqlite->getAdapter()->getPdo(); 147 148 /* @var \helper_plugin_ireadit $helper */ 149 $helper = plugin_load('helper', 'ireadit'); 150 151 152 $datadir = $conf['datadir']; 153 if (substr($datadir, -1) != '/') { 154 $datadir .= '/'; 155 } 156 157 $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir)); 158 $pages = []; 159 foreach ($rii as $file) { 160 if ($file->isDir()){ 161 continue; 162 } 163 164 //remove start path and extension 165 $page = substr($file->getPathname(), strlen($datadir), -4); 166 $pages[] = str_replace('/', ':', $page); 167 } 168 169 $db->beginTransaction(); 170 171 foreach ($pages as $page) { 172 //import historic data 173 $meta = p_get_metadata($page, 'plugin ireadit'); 174 if (!$meta) continue; 175 176 $sqlite->storeEntry('meta', [ 177 'page' => $page, 178 'meta' => json_encode($meta) 179 ]); 180 } 181 $db->commit(); 182 183 184 } 185 186 protected function migration1($data) 187 { 188 global $conf; 189 190 /** @var helper_plugin_sqlite $sqlite */ 191 $sqlite = $data['sqlite']; 192 $db = $sqlite->getAdapter()->getPdo(); 193 194 /* @var \helper_plugin_ireadit $helper */ 195 $helper = plugin_load('helper', 'ireadit'); 196 197 198 $datadir = $conf['datadir']; 199 if (substr($datadir, -1) != '/') { 200 $datadir .= '/'; 201 } 202 203 $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir)); 204 $pages = []; 205 foreach ($rii as $file) { 206 if ($file->isDir()){ 207 continue; 208 } 209 210 //remove start path and extension 211 $page = substr($file->getPathname(), strlen($datadir), -4); 212 $pages[] = str_replace('/', ':', $page); 213 } 214 $db->beginTransaction(); 215 216 foreach ($pages as $page) { 217 //import historic data 218 $meta = p_get_metadata($page, 'plugin_ireadit'); 219 if (!$meta) continue; //no metadata 220 221 foreach ($meta as $rev => $data) { 222 if ($rev === '' || count($data) == 0) continue; 223 foreach ($data as $user_read) { 224 $sqlite->storeEntry('ireadit', [ 225 'page' => $page, 226 'rev' => $rev, 227 'user' => $user_read['client'], 228 'timestamp' => date('c', $user_read['time']) 229 ]); 230 } 231 } 232 233 //import current data 234 $content = file_get_contents($datadir . str_replace(':', '/', $page) . '.txt'); 235 $status = preg_match('/~~IREADIT.*~~/', $content, $matches); 236 //no ireadit on page 237 if ($status !== 1) continue; 238 239 $match = trim(substr($matches[0], strlen('~~IREADIT'), -2)); 240 $splits = preg_split('/\s+/', $match, -1, PREG_SPLIT_NO_EMPTY); 241 242 $users = []; 243 $groups = []; 244 foreach ($splits as $split) { 245 if ($split[0] == '@') { 246 $group = substr($split, 1); 247 $groups[] = $group; 248 } else { 249 $users[] = $split; 250 } 251 } 252 253 $usersToInsert = $helper->users_set($users, $groups); 254 255 if ($usersToInsert) { 256 $last_change_date = p_get_metadata($page, 'last_change date'); 257 foreach ($usersToInsert as $user) { 258 $this->insertOrIgnore($sqlite,'ireadit', [ 259 'page' => $page, 260 'rev' => $last_change_date, 261 'user' => $user 262 ]); 263 } 264 } 265 266 } 267 $db->commit(); 268 269 return true; 270 } 271} 272