1<?php 2/** 3 * Wiki farm manager admin plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Etienne MELEARD <etienne.meleard@cru.fr> 7 * @desc Allow farm administration through the DokuWiki admin interface, 8 * handle a farm command from $_REQUEST['farm_cmd'], loads a handler class 9 * form it then process request / display output html 10 */ 11 12// must be run within Dokuwiki 13if(!defined('DOKU_INC')) die(); 14 15if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 16if(!defined('DOKU_FARM_PLUGIN')) define('DOKU_FARM_PLUGIN', DOKU_PLUGIN.'farm/'); 17 18if(!defined('DOKU_FARM_WWW')) define('DOKU_FARM_WWW', 'lib/plugins/farm/'); 19 20if(!defined('DOKU_FARMPLUGINLOADED')) define('DOKU_FARMPLUGINLOADED', true); 21 22require_once(DOKU_PLUGIN.'admin.php'); 23 24/** 25 * Version string, will be used to check whether we need to upgrade the farm or not, 26 * it can be in the case of a new installation or if we updated the plugin from 27 * plugin manager / fs and the downloaded version is higher than the installed one, 28 * in this case we update structure / config if needed. 29 */ 30define('DOKU_FARM_VERSION', '1'); 31 32/** 33 * All DokuWiki plugins to extend the admin function 34 * need to inherit from this class 35 */ 36class admin_plugin_farm extends DokuWiki_Admin_Plugin { 37 var $disabled = 0; 38 39 var $cmd = ''; 40 var $opt = array(); 41 42 var $conf = array(); 43 44 var $handler = null; 45 var $lang = array(); 46 var $localised = false; 47 48 var $errors = array(); 49 var $success = array(); 50 51 var $version = null; 52 53 function __construct() { 54 global $conf; 55 56 if(defined('DOKU_IS_FARMER')) $this->getConf(); 57 58 $this->disabled = (isset($conf['pluginfarm']) && ($conf['pluginfarm'] == 0)); 59 } 60 61 /** 62 * Return some info 63 */ 64 function getInfo() { 65 return array( 66 'author' => 'Etienne Meleard', 67 'email' => 'etienne.meleard@cru.fr', 68 'date' => '2009-12-16', 69 'name' => 'Farm Manager', 70 'desc' => 'Manage Wiki farm'.($this->disabled ? ' (disabled)' : ''), 71 'url' => 'http://wiki.splitbrain.org/plugin:farm', 72 ); 73 } 74 75 /** 76 * Return prompt for admin menu 77 * @param $l language identifier 78 * @return nothing if not in farmer context, menu title otherwise 79 */ 80 function getMenuText($l) { 81 if(!defined('DOKU_IS_FARMER')) { 82 @touch(DOKU_CONF.'local.php'); 83 return $this->getLang('menu'); // not installed 84 } 85 if(!DOKU_IS_FARMER) return; // don't display farm management item in the animals' admin page 86 if(!$this->disabled) return $this->getLang('menu'); 87 return ''; 88 } 89 90 /** 91 * Return sort order for position in admin menu 92 * @return integer 93 */ 94 function getMenuSort() { 95 return 20; 96 } 97 98 /** 99 * Get localized string 100 * @param $code lang string identifier 101 * @param $data string or array used to replace %s occurences in the localized string 102 * @param $opt option to postprocess localized string 103 * @return localized string 104 */ 105 function getLang($code, $data = null, $opt='') { 106 if(!$this->localised) $this->setupLocale(); 107 if(!isset($this->lang[$code])) return '{'.strtoupper($code).'}'; 108 $str = $this->lang[$code]; 109 if(!is_null($data)) if(!is_array($data)) $data = array($data); 110 if(is_array($data)) foreach($data as $d) $str = preg_replace('`%s`', $d, $str, 1); 111 switch($opt) { 112 case 'js': $str = htmlentities(str_replace('\'', '\\\'', $str)); break; 113 } 114 return $str; 115 } 116 117 /** 118 * Get farm config 119 * @return array of farm config parameters 120 */ 121 function getConf() { 122 $farmconf = array(); 123 include DOKU_FARM_PLUGIN.'config.php'; 124 $this->conf = $farmconf; 125 return $this->conf; 126 } 127 128 /** 129 * Add error to error list 130 * @param $family error familly identifier (lang string identifier) 131 * @param $e error code (lang string identifier) or array containing 'code' => string and 'data => array entries 132 */ 133 function error($family, $e) { 134 if($family == '') $family = 'not_classified_errors'; 135 if(!isset($this->errors[$family])) $this->errors[$family] = array(); 136 $this->errors[$family][] = $e; 137 } 138 139 /** 140 * Print errors 141 */ 142 function putErrors() { 143 if(!count($this->errors)) return; 144 foreach($this->errors as $c => $list) { 145 ptln('<div class="error">'); 146 ptln(' '.$this->getLang($c)); 147 ptln(' <ul>'); 148 foreach($list as $e) ptln(' <li>'.$this->getLang(is_array($e) ? $e['code'] : $e, is_array($e) ? $e['data'] : null).'</li>'); 149 ptln(' </ul>'); 150 ptln('</div>'); 151 } 152 } 153 154 /** 155 * Add success to success list 156 * @param $s success code (lang string identifier) 157 */ 158 function success($s) { 159 $this->success[] = $s; 160 } 161 162 /** 163 * Print successes 164 */ 165 function putSuccess() { 166 if(!count($this->success)) return; 167 ptln('<div class="success">'); 168 if(count($this->success) > 1) { 169 ptln(' <ul>'); 170 foreach($this->success as $s) ptln(' <li>'.$this->getLang(is_array($s) ? $s['code'] : $s, is_array($s) ? $s['data'] : null).'</li>'); 171 ptln(' </ul>'); 172 }else{ 173 $s = reset($this->success); 174 ptln(' '.$this->getLang(is_array($s) ? $s['code'] : $s, is_array($s) ? $s['data'] : null)); 175 } 176 ptln('</div>'); 177 } 178 179 /** 180 * Returns human readable size 181 * @param $s size as integer 182 * @return human readabe localized size as a string 183 */ 184 function nicesize($s) { 185 $e = ''; 186 $m = array('k', 'M', 'G', 'T'); 187 foreach($m as $p) { 188 if($s < 1024) break; 189 $s /= 1024; 190 $e = $p; 191 } 192 return number_format($s, ($s >= 100 || $e == '') ? 0 : 1).$e.$this->getLang('size_unit'); 193 } 194 195 /** 196 * Print form head 197 * @param $data associative array of hidden fields names and values to be printed in the form 198 */ 199 function formHead($data = array()) { 200 global $ID; 201 echo '<form method="post" action="'.wl($ID).'">'."\n"; 202 echo ' <fieldset class="hidden">'."\n"; 203 echo ' <input type="hidden" name="do" value="admin" />'."\n"; 204 echo ' <input type="hidden" name="page" value="farm" />'."\n"; 205 foreach($data as $k => $v) echo ' <input type="hidden" name="'.$k.'" value="'.$v.'" />'."\n"; 206 formSecurityToken(); 207 echo ' </fieldset>'."\n"; 208 } 209 210 /** 211 * Builds a link inside farm manager 212 * @param $cmd farm command 213 * @param $opt associative array of farm options 214 * @return url string 215 */ 216 function wl($cmd, $opt = array()) { 217 global $ID; 218 $p = array('do' => 'admin', 'page' => 'farm', 'farm_cmd' => $cmd); 219 foreach($opt as $k => $v) $p['farm_opt__'.$k] = $v; 220 return wl($ID, $p); 221 } 222 223 /** 224 * Handle requests 225 */ 226 function handle() { 227 // Do nothing if disabled / not installed 228 if($this->disabled) return; 229 if(defined('DOKU_IS_FARMER')) if(!DOKU_IS_FARMER) return; 230 231 // Enable direct access to language strings 232 $this->setupLocale(); 233 234 // get installed version 235 $this->version = @file_exists(DOKU_FARM_PLUGIN.'installed') ? trim(@file_get_contents(DOKU_FARM_PLUGIN.'installed'), "\n") : null; 236 if($this->version != DOKU_FARM_VERSION) { 237 // set installer class as handler if the farm is not installed 238 if(is_null($this->version)) { 239 $_REQUEST['farm_cmd'] = 'farminstall'; 240 }elseif($this->version == '0.99') { 241 if($fp = fopen(DOKU_FARM_PLUGIN.'installed', 'w')) { 242 fwrite($fp, '1'); 243 fclose($fp); 244 $this->success('install_success'); 245 $_REQUEST['farm_plugin_cmd'] = 'farmconfig'; 246 }else $this->error('install_errors', 'install_stepupdate_failure'); 247 } 248 // Add code here to upgrade to other (future) version 249 } 250 251 // Fetch command from request 252 $this->cmd = 'overview'; 253 $this->opt = array(); 254 if(isset($_REQUEST['farm_cmd'])) { 255 if(is_array($_REQUEST['farm_cmd'])) { 256 $this->cmd = key($_REQUEST['farm_cmd']); 257 $t = $_REQUEST['farm_cmd'][$this->cmd]; 258 while(is_array($t)) { 259 $k = key($t); 260 if(is_array($t[$k])) { 261 $v = key($t[$k]); 262 $t = $t[$k][$v]; 263 if(preg_match('`^(true|false)$`i', $v, $m)) { 264 $v = (strtolower($m[1]) == 'true'); 265 }elseif(preg_match('`^([0-9]+)$`', $v, $m)) { 266 $v = (int)$m[1]; 267 }elseif(preg_match('`^([0-9]+\.[0-9]+)$`', $v, $m)) { 268 $v = (float)$m[1]; 269 } 270 $this->opt[$k] = $v; 271 }else{ 272 $this->opt[$k] = $t[$k]; 273 $t = null; 274 } 275 } 276 }else $this->cmd = $_REQUEST['farm_cmd']; 277 } 278 279 // Fetch arguments from request 280 if(isset($_REQUEST['farm_opt']) && !empty($_REQUEST['farm_opt'])) { 281 if(is_array($_REQUEST['farm_opt'])) { 282 foreach($_REQUEST['farm_opt'] as $k => $v) { 283 if(preg_match('`^(true|false)$`i', $v, $m)) { 284 $v = (strtolower($m[1]) == 'true'); 285 }elseif(preg_match('`^([0-9]+)$`', $v, $m)) { 286 $v = (int)$m[1]; 287 }elseif(preg_match('`^([0-9]+\.[0-9]+)$`', $v, $m)) { 288 $v = (float)$m[1]; 289 } 290 if(!isset($this->opt[$k])) $this->opt[$k] = $v; 291 } 292 }else $this->opt[$_REQUEST['farm_opt']] = true; 293 } 294 295 // Fetch arguments from non array get var 296 foreach($_GET as $k => $v) { 297 if(preg_match('`^farm_opt__([a-zA-Z0-9_]+)$`', $k, $m)) { 298 $this->opt[$m[1]] = $v; 299 } 300 } 301 302 //echo 'REQUEST : '; print_r($_REQUEST); 303 //echo '<br />CMD : '; print_r($this->cmd); 304 //echo '<br />OPT : '; print_r($this->opt); 305 306 // List of allowed commands and their handlers 307 $commands = array( 308 'farminstall' => 'install', 309 'overview' => 'overview', 310 'farmconfig' => 'config', 311 'soapconfig' => 'soapconfig', 312 'virtualhostconfig' => 'virtualhostconfig', 313 'animal' => 'animalmanager' 314 ); 315 316 // verify command vars 317 if(!isset($commands[$this->cmd])) $this->cmd = 'overview'; 318 319 // create an object to handle the command, then process request with it 320 $file = DOKU_FARM_PLUGIN.$commands[$this->cmd].'.class.php'; 321 if(@file_exists($file)) { 322 include_once $file; 323 $class = 'dokuwiki_farm_'.$commands[$this->cmd]; 324 if(!class_exists($class)) { 325 include_once DOKU_FARM_PLUGIN.'overview.class.php'; 326 $class = 'dokuwiki_farm_overview'; 327 } 328 $this->handler = & new $class($this); 329 if($this->handler) $this->handler->process(); 330 } 331 } 332 333 /** 334 * Output appropriate html 335 */ 336 function html() { 337 global $ID; 338 339 // Do nothing if disabled / not installed 340 if($this->disabled) return; 341 if(defined('DOKU_IS_FARMER')) if(!DOKU_IS_FARMER) return; 342 343 // Enable direct access to language strings 344 $this->setupLocale(); 345 346 ptln('<div id="farm__manager">'); 347 ptln(' <div class="farm_title">'.$this->getLang('menu').'</div>'); 348 349 // Farm menu 350 if($this->cmd != 'farminstall') { 351 ptln(' <div class="farm_commands">'); 352 ptln(' <a '.($this->cmd == 'overview' ? 'class="current_cmd"' : '').' href="'.$this->wl('overview').'"><img src="'.DOKU_FARM_WWW.'images/home.png" alt="overview" /> '.$this->getLang('overview_title').'</a>'); 353 if($this->cmd == 'animal' && isset($this->opt['aid'])) ptln(' <a class="current_cmd" href="'.$this->wl('animal', array('aid' => $this->opt['aid'])).'"><img src="'.DOKU_FARM_WWW.'images/aconf.png" alt="animal settings" /> '.$this->getLang('animal_title', array($this->opt['aid'])).'</a>'); 354 ptln(' <a '.($this->cmd == 'animal' && isset($this->opt['new']) ? 'class="current_cmd"' : '').' href="'.$this->wl('animal', array('new' => 1)).'"><img src="'.DOKU_FARM_WWW.'images/add.png" alt="add animal" /> '.$this->getLang('animal_new_title').'</a>'); 355 ptln(' <a '.($this->cmd == 'farmconfig' ? 'class="current_cmd"' : '').' href="'.$this->wl('farmconfig').'"><img src="'.DOKU_FARM_WWW.'images/configure.png" alt="config" /> '.$this->getLang('config_title').'</a>'); 356 if($this->conf['enablesoap']) ptln(' <a '.($this->cmd == 'soapconfig' ? 'class="current_cmd"' : '').' href="'.$this->wl('soapconfig').'"><img src="'.DOKU_FARM_WWW.'images/soap.png" alt="soap config" /> '.$this->getLang('soapconfig_title').'</a>'); 357 if($this->conf['virtual']) ptln(' <a '.($this->cmd == 'virtualhostconfig' ? 'class="current_cmd"' : '').' href="'.$this->wl('virtualhostconfig').'"><img src="'.DOKU_FARM_WWW.'images/virtualhost.png" alt="virtualhost config" /> '.$this->getLang('virtualhostconfig_title').'</a>'); 358 ptln(' </div>'); 359 } 360 361 // Call handler renderer, prints errors / successes if needed 362 ptln(' <div class="farm_cmd farm_cmd_'.$this->cmd.'_class">'); 363 if(!$this->handler) $this->error('system_errors', array('code' => 'system_nohandler_failure', 'data' => array($this->cmd))); 364 if($this->handler) if(method_exists($this->handler, 'htmlheader')) $this->handler->htmlheader(); 365 $this->putErrors(); 366 $this->putSuccess(); 367 if($this->handler) $this->handler->html(); 368 ptln(' </div>'); 369 ptln('</div><!-- #farm__manager -->'); 370 } 371} 372 373?> 374