1<?php 2// must be run within Dokuwiki 3if(!defined('DOKU_INC')) die(); 4 5if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 6require_once(DOKU_PLUGIN.'admin.php'); 7 8/** 9 * All DokuWiki plugins to extend the admin function 10 * need to inherit from this class 11 */ 12class admin_plugin_csvtodwpages extends DokuWiki_Admin_Plugin 13{ 14 /** 15 * Version: see lang.php 16 */ 17 18 protected $params; 19 protected $paramcount; 20 21 /** 22 * access for managers 23 */ 24 function forAdminOnly() 25 { 26 return false; 27 } 28 29 /** 30 * return sort order for position in admin menu 31 */ 32 function getMenuSort() 33 { 34 return 1; 35 } 36 37 /** 38 * handle user request 39 */ 40 function handle() 41 { 42 global $params; 43 global $paramcount; 44 45 // todo: use the $INPUT dokuwiki class instead of $_REQUEST - https://www.dokuwiki.org/devel:request_vars 46 if (array_key_exists('csvdw_submit', $_REQUEST)) { 47 if (checkSecurityToken()) { 48 foreach ($_REQUEST as $key => $value) { 49 if (in_array($key, array('csvdw_namespace','csvdw_delim','csvdw_pagename','csvdw_csvdata','csvdw_csvtemplate','csvdw_overwrite','csvdw_dummyrun' ,'csvdw_trim'))){ 50 // if (!empty($value) || is_numeric($value)) { 51 if (!blank($value)) { 52 $paramcount++; 53 $params[$key] = $value; 54 } 55 } 56 } 57 } 58 } 59 } 60 61 /** 62 * output appropriate html 63 */ 64 function html() 65 { 66 global $params; 67 global $paramcount; 68 69 $fieldcount = 0; 70 71 // update the label when the namespace is changed 72 echo "<script language='javascript'>function csvtodw_nslabel(){document.getElementById('csvtodw_nslabel').innerHTML=document.getElementById('csvtodw_ns').value;};</script>"; 73 74 ptln( $this->locale_xhtml('intro') ); 75 ptln( '<form method="post" action="" class="csvtodwpages">' ); 76 ptln( '<input type="hidden" name="do" value="admin"/>' ); 77 ptln( '<input type="hidden" name="page" value="'.$this->getPluginName().'"/>' ); 78 formSecurityToken(); 79 80 ptln( '<fieldset class="csvtodwpages">' ); 81 82 ptln( '<table class="csvtodwpages"><tr><td>' ); 83 84 ptln( '<h4>'.$this->getLang('csvdw_namespace').'</h4>' ); 85 ptln( '<input type="text" name="csvdw_namespace" value="'.$this->_field('csvdw_namespace','').'" id="csvtodw_ns" onblur="csvtodw_nslabel()"/>' ); 86 $fieldcount++; 87 88 ptln( '</td><td>' ); 89 90 ptln( '<h4>'.$this->getLang('csvdw_pagename').'</h4>' ); 91 ptln( '<input type="text" name="csvdw_pagename" value="'.$this->_field('csvdw_pagename','').'"/>' ); 92 $fieldcount++; 93 94 ptln( '</td><td>' ); 95 96 ptln( '<h4>'.$this->getLang('csvdw_delim').'</h4>' ); 97 ptln( '<input type="text" name="csvdw_delim" maxlength="1" value="'.$this->_field('csvdw_delim',',').'"/>' ); 98 $fieldcount++; 99 100 ptln( '</td></tr></table>' ); 101 102 ptln( '<h4>'.$this->getLang('csvdw_csvtemplate').'</h4>' ); 103 ptln( '<textarea name="csvdw_csvtemplate" class="edit">'.$this->_field('csvdw_csvtemplate').'</textarea><br/><br/>' ); 104 $fieldcount++; 105 106 ptln( '<h4>'.$this->getLang('csvdw_csvdata').'</h4>' ); 107 ptln( '<textarea name="csvdw_csvdata" class="edit">'.$this->_field('csvdw_csvdata').'</textarea><br/><br/>' ); 108 $fieldcount++; 109 110 ptln( '<table class="csvtodwpages"><tr><td>' ); 111 112 ptln( '<h4>'.sprintf($this->getLang('csvdw_overwrite'), $this->_field('csvdw_namespace','csvexploded')).'</h4>' ); 113 ptln( '<input type="radio" class="csvtodwpages" name="csvdw_overwrite[]" value="true" id="owt" '.$this->_field('csvdw_overwrite','true',true).'/> '); 114 ptln( '<label class="csvtodwpages" for="owt">'.$this->getLang('csvdw_yes').'</label> --- <label class="csvtodwpages" for="owf">'.$this->getLang('csvdw_no').'</label>' ); 115 ptln( '<input type="radio" class="csvtodwpages" name="csvdw_overwrite[]" value="false" id="owf" '.$this->_field('csvdw_overwrite','false',true).'/>' ); 116 $fieldcount++; 117 118 ptln( '</td><td>' ); 119 120 ptln( '<h4>'.$this->getLang('csvdw_dummyrun').'</h4>' ); 121 ptln( '<input type="radio" class="csvtodwpages" name="csvdw_dummyrun[]" value="true" id="drt" '.$this->_field('csvdw_dummyrun','true',true).'/> ' ); 122 ptln( '<label class="csvtodwpages" for="drt">'.$this->getLang('csvdw_yes').'</label> --- <label class="csvtodwpages" for="drf">'.$this->getLang('csvdw_no').'</label>' ); 123 ptln( '<input type="radio" class="csvtodwpages" name="csvdw_dummyrun[]" value="false" id="drf" '.$this->_field('csvdw_dummyrun','false',true).'/>' ); 124 $fieldcount++; 125 126 ptln( '</td><td>' ); 127 128 ptln( '<h4>'.$this->getLang('csvdw_trim').'</h4>' ); 129 ptln( '<input type="radio" name="csvdw_trim[]" value="true" id="trimt" '.$this->_field('csvdw_trim','true',true).'/> ' ); 130 ptln( '<label class="csvtodwpages" for="trimt">'.$this->getLang('csvdw_yes').'</label> --- <label class="csvtodwpages" for="trimf">'.$this->getLang('csvdw_no').'</label>' ); 131 ptln( '<input type="radio" name="csvdw_trim[]" value="false" id="trimf" '.$this->_field('csvdw_trim','false',true).'/>' ); 132 $fieldcount++; 133 134 ptln( '</td></tr></table>' ); 135 136 // required fields warning 137 ptln( (is_numeric($paramcount) && $paramcount !== $fieldcount) ? "<span class='csvtodwpageswarning'>".$this->getLang('csvdw_allfields')."</span><br/>" : '' ); 138 139 ptln( '<input type="submit" name="csvdw_submit" class="csvtodwpages" value="'.$this->getLang('csvdw_submitbtn').'"/>' ); 140 141 echo '<div class="csvtodwpages_ver">'.$this->getLang('csvdw_ver').'</div>'; 142 echo '</fieldset>'; 143 144 echo '</form>'; 145 146 // if all form values recieved, let's explode! 147 if ($paramcount == $fieldcount) { 148 $this->_csvexploder(); 149 150 } elseif ($paramcount > $fieldcount) { 151 // something weird going on 152 ptln( '<br/><fieldset><span class="csvtodwpageswarning">Incorrect number of form parameters received. We\'re screwed!<br/>Needed '.$fieldcount.', got '.$paramcount.'</span></fieldset>'); 153 } 154 } 155 156 157 /** 158 * take form values and explode the submitted csvdata into dokuwiki pages based on submitted csvtemplate 159 */ 160 function _csvexploder() 161 { 162 global $conf; // get dokuwiki conf array 163 global $params; 164 global $paramcount; 165 166 167 $namespace = strtolower($params['csvdw_namespace']); // which namespace to create pages within 168 169 $pagename_column = $params['csvdw_pagename']; // which column(s) in the csv file used for the pagename 170 171 $indexpage = (empty($conf['start'])) ? 'start' : $conf['start']; // the dokuwiki index page name 172 173 $csvdata = $params['csvdw_csvdata']; // the dokuwiki page in which you pasted the csv data 174 $csvtemplate = $params['csvdw_csvtemplate']; // the dokuwiki page you created holding the template 175 $csvdelim = $params['csvdw_delim'][0]; // the csv delimiter character (single character) 176 177 $overwrite_files = ($params['csvdw_overwrite'][0] == 'true') ? TRUE : FALSE; // set this to TRUE to overwrite existing pages 178 $dummyrun = ($params['csvdw_dummyrun'][0] == 'true') ? TRUE : FALSE; // is this just a dummy run? 179 $trimspaces = ($params['csvdw_trim'][0] == 'true') ? TRUE : FALSE; // is this just a dummy run? 180 181 $indexpagecontent = $this->getLang('csvdw_indexpagecontent'); // template for autogenerated index page 182 183 // $dr = rtrim( $_SERVER['DOCUMENT_ROOT'], "/" ) .'/'; 184 185 // get field names from first row 186 $csvfieldnames = str_getcsv(strtok($csvdata, PHP_EOL), $csvdelim); 187 188 // if we have some csvfieldnames lets rock'n'roll 189 if ($csvfieldnames !== FALSE) { 190 191 if ($dummyrun) { 192 ptln( $this->getLang('csvdw_dummyrunnotice') ); 193 } 194 195 ptln( $this->getLang('csvdw_explodednotice') ); 196 197 if (array_count_values($csvfieldnames) >= 1) { 198 199 while (($line = strtok(PHP_EOL)) !== FALSE) { 200 201 $line = str_getcsv($line, $csvdelim); 202 203 if (!empty(array_filter($line))) { 204 205 // get clean copy of the template 206 $thispage = $csvtemplate; 207 208 // set the page name for the index page text 209 $pagename = $this->_get_filename($pagename_column, $line); 210 211 // clean output filename to dokuwiki standards 212 $cleanpagename = cleanID($pagename); 213 214 $indexpagecontent .= " * [[$cleanpagename|$pagename]]\r\n"; 215 216 // replace the template [placeholder] names with content 217 foreach ($csvfieldnames as $key => $field) { 218 $thispage = str_replace('['.strtolower($field).']', $trimspaces ? trim($line[$key]) : $line[$key], $thispage); 219 } 220 221 // create wiki page 222 $filecreated = FALSE; 223 224 if ($overwrite_files !== TRUE && page_exists(resolve_id($namespace, $cleanpagename))) { 225 echo $this->getLang('csvdw_skipnoticep'); // msg($this->getLang('csvdw_skipnotice')); 226 } else { 227 if ($dummyrun) { 228 $filecreated = TRUE; 229 } else { 230 // we are assuming that if the file exists after saveWikiText() then it was created 231 // Unfortunately saveWikiText() doesn't provide a return value to indicate if it succeeded or failed. 232 // This leaves it possible that a page existed previously but we were unable to overwrite it. 233 // The DW notice system will put a notice in the exploded file list to indicate the failure though. 234 // see io_writeWikiPage() and _io_writeWikiPage_action() in .\dokuwiki\inc\io.php 235 saveWikiText(resolve_id($namespace, $cleanpagename), $thispage, $this->getLang('csvdw_summary')); 236 $filecreated = page_exists(resolve_id($namespace, $cleanpagename)); 237 } 238 239 if ($filecreated == FALSE) { 240 echo $this->getLang('csvdw_errornotice'); 241 } else { 242 echo $this->getLang('csvdw_creatednoticep'); 243 } 244 } 245 246 ptln( wikiFN(resolve_id($namespace, $cleanpagename))."<br/>" ); 247 248 } 249 250 } 251 252 // show an example template page if this is a dummy run 253 // (uses the data from the last processed csv row) 254 if ($dummyrun) { 255 ptln( $this->getLang('csvdw_examplepagenotice') ); 256 ptln( nl2br($thispage) ); 257 } 258 259 ptln( "<br/><br/><hr/>" ); 260 261 // create index page 262 $filecreated = FALSE; 263 264 if ($overwrite_files !== TRUE && page_exists(resolve_id($namespace, $indexpage))) { 265 echo $this->getLang('csvdw_skipnoticei'); // msg($this->getLang('csvdw_skipnoticei')); 266 267 } else { 268 if ($dummyrun) { 269 $filecreated = TRUE; 270 } else { 271 saveWikiText(resolve_id($namespace, $indexpage), $indexpagecontent, $this->getLang('csvdw_summary')); 272 $filecreated = page_exists(resolve_id($namespace, $indexpage)); 273 } 274 if ($filecreated == FALSE) { 275 echo $this->getLang('csvdw_errornotice'); 276 } else { 277 echo $this->getLang('csvdw_creatednoticei'); 278 } 279 } 280 281 ptln( wikiFN(resolve_id($namespace, $indexpage))."<br/>" ); 282 } 283 284 ptln( "<br/>" ); 285 // ptln( 'Go to '.$namespace.' <a href="/'.$namespace.'/'.$indexpage.'">index</a> page.' ); 286 ptln( 'Go to '.$namespace.' <a href="'.wl($ID,'',true).resolve_id($namespace, $indexpage).'">index</a> page.' ); 287 } 288 289 strtok('',''); // release strtok memory 290 } 291 292 293 /** 294 * Helper to build a unique pagename from specified csv column data 295 * 296 * Will combine multiple column data together if comma separated list 297 * is supplied. Each field will be separated with underscores _ 298 * 299 * @param $pagecols string Single int value or comma separated list eg. 0,3 300 * @param $line array An array containing the csv values for the current row 301 * @return string A page name combining all row values separated with _ eg. youngstown_oh 302 */ 303 protected function _get_filename($pagecols='', &$line) 304 { 305 $pagename = ''; 306 $pagecols = explode(',', $pagecols); 307 308 // combine column data into filename 309 foreach ($pagecols as $col) { 310 $pagename .= trim($line[$col]).'_'; 311 } 312 313 return rtrim($pagename, "_"); 314 } 315 316 /** 317 * Helper to repopulate form field values from POST data 318 * 319 * @param $field = fieldname 320 * @param $default = default value to return if no value present 321 * @param $isradio = flag indicating if field is a radiobutton - return 'checked' instead of value 322 * @return string : form field value or default 323 * @return array : first element of array if incoming field was an array (multivalue field) 324 */ 325 protected function _field($field, $default='', $isradio=false) 326 { 327 global $params; 328 global $paramcount; 329 330 $val = ''; 331 if (!empty($params[$field])) { 332 $val = is_array($params[$field]) ? $params[$field][0] : $params[$field]; 333 } 334 335 if ($isradio) { 336 if ($val==$default) { 337 return 'checked'; 338 } 339 return ''; 340 } 341 342 return !empty($val) ? $val : $default; 343 } 344 345} 346 347