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\Schema; 15use dokuwiki\plugin\struct\meta\SchemaBuilder; 16use dokuwiki\plugin\struct\meta\SchemaEditor; 17use dokuwiki\plugin\struct\meta\SchemaImporter; 18use dokuwiki\plugin\struct\meta\StructException; 19 20class admin_plugin_struct_schemas extends DokuWiki_Admin_Plugin 21{ 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 // FIXME 87 if ($INPUT->str('importtype') === 'page') { 88 $csvImporter = new CSVPageImporter($table, $_FILES['csvfile']['tmp_name']); 89 } else { 90 $csvImporter = new CSVImporter($table, $_FILES['csvfile']['tmp_name']); 91 } 92 $csvImporter->import(); 93 msg($this->getLang('admin_csvdone'), 1); 94 } catch (StructException $e) { 95 msg(hsc($e->getMessage()), -1); 96 } 97 } 98 } 99 100 // export CSV 101 if ($table && $INPUT->bool('exportcsv')) { 102 header('Content-Type: text/csv'); 103 header('Content-Disposition: attachment; filename="' . $table . '.csv";'); 104 new CSVExporter($table, $INPUT->str('exporttype')); 105 exit(); 106 } 107 108 // delete 109 if ($table && $INPUT->bool('delete')) { 110 if ($table != $INPUT->str('confirm')) { 111 msg($this->getLang('del_fail'), -1); 112 } else { 113 try { 114 $schema = new Schema($table); 115 $schema->delete(); 116 msg($this->getLang('del_ok'), 1); 117 touch(action_plugin_struct_cache::getSchemaRefreshFile()); 118 send_redirect(wl($ID, array('do' => 'admin', 'page' => 'struct_schemas'), true, '&')); 119 } catch (StructException $e) { 120 msg(hsc($e->getMessage()), -1); 121 } 122 } 123 } 124 125 // clear 126 if ($table && $INPUT->bool('clear')) { 127 if ($table != $INPUT->str('confirm_clear')) { 128 msg($this->getLang('clear_fail'), -1); 129 } else { 130 try { 131 $schema = new Schema($table); 132 $schema->clear(); 133 msg($this->getLang('clear_ok'), 1); 134 touch(action_plugin_struct_cache::getSchemaRefreshFile()); 135 send_redirect(wl($ID, array('do' => 'admin', 'page' => 'struct_schemas'), true, '&')); 136 } catch (StructException $e) { 137 msg(hsc($e->getMessage()), -1); 138 } 139 } 140 } 141 } 142 143 /** 144 * Render HTML output, e.g. helpful text and a form 145 */ 146 public function html() 147 { 148 global $INPUT; 149 150 $table = Schema::cleanTableName($INPUT->str('table')); 151 if ($table) { 152 $schema = new Schema($table, 0); 153 154 echo $this->locale_xhtml('editor_edit'); 155 echo '<h2>' . sprintf($this->getLang('edithl'), hsc($table)) . '</h2>'; 156 157 echo '<ul class="tabs" id="plugin__struct_tabs">'; 158 /** @noinspection HtmlUnknownAnchorTarget */ 159 echo '<li class="active"><a href="#plugin__struct_editor">' . $this->getLang('tab_edit') . '</a></li>'; 160 /** @noinspection HtmlUnknownAnchorTarget */ 161 echo '<li><a href="#plugin__struct_json">' . $this->getLang('tab_export') . '</a></li>'; 162 /** @noinspection HtmlUnknownAnchorTarget */ 163 echo '<li><a href="#plugin__struct_delete">' . $this->getLang('tab_delete') . '</a></li>'; 164 echo '</ul>'; 165 echo '<div class="panelHeader"></div>'; 166 167 $editor = new SchemaEditor($schema); 168 echo $editor->getEditor(); 169 echo $this->htmlJson($schema); 170 echo $this->htmlDelete($schema); 171 } else { 172 echo $this->locale_xhtml('editor_intro'); 173 echo $this->htmlNewschema(); 174 } 175 } 176 177 /** 178 * Form for handling import/export from/to JSON and CSV 179 * 180 * @param Schema $schema 181 * @return string 182 */ 183 protected function htmlJson(Schema $schema) 184 { 185 $form = new Form(array('enctype' => 'multipart/form-data', 'id' => 'plugin__struct_json')); 186 $form->setHiddenField('do', 'admin'); 187 $form->setHiddenField('page', 'struct_schemas'); 188 $form->setHiddenField('table', $schema->getTable()); 189 190 // schemas 191 $form->addFieldsetOpen($this->getLang('export')); 192 $form->addButton('export', $this->getLang('btn_export')); 193 $form->addFieldsetClose(); 194 195 $form->addFieldsetOpen($this->getLang('import')); 196 $form->addElement(new \dokuwiki\Form\InputElement('file', 'schemafile'))->attr('accept', '.json'); 197 $form->addButton('import', $this->getLang('btn_import')); 198 $form->addHTML('<p>' . $this->getLang('import_warning') . '</p>'); 199 $form->addFieldsetClose(); 200 201 // data 202 $form->addFieldsetOpen($this->getLang('admin_csvexport')); 203 $form->addTagOpen('legend'); 204 $form->addHTML($this->getLang('admin_csvexport_datatype')); 205 $form->addTagClose('legend'); 206 $form->addRadioButton('exporttype',$this->getLang('admin_csv_page'))->val('page')->attr('checked', 'checked'); 207 $form->addRadioButton('exporttype',$this->getLang('admin_csv_lookup'))->val('lookup'); 208 $form->addRadioButton('exporttype',$this->getLang('admin_csv_serial'))->val('serial'); 209 $form->addHTML('<br>'); 210 $form->addButton('exportcsv', $this->getLang('btn_export')); 211 $form->addFieldsetClose(); 212 213 $form->addFieldsetOpen($this->getLang('admin_csvimport')); 214 $form->addTagOpen('legend'); 215 $form->addHTML($this->getLang('admin_csvimport_datatype')); 216 $form->addTagClose('legend'); 217 $form->addRadioButton('importype',$this->getLang('admin_csv_page'))->val('page')->attr('checked', 'checked'); 218 $form->addRadioButton('importype',$this->getLang('admin_csv_lookup'))->val('lookup'); 219 $form->addRadioButton('importype',$this->getLang('admin_csv_serial'))->val('serial'); 220 $form->addHTML('<br>'); 221 $form->addElement(new \dokuwiki\Form\InputElement('file', 'csvfile'))->attr('accept', '.csv'); 222 $form->addButton('importcsv', $this->getLang('btn_import')); 223 $form->addCheckbox('createPage', 'Create missing pages')->addClass('block edit'); 224 $form->addHTML('<p><a href="https://www.dokuwiki.org/plugin:struct:csvimport">' . $this->getLang('admin_csvhelp') . '</a></p>'); 225 $form->addFieldsetClose(); 226 227 return $form->toHTML(); 228 } 229 230 /** 231 * Form for deleting schemas 232 * 233 * @param Schema $schema 234 * @return string 235 */ 236 protected function htmlDelete(Schema $schema) 237 { 238 $form = new Form(array('id' => 'plugin__struct_delete')); 239 $form->setHiddenField('do', 'admin'); 240 $form->setHiddenField('page', 'struct_schemas'); 241 $form->setHiddenField('table', $schema->getTable()); 242 243 $form->addFieldsetOpen($this->getLang('btn_delete')); 244 $form->addHTML($this->locale_xhtml('delete_intro')); 245 $form->addTextInput('confirm', $this->getLang('del_confirm')); 246 $form->addButton('delete', $this->getLang('btn_delete')); 247 $form->addFieldsetClose(); 248 249 $form->addFieldsetOpen($this->getLang('btn_clear')); 250 $form->addHTML($this->locale_xhtml('clear_intro')); 251 $form->addTextInput('confirm_clear', $this->getLang('clear_confirm')); 252 $form->addButton('clear', $this->getLang('btn_clear')); 253 $form->addFieldsetClose(); 254 255 return $form->toHTML(); 256 } 257 258 /** 259 * Form to add a new schema 260 * 261 * @return string 262 */ 263 protected function htmlNewschema() 264 { 265 $form = new Form(); 266 $form->addClass('struct_newschema'); 267 $form->addFieldsetOpen($this->getLang('create')); 268 $form->setHiddenField('do', 'admin'); 269 $form->setHiddenField('page', 'struct_schemas'); 270 $form->addTextInput('table', $this->getLang('schemaname')); 271 $form->addButton('', $this->getLang('save')); 272 $form->addHTML('<p>' . $this->getLang('createhint') . '</p>'); // FIXME is that true? we probably could 273 $form->addFieldsetClose(); 274 return $form->toHTML(); 275 } 276 277 /** 278 * Adds all available schemas to the Table of Contents 279 * 280 * @return array 281 */ 282 public function getTOC() 283 { 284 global $ID; 285 286 $toc = array(); 287 $link = wl( 288 $ID, 289 array( 290 'do' => 'admin', 291 'page' => 'struct_assignments' 292 ) 293 ); 294 $toc[] = html_mktocitem($link, $this->getLang('menu_assignments'), 0, ''); 295 $slink = wl( 296 $ID, 297 array( 298 'do' => 'admin', 299 'page' => 'struct_schemas' 300 ) 301 ); 302 $toc[] = html_mktocitem($slink, $this->getLang('menu'), 0, ''); 303 304 $tables = Schema::getAll(); 305 if ($tables) { 306 foreach ($tables as $table) { 307 $link = wl( 308 $ID, 309 array( 310 'do' => 'admin', 311 'page' => 'struct_schemas', 312 'table' => $table 313 ) 314 ); 315 316 $toc[] = html_mktocitem($link, hsc($table), 1, ''); 317 } 318 } 319 320 return $toc; 321 } 322} 323 324// vim:ts=4:sw=4:et: 325