187fdbc6bSMichael Große<?php 2d6d97f60SAnna Dabrowska 387fdbc6bSMichael Große/** 487fdbc6bSMichael Große * DokuWiki Plugin struct (Admin Component) 587fdbc6bSMichael Große * 687fdbc6bSMichael Große * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 787fdbc6bSMichael Große * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 887fdbc6bSMichael Große */ 987fdbc6bSMichael Große 10*7234bfb1Ssplitbrainuse dokuwiki\Extension\AdminPlugin; 11*7234bfb1Ssplitbrainuse dokuwiki\Form\InputElement; 1287fdbc6bSMichael Großeuse dokuwiki\Form\Form; 13f36cc634SAndreas Gohruse dokuwiki\plugin\struct\meta\CSVExporter; 1469d92b7aSAnna Dabrowskause dokuwiki\plugin\struct\meta\CSVImporter; 151fc2361fSSzymon Olewniczakuse dokuwiki\plugin\struct\meta\CSVPageImporter; 16ad86a824SAnna Dabrowskause dokuwiki\plugin\struct\meta\CSVSerialImporter; 17ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Schema; 18ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\SchemaBuilder; 19ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\SchemaEditor; 20ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\SchemaImporter; 21ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\StructException; 2287fdbc6bSMichael Große 23*7234bfb1Ssplitbrainclass admin_plugin_struct_schemas extends AdminPlugin 24d6d97f60SAnna Dabrowska{ 2587fdbc6bSMichael Große /** 2687fdbc6bSMichael Große * @return int sort number in admin menu 2787fdbc6bSMichael Große */ 28d6d97f60SAnna Dabrowska public function getMenuSort() 29d6d97f60SAnna Dabrowska { 3087fdbc6bSMichael Große return 500; 3187fdbc6bSMichael Große } 3287fdbc6bSMichael Große 3387fdbc6bSMichael Große /** 3487fdbc6bSMichael Große * @return bool true if only access for superuser, false is for superusers and moderators 3587fdbc6bSMichael Große */ 36d6d97f60SAnna Dabrowska public function forAdminOnly() 37d6d97f60SAnna Dabrowska { 384d220607SAndreas Gohr return false; 3987fdbc6bSMichael Große } 4087fdbc6bSMichael Große 4187fdbc6bSMichael Große /** 4287fdbc6bSMichael Große * Should carry out any processing required by the plugin. 4387fdbc6bSMichael Große */ 44d6d97f60SAnna Dabrowska public function handle() 45d6d97f60SAnna Dabrowska { 4687fdbc6bSMichael Große global $INPUT; 47d5a1a6dcSAndreas Gohr global $ID; 48e33460e2SMichael Grosse global $config_cascade; 4987fdbc6bSMichael Große 508ddf87afSAndreas Gohr // form submit 5187fdbc6bSMichael Große $table = Schema::cleanTableName($INPUT->str('table')); 5287fdbc6bSMichael Große if ($table && $INPUT->bool('save') && checkSecurityToken()) { 53d5a1a6dcSAndreas Gohr $builder = new SchemaBuilder($table, $INPUT->arr('schema')); 5487fdbc6bSMichael Große if (!$builder->build()) { 5587fdbc6bSMichael Große msg('something went wrong while saving', -1); 5687fdbc6bSMichael Große } 57ae5c46faSAndreas Gohr touch(action_plugin_struct_cache::getSchemaRefreshFile()); 5887fdbc6bSMichael Große } 598ddf87afSAndreas Gohr // export 60d486d6d7SAndreas Gohr if ($table && $INPUT->bool('export')) { 61d5a1a6dcSAndreas Gohr $builder = new Schema($table); 62d486d6d7SAndreas Gohr header('Content-Type: application/json'); 63d486d6d7SAndreas Gohr header("Content-Disposition: attachment; filename=$table.struct.json"); 64d486d6d7SAndreas Gohr echo $builder->toJSON(); 65d486d6d7SAndreas Gohr exit; 66d486d6d7SAndreas Gohr } 678ddf87afSAndreas Gohr // import 688ddf87afSAndreas Gohr if ($table && $INPUT->bool('import')) { 698ddf87afSAndreas Gohr if (isset($_FILES['schemafile']['tmp_name'])) { 708ddf87afSAndreas Gohr $json = io_readFile($_FILES['schemafile']['tmp_name'], false); 718ddf87afSAndreas Gohr if (!$json) { 728ddf87afSAndreas Gohr msg('Something went wrong with the upload', -1); 738ddf87afSAndreas Gohr } else { 7469d92b7aSAnna Dabrowska $builder = new SchemaImporter($table, $json); 758ddf87afSAndreas Gohr if (!$builder->build()) { 768ddf87afSAndreas Gohr msg('something went wrong while saving', -1); 778ddf87afSAndreas Gohr } 78ae5c46faSAndreas Gohr touch(action_plugin_struct_cache::getSchemaRefreshFile()); 798ddf87afSAndreas Gohr } 808ddf87afSAndreas Gohr } 818ddf87afSAndreas Gohr } 82a0b3799eSAndreas Gohr 83a0b3799eSAndreas Gohr // import CSV 84a0b3799eSAndreas Gohr if ($table && $INPUT->bool('importcsv')) { 85a0b3799eSAndreas Gohr if (isset($_FILES['csvfile']['tmp_name'])) { 86a0b3799eSAndreas Gohr try { 8728d21c10SAnna Dabrowska $datatype = $INPUT->str('importtype'); 88ad86a824SAnna Dabrowska if ($datatype === CSVExporter::DATATYPE_PAGE) { 8928d21c10SAnna Dabrowska $csvImporter = new CSVPageImporter($table, $_FILES['csvfile']['tmp_name'], $datatype); 90ad86a824SAnna Dabrowska } elseif ($datatype === CSVExporter::DATATYPE_SERIAL) { 91ad86a824SAnna Dabrowska $csvImporter = new CSVSerialImporter($table, $_FILES['csvfile']['tmp_name'], $datatype); 9269d92b7aSAnna Dabrowska } else { 9328d21c10SAnna Dabrowska $csvImporter = new CSVImporter($table, $_FILES['csvfile']['tmp_name'], $datatype); 941fc2361fSSzymon Olewniczak } 951fc2361fSSzymon Olewniczak $csvImporter->import(); 966d2df532SAndreas Gohr msg($this->getLang('admin_csvdone'), 1); 97a0b3799eSAndreas Gohr } catch (StructException $e) { 98a0b3799eSAndreas Gohr msg(hsc($e->getMessage()), -1); 99a0b3799eSAndreas Gohr } 100a0b3799eSAndreas Gohr } 101a0b3799eSAndreas Gohr } 102a0b3799eSAndreas Gohr 103f36cc634SAndreas Gohr // export CSV 104f36cc634SAndreas Gohr if ($table && $INPUT->bool('exportcsv')) { 105f36cc634SAndreas Gohr header('Content-Type: text/csv'); 106f36cc634SAndreas Gohr header('Content-Disposition: attachment; filename="' . $table . '.csv";'); 10769d92b7aSAnna Dabrowska new CSVExporter($table, $INPUT->str('exporttype')); 108f36cc634SAndreas Gohr exit(); 109f36cc634SAndreas Gohr } 110f36cc634SAndreas Gohr 111d5a1a6dcSAndreas Gohr // delete 112d5a1a6dcSAndreas Gohr if ($table && $INPUT->bool('delete')) { 113d5a1a6dcSAndreas Gohr if ($table != $INPUT->str('confirm')) { 114d5a1a6dcSAndreas Gohr msg($this->getLang('del_fail'), -1); 115d5a1a6dcSAndreas Gohr } else { 116d5a1a6dcSAndreas Gohr try { 117d5a1a6dcSAndreas Gohr $schema = new Schema($table); 118d5a1a6dcSAndreas Gohr $schema->delete(); 119d5a1a6dcSAndreas Gohr msg($this->getLang('del_ok'), 1); 120ae5c46faSAndreas Gohr touch(action_plugin_struct_cache::getSchemaRefreshFile()); 121*7234bfb1Ssplitbrain send_redirect(wl($ID, ['do' => 'admin', 'page' => 'struct_schemas'], true, '&')); 122d5a1a6dcSAndreas Gohr } catch (StructException $e) { 123d5a1a6dcSAndreas Gohr msg(hsc($e->getMessage()), -1); 124d5a1a6dcSAndreas Gohr } 125d5a1a6dcSAndreas Gohr } 126d5a1a6dcSAndreas Gohr } 127d5a1a6dcSAndreas Gohr 12879c83e06SMichael Große // clear 12979c83e06SMichael Große if ($table && $INPUT->bool('clear')) { 13079c83e06SMichael Große if ($table != $INPUT->str('confirm_clear')) { 13179c83e06SMichael Große msg($this->getLang('clear_fail'), -1); 13279c83e06SMichael Große } else { 13379c83e06SMichael Große try { 13479c83e06SMichael Große $schema = new Schema($table); 13579c83e06SMichael Große $schema->clear(); 13679c83e06SMichael Große msg($this->getLang('clear_ok'), 1); 13779c83e06SMichael Große touch(action_plugin_struct_cache::getSchemaRefreshFile()); 138*7234bfb1Ssplitbrain send_redirect(wl($ID, ['do' => 'admin', 'page' => 'struct_schemas'], true, '&')); 13979c83e06SMichael Große } catch (StructException $e) { 14079c83e06SMichael Große msg(hsc($e->getMessage()), -1); 14179c83e06SMichael Große } 14279c83e06SMichael Große } 14379c83e06SMichael Große } 14487fdbc6bSMichael Große } 14587fdbc6bSMichael Große 14687fdbc6bSMichael Große /** 14787fdbc6bSMichael Große * Render HTML output, e.g. helpful text and a form 14887fdbc6bSMichael Große */ 149d6d97f60SAnna Dabrowska public function html() 150d6d97f60SAnna Dabrowska { 15187fdbc6bSMichael Große global $INPUT; 15287fdbc6bSMichael Große 15387fdbc6bSMichael Große $table = Schema::cleanTableName($INPUT->str('table')); 15487fdbc6bSMichael Große if ($table) { 1550ceefd5cSAnna Dabrowska $schema = new Schema($table, 0); 1567c080d69SAndreas Gohr 1576af24d3eSAndreas Gohr echo $this->locale_xhtml('editor_edit'); 1580ceefd5cSAnna Dabrowska echo '<h2>' . sprintf($this->getLang('edithl'), hsc($table)) . '</h2>'; 1598ddf87afSAndreas Gohr 1606c9d1a10SAnna Dabrowska if ($schema->getConfig()['internal']) { 1616c9d1a10SAnna Dabrowska echo $this->getLang('internal'); 16255e23b11SAnna Dabrowska return; 16355e23b11SAnna Dabrowska } 16455e23b11SAnna Dabrowska 1658ddf87afSAndreas Gohr echo '<ul class="tabs" id="plugin__struct_tabs">'; 1668ddf87afSAndreas Gohr /** @noinspection HtmlUnknownAnchorTarget */ 1678ddf87afSAndreas Gohr echo '<li class="active"><a href="#plugin__struct_editor">' . $this->getLang('tab_edit') . '</a></li>'; 1688ddf87afSAndreas Gohr /** @noinspection HtmlUnknownAnchorTarget */ 1698ddf87afSAndreas Gohr echo '<li><a href="#plugin__struct_json">' . $this->getLang('tab_export') . '</a></li>'; 170d5a1a6dcSAndreas Gohr /** @noinspection HtmlUnknownAnchorTarget */ 171d5a1a6dcSAndreas Gohr echo '<li><a href="#plugin__struct_delete">' . $this->getLang('tab_delete') . '</a></li>'; 1728ddf87afSAndreas Gohr echo '</ul>'; 1738ddf87afSAndreas Gohr echo '<div class="panelHeader"></div>'; 1748ddf87afSAndreas Gohr 1757c080d69SAndreas Gohr $editor = new SchemaEditor($schema); 17687fdbc6bSMichael Große echo $editor->getEditor(); 177748e747fSAnna Dabrowska echo $this->htmlJson($schema); 178748e747fSAnna Dabrowska echo $this->htmlDelete($schema); 17987fdbc6bSMichael Große } else { 1806af24d3eSAndreas Gohr echo $this->locale_xhtml('editor_intro'); 181748e747fSAnna Dabrowska echo $this->htmlNewschema(); 18287fdbc6bSMichael Große } 18387fdbc6bSMichael Große } 18487fdbc6bSMichael Große 18587fdbc6bSMichael Große /** 18669d92b7aSAnna Dabrowska * Form for handling import/export from/to JSON and CSV 1870845722bSAndreas Gohr * 1880845722bSAndreas Gohr * @param Schema $schema 1898ddf87afSAndreas Gohr * @return string 1908ddf87afSAndreas Gohr */ 191748e747fSAnna Dabrowska protected function htmlJson(Schema $schema) 192d6d97f60SAnna Dabrowska { 193*7234bfb1Ssplitbrain $form = new Form(['enctype' => 'multipart/form-data', 'id' => 'plugin__struct_json']); 1948ddf87afSAndreas Gohr $form->setHiddenField('do', 'admin'); 1958ddf87afSAndreas Gohr $form->setHiddenField('page', 'struct_schemas'); 1960845722bSAndreas Gohr $form->setHiddenField('table', $schema->getTable()); 1978ddf87afSAndreas Gohr 19869d92b7aSAnna Dabrowska // schemas 1998ddf87afSAndreas Gohr $form->addFieldsetOpen($this->getLang('export')); 2008ddf87afSAndreas Gohr $form->addButton('export', $this->getLang('btn_export')); 2018ddf87afSAndreas Gohr $form->addFieldsetClose(); 2028ddf87afSAndreas Gohr 2038ddf87afSAndreas Gohr $form->addFieldsetOpen($this->getLang('import')); 204*7234bfb1Ssplitbrain $form->addElement(new InputElement('file', 'schemafile'))->attr('accept', '.json'); 2058ddf87afSAndreas Gohr $form->addButton('import', $this->getLang('btn_import')); 2068ddf87afSAndreas Gohr $form->addHTML('<p>' . $this->getLang('import_warning') . '</p>'); 2078ddf87afSAndreas Gohr $form->addFieldsetClose(); 208a0b3799eSAndreas Gohr 20969d92b7aSAnna Dabrowska // data 2106d2df532SAndreas Gohr $form->addFieldsetOpen($this->getLang('admin_csvexport')); 21169d92b7aSAnna Dabrowska $form->addTagOpen('legend'); 21269d92b7aSAnna Dabrowska $form->addHTML($this->getLang('admin_csvexport_datatype')); 21369d92b7aSAnna Dabrowska $form->addTagClose('legend'); 2144fc908c2SAnna Dabrowska $form->addRadioButton('exporttype', $this->getLang('admin_csv_page')) 21515601745SAnna Dabrowska ->val(CSVExporter::DATATYPE_PAGE) 2164fc908c2SAnna Dabrowska ->attr('checked', 'checked')->addClass('edit block'); 2174fc908c2SAnna Dabrowska $form->addRadioButton('exporttype', $this->getLang('admin_csv_lookup')) 21815601745SAnna Dabrowska ->val(CSVExporter::DATATYPE_GLOBAL) 2194fc908c2SAnna Dabrowska ->addClass('edit block'); 2204fc908c2SAnna Dabrowska $form->addRadioButton('exporttype', $this->getLang('admin_csv_serial')) 22115601745SAnna Dabrowska ->val(CSVExporter::DATATYPE_SERIAL) 2224fc908c2SAnna Dabrowska ->addClass('edit block'); 22369d92b7aSAnna Dabrowska $form->addHTML('<br>'); 224f36cc634SAndreas Gohr $form->addButton('exportcsv', $this->getLang('btn_export')); 225f36cc634SAndreas Gohr $form->addFieldsetClose(); 226f36cc634SAndreas Gohr 2276d2df532SAndreas Gohr $form->addFieldsetOpen($this->getLang('admin_csvimport')); 22869d92b7aSAnna Dabrowska $form->addTagOpen('legend'); 22969d92b7aSAnna Dabrowska $form->addHTML($this->getLang('admin_csvimport_datatype')); 23069d92b7aSAnna Dabrowska $form->addTagClose('legend'); 2314fc908c2SAnna Dabrowska $form->addRadioButton('importtype', $this->getLang('admin_csv_page')) 23215601745SAnna Dabrowska ->val(CSVExporter::DATATYPE_PAGE) 2334fc908c2SAnna Dabrowska ->attr('checked', 'checked') 2344fc908c2SAnna Dabrowska ->addClass('edit block'); 2354fc908c2SAnna Dabrowska $form->addRadioButton('importtype', $this->getLang('admin_csv_lookup')) 23615601745SAnna Dabrowska ->val(CSVExporter::DATATYPE_GLOBAL) 2374fc908c2SAnna Dabrowska ->addClass('edit block'); 2384fc908c2SAnna Dabrowska $form->addRadioButton('importtype', $this->getLang('admin_csv_serial')) 23915601745SAnna Dabrowska ->val(CSVExporter::DATATYPE_SERIAL) 2404fc908c2SAnna Dabrowska ->addClass('edit block'); 24169d92b7aSAnna Dabrowska $form->addHTML('<br>'); 242*7234bfb1Ssplitbrain $form->addElement(new InputElement('file', 'csvfile'))->attr('accept', '.csv'); 243a0b3799eSAndreas Gohr $form->addButton('importcsv', $this->getLang('btn_import')); 244a22f2592SMichael Große $form->addCheckbox('createPage', 'Create missing pages')->addClass('block edit'); 24517a3a578SAndreas Gohr $form->addHTML( 24617a3a578SAndreas Gohr '<p><a href="https://www.dokuwiki.org/plugin:struct:csvimport">' . 24717a3a578SAndreas Gohr $this->getLang('admin_csvhelp') . '</a></p>' 24817a3a578SAndreas Gohr ); 249a0b3799eSAndreas Gohr $form->addFieldsetClose(); 250a0b3799eSAndreas Gohr 2518ddf87afSAndreas Gohr return $form->toHTML(); 2528ddf87afSAndreas Gohr } 2538ddf87afSAndreas Gohr 2548ddf87afSAndreas Gohr /** 255d5a1a6dcSAndreas Gohr * Form for deleting schemas 2560845722bSAndreas Gohr * 2570845722bSAndreas Gohr * @param Schema $schema 258d5a1a6dcSAndreas Gohr * @return string 259d5a1a6dcSAndreas Gohr */ 260748e747fSAnna Dabrowska protected function htmlDelete(Schema $schema) 261d6d97f60SAnna Dabrowska { 262*7234bfb1Ssplitbrain $form = new Form(['id' => 'plugin__struct_delete']); 263d5a1a6dcSAndreas Gohr $form->setHiddenField('do', 'admin'); 264d5a1a6dcSAndreas Gohr $form->setHiddenField('page', 'struct_schemas'); 2650845722bSAndreas Gohr $form->setHiddenField('table', $schema->getTable()); 266d5a1a6dcSAndreas Gohr 26779c83e06SMichael Große $form->addFieldsetOpen($this->getLang('btn_delete')); 268d5a1a6dcSAndreas Gohr $form->addHTML($this->locale_xhtml('delete_intro')); 269d5a1a6dcSAndreas Gohr $form->addTextInput('confirm', $this->getLang('del_confirm')); 270d5a1a6dcSAndreas Gohr $form->addButton('delete', $this->getLang('btn_delete')); 271d5a1a6dcSAndreas Gohr $form->addFieldsetClose(); 27279c83e06SMichael Große 27379c83e06SMichael Große $form->addFieldsetOpen($this->getLang('btn_clear')); 27479c83e06SMichael Große $form->addHTML($this->locale_xhtml('clear_intro')); 27579c83e06SMichael Große $form->addTextInput('confirm_clear', $this->getLang('clear_confirm')); 27679c83e06SMichael Große $form->addButton('clear', $this->getLang('btn_clear')); 27779c83e06SMichael Große $form->addFieldsetClose(); 27879c83e06SMichael Große 279d5a1a6dcSAndreas Gohr return $form->toHTML(); 280d5a1a6dcSAndreas Gohr } 281d5a1a6dcSAndreas Gohr 282d5a1a6dcSAndreas Gohr /** 28387fdbc6bSMichael Große * Form to add a new schema 2848ddf87afSAndreas Gohr * 2858ddf87afSAndreas Gohr * @return string 28687fdbc6bSMichael Große */ 287748e747fSAnna Dabrowska protected function htmlNewschema() 288d6d97f60SAnna Dabrowska { 28987fdbc6bSMichael Große $form = new Form(); 2904e427bd5SAndreas Gohr $form->addClass('struct_newschema'); 29187fdbc6bSMichael Große $form->addFieldsetOpen($this->getLang('create')); 29287fdbc6bSMichael Große $form->setHiddenField('do', 'admin'); 293dbffe06eSAndreas Gohr $form->setHiddenField('page', 'struct_schemas'); 29487fdbc6bSMichael Große $form->addTextInput('table', $this->getLang('schemaname')); 29587fdbc6bSMichael Große $form->addButton('', $this->getLang('save')); 29687fdbc6bSMichael Große $form->addHTML('<p>' . $this->getLang('createhint') . '</p>'); // FIXME is that true? we probably could 29787fdbc6bSMichael Große $form->addFieldsetClose(); 2988ddf87afSAndreas Gohr return $form->toHTML(); 29987fdbc6bSMichael Große } 30087fdbc6bSMichael Große 30187fdbc6bSMichael Große /** 30287fdbc6bSMichael Große * Adds all available schemas to the Table of Contents 30387fdbc6bSMichael Große * 30487fdbc6bSMichael Große * @return array 30587fdbc6bSMichael Große */ 306d6d97f60SAnna Dabrowska public function getTOC() 307d6d97f60SAnna Dabrowska { 30887fdbc6bSMichael Große global $ID; 30987fdbc6bSMichael Große 310*7234bfb1Ssplitbrain $toc = []; 3118ddf87afSAndreas Gohr $link = wl( 312d6d97f60SAnna Dabrowska $ID, 313*7234bfb1Ssplitbrain ['do' => 'admin', 'page' => 'struct_assignments'] 3148ddf87afSAndreas Gohr ); 315dbffe06eSAndreas Gohr $toc[] = html_mktocitem($link, $this->getLang('menu_assignments'), 0, ''); 3167c080d69SAndreas Gohr $slink = wl( 317d6d97f60SAnna Dabrowska $ID, 318*7234bfb1Ssplitbrain ['do' => 'admin', 'page' => 'struct_schemas'] 3198ddf87afSAndreas Gohr ); 3207c080d69SAndreas Gohr $toc[] = html_mktocitem($slink, $this->getLang('menu'), 0, ''); 32187fdbc6bSMichael Große 3226c9d1a10SAnna Dabrowska $schemas = helper_plugin_struct::getSchema(); 3236c9d1a10SAnna Dabrowska if ($schemas) { 3246c9d1a10SAnna Dabrowska foreach ($schemas as $schema) { 3256c9d1a10SAnna Dabrowska if ($schema->isInternal()) continue; 3266c9d1a10SAnna Dabrowska $table = $schema->getTable(); 3278ddf87afSAndreas Gohr $link = wl( 328d6d97f60SAnna Dabrowska $ID, 329*7234bfb1Ssplitbrain ['do' => 'admin', 'page' => 'struct_schemas', 'table' => $table] 3308ddf87afSAndreas Gohr ); 33187fdbc6bSMichael Große 3320ceefd5cSAnna Dabrowska $toc[] = html_mktocitem($link, hsc($table), 1, ''); 3337c080d69SAndreas Gohr } 3347c080d69SAndreas Gohr } 3357c080d69SAndreas Gohr 33687fdbc6bSMichael Große return $toc; 33787fdbc6bSMichael Große } 33887fdbc6bSMichael Große} 33987fdbc6bSMichael Große 34087fdbc6bSMichael Große// vim:ts=4:sw=4:et: 341