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 $db = $sqlite->getAdapter()->getDb(); 92 93 /** @var helper_plugin_ireadit $helper */ 94 $helper = plugin_load('helper', 'ireadit'); 95 96 //remove old rows 97 $sqlite->query('DELETE FROM ireadit WHERE timestamp IS NULL'); 98 99 $res = $sqlite->query('SELECT page,meta FROM meta'); 100 while ($row = $sqlite->res_fetch_assoc($res)) { 101 $page = $row['page']; 102 $meta = json_decode($row['meta'], true); 103 $user_set = $helper->users_set($meta); 104 $last_change_date = p_get_metadata($page, 'last_change date'); 105 106 $users = $auth->retrieveUsers(); 107 foreach ($users as $user => $info) { 108 $res2 = $sqlite->query('SELECT user FROM ireadit WHERE page=? AND rev=? AND user=?', $page, $last_change_date, $user); 109 $existsAlready = $sqlite->res2single($res2); 110 if (!$existsAlready && in_array($user, $user_set)) { 111 $sqlite->storeEntry('ireadit', [ 112 'page' => $page, 113 'rev' => $last_change_date, 114 'user' => $user 115 ]); 116 } 117 } 118 } 119 } 120 121 protected function migration3($data) 122 { 123 global $conf; 124 125 /** @var helper_plugin_sqlite $sqlite */ 126 $sqlite = $data['sqlite']; 127 $db = $sqlite->getAdapter()->getDb(); 128 129 $res = $sqlite->query('SELECT page,meta FROM meta'); 130 while ($row = $sqlite->res_fetch_assoc($res)) { 131 $last_change_date = p_get_metadata($row['page'], 'last_change date'); 132 $sqlite->storeEntry('meta2', [ 133 'page' => $row['page'], 134 'meta' => $row['meta'], 135 'last_change_date' => $last_change_date 136 ]); 137 } 138 $sqlite->query('DROP TABLE meta'); 139 $sqlite->query('ALTER TABLE meta2 RENAME TO meta'); 140 } 141 142 protected function migration2($data) 143 { 144 global $conf; 145 146 /** @var helper_plugin_sqlite $sqlite */ 147 $sqlite = $data['sqlite']; 148 $db = $sqlite->getAdapter()->getDb(); 149 150 /* @var \helper_plugin_ireadit $helper */ 151 $helper = plugin_load('helper', 'ireadit'); 152 153 154 $datadir = $conf['datadir']; 155 if (substr($datadir, -1) != '/') { 156 $datadir .= '/'; 157 } 158 159 $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir)); 160 $pages = []; 161 foreach ($rii as $file) { 162 if ($file->isDir()){ 163 continue; 164 } 165 166 //remove start path and extension 167 $page = substr($file->getPathname(), strlen($datadir), -4); 168 $pages[] = str_replace('/', ':', $page); 169 } 170 171 $db->beginTransaction(); 172 173 foreach ($pages as $page) { 174 //import historic data 175 $meta = p_get_metadata($page, 'plugin ireadit'); 176 if (!$meta) continue; 177 178 $sqlite->storeEntry('meta', [ 179 'page' => $page, 180 'meta' => json_encode($meta) 181 ]); 182 } 183 $db->commit(); 184 185 186 } 187 188 protected function migration1($data) 189 { 190 global $conf; 191 192 /** @var helper_plugin_sqlite $sqlite */ 193 $sqlite = $data['sqlite']; 194 $db = $sqlite->getAdapter()->getDb(); 195 196 /* @var \helper_plugin_ireadit $helper */ 197 $helper = plugin_load('helper', 'ireadit'); 198 199 200 $datadir = $conf['datadir']; 201 if (substr($datadir, -1) != '/') { 202 $datadir .= '/'; 203 } 204 205 $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir)); 206 $pages = []; 207 foreach ($rii as $file) { 208 if ($file->isDir()){ 209 continue; 210 } 211 212 //remove start path and extension 213 $page = substr($file->getPathname(), strlen($datadir), -4); 214 $pages[] = str_replace('/', ':', $page); 215 } 216 $db->beginTransaction(); 217 218 foreach ($pages as $page) { 219 //import historic data 220 $meta = p_get_metadata($page, 'plugin_ireadit'); 221 if (!$meta) continue; //no metadata 222 223 foreach ($meta as $rev => $data) { 224 if ($rev === '' || count($data) == 0) continue; 225 foreach ($data as $user_read) { 226 $sqlite->storeEntry('ireadit', [ 227 'page' => $page, 228 'rev' => $rev, 229 'user' => $user_read['client'], 230 'timestamp' => date('c', $user_read['time']) 231 ]); 232 } 233 } 234 235 //import current data 236 $content = file_get_contents($datadir . str_replace(':', '/', $page) . '.txt'); 237 $status = preg_match('/~~IREADIT.*~~/', $content, $matches); 238 //no ireadit on page 239 if ($status !== 1) continue; 240 241 $match = trim(substr($matches[0], strlen('~~IREADIT'), -2)); 242 $splits = preg_split('/\s+/', $match, -1, PREG_SPLIT_NO_EMPTY); 243 244 $users = []; 245 $groups = []; 246 foreach ($splits as $split) { 247 if ($split[0] == '@') { 248 $group = substr($split, 1); 249 $groups[] = $group; 250 } else { 251 $users[] = $split; 252 } 253 } 254 255 $usersToInsert = $helper->users_set($users, $groups); 256 257 if ($usersToInsert) { 258 $last_change_date = p_get_metadata($page, 'last_change date'); 259 foreach ($usersToInsert as $user) { 260 $this->insertOrIgnore($sqlite,'ireadit', [ 261 'page' => $page, 262 'rev' => $last_change_date, 263 'user' => $user 264 ]); 265 } 266 } 267 268 } 269 $db->commit(); 270 271 return true; 272 } 273} 274