Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

   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 will show all the actions available under the XMLDB editor interface
  25   *
  26   * From here, files can be created, edited, saved and deleted, plus some
  27   * extra utilities like displaying docs, xml info and performing various consistency tests
  28   *
  29   * @package    tool_xmldb
  30   * @copyright  2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class main_view extends XMLDBAction {
  34  
  35      /**
  36       * Init method, every subclass will have its own
  37       */
  38      function init() {
  39          parent::init();
  40  
  41          // Set own custom attributes
  42          $this->sesskey_protected = false; // This action doesn't need sesskey protection
  43  
  44          // Get needed strings
  45          $this->loadStrings(array(
  46              'load' => 'tool_xmldb',
  47              'create' => 'tool_xmldb',
  48              'edit' => 'tool_xmldb',
  49              'save' => 'tool_xmldb',
  50              'revert' => 'tool_xmldb',
  51              'unload' => 'tool_xmldb',
  52              'delete' => 'tool_xmldb',
  53              'reservedwords' => 'tool_xmldb',
  54              'gotolastused' => 'tool_xmldb',
  55              'checkindexes' => 'tool_xmldb',
  56              'checkdefaults' => 'tool_xmldb',
  57              'checkforeignkeys' => 'tool_xmldb',
  58              'checkbigints' => 'tool_xmldb',
  59              'checkoraclesemantics' => 'tool_xmldb',
  60              'reconcilefiles' => 'tool_xmldb',
  61              'doc' => 'tool_xmldb',
  62              'filemodifiedoutfromeditor' => 'tool_xmldb',
  63              'viewxml' => 'tool_xmldb',
  64              'pendingchangescannotbesavedreload' => 'tool_xmldb'
  65          ));
  66      }
  67  
  68      /**
  69       * Invoke method, every class will have its own
  70       * returns true/false on completion, setting both
  71       * errormsg and output as necessary
  72       */
  73      function invoke() {
  74          parent::invoke();
  75  
  76          $result = true;
  77  
  78          // Set own core attributes
  79          $this->does_generate = ACTION_GENERATE_HTML;
  80  
  81          // These are always here
  82          global $CFG, $XMLDB, $SESSION, $DB;
  83  
  84          // Get lastused
  85          $o = '';
  86          if (isset($SESSION->lastused)) {
  87              if ($lastused = $SESSION->lastused) {
  88                  // Print link
  89                  $o .= '<p class="centerpara"><a href="#lastused">' . $this->str['gotolastused'] . '</a></p>';
  90              }
  91          } else {
  92              $lastused = NULL;
  93          }
  94  
  95          // Calculate the buttons
  96          $b = '<p class="centerpara buttons">';
  97          // The reserved_words button
  98          $b .= '&nbsp;<a href="index.php?action=view_reserved_words">[' . $this->str['reservedwords'] . ']</a>';
  99          // The docs button
 100          $b .= '&nbsp;<a href="index.php?action=generate_all_documentation">[' . $this->str['doc'] . ']</a>';
 101          // The reconcile XMLDB files button.
 102          $b .= '&nbsp;<a href="index.php?action=reconcile_files">[' . $this->str['reconcilefiles'] . ']</a>';
 103          // The check indexes button
 104          $b .= '&nbsp;<a href="index.php?action=check_indexes&amp;sesskey=' . sesskey() . '">[' . $this->str['checkindexes'] . ']</a>';
 105          // The check defaults button
 106          $b .= '&nbsp;<a href="index.php?action=check_defaults&amp;sesskey=' . sesskey() . '">[' . $this->str['checkdefaults'] . ']</a>';
 107          // The check bigints button (only for MySQL and PostgreSQL) MDL-11038a
 108          if ($DB->get_dbfamily() == 'mysql' || $DB->get_dbfamily() == 'postgres') {
 109              $b .= '&nbsp;<a href="index.php?action=check_bigints&amp;sesskey=' . sesskey() . '">[' . $this->str['checkbigints'] . ']</a>';
 110          }
 111          // The check semantics button (only for Oracle) MDL-29416
 112          if ($DB->get_dbfamily() == 'oracle') {
 113              $b .= '&nbsp;<a href="index.php?action=check_oracle_semantics&amp;sesskey=' . sesskey() . '">[' . $this->str['checkoraclesemantics'] . ']</a>';
 114          }
 115          $b .= '&nbsp;<a href="index.php?action=check_foreign_keys&amp;sesskey=' . sesskey() . '">[' . $this->str['checkforeignkeys'] . ']</a>';
 116          $b .= '</p>';
 117          // Send buttons to output
 118          $o .= $b;
 119  
 120          // Do the job
 121  
 122          // Get the list of DB directories
 123          $result = $this->launch('get_db_directories');
 124          // Display list of DB directories if everything is ok
 125          if ($result && !empty($XMLDB->dbdirs)) {
 126              $o .= '<table id="listdirectories" border="0" cellpadding="5" cellspacing="1"' .
 127                  ' class="table-striped table-sm admintable generaltable">';
 128              $row = 0;
 129              foreach ($XMLDB->dbdirs as $key => $dbdir) {
 130                  // Detect if this is the lastused dir
 131                  $hithis = false;
 132                  if (str_replace($CFG->dirroot, '', $key) == $lastused) {
 133                      $hithis = true;
 134                  }
 135                  $elementtext = str_replace($CFG->dirroot . '/', '', $key);
 136                  // Calculate the dbdir has_changed field if needed
 137                  if (!isset($dbdir->has_changed) && isset($dbdir->xml_loaded)) {
 138                      $dbdir->xml_changed = false;
 139                      if (isset($XMLDB->editeddirs[$key])) {
 140                          $editeddir = $XMLDB->editeddirs[$key];
 141                          if (isset($editeddir->xml_file)) {
 142                              $structure = $editeddir->xml_file->getStructure();
 143                              if ($structure->hasChanged()) {
 144                                  $dbdir->xml_changed = true;
 145                                  $editeddir->xml_changed = true;
 146                              }
 147                          }
 148                      }
 149                  }
 150                  // The file name (link to edit if the file is loaded)
 151                  if ($dbdir->path_exists &&
 152                      file_exists($key . '/install.xml') &&
 153                      is_readable($key . '/install.xml') &&
 154                      is_readable($key) &&
 155                      !empty($dbdir->xml_loaded)) {
 156                      $f = '<a href="index.php?action=edit_xml_file&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '">' . $elementtext . '</a>';
 157                  } else {
 158                      $f = $elementtext;
 159                  }
 160                  // Calculate the buttons
 161                  $b = ' <td class="button cell">';
 162                  // The create button
 163                  if ($dbdir->path_exists &&
 164                      !file_exists($key . '/install.xml') &&
 165                      is_writeable($key)) {
 166                      $b .= '<a href="index.php?action=create_xml_file&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '&amp;time=' . time() . '&amp;postaction=main_view#lastused">[' . $this->str['create'] . ']</a>';
 167                  } else {
 168                      $b .= '[' . $this->str['create'] . ']';
 169                  }
 170                  $b .= '</td><td class="button cell">';
 171                  // The load button
 172                  if ($dbdir->path_exists &&
 173                      file_exists($key . '/install.xml') &&
 174                      is_readable($key . '/install.xml') &&
 175                      empty($dbdir->xml_loaded)) {
 176                      $b .= '<a href="index.php?action=load_xml_file&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '&amp;time=' . time() . '&amp;postaction=main_view#lastused">[' . $this->str['load'] . ']</a>';
 177                  } else {
 178                      $b .= '[' . $this->str['load'] . ']';
 179                  }
 180                  $b .= '</td><td class="button cell">';
 181                  // The edit button
 182                  if ($dbdir->path_exists &&
 183                      file_exists($key . '/install.xml') &&
 184                      is_readable($key . '/install.xml') &&
 185                      is_readable($key) &&
 186                      !empty($dbdir->xml_loaded)) {
 187                      $b .= '<a href="index.php?action=edit_xml_file&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '">[' . $this->str['edit'] . ']</a>';
 188                  } else {
 189                      $b .= '[' . $this->str['edit'] . ']';
 190                  }
 191                  $b .= '</td><td class="button cell">';
 192                  // The save button
 193                  if ($dbdir->path_exists &&
 194                      file_exists($key . '/install.xml') &&
 195                      is_writeable($key . '/install.xml') &&
 196                      is_writeable($key) &&
 197                      !empty($dbdir->xml_loaded) &&
 198                      !empty($dbdir->xml_changed)) {
 199                      $b .= '<a href="index.php?action=save_xml_file&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '&amp;time=' . time() . '&amp;postaction=main_view#lastused">[' . $this->str['save'] . ']</a>';
 200                      // Check if the file has been manually edited while being modified in the editor
 201                      if ($dbdir->filemtime != filemtime($key . '/install.xml')) {
 202                          // File manually modified. Add to action error, will be displayed inline.
 203                          $this->errormsg = $this->str['filemodifiedoutfromeditor'];
 204                      }
 205                  } else {
 206                      $b .= '[' . $this->str['save'] . ']';
 207                  }
 208                  $b .= '</td><td class="button cell">';
 209                  // The document button
 210                  if ($dbdir->path_exists &&
 211                      file_exists($key . '/install.xml') &&
 212                      is_readable($key . '/install.xml') &&
 213                      is_readable($key)) {
 214                      $b .= '<a href="index.php?action=generate_documentation&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '">[' . $this->str['doc'] . ']</a>';
 215                  } else {
 216                      $b .= '[' . $this->str['doc'] . ']';
 217                  }
 218                  $b .= '</td><td class="button cell">';
 219                  // The view xml button
 220                  if ($dbdir->path_exists &&
 221                      file_exists($key . '/install.xml') &&
 222                      is_readable($key . '/install.xml')) {
 223                      $b .= '<a href="index.php?action=view_xml&amp;file=' . urlencode(str_replace($CFG->dirroot, '', $key) . '/install.xml') . '">[' . $this->str['viewxml'] . ']</a>';
 224                  } else {
 225                      $b .= '[' . $this->str['viewxml'] . ']';
 226                  }
 227                  $b .= '</td><td class="button cell">';
 228                  // The revert button
 229                  if ($dbdir->path_exists &&
 230                      file_exists($key . '/install.xml') &&
 231                      is_readable($key . '/install.xml') &&
 232                      is_writeable($key) &&
 233                      !empty($dbdir->xml_loaded) &&
 234                      !empty($dbdir->xml_changed)) {
 235                      $b .= '<a href="index.php?action=revert_changes&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '">[' . $this->str['revert'] . ']</a>';
 236                  } else {
 237                      $b .= '[' . $this->str['revert'] . ']';
 238                  }
 239                  $b .= '</td><td class="button cell">';
 240                  // The unload button
 241                  if ($dbdir->path_exists &&
 242                      file_exists($key . '/install.xml') &&
 243                      is_readable($key . '/install.xml') &&
 244                      !empty($dbdir->xml_loaded) &&
 245                      empty($dbdir->xml_changed)) {
 246                      $b .= '<a href="index.php?action=unload_xml_file&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '&amp;time=' . time() . '&amp;postaction=main_view#lastused">[' . $this->str['unload'] . ']</a>';
 247                  } else {
 248                      $b .= '[' . $this->str['unload'] . ']';
 249                  }
 250                  $b .= '</td><td class="button cell">';
 251                  // The delete button
 252                  if ($dbdir->path_exists &&
 253                      file_exists($key . '/install.xml') &&
 254                      is_readable($key . '/install.xml') &&
 255                      is_writeable($key) &&
 256                      empty($dbdir->xml_loaded)) {
 257                      $b .= '<a href="index.php?action=delete_xml_file&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $key)) . '">[' . $this->str['delete'] . ']</a>';
 258                  } else {
 259                      $b .= '[' . $this->str['delete'] . ']';
 260                  }
 261                  $b .= '</td>';
 262                  // include the higlight
 263                  if ($hithis) {
 264                      $o .= '<tr class="highlight"><td class="directory cell"><a name="lastused" />' . $f . '</td>' . $b . '</tr>';
 265                  } else {
 266                      $o .= '<tr class="r' . $row . '"><td class="directory cell">' . $f . '</td>' . $b . '</tr>';
 267                  }
 268                  $row = ($row + 1) % 2;
 269                  // show errors if they exist
 270                  if (isset($dbdir->xml_file)) {
 271                      if ($structure = $dbdir->xml_file->getStructure()) {
 272                          $errors = !empty($this->errormsg) ? array($this->errormsg) : array();
 273                          $structureerrors = $structure->getAllErrors();
 274                          if ($structureerrors) {
 275                              $errors = array_merge($errors, $structureerrors);
 276                          }
 277                          if (!empty($errors)) {
 278                              if ($hithis) {
 279                                  $o .= '<tr class="highlight"><td class="error cell" colspan="10">' . implode (', ', $errors) . '</td></tr>';
 280                              } else {
 281                                  $o .= '<tr class="r' . $row . '"><td class="error cell" colspan="10">' . implode (', ', $errors) . '</td></tr>';
 282                              }
 283                          }
 284                      }
 285                  }
 286                  // If there are changes pending to be saved, but the file cannot be written... inform here
 287                  if ($dbdir->path_exists &&
 288                      file_exists($key . '/install.xml') &&
 289                      !empty($dbdir->xml_loaded) &&
 290                      !empty($dbdir->xml_changed) &&
 291                      (!is_writeable($key . '/install.xml') || !is_writeable($key))) {
 292  
 293                      if ($hithis) {
 294                          $o .= '<tr class="highlight"><td class="error cell" colspan="10">';
 295                      } else {
 296                          $o .= '<tr class="r' . $row . '"><td class="error cell" colspan="10">';
 297                      }
 298                      $o .= $this->str['pendingchangescannotbesavedreload'];
 299                      $o .= '</td></tr>';
 300                  }
 301              }
 302              $o .= '</table>';
 303  
 304              // Set the output
 305              $this->output = $o;
 306          }
 307  
 308          // Finally, return result
 309          return $result;
 310      }
 311  }
 312