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