1*4474ed8aSSzymon Olewniczak<?php 2*4474ed8aSSzymon Olewniczak/** 3*4474ed8aSSzymon Olewniczak * DokuWiki Plugin bez (Action Component) 4*4474ed8aSSzymon Olewniczak * 5*4474ed8aSSzymon Olewniczak */ 6*4474ed8aSSzymon Olewniczak 7*4474ed8aSSzymon Olewniczak// must be run within Dokuwiki 8*4474ed8aSSzymon Olewniczak 9*4474ed8aSSzymon Olewniczakuse dokuwiki\plugin\approve\meta\ApproveConst; 10*4474ed8aSSzymon Olewniczak 11*4474ed8aSSzymon Olewniczakif (!defined('DOKU_INC')) die(); 12*4474ed8aSSzymon Olewniczak 13*4474ed8aSSzymon Olewniczak/** 14*4474ed8aSSzymon Olewniczak * Class action_plugin_bez_migration 15*4474ed8aSSzymon Olewniczak * 16*4474ed8aSSzymon Olewniczak * Handle migrations that need more than just SQL 17*4474ed8aSSzymon Olewniczak */ 18*4474ed8aSSzymon Olewniczakclass action_plugin_approve_migration extends DokuWiki_Action_Plugin 19*4474ed8aSSzymon Olewniczak{ 20*4474ed8aSSzymon Olewniczak /** 21*4474ed8aSSzymon Olewniczak * @inheritDoc 22*4474ed8aSSzymon Olewniczak */ 23*4474ed8aSSzymon Olewniczak public function register(Doku_Event_Handler $controller) 24*4474ed8aSSzymon Olewniczak { 25*4474ed8aSSzymon Olewniczak $controller->register_hook('PLUGIN_SQLITE_DATABASE_UPGRADE', 'AFTER', $this, 'handle_migrations'); 26*4474ed8aSSzymon Olewniczak } 27*4474ed8aSSzymon Olewniczak 28*4474ed8aSSzymon Olewniczak /** 29*4474ed8aSSzymon Olewniczak * Call our custom migrations when defined 30*4474ed8aSSzymon Olewniczak * 31*4474ed8aSSzymon Olewniczak * @param Doku_Event $event 32*4474ed8aSSzymon Olewniczak * @param $param 33*4474ed8aSSzymon Olewniczak */ 34*4474ed8aSSzymon Olewniczak public function handle_migrations(Doku_Event $event, $param) 35*4474ed8aSSzymon Olewniczak { 36*4474ed8aSSzymon Olewniczak if ($event->data['sqlite']->getAdapter()->getDbname() !== 'approve') { 37*4474ed8aSSzymon Olewniczak return; 38*4474ed8aSSzymon Olewniczak } 39*4474ed8aSSzymon Olewniczak $to = $event->data['to']; 40*4474ed8aSSzymon Olewniczak 41*4474ed8aSSzymon Olewniczak if (is_callable([$this, "migration$to"])) { 42*4474ed8aSSzymon Olewniczak $event->result = call_user_func([$this, "migration$to"], $event->data); 43*4474ed8aSSzymon Olewniczak } 44*4474ed8aSSzymon Olewniczak } 45*4474ed8aSSzymon Olewniczak 46*4474ed8aSSzymon Olewniczak /** 47*4474ed8aSSzymon Olewniczak * Convenience function to run an INSERT ... ON CONFLICT IGNORE operation 48*4474ed8aSSzymon Olewniczak * 49*4474ed8aSSzymon Olewniczak * The function takes a key-value array with the column names in the key and the actual value in the value, 50*4474ed8aSSzymon Olewniczak * build the appropriate query and executes it. 51*4474ed8aSSzymon Olewniczak * 52*4474ed8aSSzymon Olewniczak * @param string $table the table the entry should be saved to (will not be escaped) 53*4474ed8aSSzymon Olewniczak * @param array $entry A simple key-value pair array (only values will be escaped) 54*4474ed8aSSzymon Olewniczak * @return bool|SQLiteResult 55*4474ed8aSSzymon Olewniczak */ 56*4474ed8aSSzymon Olewniczak protected function insertOrIgnore(helper_plugin_sqlite $sqlite, $table, $entry) { 57*4474ed8aSSzymon Olewniczak $keys = join(',', array_keys($entry)); 58*4474ed8aSSzymon Olewniczak $vals = join(',', array_fill(0,count($entry),'?')); 59*4474ed8aSSzymon Olewniczak 60*4474ed8aSSzymon Olewniczak $sql = "INSERT OR IGNORE INTO $table ($keys) VALUES ($vals)"; 61*4474ed8aSSzymon Olewniczak return $sqlite->query($sql, array_values($entry)); 62*4474ed8aSSzymon Olewniczak } 63*4474ed8aSSzymon Olewniczak 64*4474ed8aSSzymon Olewniczak protected function migration1($data) 65*4474ed8aSSzymon Olewniczak { 66*4474ed8aSSzymon Olewniczak global $conf; 67*4474ed8aSSzymon Olewniczak 68*4474ed8aSSzymon Olewniczak /** @var helper_plugin_sqlite $sqlite */ 69*4474ed8aSSzymon Olewniczak $sqlite = $data['sqlite']; 70*4474ed8aSSzymon Olewniczak $db = $sqlite->getAdapter()->getDb(); 71*4474ed8aSSzymon Olewniczak 72*4474ed8aSSzymon Olewniczak 73*4474ed8aSSzymon Olewniczak $datadir = $conf['datadir']; 74*4474ed8aSSzymon Olewniczak if (substr($datadir, -1) != '/') { 75*4474ed8aSSzymon Olewniczak $datadir .= '/'; 76*4474ed8aSSzymon Olewniczak } 77*4474ed8aSSzymon Olewniczak 78*4474ed8aSSzymon Olewniczak $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir)); 79*4474ed8aSSzymon Olewniczak $pages = []; 80*4474ed8aSSzymon Olewniczak foreach ($rii as $file) { 81*4474ed8aSSzymon Olewniczak if ($file->isDir()){ 82*4474ed8aSSzymon Olewniczak continue; 83*4474ed8aSSzymon Olewniczak } 84*4474ed8aSSzymon Olewniczak 85*4474ed8aSSzymon Olewniczak //remove start path and extension 86*4474ed8aSSzymon Olewniczak $page = substr($file->getPathname(), strlen($datadir), -4); 87*4474ed8aSSzymon Olewniczak $pages[] = str_replace('/', ':', $page); 88*4474ed8aSSzymon Olewniczak } 89*4474ed8aSSzymon Olewniczak 90*4474ed8aSSzymon Olewniczak $db->beginTransaction(); 91*4474ed8aSSzymon Olewniczak 92*4474ed8aSSzymon Olewniczak $apr_namespaces = preg_split('/\s+/', $this->getConf('apr_namespaces'), 93*4474ed8aSSzymon Olewniczak -1,PREG_SPLIT_NO_EMPTY); 94*4474ed8aSSzymon Olewniczak 95*4474ed8aSSzymon Olewniczak if (!$apr_namespaces) { 96*4474ed8aSSzymon Olewniczak $sqlite->storeEntry('maintainer',[ 97*4474ed8aSSzymon Olewniczak 'namespace' => '**' 98*4474ed8aSSzymon Olewniczak ]); 99*4474ed8aSSzymon Olewniczak } else { 100*4474ed8aSSzymon Olewniczak foreach ($apr_namespaces as $namespace) { 101*4474ed8aSSzymon Olewniczak $namespace = rtrim($namespace, ':'); 102*4474ed8aSSzymon Olewniczak $namespace .= ':**'; 103*4474ed8aSSzymon Olewniczak $sqlite->storeEntry('maintainer',[ 104*4474ed8aSSzymon Olewniczak 'namespace' => $namespace 105*4474ed8aSSzymon Olewniczak ]); 106*4474ed8aSSzymon Olewniczak } 107*4474ed8aSSzymon Olewniczak } 108*4474ed8aSSzymon Olewniczak 109*4474ed8aSSzymon Olewniczak //store config 110*4474ed8aSSzymon Olewniczak $no_apr_namespaces = $this->getConf('no_apr_namespaces'); 111*4474ed8aSSzymon Olewniczak $sqlite->storeEntry('config',[ 112*4474ed8aSSzymon Olewniczak 'key' => 'no_apr_namespaces', 113*4474ed8aSSzymon Olewniczak 'value' => $no_apr_namespaces 114*4474ed8aSSzymon Olewniczak ]); 115*4474ed8aSSzymon Olewniczak 116*4474ed8aSSzymon Olewniczak $no_apr_namespaces_list = preg_split('/\s+/', $no_apr_namespaces,-1, 117*4474ed8aSSzymon Olewniczak PREG_SPLIT_NO_EMPTY); 118*4474ed8aSSzymon Olewniczak $no_apr_namespaces_list = array_map(function ($namespace) { 119*4474ed8aSSzymon Olewniczak return trim($namespace, ':'); 120*4474ed8aSSzymon Olewniczak }, $no_apr_namespaces_list); 121*4474ed8aSSzymon Olewniczak 122*4474ed8aSSzymon Olewniczak foreach ($pages as $page) { 123*4474ed8aSSzymon Olewniczak //import historic data 124*4474ed8aSSzymon Olewniczak $versions = p_get_metadata($page, ApproveConst::METADATA_VERSIONS_KEY); 125*4474ed8aSSzymon Olewniczak if (!$versions) { 126*4474ed8aSSzymon Olewniczak $versions = $this->render_metadata_for_approved_page($page); 127*4474ed8aSSzymon Olewniczak } 128*4474ed8aSSzymon Olewniczak 129*4474ed8aSSzymon Olewniczak// $last_change_date = p_get_metadata($page, 'last_change date'); 130*4474ed8aSSzymon Olewniczak $last_change_date = @filemtime(wikiFN($page)); 131*4474ed8aSSzymon Olewniczak $last_version = $versions[0]; 132*4474ed8aSSzymon Olewniczak 133*4474ed8aSSzymon Olewniczak //remove current versions to not process it here 134*4474ed8aSSzymon Olewniczak unset($versions[0]); 135*4474ed8aSSzymon Olewniczak unset($versions[$last_change_date]); 136*4474ed8aSSzymon Olewniczak 137*4474ed8aSSzymon Olewniczak foreach ($versions as $rev => $version) { 138*4474ed8aSSzymon Olewniczak $data = [ 139*4474ed8aSSzymon Olewniczak 'page' => $page, 140*4474ed8aSSzymon Olewniczak 'rev' => $rev, 141*4474ed8aSSzymon Olewniczak 'approved' => date('c', $rev), 142*4474ed8aSSzymon Olewniczak 'version' => $version 143*4474ed8aSSzymon Olewniczak ]; 144*4474ed8aSSzymon Olewniczak $sqlite->storeEntry('revision', $data); 145*4474ed8aSSzymon Olewniczak } 146*4474ed8aSSzymon Olewniczak 147*4474ed8aSSzymon Olewniczak //process current data 148*4474ed8aSSzymon Olewniczak $summary = p_get_metadata($page, 'last_change sum'); 149*4474ed8aSSzymon Olewniczak $data = [ 150*4474ed8aSSzymon Olewniczak 'page' => $page, 151*4474ed8aSSzymon Olewniczak 'rev' => $last_change_date, 152*4474ed8aSSzymon Olewniczak 'current' => 1 153*4474ed8aSSzymon Olewniczak ]; 154*4474ed8aSSzymon Olewniczak if ($this->getConf('ready_for_approval') && 155*4474ed8aSSzymon Olewniczak $summary == $this->getConf('sum ready for approval')) { 156*4474ed8aSSzymon Olewniczak $data['ready_for_approval'] = date('c', $last_change_date); 157*4474ed8aSSzymon Olewniczak } elseif($summary == $this->getConf('sum approved')) { 158*4474ed8aSSzymon Olewniczak $data['approved'] = date('c', $last_change_date); 159*4474ed8aSSzymon Olewniczak $data['version'] = $last_version; 160*4474ed8aSSzymon Olewniczak } 161*4474ed8aSSzymon Olewniczak $sqlite->storeEntry('revision', $data); 162*4474ed8aSSzymon Olewniczak 163*4474ed8aSSzymon Olewniczak 164*4474ed8aSSzymon Olewniczak //empty apr_namespaces - all match 165*4474ed8aSSzymon Olewniczak if (!$apr_namespaces) { 166*4474ed8aSSzymon Olewniczak $in_apr_namespace = true; 167*4474ed8aSSzymon Olewniczak } else { 168*4474ed8aSSzymon Olewniczak $in_apr_namespace = false; 169*4474ed8aSSzymon Olewniczak foreach ($apr_namespaces as $namespace) { 170*4474ed8aSSzymon Olewniczak if (substr($page, 0, strlen($namespace)) == $namespace) { 171*4474ed8aSSzymon Olewniczak $in_apr_namespace = true; 172*4474ed8aSSzymon Olewniczak break; 173*4474ed8aSSzymon Olewniczak } 174*4474ed8aSSzymon Olewniczak } 175*4474ed8aSSzymon Olewniczak } 176*4474ed8aSSzymon Olewniczak 177*4474ed8aSSzymon Olewniczak if ($in_apr_namespace) { 178*4474ed8aSSzymon Olewniczak $hidden = '0'; 179*4474ed8aSSzymon Olewniczak foreach ($no_apr_namespaces_list as $namespace) { 180*4474ed8aSSzymon Olewniczak if (substr($page, 0, strlen($namespace)) == $namespace) { 181*4474ed8aSSzymon Olewniczak $hidden = '1'; 182*4474ed8aSSzymon Olewniczak break; 183*4474ed8aSSzymon Olewniczak } 184*4474ed8aSSzymon Olewniczak } 185*4474ed8aSSzymon Olewniczak $sqlite->storeEntry('page', [ 186*4474ed8aSSzymon Olewniczak 'page' => $page, 187*4474ed8aSSzymon Olewniczak 'hidden' => $hidden 188*4474ed8aSSzymon Olewniczak ]); 189*4474ed8aSSzymon Olewniczak } 190*4474ed8aSSzymon Olewniczak } 191*4474ed8aSSzymon Olewniczak 192*4474ed8aSSzymon Olewniczak 193*4474ed8aSSzymon Olewniczak $db->commit(); 194*4474ed8aSSzymon Olewniczak 195*4474ed8aSSzymon Olewniczak return true; 196*4474ed8aSSzymon Olewniczak } 197*4474ed8aSSzymon Olewniczak 198*4474ed8aSSzymon Olewniczak /** 199*4474ed8aSSzymon Olewniczak * Calculate current version 200*4474ed8aSSzymon Olewniczak * 201*4474ed8aSSzymon Olewniczak * @param $id 202*4474ed8aSSzymon Olewniczak * @return array 203*4474ed8aSSzymon Olewniczak */ 204*4474ed8aSSzymon Olewniczak protected function render_metadata_for_approved_page($id, $currev=false) { 205*4474ed8aSSzymon Olewniczak if (!$currev) $currev = @filemtime(wikiFN($id)); 206*4474ed8aSSzymon Olewniczak 207*4474ed8aSSzymon Olewniczak $version = $this->approved($id); 208*4474ed8aSSzymon Olewniczak //version for current page 209*4474ed8aSSzymon Olewniczak $curver = $version + 1; 210*4474ed8aSSzymon Olewniczak $versions = array(0 => $curver, $currev => $curver); 211*4474ed8aSSzymon Olewniczak 212*4474ed8aSSzymon Olewniczak $changelog = new PageChangeLog($id); 213*4474ed8aSSzymon Olewniczak $first = 0; 214*4474ed8aSSzymon Olewniczak $num = 100; 215*4474ed8aSSzymon Olewniczak while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 216*4474ed8aSSzymon Olewniczak foreach ($revs as $rev) { 217*4474ed8aSSzymon Olewniczak $revInfo = $changelog->getRevisionInfo($rev); 218*4474ed8aSSzymon Olewniczak if ($revInfo['sum'] == $this->getConf('sum approved')) { 219*4474ed8aSSzymon Olewniczak $versions[$rev] = $version; 220*4474ed8aSSzymon Olewniczak $version -= 1; 221*4474ed8aSSzymon Olewniczak } 222*4474ed8aSSzymon Olewniczak } 223*4474ed8aSSzymon Olewniczak $first += $num; 224*4474ed8aSSzymon Olewniczak } 225*4474ed8aSSzymon Olewniczak 226*4474ed8aSSzymon Olewniczak// p_set_metadata($id, array(ApproveConst::METADATA_VERSIONS_KEY => $versions)); 227*4474ed8aSSzymon Olewniczak 228*4474ed8aSSzymon Olewniczak return $versions; 229*4474ed8aSSzymon Olewniczak } 230*4474ed8aSSzymon Olewniczak 231*4474ed8aSSzymon Olewniczak /** 232*4474ed8aSSzymon Olewniczak * Get the number of approved pages 233*4474ed8aSSzymon Olewniczak * @param $id 234*4474ed8aSSzymon Olewniczak * @return int 235*4474ed8aSSzymon Olewniczak */ 236*4474ed8aSSzymon Olewniczak protected function approved($id) { 237*4474ed8aSSzymon Olewniczak $count = 0; 238*4474ed8aSSzymon Olewniczak 239*4474ed8aSSzymon Olewniczak $changelog = new PageChangeLog($id); 240*4474ed8aSSzymon Olewniczak $first = 0; 241*4474ed8aSSzymon Olewniczak $num = 100; 242*4474ed8aSSzymon Olewniczak while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 243*4474ed8aSSzymon Olewniczak foreach ($revs as $rev) { 244*4474ed8aSSzymon Olewniczak $revInfo = $changelog->getRevisionInfo($rev); 245*4474ed8aSSzymon Olewniczak if ($revInfo['sum'] == $this->getConf('sum approved')) { 246*4474ed8aSSzymon Olewniczak $count += 1; 247*4474ed8aSSzymon Olewniczak } 248*4474ed8aSSzymon Olewniczak } 249*4474ed8aSSzymon Olewniczak $first += $num; 250*4474ed8aSSzymon Olewniczak } 251*4474ed8aSSzymon Olewniczak 252*4474ed8aSSzymon Olewniczak return $count; 253*4474ed8aSSzymon Olewniczak } 254*4474ed8aSSzymon Olewniczak} 255