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.
   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  2008 onwards Tim Hunt
  20   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21   */
  22  
  23  /**
  24   * This is a base class for the various actions that interate over all the
  25   * tables and check some aspect of their definition.
  26   *
  27   * @package    tool_xmldb
  28   * @copyright  2008 onwards Tim Hunt
  29   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  abstract class XMLDBCheckAction extends XMLDBAction {
  32      /**
  33       * @var string This string is displayed with a yes/no choice before the report is run.
  34       * You must set this to the name of a lang string in xmldb.php before calling init.
  35       */
  36      protected $introstr = '';
  37  
  38      /**
  39       * Init method, every subclass will have its own
  40       */
  41      function init() {
  42          parent::init();
  43  
  44          // Set own core attributes
  45  
  46          // Set own custom attributes
  47  
  48          // Get needed strings
  49          $this->loadStrings(array(
  50              $this->introstr => 'tool_xmldb',
  51              'ok' => '',
  52              'wrong' => 'tool_xmldb',
  53              'table' => 'tool_xmldb',
  54              'field' => 'tool_xmldb',
  55              'searchresults' => 'tool_xmldb',
  56              'completelogbelow' => 'tool_xmldb',
  57              'yes' => '',
  58              'no' => '',
  59              'error' => '',
  60              'back' => 'tool_xmldb'
  61          ));
  62      }
  63  
  64      /**
  65       * Invoke method, every class will have its own
  66       * returns true/false on completion, setting both
  67       * errormsg and output as necessary
  68       */
  69      function invoke() {
  70          parent::invoke();
  71  
  72          $result = true;
  73  
  74          // Set own core attributes
  75          $this->does_generate = ACTION_GENERATE_HTML;
  76  
  77          // These are always here
  78          global $CFG, $XMLDB, $DB, $OUTPUT;
  79  
  80          // And we nedd some ddl suff
  81          $dbman = $DB->get_manager();
  82  
  83          // Here we'll acummulate all the wrong fields found
  84          $problemsfound = array();
  85  
  86          // Do the job, setting $result as needed
  87  
  88          // Get the confirmed to decide what to do
  89          $confirmed = optional_param('confirmed', false, PARAM_BOOL);
  90  
  91          // If  not confirmed, show confirmation box
  92          if (!$confirmed) {
  93              $o = '<table class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
  94              $o.= '  <tr><td class="generalboxcontent">';
  95              $o.= '    <p class="centerpara">' . $this->str[$this->introstr] . '</p>';
  96              $o.= '    <table class="boxaligncenter" cellpadding="20"><tr><td>';
  97              $o.= '      <div class="singlebutton">';
  98              $o.= '        <form action="index.php?action=' . $this->title . '&amp;confirmed=yes&amp;sesskey=' . sesskey() . '" method="post"><fieldset class="invisiblefieldset">';
  99              $o.= '          <input type="submit" value="'. $this->str['yes'] .'" /></fieldset></form></div>';
 100              $o.= '      </td><td>';
 101              $o.= '      <div class="singlebutton">';
 102              $o.= '        <form action="index.php?action=main_view" method="post"><fieldset class="invisiblefieldset">';
 103              $o.= '          <input type="submit" value="'. $this->str['no'] .'" /></fieldset></form></div>';
 104              $o.= '      </td></tr>';
 105              $o.= '    </table>';
 106              $o.= '  </td></tr>';
 107              $o.= '</table>';
 108  
 109              $this->output = $o;
 110          } else {
 111              // The back to edit table button
 112              $b = ' <p class="centerpara buttons">';
 113              $b .= '<a href="index.php">[' . $this->str['back'] . ']</a>';
 114              $b .= '</p>';
 115  
 116              // Iterate over $XMLDB->dbdirs, loading their XML data to memory
 117              if ($XMLDB->dbdirs) {
 118                  $dbdirs = $XMLDB->dbdirs;
 119                  $o='<ul>';
 120                  foreach ($dbdirs as $dbdir) {
 121                      // Only if the directory exists
 122                      if (!$dbdir->path_exists) {
 123                          continue;
 124                      }
 125                      // Load the XML file
 126                      $xmldb_file = new xmldb_file($dbdir->path . '/install.xml');
 127  
 128                      // Only if the file exists
 129                      if (!$xmldb_file->fileExists()) {
 130                          continue;
 131                      }
 132                      // Load the XML contents to structure
 133                      $loaded = $xmldb_file->loadXMLStructure();
 134                      if (!$loaded || !$xmldb_file->isLoaded()) {
 135                          echo $OUTPUT->notification('Errors found in XMLDB file: '. $dbdir->path . '/install.xml');
 136                          continue;
 137                      }
 138                      // Arriving here, everything is ok, get the XMLDB structure
 139                      $structure = $xmldb_file->getStructure();
 140  
 141                      $o.='    <li>' . str_replace($CFG->dirroot . '/', '', $dbdir->path . '/install.xml');
 142                      // Getting tables
 143                      if ($xmldb_tables = $structure->getTables()) {
 144                          $o.='        <ul>';
 145                          // Foreach table, process its fields
 146                          foreach ($xmldb_tables as $xmldb_table) {
 147                              // Skip table if not exists
 148                              if (!$dbman->table_exists($xmldb_table)) {
 149                                  continue;
 150                              }
 151                              // Fetch metadata from physical DB. All the columns info.
 152                              if (!$metacolumns = $DB->get_columns($xmldb_table->getName(), false)) {
 153                                  // / Skip table if no metacolumns is available for it
 154                                  continue;
 155                              }
 156                              // Table processing starts here
 157                              $o.='            <li>' . $xmldb_table->getName();
 158                              // Do the specific check.
 159                              list($output, $newproblems) = $this->check_table($xmldb_table, $metacolumns);
 160                              $o.=$output;
 161                              $problemsfound = array_merge($problemsfound, $newproblems);
 162                              $o.='    </li>';
 163                              // Give the script some more time (resetting to current if exists)
 164                              if ($currenttl = @ini_get('max_execution_time')) {
 165                                  @ini_set('max_execution_time',$currenttl);
 166                              }
 167                          }
 168                          $o.='        </ul>';
 169                      }
 170                      $o.='    </li>';
 171                  }
 172                  $o.='</ul>';
 173              }
 174  
 175              // Create a report of the problems found.
 176              $r = $this->display_results($problemsfound);
 177  
 178              // Combine the various bits of output.
 179              $this->output = $b . $r . $o;
 180          }
 181  
 182          // Launch postaction if exists (leave this here!)
 183          if ($this->getPostAction() && $result) {
 184              return $this->launch($this->getPostAction());
 185          }
 186  
 187          // Return ok if arrived here
 188          return $result;
 189      }
 190  
 191      /**
 192       * Do the checks necessary on one particular table.
 193       *
 194       * @param xmldb_table $xmldb_table the table definition from the install.xml file.
 195       * @param array $metacolumns the column information read from the database.
 196       * @return array an array with two elements: First, some additional progress output,
 197       *      for example a list (<ul>) of the things check each with an one work ok/not ok summary.
 198       *      Second, an array giving the details of any problems found. These arrays
 199       *      for all tables will be aggregated, and then passed to
 200       */
 201      abstract protected function check_table(xmldb_table $xmldb_table, array $metacolumns);
 202  
 203      /**
 204       * Display a list of the problems found.
 205       *
 206       * @param array $problems_found an aggregation of all the problems found by
 207       *      all the check_table calls.
 208       * @return string a display of all the problems found as HTML.
 209       */
 210      abstract protected function display_results(array $problems_found);
 211  }