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