Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.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  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  defined('MOODLE_INTERNAL') || die();
  24  
  25  /**
  26   * This class will check all the default values existing in the DB
  27   * match those specified in the xml specs
  28   * and providing one SQL script to fix all them.
  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 check_defaults extends XMLDBCheckAction {
  35  
  36      /**
  37       * Init method, every subclass will have its own
  38       */
  39      public function init() {
  40          $this->introstr = 'confirmcheckdefaults';
  41          parent::init();
  42  
  43          // Set own core attributes.
  44  
  45          // Set own custom attributes.
  46  
  47          // Get needed strings.
  48          $this->loadStrings(array(
  49              'wrongdefaults' => 'tool_xmldb',
  50              'nowrongdefaultsfound' => 'tool_xmldb',
  51              'yeswrongdefaultsfound' => 'tool_xmldb',
  52              'expected' => 'tool_xmldb',
  53              'actual' => 'tool_xmldb',
  54          ));
  55      }
  56  
  57      protected function check_table(xmldb_table $xmldbtable, array $metacolumns) {
  58          $o = '';
  59          $wrongfields = array();
  60  
  61          // Get and process XMLDB fields.
  62          if ($xmldbfields = $xmldbtable->getFields()) {
  63              $o .= '        <ul>';
  64              foreach ($xmldbfields as $xmldbfield) {
  65  
  66                  // Get the default value for the field.
  67                  $xmldbdefault = $xmldbfield->getDefault();
  68  
  69                  // Char fields with not null currently have default '' when actually installed.
  70                  if ($xmldbdefault === null && $xmldbfield->getType() === XMLDB_TYPE_CHAR &&
  71                          $xmldbfield->getNotNull()) {
  72                      $xmldbdefault = '';
  73                  }
  74                  if ($xmldbdefault !== null) {
  75                      $xmldbdefault = (string)$xmldbdefault;
  76                  }
  77  
  78                  // If the metadata for that column doesn't exist or 'id' field found, skip.
  79                  if (!isset($metacolumns[$xmldbfield->getName()]) or $xmldbfield->getName() == 'id') {
  80                      continue;
  81                  }
  82  
  83                  // To variable for better handling.
  84                  $metacolumn = $metacolumns[$xmldbfield->getName()];
  85  
  86                  // Going to check this field in DB.
  87                  $o .= '            <li>' . $this->str['field'] . ': ' . $xmldbfield->getName() . ' ';
  88  
  89                  // Get the value of the physical default (or blank if there isn't one).
  90                  if ($metacolumn->has_default == 1) {
  91                      $physicaldefault = $metacolumn->default_value;
  92                  } else {
  93                      $physicaldefault = null;
  94                  }
  95  
  96                  // For number fields there are issues with type differences, so let's convert
  97                  // everything to a float.
  98                  if ($xmldbfield->getType() === XMLDB_TYPE_NUMBER) {
  99                      if ($physicaldefault !== null) {
 100                          $physicaldefault = (float) $physicaldefault;
 101                      }
 102                      if ($xmldbdefault !== null) {
 103                          $xmldbdefault = (float) $xmldbdefault;
 104                      }
 105                  }
 106  
 107                  // There *is* a default and it's wrong.
 108                  if ($physicaldefault !== $xmldbdefault) {
 109                      $xmldbtext = self::display_default($xmldbdefault);
 110                      $physicaltext = self::display_default($physicaldefault);
 111                      $info = "({$this->str['expected']} {$xmldbtext}, {$this->str['actual']} {$physicaltext})";
 112                      $o .= '<font color="red">' . $this->str['wrong'] . " $info</font>";
 113                      // Add the wrong field to the list.
 114                      $obj = new stdClass();
 115                      $obj->table = $xmldbtable;
 116                      $obj->field = $xmldbfield;
 117                      $obj->physicaldefault = $physicaldefault;
 118                      $obj->xmldbdefault = $xmldbdefault;
 119                      $wrongfields[] = $obj;
 120                  } else {
 121                      $o .= '<font color="green">' . $this->str['ok'] . '</font>';
 122                  }
 123                  $o .= '</li>';
 124              }
 125              $o .= '        </ul>';
 126          }
 127  
 128          return array($o, $wrongfields);
 129      }
 130  
 131      /**
 132       * Converts a default value suitable for display.
 133       *
 134       * @param string|null $defaultvalue Default value
 135       * @return string Displayed version
 136       */
 137      protected static function display_default($defaultvalue) {
 138          if ($defaultvalue === null) {
 139              return '-';
 140          } else {
 141              return "'" . s($defaultvalue) . "'";
 142          }
 143      }
 144  
 145      protected function display_results(array $wrongfields) {
 146          global $DB;
 147          $dbman = $DB->get_manager();
 148  
 149          $s = '';
 150          $r = '<table class="generaltable boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
 151          $r .= '  <tr><td class="generalboxcontent">';
 152          $r .= '    <h2 class="main">' . $this->str['searchresults'] . '</h2>';
 153          $r .= '    <p class="centerpara">' . $this->str['wrongdefaults'] . ': ' . count($wrongfields) . '</p>';
 154          $r .= '  </td></tr>';
 155          $r .= '  <tr><td class="generalboxcontent">';
 156  
 157          // If we have found wrong defaults inform about them.
 158          if (count($wrongfields)) {
 159              $r .= '    <p class="centerpara">' . $this->str['yeswrongdefaultsfound'] . '</p>';
 160              $r .= '        <ul>';
 161              foreach ($wrongfields as $obj) {
 162                  $xmldbtable = $obj->table;
 163                  $xmldbfield = $obj->field;
 164                  $physicaltext = self::display_default($obj->physicaldefault);
 165                  $xmldbtext = self::display_default($obj->xmldbdefault);
 166  
 167                  // Get the alter table command.
 168                  $sqlarr = $dbman->generator->getAlterFieldSQL($xmldbtable, $xmldbfield);
 169  
 170                  $r .= '            <li>' . $this->str['table'] . ': ' . $xmldbtable->getName() . '. ' .
 171                          $this->str['field'] . ': ' . $xmldbfield->getName() . ', ' .
 172                          $this->str['expected'] . ' ' . $xmldbtext . ' ' .
 173                          $this->str['actual'] . ' ' . $physicaltext . '</li>';
 174                  // Add to output if we have sentences.
 175                  if ($sqlarr) {
 176                      $sqlarr = $dbman->generator->getEndedStatements($sqlarr);
 177                      $s .= '<code>' . str_replace("\n", '<br />', implode('<br />', $sqlarr)) . '</code><br />';
 178                  }
 179              }
 180              $r .= '        </ul>';
 181              // Add the SQL statements (all together).
 182              $r .= '<hr />' . $s;
 183          } else {
 184              $r .= '    <p class="centerpara">' . $this->str['nowrongdefaultsfound'] . '</p>';
 185          }
 186          $r .= '  </td></tr>';
 187          $r .= '  <tr><td class="generalboxcontent">';
 188          // Add the complete log message.
 189          $r .= '    <p class="centerpara">' . $this->str['completelogbelow'] . '</p>';
 190          $r .= '  </td></tr>';
 191          $r .= '</table>';
 192  
 193          return $r;
 194      }
 195  }