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\Extension\AdminPlugin; 11use dokuwiki\Form\InputElement; 12use dokuwiki\Form\Form; 13use dokuwiki\plugin\struct\meta\CSVExporter; 14use dokuwiki\plugin\struct\meta\CSVImporter; 15use dokuwiki\plugin\struct\meta\CSVPageImporter; 16use dokuwiki\plugin\struct\meta\CSVSerialImporter; 17use dokuwiki\plugin\struct\meta\Schema; 18use dokuwiki\plugin\struct\meta\SchemaBuilder; 19use dokuwiki\plugin\struct\meta\SchemaEditor; 20use dokuwiki\plugin\struct\meta\SchemaImporter; 21use dokuwiki\plugin\struct\meta\StructException; 22 23class admin_plugin_struct_schemas extends AdminPlugin 24{ 25 /** 26 * @return int sort number in admin menu 27 */ 28 public function getMenuSort() 29 { 30 return 500; 31 } 32 33 /** 34 * @return bool true if only access for superuser, false is for superusers and moderators 35 */ 36 public function forAdminOnly() 37 { 38 return false; 39 } 40 41 /** 42 * Should carry out any processing required by the plugin. 43 */ 44 public function handle() 45 { 46 global $INPUT; 47 global $ID; 48 global $config_cascade; 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 } elseif ($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, ['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, ['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 if ($schema->getConfig()['internal']) { 161 echo $this->getLang('internal'); 162 return; 163 } 164 165 echo '<ul class="tabs" id="plugin__struct_tabs">'; 166 /** @noinspection HtmlUnknownAnchorTarget */ 167 echo '<li class="active"><a href="#plugin__struct_editor">' . $this->getLang('tab_edit') . '</a></li>'; 168 /** @noinspection HtmlUnknownAnchorTarget */ 169 echo '<li><a href="#plugin__struct_json">' . $this->getLang('tab_export') . '</a></li>'; 170 /** @noinspection HtmlUnknownAnchorTarget */ 171 echo '<li><a href="#plugin__struct_delete">' . $this->getLang('tab_delete') . '</a></li>'; 172 echo '</ul>'; 173 echo '<div class="panelHeader"></div>'; 174 175 $editor = new SchemaEditor($schema); 176 echo $editor->getEditor(); 177 echo $this->htmlJson($schema); 178 echo $this->htmlDelete($schema); 179 } else { 180 echo $this->locale_xhtml('editor_intro'); 181 echo $this->htmlNewschema(); 182 } 183 } 184 185 /** 186 * Form for handling import/export from/to JSON and CSV 187 * 188 * @param Schema $schema 189 * @return string 190 */ 191 protected function htmlJson(Schema $schema) 192 { 193 $form = new Form(['enctype' => 'multipart/form-data', 'id' => 'plugin__struct_json']); 194 $form->setHiddenField('do', 'admin'); 195 $form->setHiddenField('page', 'struct_schemas'); 196 $form->setHiddenField('table', $schema->getTable()); 197 198 // schemas 199 $form->addFieldsetOpen($this->getLang('export')); 200 $form->addButton('export', $this->getLang('btn_export')); 201 $form->addFieldsetClose(); 202 203 $form->addFieldsetOpen($this->getLang('import')); 204 $form->addElement(new InputElement('file', 'schemafile'))->attr('accept', '.json'); 205 $form->addButton('import', $this->getLang('btn_import')); 206 $form->addHTML('<p>' . $this->getLang('import_warning') . '</p>'); 207 $form->addFieldsetClose(); 208 209 // data 210 $form->addFieldsetOpen($this->getLang('admin_csvexport')); 211 $form->addTagOpen('legend'); 212 $form->addHTML($this->getLang('admin_csvexport_datatype')); 213 $form->addTagClose('legend'); 214 $form->addRadioButton('exporttype', $this->getLang('admin_csv_page')) 215 ->val(CSVExporter::DATATYPE_PAGE) 216 ->attr('checked', 'checked')->addClass('edit block'); 217 $form->addRadioButton('exporttype', $this->getLang('admin_csv_lookup')) 218 ->val(CSVExporter::DATATYPE_GLOBAL) 219 ->addClass('edit block'); 220 $form->addRadioButton('exporttype', $this->getLang('admin_csv_serial')) 221 ->val(CSVExporter::DATATYPE_SERIAL) 222 ->addClass('edit block'); 223 $form->addHTML('<br>'); 224 $form->addButton('exportcsv', $this->getLang('btn_export')); 225 $form->addFieldsetClose(); 226 227 $form->addFieldsetOpen($this->getLang('admin_csvimport')); 228 $form->addTagOpen('legend'); 229 $form->addHTML($this->getLang('admin_csvimport_datatype')); 230 $form->addTagClose('legend'); 231 $form->addRadioButton('importtype', $this->getLang('admin_csv_page')) 232 ->val(CSVExporter::DATATYPE_PAGE) 233 ->attr('checked', 'checked') 234 ->addClass('edit block'); 235 $form->addRadioButton('importtype', $this->getLang('admin_csv_lookup')) 236 ->val(CSVExporter::DATATYPE_GLOBAL) 237 ->addClass('edit block'); 238 $form->addRadioButton('importtype', $this->getLang('admin_csv_serial')) 239 ->val(CSVExporter::DATATYPE_SERIAL) 240 ->addClass('edit block'); 241 $form->addHTML('<br>'); 242 $form->addElement(new InputElement('file', 'csvfile'))->attr('accept', '.csv'); 243 $form->addButton('importcsv', $this->getLang('btn_import')); 244 $form->addCheckbox('createPage', 'Create missing pages')->addClass('block edit'); 245 $form->addHTML( 246 '<p><a href="https://www.dokuwiki.org/plugin:struct:csvimport">' . 247 $this->getLang('admin_csvhelp') . '</a></p>' 248 ); 249 $form->addFieldsetClose(); 250 251 return $form->toHTML(); 252 } 253 254 /** 255 * Form for deleting schemas 256 * 257 * @param Schema $schema 258 * @return string 259 */ 260 protected function htmlDelete(Schema $schema) 261 { 262 $form = new Form(['id' => 'plugin__struct_delete']); 263 $form->setHiddenField('do', 'admin'); 264 $form->setHiddenField('page', 'struct_schemas'); 265 $form->setHiddenField('table', $schema->getTable()); 266 267 $form->addFieldsetOpen($this->getLang('btn_delete')); 268 $form->addHTML($this->locale_xhtml('delete_intro')); 269 $form->addTextInput('confirm', $this->getLang('del_confirm')); 270 $form->addButton('delete', $this->getLang('btn_delete')); 271 $form->addFieldsetClose(); 272 273 $form->addFieldsetOpen($this->getLang('btn_clear')); 274 $form->addHTML($this->locale_xhtml('clear_intro')); 275 $form->addTextInput('confirm_clear', $this->getLang('clear_confirm')); 276 $form->addButton('clear', $this->getLang('btn_clear')); 277 $form->addFieldsetClose(); 278 279 return $form->toHTML(); 280 } 281 282 /** 283 * Form to add a new schema 284 * 285 * @return string 286 */ 287 protected function htmlNewschema() 288 { 289 $form = new Form(); 290 $form->addClass('struct_newschema'); 291 $form->addFieldsetOpen($this->getLang('create')); 292 $form->setHiddenField('do', 'admin'); 293 $form->setHiddenField('page', 'struct_schemas'); 294 $form->addTextInput('table', $this->getLang('schemaname')); 295 $form->addButton('', $this->getLang('save')); 296 $form->addHTML('<p>' . $this->getLang('createhint') . '</p>'); // FIXME is that true? we probably could 297 $form->addFieldsetClose(); 298 return $form->toHTML(); 299 } 300 301 /** 302 * Adds all available schemas to the Table of Contents 303 * 304 * @return array 305 */ 306 public function getTOC() 307 { 308 global $ID; 309 310 $toc = []; 311 $link = wl( 312 $ID, 313 ['do' => 'admin', 'page' => 'struct_assignments'] 314 ); 315 $toc[] = html_mktocitem($link, $this->getLang('menu_assignments'), 0, ''); 316 $slink = wl( 317 $ID, 318 ['do' => 'admin', 'page' => 'struct_schemas'] 319 ); 320 $toc[] = html_mktocitem($slink, $this->getLang('menu'), 0, ''); 321 322 $schemas = helper_plugin_struct::getSchema(); 323 if ($schemas) { 324 foreach ($schemas as $schema) { 325 if ($schema->isInternal()) continue; 326 $table = $schema->getTable(); 327 $link = wl( 328 $ID, 329 ['do' => 'admin', 'page' => 'struct_schemas', 'table' => $table] 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