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_approve_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() !== 'approve') { 35 return; 36 } 37 $to = $event->data['to']; 38 39 if (is_callable([$this, "migration$to"])) { 40 $event->result = call_user_func([$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 /** @var helper_plugin_sqlite $sqlite */ 65 $sqlite = $data['sqlite']; 66 $db = $sqlite->getAdapter()->getDb(); 67 68 /** @var helper_plugin_approve $helper */ 69 $helper = plugin_load('helper', 'approve'); 70 71 $db->beginTransaction(); 72 73 $apr_namespaces = preg_split('/\s+/', $this->getConf('apr_namespaces', ''), 74 -1,PREG_SPLIT_NO_EMPTY); 75 76 if (!$apr_namespaces) { 77 $sqlite->storeEntry('maintainer',[ 78 'namespace' => '**' 79 ]); 80 } else { 81 foreach ($apr_namespaces as $namespace) { 82 $namespace = rtrim($namespace, ':'); 83 $namespace .= ':**'; 84 $sqlite->storeEntry('maintainer',[ 85 'namespace' => $namespace 86 ]); 87 } 88 } 89 90 //store config 91 $no_apr_namespaces = $this->getConf('no_apr_namespaces', ''); 92 $sqlite->storeEntry('config',[ 93 'key' => 'no_apr_namespaces', 94 'value' => $no_apr_namespaces 95 ]); 96 97 $no_apr_namespaces_list = preg_split('/\s+/', $no_apr_namespaces,-1, 98 PREG_SPLIT_NO_EMPTY); 99 $no_apr_namespaces_list = array_map(function ($namespace) { 100 return trim($namespace, ':'); 101 }, $no_apr_namespaces_list); 102 103 104 $pages = $helper->getPages(); 105 foreach ($pages as $page) { 106 //import historic data 107 $versions = p_get_metadata($page, 'plugin_approve_versions'); 108 if (!$versions) { 109 $versions = $this->render_metadata_for_approved_page($page); 110 } 111 112// $last_change_date = p_get_metadata($page, 'last_change date'); 113 $last_change_date = @filemtime(wikiFN($page)); 114 $last_version = $versions[0]; 115 116 //remove current versions to not process it here 117 unset($versions[0]); 118 unset($versions[$last_change_date]); 119 120 $revision_editors = $this->revision_editors($page); 121 foreach ($versions as $rev => $version) { 122 $data = [ 123 'page' => $page, 124 'rev' => $rev, 125 'approved' => date('c', $rev), 126 'approved_by' => $revision_editors[$rev], 127 'version' => $version 128 ]; 129 $sqlite->storeEntry('revision', $data); 130 } 131 132 //process current data 133 $summary = p_get_metadata($page, 'last_change sum'); 134 $user = p_get_metadata($page, 'last_change user'); 135 $data = [ 136 'page' => $page, 137 'rev' => $last_change_date, 138 'current' => 1 139 ]; 140 if ($this->getConf('ready_for_approval') && 141 $summary == $this->getConf('sum ready for approval')) { 142 $data['ready_for_approval'] = date('c', $last_change_date); 143 $data['ready_for_approval_by'] = $user; 144 } elseif($summary == $this->getConf('sum approved')) { 145 $data['approved'] = date('c', $last_change_date); 146 $data['approved_by'] = $user; 147 $data['version'] = $last_version; 148 } 149 $sqlite->storeEntry('revision', $data); 150 151 152 //empty apr_namespaces - all match 153 if (!$apr_namespaces) { 154 $in_apr_namespace = true; 155 } else { 156 $in_apr_namespace = false; 157 foreach ($apr_namespaces as $namespace) { 158 if (substr($page, 0, strlen($namespace)) == $namespace) { 159 $in_apr_namespace = true; 160 break; 161 } 162 } 163 } 164 165 if ($in_apr_namespace) { 166 $hidden = '0'; 167 foreach ($no_apr_namespaces_list as $namespace) { 168 if (substr($page, 0, strlen($namespace)) == $namespace) { 169 $hidden = '1'; 170 break; 171 } 172 } 173 $sqlite->storeEntry('page', [ 174 'page' => $page, 175 'hidden' => $hidden 176 ]); 177 } 178 } 179 180 181 $db->commit(); 182 183 return true; 184 } 185 186 /** 187 * Calculate current version 188 * 189 * @param $id 190 * @return array 191 */ 192 protected function render_metadata_for_approved_page($id, $currev=false) { 193 if (!$currev) $currev = @filemtime(wikiFN($id)); 194 195 $version = $this->approved($id); 196 //version for current page 197 $curver = $version + 1; 198 $versions = array(0 => $curver, $currev => $curver); 199 200 $changelog = new PageChangeLog($id); 201 $first = 0; 202 $num = 100; 203 while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 204 foreach ($revs as $rev) { 205 $revInfo = $changelog->getRevisionInfo($rev); 206 if ($revInfo['sum'] == $this->getConf('sum approved')) { 207 $versions[$rev] = $version; 208 $version -= 1; 209 } 210 } 211 $first += $num; 212 } 213 214// p_set_metadata($id, array(ApproveConst::METADATA_VERSIONS_KEY => $versions)); 215 216 return $versions; 217 } 218 219 /** 220 * Get the number of approved pages 221 * @param $id 222 * @return int 223 */ 224 protected function approved($id) { 225 $count = 0; 226 227 $changelog = new PageChangeLog($id); 228 $first = 0; 229 $num = 100; 230 while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 231 foreach ($revs as $rev) { 232 $revInfo = $changelog->getRevisionInfo($rev); 233 if ($revInfo['sum'] == $this->getConf('sum approved')) { 234 $count += 1; 235 } 236 } 237 $first += $num; 238 } 239 240 return $count; 241 } 242 243 /** 244 * Calculate current version 245 * 246 * @param $id 247 * @return array 248 */ 249 protected function revision_editors($id) 250 { 251 $currev = @filemtime(wikiFN($id)); 252 $user = p_get_metadata($id, 'last_change user'); 253 254 $revision_editors = array($currev => $user); 255 256 $changelog = new PageChangeLog($id); 257 $first = 0; 258 $num = 100; 259 while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 260 foreach ($revs as $rev) { 261 $revInfo = $changelog->getRevisionInfo($rev); 262 $revision_editors[$rev] = $revInfo['user']; 263 } 264 $first += $num; 265 } 266 267 return $revision_editors; 268 } 269 270 protected function migration3($data) 271 { 272 /** @var helper_plugin_sqlite $sqlite */ 273 $sqlite = $data['sqlite']; 274 275 /** @var helper_plugin_approve $helper */ 276 $helper = plugin_load('helper', 'approve'); 277 278 $helper->updatePagesAssignments($sqlite); 279 } 280} 281