See Release Notes
Long Term Support Release
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * @package tool_xmldb 19 * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 20 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 21 */ 22 23 /** 24 * This class provides the interface for all the edit table actions 25 * 26 * Main page of edit table actions, from here fields/indexes/keys edition 27 * can be invoked, plus links to PHP code generator, view SQL, rearrange 28 * elements and so on. 29 * 30 * @package tool_xmldb 31 * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class edit_table extends XMLDBAction { 35 36 /** 37 * Init method, every subclass will have its own 38 */ 39 function init() { 40 parent::init(); 41 42 // Set own custom attributes 43 $this->sesskey_protected = false; // This action doesn't need sesskey protection 44 45 // Get needed strings 46 $this->loadStrings(array( 47 'addpersistent' => 'tool_xmldb', 48 'change' => 'tool_xmldb', 49 'vieworiginal' => 'tool_xmldb', 50 'viewedited' => 'tool_xmldb', 51 'viewsqlcode' => 'tool_xmldb', 52 'viewphpcode' => 'tool_xmldb', 53 'newfield' => 'tool_xmldb', 54 'newkey' => 'tool_xmldb', 55 'newindex' => 'tool_xmldb', 56 'fields' => 'tool_xmldb', 57 'keys' => 'tool_xmldb', 58 'indexes' => 'tool_xmldb', 59 'edit' => 'tool_xmldb', 60 'up' => 'tool_xmldb', 61 'down' => 'tool_xmldb', 62 'delete' => 'tool_xmldb', 63 'reserved' => 'tool_xmldb', 64 'back' => 'tool_xmldb', 65 'viewxml' => 'tool_xmldb', 66 'pendingchanges' => 'tool_xmldb', 67 'pendingchangescannotbesaved' => 'tool_xmldb', 68 'save' => 'tool_xmldb' 69 )); 70 } 71 72 /** 73 * Invoke method, every class will have its own 74 * returns true/false on completion, setting both 75 * errormsg and output as necessary 76 */ 77 function invoke() { 78 global $OUTPUT, $PAGE; 79 parent::invoke(); 80 81 $result = true; 82 83 // Set own core attributes 84 $this->does_generate = ACTION_GENERATE_HTML; 85 86 // These are always here 87 global $CFG, $XMLDB; 88 89 // Do the job, setting result as needed 90 // Get the dir containing the file 91 $dirpath = required_param('dir', PARAM_PATH); 92 $dirpath = $CFG->dirroot . $dirpath; 93 94 // Get the correct dirs 95 if (!empty($XMLDB->dbdirs)) { 96 $dbdir = $XMLDB->dbdirs[$dirpath]; 97 } else { 98 return false; 99 } 100 // Check if the dir exists and copy it from dbdirs 101 // (because we need straight load in case of saving from here) 102 if (!isset($XMLDB->editeddirs[$dirpath])) { 103 $XMLDB->editeddirs[$dirpath] = unserialize(serialize($dbdir)); 104 } 105 106 if (!empty($XMLDB->editeddirs)) { 107 $editeddir = $XMLDB->editeddirs[$dirpath]; 108 $structure = $editeddir->xml_file->getStructure(); 109 } 110 111 $tableparam = required_param('table', PARAM_CLEAN); 112 if (!$table = $structure->getTable($tableparam)) { 113 // Arriving here from a name change, looking for the new table name 114 $tableparam = required_param('name', PARAM_CLEAN); 115 $table = $structure->getTable($tableparam); 116 } 117 118 $dbdir = $XMLDB->dbdirs[$dirpath]; 119 $origstructure = $dbdir->xml_file->getStructure(); 120 121 // Add the main form 122 $o = '<form id="form" action="index.php" method="post">'; 123 $o.= '<div>'; 124 $o.= ' <input type="hidden" name ="dir" value="' . str_replace($CFG->dirroot, '', $dirpath) . '" />'; 125 $o.= ' <input type="hidden" name ="table" value="' . $tableparam .'" />'; 126 $o.= ' <input type="hidden" name ="action" value="edit_table_save" />'; 127 $o.= ' <input type="hidden" name ="sesskey" value="' . sesskey() .'" />'; 128 $o.= ' <input type="hidden" name ="postaction" value="edit_table" />'; 129 $o .= ' <table id="formelements">'; 130 // If the table is being used, we cannot rename it 131 if ($structure->getTableUses($table->getName())) { 132 $o.= ' <tr valign="top"><td>Name:</td><td><input type="hidden" name ="name" value="' . s($table->getName()) . '" />' . s($table->getName()) .'</td></tr>'; 133 } else { 134 $o.= ' <tr valign="top"><td><label for="name" accesskey="p">Name:</label></td><td><input name="name" type="text" size="'.xmldb_table::NAME_MAX_LENGTH.'" maxlength="'.xmldb_table::NAME_MAX_LENGTH.'" id="name" value="' . s($table->getName()) . '" /></td></tr>'; 135 } 136 $o .= ' <tr valign="top"><td><label for="comment" accesskey="c">Comment:</label></td><td> 137 <textarea name="comment" rows="3" cols="80" id="comment" class="form-control">' . 138 s($table->getComment()) . '</textarea></td></tr>'; 139 $o .= ' <tr valign="top"><td> </td><td><input type="submit" value="' . $this->str['change'] . 140 '" class="btn btn-secondary"/></td></tr>'; 141 $o.= ' </table>'; 142 $o.= '</div></form>'; 143 // Calculate the pending changes / save message 144 $e = ''; 145 $cansavenow = false; 146 if ($structure->hasChanged()) { 147 if (!is_writeable($dirpath . '/install.xml') || !is_writeable($dirpath)) { 148 $e .= '<p class="centerpara error">' . $this->str['pendingchangescannotbesaved'] . '</p>'; 149 } else { 150 $e .= '<p class="centerpara warning">' . $this->str['pendingchanges'] . '</p>'; 151 $cansavenow = true; 152 } 153 } 154 // Calculate the buttons 155 $b = ' <p class="centerpara buttons">'; 156 // The view original XML button 157 if ($origstructure->getTable($tableparam)) { 158 $b .= ' <a href="index.php?action=view_table_xml&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&select=original&table=' . $tableparam . '">[' . $this->str['vieworiginal'] . ']</a>'; 159 } else { 160 $b .= ' [' . $this->str['vieworiginal'] . ']'; 161 } 162 // The view edited XML button 163 if ($table->hasChanged()) { 164 $b .= ' <a href="index.php?action=view_table_xml&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&select=edited&table=' . $tableparam . '">[' . $this->str['viewedited'] . ']</a>'; 165 } else { 166 $b .= ' [' . $this->str['viewedited'] . ']'; 167 } 168 // The new field button 169 $b .= ' <a href="index.php?action=new_field&sesskey=' . sesskey() . '&postaction=edit_field&table=' . $tableparam . '&field=changeme&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['newfield'] . ']</a>'; 170 // The new key button 171 $b .= ' <a href="index.php?action=new_key&sesskey=' . sesskey() . '&postaction=edit_key&table=' . $tableparam . '&key=changeme&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['newkey'] . ']</a>'; 172 // The new index button 173 $b .= ' <a href="index.php?action=new_index&sesskey=' . sesskey() . '&postaction=edit_index&table=' . $tableparam . '&index=changeme&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['newindex'] . ']</a>'; 174 $b .= '</p>'; 175 176 $b .= ' <p class="centerpara buttons">'; 177 // The view sql code button 178 $b .= '<a href="index.php?action=view_table_sql&table=' . $tableparam . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' .$this->str['viewsqlcode'] . ']</a>'; 179 // The view php code button 180 $b .= ' <a href="index.php?action=view_table_php&table=' . $tableparam . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['viewphpcode'] . ']</a>'; 181 // The add persistent fields button. 182 $url = new \moodle_url('/admin/tool/xmldb/index.php', [ 183 'action' => 'add_persistent_mandatory', 184 'sesskey' => sesskey(), 185 'table' => $tableparam, 186 'dir'=> str_replace($CFG->dirroot, '', $dirpath) 187 ]); 188 $b .= ' ' . \html_writer::link($url, '[' . $this->str['addpersistent'] . ']'); 189 190 // The save button (if possible) 191 if ($cansavenow) { 192 $b .= ' <a href="index.php?action=save_xml_file&sesskey=' . sesskey() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&time=' . time() . '&unload=false&postaction=edit_table&table=' . $tableparam . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['save'] . ']</a>'; 193 } 194 // The back to edit xml file button 195 $b .= ' <a href="index.php?action=edit_xml_file&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['back'] . ']</a>'; 196 $b .= '</p>'; 197 $o .= $e . $b; 198 199 require_once("$CFG->libdir/ddl/sql_generator.php"); 200 $reserved_words = sql_generator::getAllReservedWords(); 201 202 // Delete any 'changeme' field/key/index 203 $table->deleteField('changeme'); 204 $table->deleteKey('changeme'); 205 $table->deleteIndex('changeme'); 206 207 // Add the fields list 208 $fields = $table->getFields(); 209 if (!empty($fields)) { 210 $o .= '<h3 class="main">' . $this->str['fields'] . '</h3>'; 211 $o .= '<table id="listfields" border="0" cellpadding="5" cellspacing="1" class="boxaligncenter flexible">'; 212 $row = 0; 213 foreach ($fields as $field) { 214 // Drag element up/down. 215 $move = (count($fields) > 1) ? html_writer::span($OUTPUT->render_from_template('core/drag_handle', 216 ['movetitle' => get_string('movecontent', 'moodle', $field->getName())]), '', 217 ['data-action' => 'move_updown_field', 'data-dir' => str_replace($CFG->dirroot, '', $dirpath), 218 'data-table' => $table->getName(), 'data-field' => $field->getName()]) : ''; 219 // The field name (link to edit - if the field has no uses) 220 if (!$structure->getFieldUses($table->getName(), $field->getName())) { 221 $f = '<a href="index.php?action=edit_field&field=' .$field->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">' . $field->getName() . '</a>'; 222 } else { 223 $f = $field->getName(); 224 } 225 // Calculate buttons 226 $b = '</td><td class="button cell">'; 227 // The edit button (if the field has no uses) 228 if (!$structure->getFieldUses($table->getName(), $field->getName())) { 229 $b .= '<a href="index.php?action=edit_field&field=' .$field->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['edit'] . ']</a>'; 230 } else { 231 $b .= '[' . $this->str['edit'] . ']'; 232 } 233 $b .= '</td><td class="button cell">'; 234 // The delete button (if we have more than one and it isn't used 235 if (count($fields) > 1 && 236 !$structure->getFieldUses($table->getName(), $field->getName())) { 237 $b .= '<a href="index.php?action=delete_field&sesskey=' . sesskey() . '&field=' . $field->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['delete'] . ']</a>'; 238 } else { 239 $b .= '[' . $this->str['delete'] . ']'; 240 } 241 $b .= '</td><td class="button cell">'; 242 // The view xml button 243 $b .= '<a href="index.php?action=view_field_xml&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&field=' . $field->getName() . '&table=' . $table->getName() . '&select=edited">[' . $this->str['viewxml'] . ']</a>'; 244 // Detect if the table name is a reserved word 245 if (array_key_exists($field->getName(), $reserved_words)) { 246 $b .= ' <a href="index.php?action=view_reserved_words"><span class="error">' . $this->str['reserved'] . '</span></a>'; 247 } 248 // The readable info 249 $r = '</td><td class="readableinfo cell">' . $field->readableInfo() . '</td>'; 250 // Print table row 251 $o .= '<tr class="r' . $row . '" data-name="' . s($field->getName()) . '"><td class="cell firstcol">' . $move . 252 $f . $b . $r . '</tr>'; 253 $row = ($row + 1) % 2; 254 } 255 $o .= '</table>'; 256 $PAGE->requires->js_call_amd('tool_xmldb/move', 'init', ['listfields', 'move_updown_field']); 257 } 258 // Add the keys list 259 $keys = $table->getKeys(); 260 if (!empty($keys)) { 261 $o .= '<h3 class="main">' . $this->str['keys'] . '</h3>'; 262 $o .= '<table id="listkeys" border="0" cellpadding="5" cellspacing="1" class="boxaligncenter flexible">'; 263 $row = 0; 264 foreach ($keys as $key) { 265 // Drag element up/down. 266 $move = (count($keys) > 1) ? html_writer::span($OUTPUT->render_from_template('core/drag_handle', 267 ['movetitle' => get_string('movecontent', 'moodle', $key->getName())]), '', 268 ['data-action' => 'move_updown_key', 'data-dir' => str_replace($CFG->dirroot, '', $dirpath), 269 'data-table' => $table->getName(), 'data-key' => $key->getName()]) : ''; 270 // The key name (link to edit - if the key has no uses) 271 if (!$structure->getKeyUses($table->getName(), $key->getName())) { 272 $k = '<a href="index.php?action=edit_key&key=' .$key->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">' . $key->getName() . '</a>'; 273 } else { 274 $k = $key->getName(); 275 } 276 // Calculate buttons 277 $b = '</td><td class="button cell">'; 278 // The edit button (if the key hasn't uses) 279 if (!$structure->getKeyUses($table->getName(), $key->getName())) { 280 $b .= '<a href="index.php?action=edit_key&key=' .$key->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['edit'] . ']</a>'; 281 } else { 282 $b .= '[' . $this->str['edit'] . ']'; 283 } 284 $b .= '</td><td class="button cell">'; 285 // The delete button (if the key hasn't uses) 286 if (!$structure->getKeyUses($table->getName(), $key->getName())) { 287 $b .= '<a href="index.php?action=delete_key&sesskey=' . sesskey() . '&key=' . $key->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['delete'] . ']</a>'; 288 } else { 289 $b .= '[' . $this->str['delete'] . ']'; 290 } 291 $b .= '</td><td class="button cell">'; 292 // The view xml button 293 $b .= '<a href="index.php?action=view_key_xml&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&key=' . $key->getName() . '&table=' . $table->getName() . '&select=edited">[' . $this->str['viewxml'] . ']</a>'; 294 // The readable info 295 $r = '</td><td class="readableinfo cell">' . $key->readableInfo() . '</td>'; 296 // Print table row 297 $o .= '<tr class="r' . $row . '" data-name="' . s($key->getName()) . '"><td class="cell firstcol">' . 298 $move . $k . $b . $r .'</tr>'; 299 $row = ($row + 1) % 2; 300 } 301 $o .= '</table>'; 302 $PAGE->requires->js_call_amd('tool_xmldb/move', 'init', ['listkeys', 'move_updown_key']); 303 } 304 // Add the indexes list 305 $indexes = $table->getIndexes(); 306 if (!empty($indexes)) { 307 $o .= '<h3 class="main">' . $this->str['indexes'] . '</h3>'; 308 $o .= '<table id="listindexes" border="0" cellpadding="5" cellspacing="1" class="boxaligncenter flexible">'; 309 $row = 0; 310 foreach ($indexes as $index) { 311 // Drag element up/down. 312 $move = (count($indexes) > 1) ? html_writer::span($OUTPUT->render_from_template('core/drag_handle', 313 ['movetitle' => get_string('movecontent', 'moodle', $index->getName())]), '', 314 ['data-action' => 'move_updown_index', 'data-dir' => str_replace($CFG->dirroot, '', $dirpath), 315 'data-table' => $table->getName(), 'data-index' => $index->getName()]) : ''; 316 // The index name (link to edit) 317 $i = '<a href="index.php?action=edit_index&index=' .$index->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">' . $index->getName() . '</a>'; 318 // Calculate buttons 319 $b = '</td><td class="button cell">'; 320 // The edit button 321 $b .= '<a href="index.php?action=edit_index&index=' .$index->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['edit'] . ']</a>'; 322 $b .= '</td><td class="button cell">'; 323 // The delete button 324 $b .= '<a href="index.php?action=delete_index&sesskey=' . sesskey() . '&index=' . $index->getName() . '&table=' . $table->getName() . '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['delete'] . ']</a>'; 325 $b .= '</td><td class="button cell">'; 326 // The view xml button 327 $b .= '<a href="index.php?action=view_index_xml&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&index=' . $index->getName() . '&table=' . $table->getName() . '&select=edited">[' . $this->str['viewxml'] . ']</a>'; 328 // The readable info 329 $r = '</td><td class="readableinfo cell">' . $index->readableInfo() . '</td>'; 330 // Print table row 331 $o .= '<tr class="r' . $row . '" data-name="' . s($index->getName()) . '"><td class="cell firstcol">' . 332 $move . $i . $b . $r .'</tr>'; 333 $row = ($row + 1) % 2; 334 } 335 $o .= '</table>'; 336 $PAGE->requires->js_call_amd('tool_xmldb/move', 'init', ['listindexes', 'move_updown_index']); 337 } 338 339 $this->output = $o; 340 341 // Launch postaction if exists (leave this here!) 342 if ($this->getPostAction() && $result) { 343 return $this->launch($this->getPostAction()); 344 } 345 346 // Return ok if arrived here 347 return $result; 348 } 349 } 350
title
Description
Body
title
Description
Body
title
Description
Body
title
Body