1<?php 2/** 3 * DokuWiki Plugin bez (Action Component) 4 * 5 */ 6 7// must be run within Dokuwiki 8 9if (!defined('DOKU_INC')) die(); 10 11/** 12 * Class action_plugin_bez_migration 13 * 14 * Handle migrations that need more than just SQL 15 */ 16class action_plugin_ireadit_migration extends DokuWiki_Action_Plugin 17{ 18 /** 19 * @inheritDoc 20 */ 21 public function register(Doku_Event_Handler $controller) 22 { 23 $controller->register_hook('PLUGIN_SQLITE_DATABASE_UPGRADE', 'AFTER', $this, 'handle_migrations'); 24 } 25 26 /** 27 * Call our custom migrations when defined 28 * 29 * @param Doku_Event $event 30 * @param $param 31 */ 32 public function handle_migrations(Doku_Event $event, $param) 33 { 34 if ($event->data['sqlite']->getAdapter()->getDbname() !== 'ireadit') { 35 return; 36 } 37 $to = $event->data['to']; 38 39 if (is_callable(array($this, "migration$to"))) { 40 $event->result = call_user_func(array($this, "migration$to"), $event->data); 41 } 42 } 43 44 /** 45 * Convenience function to run an INSERT ... ON CONFLICT IGNORE operation 46 * 47 * The function takes a key-value array with the column names in the key and the actual value in the value, 48 * build the appropriate query and executes it. 49 * 50 * @param string $table the table the entry should be saved to (will not be escaped) 51 * @param array $entry A simple key-value pair array (only values will be escaped) 52 * @return bool|SQLiteResult 53 */ 54 protected function insertOrIgnore(helper_plugin_sqlite $sqlite, $table, $entry) { 55 $keys = join(',', array_keys($entry)); 56 $vals = join(',', array_fill(0,count($entry),'?')); 57 58 $sql = "INSERT OR IGNORE INTO $table ($keys) VALUES ($vals)"; 59 return $sqlite->query($sql, array_values($entry)); 60 } 61 62 protected function migration1($data) 63 { 64 global $conf; 65 /** @var $auth DokuWiki_Auth_Plugin */ 66 global $auth; 67 68 /** @var helper_plugin_sqlite $sqlite */ 69 $sqlite = $data['sqlite']; 70 $db = $sqlite->getAdapter()->getDb(); 71 72 73 $datadir = $conf['datadir']; 74 if (substr($datadir, -1) != '/') { 75 $datadir .= '/'; 76 } 77 78 $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir)); 79 $pages = array(); 80 foreach ($rii as $file) { 81 if ($file->isDir()){ 82 continue; 83 } 84 85 //remove start path and extension 86 $page = substr($file->getPathname(), strlen($datadir), -4); 87 $pages[] = str_replace('/', ':', $page); 88 } 89 $db->beginTransaction(); 90 91 foreach ($pages as $page) { 92 //import historic data 93 $meta = p_get_metadata($page, 'plugin_ireadit'); 94 if (!$meta) continue; 95 $date = p_get_metadata($page, 'date modified'); 96 97 if (isset($meta[$date])) { 98 $meta[0] = $meta[$date]; 99 unset($meta[$date]); 100 } 101 102 $current = null; 103 foreach ($meta as $rev => $data) { 104 if ($rev === '' || count($data) == 0) continue; 105 $sqlite->storeEntry('ireadit', array( 106 'page' => $page, 107 'rev' => $rev 108 )); 109 $id = $db->lastInsertId(); 110 if ($rev === 0) { 111 $current = $id; 112 } 113 foreach ($data as $user_read) { 114 $sqlite->storeEntry('ireadit_user', array( 115 'ireadit_id' => $id, 116 'user' => $user_read['client'], 117 'timestamp' => date('c', $user_read['time']) 118 )); 119 } 120 } 121 122 //import current data 123 $content = file_get_contents($datadir . str_replace(':', '/', $page) . '.txt'); 124 $status = preg_match('/~~IREADIT.*~~/', $content, $matches); 125 //no ireadit on page 126 if ($status !== 1) continue; 127 128 $match = trim(substr($matches[0], strlen('~~IREADIT'), -2)); 129 $splits = preg_split('/\s+/', $match, -1, PREG_SPLIT_NO_EMPTY); 130 131 $users = array(); 132 $groups = array(); 133 foreach ($splits as $split) { 134 if ($split[0] == '@') { 135 $group = substr($match, 1); 136 $groups[] = $group; 137 } else { 138 $users[] = $split; 139 } 140 } 141 142 $usersToInsert = array(); 143 if (empty($users) && empty($groups)) { 144 $usersToInsert = $auth->retrieveUsers(); 145 } else { 146 $all_users = $auth->retrieveUsers(); 147 foreach ($all_users as $user => $info) { 148 if (in_array($user, $users)) { 149 $usersToInsert[$user] = $info; 150 } elseif (array_intersect($groups, $info['grps'])) { 151 $usersToInsert[$user] = $info; 152 } 153 } 154 } 155 156 if ($usersToInsert) { 157 if ($current === NULL) { 158 $sqlite->storeEntry('ireadit', array( 159 'page' => $page, 160 'rev' => 0 161 )); 162 $current = $db->lastInsertId(); 163 } 164 foreach ($usersToInsert as $user => $info) { 165 $this->insertOrIgnore($sqlite,'ireadit_user', array( 166 'ireadit_id' => $current, 167 'user' => $user 168 )); 169 } 170 } 171 172 } 173 $db->commit(); 174 175 return true; 176 } 177} 178