1<?php 2/** 3 * Plugin : Move 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Michael Hamann <michael@content-space.de> 7 * @author Gary Owen, 8 */ 9 10// must be run within Dokuwiki 11if(!defined('DOKU_INC')) die(); 12 13/** 14 * Admin component of the move plugin. Provides the user interface. 15 */ 16class admin_plugin_move_main extends DokuWiki_Admin_Plugin { 17 18 /** @var helper_plugin_move_plan $plan */ 19 protected $plan; 20 21 public function __construct() { 22 $this->plan = plugin_load('helper', 'move_plan'); 23 } 24 25 /** 26 * @param $language 27 * @return string 28 */ 29 public function getMenuText($language) { 30 $label = $this->getLang('menu'); 31 if($this->plan->isCommited()) $label .= ' '.$this->getLang('inprogress'); 32 return $label; 33 } 34 35 36 /** 37 * Get the sort number that defines the position in the admin menu. 38 * 39 * @return int The sort number 40 */ 41 function getMenuSort() { 42 return 1011; 43 } 44 45 /** 46 * If this admin plugin is for admins only 47 * 48 * @return bool false 49 */ 50 function forAdminOnly() { 51 return false; 52 } 53 54 /** 55 * Handle the input 56 */ 57 function handle() { 58 global $INPUT; 59 60 // create a new plan if possible and sufficient data was given 61 $this->createPlanFromInput(); 62 63 // handle workflow button presses 64 if($this->plan->isCommited()) { 65 helper_plugin_move_rewrite::addLock(); //todo: right place? 66 switch($INPUT->str('ctl')) { 67 case 'continue': 68 $this->plan->nextStep(); 69 break; 70 case 'skip': 71 $this->plan->nextStep(true); 72 break; 73 case 'abort': 74 $this->plan->abort(); 75 break; 76 } 77 } 78 } 79 80 /** 81 * Display the interface 82 */ 83 function html() { 84 // decide what to do based on the plan's state 85 if($this->plan->isCommited()) { 86 $this->GUI_progress(); 87 } else { 88 // display form 89 $this->GUI_simpleForm(); 90 } 91 } 92 93 /** 94 * Get input variables and create a move plan from them 95 * 96 * @return bool 97 */ 98 protected function createPlanFromInput() { 99 global $INPUT; 100 global $ID; 101 102 if($this->plan->isCommited()) return false; 103 104 $this->plan->setOption('autoskip', $INPUT->bool('autoskip')); 105 $this->plan->setOption('autorewrite', $INPUT->bool('autorewrite')); 106 107 if($ID && $INPUT->has('dst')) { 108 $dst = trim($INPUT->str('dst')); 109 if($dst == '') { 110 msg($this->getLang('nodst'), -1); 111 return false; 112 } 113 114 // input came from form 115 if($INPUT->str('class') == 'namespace') { 116 $src = getNS($ID); 117 118 if($INPUT->str('type') == 'both') { 119 $this->plan->addPageNamespaceMove($src, $dst); 120 $this->plan->addMediaNamespaceMove($src, $dst); 121 } else if($INPUT->str('type') == 'page') { 122 $this->plan->addPageNamespaceMove($src, $dst); 123 } else if($INPUT->str('type') == 'media') { 124 $this->plan->addMediaNamespaceMove($src, $dst); 125 } 126 } else { 127 $this->plan->addPageMove($ID, $INPUT->str('dst')); 128 } 129 $this->plan->commit(); 130 return true; 131 } elseif($INPUT->has('json')) { 132 // input came via JSON from tree manager 133 $json = new JSON(JSON_LOOSE_TYPE); 134 $data = $json->decode($INPUT->str('json')); 135 136 foreach((array) $data as $entry) { 137 if($entry['class'] == 'ns') { 138 if($entry['type'] == 'page') { 139 $this->plan->addPageNamespaceMove($entry['src'], $entry['dst']); 140 } elseif($entry['type'] == 'media') { 141 $this->plan->addMediaNamespaceMove($entry['src'], $entry['dst']); 142 } 143 } elseif($entry['class'] == 'doc') { 144 if($entry['type'] == 'page') { 145 $this->plan->addPageMove($entry['src'], $entry['dst']); 146 } elseif($entry['type'] == 'media') { 147 $this->plan->addMediaMove($entry['src'], $entry['dst']); 148 } 149 } 150 } 151 152 $this->plan->commit(); 153 return true; 154 } 155 156 return false; 157 } 158 159 /** 160 * Display the simple move form 161 */ 162 protected function GUI_simpleForm() { 163 global $ID; 164 165 echo $this->locale_xhtml('move'); 166 167 $treelink = wl($ID, array('do'=>'admin', 'page'=>'move_tree')); 168 echo '<p id="plugin_move__treelink">'; 169 printf($this->getLang('treelink'), $treelink); 170 echo '</p>'; 171 172 $form = new Doku_Form(array('action' => wl($ID), 'method' => 'post', 'class' => 'plugin_move_form')); 173 $form->addHidden('page', 'move_main'); 174 $form->addHidden('id', $ID); 175 176 $form->startFieldset($this->getLang('legend')); 177 178 $form->addElement(form_makeRadioField('class', 'page', $this->getLang('movepage') . ' <code>' . $ID . '</code>', '', 'block radio click-page', array('checked' => 'checked'))); 179 $form->addElement(form_makeRadioField('class', 'namespace', $this->getLang('movens') . ' <code>' . getNS($ID) . '</code>', '', 'block radio click-ns')); 180 181 $form->addElement(form_makeTextField('dst', $ID, $this->getLang('dst'), '', 'block indent')); 182 $form->addElement(form_makeMenuField('type', array('pages' => $this->getLang('move_pages'), 'media' => $this->getLang('move_media'), 'both' => $this->getLang('move_media_and_pages')), 'both', $this->getLang('content_to_move'), '', 'block indent select')); 183 184 $form->addElement(form_makeCheckboxField('autoskip', '1', $this->getLang('autoskip'), '', 'block', ($this->getConf('autoskip') ? array('checked' => 'checked') : array()))); 185 $form->addElement(form_makeCheckboxField('autorewrite', '1', $this->getLang('autorewrite'), '', 'block', ($this->getConf('autorewrite') ? array('checked' => 'checked') : array()))); 186 187 $form->addElement(form_makeButton('submit', 'admin', $this->getLang('btn_start'))); 188 $form->endFieldset(); 189 $form->printForm(); 190 } 191 192 /** 193 * Display the GUI while the move progresses 194 */ 195 protected function GUI_progress() { 196 echo '<div id="plugin_move__progress">'; 197 198 echo $this->locale_xhtml('progress'); 199 200 $progress = $this->plan->getProgress(); 201 202 if(!$this->plan->inProgress()) { 203 echo '<div id="plugin_move__preview">'; 204 echo '<p>'; 205 echo '<strong>' . $this->getLang('intro') . '</strong> '; 206 echo '<span>' . $this->getLang('preview') . '</span>'; 207 echo '</p>'; 208 echo $this->plan->previewHTML(); 209 echo '</div>'; 210 211 } 212 213 echo '<div class="progress" data-progress="' . $progress . '">' . $progress . '%</div>'; 214 215 echo '<div class="output">'; 216 if($this->plan->getLastError()) { 217 echo '<p><div class="error">' . $this->plan->getLastError() . '</div></p>'; 218 } elseif ($this->plan->inProgress()) { 219 echo '<p><div class="info">' . $this->getLang('inexecution') . '</div></p>'; 220 } 221 echo '</div>'; 222 223 // display all buttons but toggle visibility according to state 224 echo '<p></p>'; 225 echo '<div class="controls">'; 226 echo '<img src="' . DOKU_BASE . 'lib/images/throbber.gif" class="hide" />'; 227 $this->btn('start', !$this->plan->inProgress()); 228 $this->btn('retry', $this->plan->getLastError()); 229 $this->btn('skip', $this->plan->getLastError()); 230 $this->btn('continue', $this->plan->inProgress() && !$this->plan->getLastError()); 231 $this->btn('abort'); 232 echo '</div>'; 233 234 echo '</div>'; 235 } 236 237 /** 238 * Display a move workflow button 239 * 240 * continue, start, retry - continue next steps 241 * abort - abort the whole move 242 * skip - skip error and continue 243 * 244 * @param string $control 245 * @param bool $show should this control be visible? 246 */ 247 protected function btn($control, $show = true) { 248 global $ID; 249 250 $skip = 0; 251 $label = $this->getLang('btn_' . $control); 252 $id = $control; 253 if($control == 'start') $control = 'continue'; 254 if($control == 'retry') { 255 $control = 'continue'; 256 $skip = 0; 257 } 258 259 $class = 'move__control ctlfrm-' . $id; 260 if(!$show) $class .= ' hide'; 261 262 $form = new Doku_Form(array('action' => wl($ID), 'method' => 'post', 'class' => $class)); 263 $form->addHidden('page', 'move_main'); 264 $form->addHidden('id', $ID); 265 $form->addHidden('ctl', $control); 266 $form->addHidden('skip', $skip); 267 $form->addElement(form_makeButton('submit', 'admin', $label, array('class' => 'btn ctl-' . $control))); 268 $form->printForm(); 269 } 270} 271