1<?php 2 3/** 4 * DokuWiki Plugin struct (Admin Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 8 */ 9 10use dokuwiki\Form\Form; 11use dokuwiki\plugin\struct\meta\CSVExporter; 12use dokuwiki\plugin\struct\meta\CSVImporter; 13use dokuwiki\plugin\struct\meta\CSVPageImporter; 14use dokuwiki\plugin\struct\meta\CSVSerialImporter; 15use dokuwiki\plugin\struct\meta\Schema; 16use dokuwiki\plugin\struct\meta\SchemaBuilder; 17use dokuwiki\plugin\struct\meta\SchemaEditor; 18use dokuwiki\plugin\struct\meta\SchemaImporter; 19use dokuwiki\plugin\struct\meta\StructException; 20 21class admin_plugin_struct_schemas extends DokuWiki_Admin_Plugin 22{ 23 24 /** 25 * @return int sort number in admin menu 26 */ 27 public function getMenuSort() 28 { 29 return 500; 30 } 31 32 /** 33 * @return bool true if only access for superuser, false is for superusers and moderators 34 */ 35 public function forAdminOnly() 36 { 37 return false; 38 } 39 40 /** 41 * Should carry out any processing required by the plugin. 42 */ 43 public function handle() 44 { 45 global $INPUT; 46 global $ID; 47 global $config_cascade; 48 $config_file_path = end($config_cascade['main']['local']); 49 50 // form submit 51 $table = Schema::cleanTableName($INPUT->str('table')); 52 if ($table && $INPUT->bool('save') && checkSecurityToken()) { 53 $builder = new SchemaBuilder($table, $INPUT->arr('schema')); 54 if (!$builder->build()) { 55 msg('something went wrong while saving', -1); 56 } 57 touch(action_plugin_struct_cache::getSchemaRefreshFile()); 58 } 59 // export 60 if ($table && $INPUT->bool('export')) { 61 $builder = new Schema($table); 62 header('Content-Type: application/json'); 63 header("Content-Disposition: attachment; filename=$table.struct.json"); 64 echo $builder->toJSON(); 65 exit; 66 } 67 // import 68 if ($table && $INPUT->bool('import')) { 69 if (isset($_FILES['schemafile']['tmp_name'])) { 70 $json = io_readFile($_FILES['schemafile']['tmp_name'], false); 71 if (!$json) { 72 msg('Something went wrong with the upload', -1); 73 } else { 74 $builder = new SchemaImporter($table, $json); 75 if (!$builder->build()) { 76 msg('something went wrong while saving', -1); 77 } 78 touch(action_plugin_struct_cache::getSchemaRefreshFile()); 79 } 80 } 81 } 82 83 // import CSV 84 if ($table && $INPUT->bool('importcsv')) { 85 if (isset($_FILES['csvfile']['tmp_name'])) { 86 try { 87 $datatype = $INPUT->str('importtype'); 88 if ($datatype === CSVExporter::DATATYPE_PAGE) { 89 $csvImporter = new CSVPageImporter($table, $_FILES['csvfile']['tmp_name'], $datatype); 90 } else if ($datatype === CSVExporter::DATATYPE_SERIAL) { 91 $csvImporter = new CSVSerialImporter($table, $_FILES['csvfile']['tmp_name'], $datatype); 92 } else { 93 $csvImporter = new CSVImporter($table, $_FILES['csvfile']['tmp_name'], $datatype); 94 } 95 $csvImporter->import(); 96 msg($this->getLang('admin_csvdone'), 1); 97 } catch (StructException $e) { 98 msg(hsc($e->getMessage()), -1); 99 } 100 } 101 } 102 103 // export CSV 104 if ($table && $INPUT->bool('exportcsv')) { 105 header('Content-Type: text/csv'); 106 header('Content-Disposition: attachment; filename="' . $table . '.csv";'); 107 new CSVExporter($table, $INPUT->str('exporttype')); 108 exit(); 109 } 110 111 // delete 112 if ($table && $INPUT->bool('delete')) { 113 if ($table != $INPUT->str('confirm')) { 114 msg($this->getLang('del_fail'), -1); 115 } else { 116 try { 117 $schema = new Schema($table); 118 $schema->delete(); 119 msg($this->getLang('del_ok'), 1); 120 touch(action_plugin_struct_cache::getSchemaRefreshFile()); 121 send_redirect(wl($ID, array('do' => 'admin', 'page' => 'struct_schemas'), true, '&')); 122 } catch (StructException $e) { 123 msg(hsc($e->getMessage()), -1); 124 } 125 } 126 } 127 128 // clear 129 if ($table && $INPUT->bool('clear')) { 130 if ($table != $INPUT->str('confirm_clear')) { 131 msg($this->getLang('clear_fail'), -1); 132 } else { 133 try { 134 $schema = new Schema($table); 135 $schema->clear(); 136 msg($this->getLang('clear_ok'), 1); 137 touch(action_plugin_struct_cache::getSchemaRefreshFile()); 138 send_redirect(wl($ID, array('do' => 'admin', 'page' => 'struct_schemas'), true, '&')); 139 } catch (StructException $e) { 140 msg(hsc($e->getMessage()), -1); 141 } 142 } 143 } 144 } 145 146 /** 147 * Render HTML output, e.g. helpful text and a form 148 */ 149 public function html() 150 { 151 global $INPUT; 152 153 $table = Schema::cleanTableName($INPUT->str('table')); 154 if ($table) { 155 $schema = new Schema($table, 0); 156 157 echo $this->locale_xhtml('editor_edit'); 158 echo '<h2>' . sprintf($this->getLang('edithl'), hsc($table)) . '</h2>'; 159 160 echo '<ul class="tabs" id="plugin__struct_tabs">'; 161 /** @noinspection HtmlUnknownAnchorTarget */ 162 echo '<li class="active"><a href="#plugin__struct_editor">' . $this->getLang('tab_edit') . '</a></li>'; 163 /** @noinspection HtmlUnknownAnchorTarget */ 164 echo '<li><a href="#plugin__struct_json">' . $this->getLang('tab_export') . '</a></li>'; 165 /** @noinspection HtmlUnknownAnchorTarget */ 166 echo '<li><a href="#plugin__struct_delete">' . $this->getLang('tab_delete') . '</a></li>'; 167 echo '</ul>'; 168 echo '<div class="panelHeader"></div>'; 169 170 $editor = new SchemaEditor($schema); 171 echo $editor->getEditor(); 172 echo $this->htmlJson($schema); 173 echo $this->htmlDelete($schema); 174 } else { 175 echo $this->locale_xhtml('editor_intro'); 176 echo $this->htmlNewschema(); 177 } 178 } 179 180 /** 181 * Form for handling import/export from/to JSON and CSV 182 * 183 * @param Schema $schema 184 * @return string 185 */ 186 protected function htmlJson(Schema $schema) 187 { 188 $form = new Form(array('enctype' => 'multipart/form-data', 'id' => 'plugin__struct_json')); 189 $form->setHiddenField('do', 'admin'); 190 $form->setHiddenField('page', 'struct_schemas'); 191 $form->setHiddenField('table', $schema->getTable()); 192 193 // schemas 194 $form->addFieldsetOpen($this->getLang('export')); 195 $form->addButton('export', $this->getLang('btn_export')); 196 $form->addFieldsetClose(); 197 198 $form->addFieldsetOpen($this->getLang('import')); 199 $form->addElement(new \dokuwiki\Form\InputElement('file', 'schemafile'))->attr('accept', '.json'); 200 $form->addButton('import', $this->getLang('btn_import')); 201 $form->addHTML('<p>' . $this->getLang('import_warning') . '</p>'); 202 $form->addFieldsetClose(); 203 204 // data 205 $form->addFieldsetOpen($this->getLang('admin_csvexport')); 206 $form->addTagOpen('legend'); 207 $form->addHTML($this->getLang('admin_csvexport_datatype')); 208 $form->addTagClose('legend'); 209 $form->addRadioButton('exporttype', $this->getLang('admin_csv_page')) 210 ->val(CSVExporter::DATATYPE_PAGE) 211 ->attr('checked', 'checked')->addClass('edit block'); 212 $form->addRadioButton('exporttype', $this->getLang('admin_csv_lookup')) 213 ->val(CSVExporter::DATATYPE_GLOBAL) 214 ->addClass('edit block'); 215 $form->addRadioButton('exporttype', $this->getLang('admin_csv_serial')) 216 ->val(CSVExporter::DATATYPE_SERIAL) 217 ->addClass('edit block'); 218 $form->addHTML('<br>'); 219 $form->addButton('exportcsv', $this->getLang('btn_export')); 220 $form->addFieldsetClose(); 221 222 $form->addFieldsetOpen($this->getLang('admin_csvimport')); 223 $form->addTagOpen('legend'); 224 $form->addHTML($this->getLang('admin_csvimport_datatype')); 225 $form->addTagClose('legend'); 226 $form->addRadioButton('importtype', $this->getLang('admin_csv_page')) 227 ->val(CSVExporter::DATATYPE_PAGE) 228 ->attr('checked', 'checked') 229 ->addClass('edit block'); 230 $form->addRadioButton('importtype', $this->getLang('admin_csv_lookup')) 231 ->val(CSVExporter::DATATYPE_GLOBAL) 232 ->addClass('edit block'); 233 $form->addRadioButton('importtype', $this->getLang('admin_csv_serial')) 234 ->val(CSVExporter::DATATYPE_SERIAL) 235 ->addClass('edit block'); 236 $form->addHTML('<br>'); 237 $form->addElement(new \dokuwiki\Form\InputElement('file', 'csvfile'))->attr('accept', '.csv'); 238 $form->addButton('importcsv', $this->getLang('btn_import')); 239 $form->addCheckbox('createPage', 'Create missing pages')->addClass('block edit'); 240 $form->addHTML('<p><a href="https://www.dokuwiki.org/plugin:struct:csvimport">' . $this->getLang('admin_csvhelp') . '</a></p>'); 241 $form->addFieldsetClose(); 242 243 return $form->toHTML(); 244 } 245 246 /** 247 * Form for deleting schemas 248 * 249 * @param Schema $schema 250 * @return string 251 */ 252 protected function htmlDelete(Schema $schema) 253 { 254 $form = new Form(array('id' => 'plugin__struct_delete')); 255 $form->setHiddenField('do', 'admin'); 256 $form->setHiddenField('page', 'struct_schemas'); 257 $form->setHiddenField('table', $schema->getTable()); 258 259 $form->addFieldsetOpen($this->getLang('btn_delete')); 260 $form->addHTML($this->locale_xhtml('delete_intro')); 261 $form->addTextInput('confirm', $this->getLang('del_confirm')); 262 $form->addButton('delete', $this->getLang('btn_delete')); 263 $form->addFieldsetClose(); 264 265 $form->addFieldsetOpen($this->getLang('btn_clear')); 266 $form->addHTML($this->locale_xhtml('clear_intro')); 267 $form->addTextInput('confirm_clear', $this->getLang('clear_confirm')); 268 $form->addButton('clear', $this->getLang('btn_clear')); 269 $form->addFieldsetClose(); 270 271 return $form->toHTML(); 272 } 273 274 /** 275 * Form to add a new schema 276 * 277 * @return string 278 */ 279 protected function htmlNewschema() 280 { 281 $form = new Form(); 282 $form->addClass('struct_newschema'); 283 $form->addFieldsetOpen($this->getLang('create')); 284 $form->setHiddenField('do', 'admin'); 285 $form->setHiddenField('page', 'struct_schemas'); 286 $form->addTextInput('table', $this->getLang('schemaname')); 287 $form->addButton('', $this->getLang('save')); 288 $form->addHTML('<p>' . $this->getLang('createhint') . '</p>'); // FIXME is that true? we probably could 289 $form->addFieldsetClose(); 290 return $form->toHTML(); 291 } 292 293 /** 294 * Adds all available schemas to the Table of Contents 295 * 296 * @return array 297 */ 298 public function getTOC() 299 { 300 global $ID; 301 302 $toc = array(); 303 $link = wl( 304 $ID, 305 array( 306 'do' => 'admin', 307 'page' => 'struct_assignments' 308 ) 309 ); 310 $toc[] = html_mktocitem($link, $this->getLang('menu_assignments'), 0, ''); 311 $slink = wl( 312 $ID, 313 array( 314 'do' => 'admin', 315 'page' => 'struct_schemas' 316 ) 317 ); 318 $toc[] = html_mktocitem($slink, $this->getLang('menu'), 0, ''); 319 320 $tables = Schema::getAll(); 321 if ($tables) { 322 foreach ($tables as $table) { 323 $link = wl( 324 $ID, 325 array( 326 'do' => 'admin', 327 'page' => 'struct_schemas', 328 'table' => $table 329 ) 330 ); 331 332 $toc[] = html_mktocitem($link, hsc($table), 1, ''); 333 } 334 } 335 336 return $toc; 337 } 338} 339 340// vim:ts=4:sw=4:et: 341