Moodle PHP Cross Reference Learning Management Systems

Source: /lib/environmentlib.php - 1429 lines - 48938 bytes - Summary - Text - Print

Description: This library includes all the necessary stuff to execute some standard tests of required versions and libraries to run Moodle. It can be used from the admin interface, and both at install and upgrade. All the info is stored in the admin/environment.xml file, supporting to have an updated version in dataroot/environment

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * This library includes all the necessary stuff to execute some standard
  20   * tests of required versions and libraries to run Moodle. It can be
  21   * used from the admin interface, and both at install and upgrade.
  22   *
  23   * All the info is stored in the admin/environment.xml file,
  24   * supporting to have an updated version in dataroot/environment
  25   *
  26   * @copyright  (C) 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com}
  27   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28   * @package    core
  29   * @subpackage admin
  30   */
  31  
  32  defined('MOODLE_INTERNAL') || die();
  33  
  34  /// Add required files
  35  /**
  36   * Include the necessary
  37   */
  38      require_once($CFG->libdir.'/xmlize.php');
  39  
  40  /// Define a bunch of XML processing errors
  41      /** XML Processing Error */
  42      define('NO_ERROR',                           0);
  43      /** XML Processing Error */
  44      define('NO_VERSION_DATA_FOUND',              1);
  45      /** XML Processing Error */
  46      define('NO_DATABASE_SECTION_FOUND',          2);
  47      /** XML Processing Error */
  48      define('NO_DATABASE_VENDORS_FOUND',          3);
  49      /** XML Processing Error */
  50      define('NO_DATABASE_VENDOR_MYSQL_FOUND',     4);
  51      /** XML Processing Error */
  52      define('NO_DATABASE_VENDOR_POSTGRES_FOUND',  5);
  53      /** XML Processing Error */
  54      define('NO_PHP_SECTION_FOUND',               6);
  55      /** XML Processing Error */
  56      define('NO_PHP_VERSION_FOUND',               7);
  57      /** XML Processing Error */
  58      define('NO_PHP_EXTENSIONS_SECTION_FOUND',    8);
  59      /** XML Processing Error */
  60      define('NO_PHP_EXTENSIONS_NAME_FOUND',       9);
  61      /** XML Processing Error */
  62      define('NO_DATABASE_VENDOR_VERSION_FOUND',  10);
  63      /** XML Processing Error */
  64      define('NO_UNICODE_SECTION_FOUND',          11);
  65      /** XML Processing Error */
  66      define('NO_CUSTOM_CHECK_FOUND',             12);
  67      /** XML Processing Error */
  68      define('CUSTOM_CHECK_FILE_MISSING',         13);
  69      /** XML Processing Error */
  70      define('CUSTOM_CHECK_FUNCTION_MISSING',     14);
  71      /** XML Processing Error */
  72      define('NO_PHP_SETTINGS_NAME_FOUND',        15);
  73      /** XML Processing Error */
  74      define('INCORRECT_FEEDBACK_FOR_REQUIRED',   16);
  75      /** XML Processing Error */
  76      define('INCORRECT_FEEDBACK_FOR_OPTIONAL',   17);
  77  
  78  /// Define algorithm used to select the xml file
  79      /** To select the newer file available to perform checks */
  80      define('ENV_SELECT_NEWER',                   0);
  81      /** To enforce the use of the file under dataroot */
  82      define('ENV_SELECT_DATAROOT',                1);
  83      /** To enforce the use of the file under admin (release) */
  84      define('ENV_SELECT_RELEASE',                 2);
  85  
  86  /**
  87   * This function checks all the requirements defined in environment.xml.
  88   *
  89   * @staticvar bool $result
  90   * @staticvar array $env_results
  91   * @staticvar bool $cache_exists
  92   *
  93   * @param string $version version to check.
  94   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. Default ENV_SELECT_NEWER (BC)
  95   * @return array with two elements. The first element true/false, depending on
  96   *      on whether the check passed. The second element is an array of environment_results
  97   *      objects that has detailed information about the checks and which ones passed.
  98   */
  99  function check_moodle_environment($version, $env_select = ENV_SELECT_NEWER) {
 100  
 101      $status = true;
 102  
 103  /// This are cached per request
 104      static $result = true;
 105      static $env_results;
 106      static $cache_exists = false;
 107  
 108  /// if we have results cached, use them
 109      if ($cache_exists) {
 110          $environment_results = $env_results;
 111  /// No cache exists, calculate everything
 112      } else {
 113      /// Get the more recent version before the requested
 114          if (!$version = get_latest_version_available($version, $env_select)) {
 115              $status = false;
 116          }
 117  
 118      /// Perform all the checks
 119          if (!($environment_results = environment_check($version, $env_select)) && $status) {
 120              $status = false;
 121          }
 122  
 123      /// Iterate over all the results looking for some error in required items
 124      /// or some error_code
 125          if ($status) {
 126              foreach ($environment_results as $environment_result) {
 127                  if (!$environment_result->getStatus() && $environment_result->getLevel() == 'required'
 128                    && !$environment_result->getBypassStr()) {
 129                      $result = false; // required item that is not bypased
 130                  } else if ($environment_result->getStatus() && $environment_result->getLevel() == 'required'
 131                    && $environment_result->getRestrictStr()) {
 132                      $result = false; // required item that is restricted
 133                  } else if ($environment_result->getErrorCode()) {
 134                      $result = false;
 135                  }
 136              }
 137          }
 138      /// Going to end, we store environment_results to cache
 139          $env_results = $environment_results;
 140          $cache_exists = true;
 141      } ///End of cache block
 142  
 143      return array($result && $status, $environment_results);
 144  }
 145  
 146  
 147  /**
 148   * Returns array of critical errors in plain text format
 149   * @param array $environment_results array of results gathered
 150   * @return array errors
 151   */
 152  function environment_get_errors($environment_results) {
 153      global $CFG;
 154      $errors = array();
 155  
 156      // Iterate over each environment_result
 157      foreach ($environment_results as $environment_result) {
 158          $type = $environment_result->getPart();
 159          $info = $environment_result->getInfo();
 160          $status = $environment_result->getStatus();
 161          $error_code = $environment_result->getErrorCode();
 162  
 163          $a = new stdClass();
 164          if ($error_code) {
 165              $a->error_code = $error_code;
 166              $errors[] = array($info, get_string('environmentxmlerror', 'admin', $a));
 167              return $errors;
 168          }
 169  
 170          /// Calculate the status value
 171          if ($environment_result->getBypassStr() != '') {
 172              // not interesting
 173              continue;
 174          } else if ($environment_result->getRestrictStr() != '') {
 175              // error
 176          } else {
 177              if ($status) {
 178                  // ok
 179                  continue;
 180              } else {
 181                  if ($environment_result->getLevel() == 'optional') {
 182                      // just a warning
 183                      continue;
 184                  } else {
 185                      // error
 186                  }
 187              }
 188          }
 189  
 190          // We are comparing versions
 191          $rec = new stdClass();
 192          if ($rec->needed = $environment_result->getNeededVersion()) {
 193              $rec->current = $environment_result->getCurrentVersion();
 194              if ($environment_result->getLevel() == 'required') {
 195                  $stringtouse = 'environmentrequireversion';
 196              } else {
 197                  $stringtouse = 'environmentrecommendversion';
 198              }
 199          // We are checking installed & enabled things
 200          } else if ($environment_result->getPart() == 'custom_check') {
 201              if ($environment_result->getLevel() == 'required') {
 202                  $stringtouse = 'environmentrequirecustomcheck';
 203              } else {
 204                  $stringtouse = 'environmentrecommendcustomcheck';
 205              }
 206          } else if ($environment_result->getPart() == 'php_setting') {
 207              if ($status) {
 208                  $stringtouse = 'environmentsettingok';
 209              } else if ($environment_result->getLevel() == 'required') {
 210                  $stringtouse = 'environmentmustfixsetting';
 211              } else {
 212                  $stringtouse = 'environmentshouldfixsetting';
 213              }
 214          } else {
 215              if ($environment_result->getLevel() == 'required') {
 216                  $stringtouse = 'environmentrequireinstall';
 217              } else {
 218                  $stringtouse = 'environmentrecommendinstall';
 219              }
 220          }
 221          $report = get_string($stringtouse, 'admin', $rec);
 222  
 223          // Here we'll store all the feedback found
 224          $feedbacktext = '';
 225          // Append  the feedback if there is some
 226          $feedbacktext .= $environment_result->strToReport($environment_result->getFeedbackStr(), 'error');
 227          // Append the restrict if there is some
 228          $feedbacktext .= $environment_result->strToReport($environment_result->getRestrictStr(), 'error');
 229  
 230          $report .= html_to_text($feedbacktext);
 231  
 232          if ($environment_result->getPart() == 'custom_check'){
 233              $errors[] = array($info, $report);
 234          } else {
 235              $errors[] = array(($info !== '' ? "$type $info" : $type), $report);
 236          }
 237      }
 238  
 239      return $errors;
 240  }
 241  
 242  
 243  /**
 244   * This function will normalize any version to just a serie of numbers
 245   * separated by dots. Everything else will be removed.
 246   *
 247   * @param string $version the original version
 248   * @return string the normalized version
 249   */
 250  function normalize_version($version) {
 251  
 252  /// 1.9 Beta 2 should be read 1.9 on enviromental checks, not 1.9.2
 253  /// we can discard everything after the first space
 254      $version = trim($version);
 255      $versionarr = explode(" ",$version);
 256      if (!empty($versionarr)) {
 257          $version = $versionarr[0];
 258      }
 259  /// Replace everything but numbers and dots by dots
 260      $version = preg_replace('/[^\.\d]/', '.', $version);
 261  /// Combine multiple dots in one
 262      $version = preg_replace('/(\.{2,})/', '.', $version);
 263  /// Trim possible leading and trailing dots
 264      $version = trim($version, '.');
 265  
 266      return $version;
 267  }
 268  
 269  
 270  /**
 271   * This function will load the environment.xml file and xmlize it
 272   *
 273   * @global object
 274   * @staticvar mixed $data
 275   * @uses ENV_SELECT_NEWER
 276   * @uses ENV_SELECT_DATAROOT
 277   * @uses ENV_SELECT_RELEASE
 278   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. Default ENV_SELECT_NEWER (BC)
 279   * @return mixed the xmlized structure or false on error
 280   */
 281  function load_environment_xml($env_select=ENV_SELECT_NEWER) {
 282  
 283      global $CFG;
 284  
 285      static $data; //Only load and xmlize once by request
 286  
 287      if (!empty($data)) {
 288          return $data;
 289      }
 290  
 291  /// First of all, take a look inside $CFG->dataroot/environment/environment.xml
 292      $file = $CFG->dataroot.'/environment/environment.xml';
 293      $internalfile = $CFG->dirroot.'/'.$CFG->admin.'/environment.xml';
 294      switch ($env_select) {
 295          case ENV_SELECT_NEWER:
 296              if (!is_file($file) || !is_readable($file) || filemtime($file) < filemtime($internalfile) ||
 297                  !$contents = file_get_contents($file)) {
 298              /// Fallback to fixed $CFG->admin/environment.xml
 299                  if (!is_file($internalfile) || !is_readable($internalfile) || !$contents = file_get_contents($internalfile)) {
 300                      return false;
 301                  }
 302              }
 303              break;
 304          case ENV_SELECT_DATAROOT:
 305              if (!is_file($file) || !is_readable($file) || !$contents = file_get_contents($file)) {
 306                  return false;
 307              }
 308              break;
 309          case ENV_SELECT_RELEASE:
 310              if (!is_file($internalfile) || !is_readable($internalfile) || !$contents = file_get_contents($internalfile)) {
 311                  return false;
 312              }
 313              break;
 314      }
 315  /// XML the whole file
 316      $data = xmlize($contents);
 317  
 318      return $data;
 319  }
 320  
 321  
 322  /**
 323   * This function will return the list of Moodle versions available
 324   *
 325   * @staticvar array $versions
 326   * @return mixed array of versions. False on error.
 327   */
 328  function get_list_of_environment_versions ($contents) {
 329  
 330      static $versions = array();
 331  
 332      if (!empty($versions)) {
 333          return $versions;
 334      }
 335  
 336      if (isset($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'])) {
 337          foreach ($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'] as $version) {
 338              $versions[] = $version['@']['version'];
 339          }
 340      }
 341  
 342      return $versions;
 343  }
 344  
 345  
 346  /**
 347   * This function will return the most recent version in the environment.xml
 348   * file previous or equal to the version requested
 349   *
 350   * @param string $version top version from which we start to look backwards
 351   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 352   * @return string|bool string more recent version or false if not found
 353   */
 354  function get_latest_version_available ($version, $env_select) {
 355  
 356  /// Normalize the version requested
 357      $version = normalize_version($version);
 358  
 359  /// Load xml file
 360      if (!$contents = load_environment_xml($env_select)) {
 361          return false;
 362      }
 363  
 364  /// Detect available versions
 365      if (!$versions = get_list_of_environment_versions($contents)) {
 366          return false;
 367      }
 368  /// First we look for exact version
 369      if (in_array($version, $versions)) {
 370          return $version;
 371      } else {
 372          $found_version = false;
 373      /// Not exact match, so we are going to iterate over the list searching
 374      /// for the latest version before the requested one
 375          foreach ($versions as $arrversion) {
 376              if (version_compare($arrversion, $version, '<')) {
 377                  $found_version = $arrversion;
 378              }
 379          }
 380      }
 381  
 382      return $found_version;
 383  }
 384  
 385  
 386  /**
 387   * This function will return the xmlized data belonging to one Moodle version
 388   *
 389   * @param string $version top version from which we start to look backwards
 390   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 391   * @return mixed the xmlized structure or false on error
 392   */
 393  function get_environment_for_version($version, $env_select) {
 394  
 395  /// Normalize the version requested
 396      $version = normalize_version($version);
 397  
 398  /// Load xml file
 399      if (!$contents = load_environment_xml($env_select)) {
 400          return false;
 401      }
 402  
 403  /// Detect available versions
 404      if (!$versions = get_list_of_environment_versions($contents)) {
 405          return false;
 406      }
 407  
 408  /// If the version requested is available
 409      if (!in_array($version, $versions)) {
 410          return false;
 411      }
 412  
 413  /// We now we have it. Extract from full contents.
 414      $fl_arr = array_flip($versions);
 415  
 416      return $contents['COMPATIBILITY_MATRIX']['#']['MOODLE'][$fl_arr[$version]];
 417  }
 418  
 419  
 420  /**
 421   * This function will check for everything (DB, PHP and PHP extensions for now)
 422   * returning an array of environment_result objects.
 423   *
 424   * @global object
 425   * @param string $version xml version we are going to use to test this server
 426   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 427   * @return array array of results encapsulated in one environment_result object
 428   */
 429  function environment_check($version, $env_select) {
 430      global $CFG;
 431  
 432  /// Normalize the version requested
 433      $version = normalize_version($version);
 434  
 435      $results = array(); //To store all the results
 436  
 437  /// Only run the moodle versions checker on upgrade, not on install
 438      if (!empty($CFG->version)) {
 439          $results[] = environment_check_moodle($version, $env_select);
 440      }
 441      $results[] = environment_check_unicode($version, $env_select);
 442      $results[] = environment_check_database($version, $env_select);
 443      $results[] = environment_check_php($version, $env_select);
 444  
 445      if ($result = environment_check_pcre_unicode($version, $env_select)) {
 446          $results[] = $result;
 447      }
 448  
 449      $phpext_results = environment_check_php_extensions($version, $env_select);
 450      $results = array_merge($results, $phpext_results);
 451  
 452      $phpsetting_results = environment_check_php_settings($version, $env_select);
 453      $results = array_merge($results, $phpsetting_results);
 454  
 455      $custom_results = environment_custom_checks($version, $env_select);
 456      $results = array_merge($results, $custom_results);
 457  
 458      return $results;
 459  }
 460  
 461  
 462  /**
 463   * This function will check if php extensions requirements are satisfied
 464   *
 465   * @uses NO_VERSION_DATA_FOUND
 466   * @uses NO_PHP_EXTENSIONS_SECTION_FOUND
 467   * @uses NO_PHP_EXTENSIONS_NAME_FOUND
 468   * @param string $version xml version we are going to use to test this server
 469   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 470   * @return array array of results encapsulated in one environment_result object
 471   */
 472  function environment_check_php_extensions($version, $env_select) {
 473  
 474      $results = array();
 475  
 476  /// Get the enviroment version we need
 477      if (!$data = get_environment_for_version($version, $env_select)) {
 478      /// Error. No version data found
 479          $result = new environment_results('php_extension');
 480          $result->setStatus(false);
 481          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 482          return array($result);
 483      }
 484  
 485  /// Extract the php_extension part
 486      if (!isset($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'])) {
 487      /// Error. No PHP section found
 488          $result = new environment_results('php_extension');
 489          $result->setStatus(false);
 490          $result->setErrorCode(NO_PHP_EXTENSIONS_SECTION_FOUND);
 491          return array($result);
 492      }
 493  /// Iterate over extensions checking them and creating the needed environment_results
 494      foreach($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'] as $extension) {
 495          $result = new environment_results('php_extension');
 496      /// Check for level
 497          $level = get_level($extension);
 498      /// Check for extension name
 499          if (!isset($extension['@']['name'])) {
 500              $result->setStatus(false);
 501              $result->setErrorCode(NO_PHP_EXTENSIONS_NAME_FOUND);
 502          } else {
 503              $extension_name = $extension['@']['name'];
 504          /// The name exists. Just check if it's an installed extension
 505              if (!extension_loaded($extension_name)) {
 506                  $result->setStatus(false);
 507              } else {
 508                  $result->setStatus(true);
 509              }
 510              $result->setLevel($level);
 511              $result->setInfo($extension_name);
 512          }
 513  
 514      /// Do any actions defined in the XML file.
 515          process_environment_result($extension, $result);
 516  
 517      /// Add the result to the array of results
 518          $results[] = $result;
 519      }
 520  
 521  
 522      return $results;
 523  }
 524  
 525  /**
 526   * This function will check if php extensions requirements are satisfied
 527   *
 528   * @uses NO_VERSION_DATA_FOUND
 529   * @uses NO_PHP_SETTINGS_NAME_FOUND
 530   * @param string $version xml version we are going to use to test this server
 531   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 532   * @return array array of results encapsulated in one environment_result object
 533   */
 534  function environment_check_php_settings($version, $env_select) {
 535  
 536      $results = array();
 537  
 538  /// Get the enviroment version we need
 539      if (!$data = get_environment_for_version($version, $env_select)) {
 540      /// Error. No version data found
 541          $result = new environment_results('php_setting');
 542          $result->setStatus(false);
 543          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 544          $results[] = $result;
 545          return $results;
 546      }
 547  
 548  /// Extract the php_setting part
 549      if (!isset($data['#']['PHP_SETTINGS']['0']['#']['PHP_SETTING'])) {
 550      /// No PHP section found - ignore
 551          return $results;
 552      }
 553  /// Iterate over settings checking them and creating the needed environment_results
 554      foreach($data['#']['PHP_SETTINGS']['0']['#']['PHP_SETTING'] as $setting) {
 555          $result = new environment_results('php_setting');
 556      /// Check for level
 557          $level = get_level($setting);
 558          $result->setLevel($level);
 559      /// Check for extension name
 560          if (!isset($setting['@']['name'])) {
 561              $result->setStatus(false);
 562              $result->setErrorCode(NO_PHP_SETTINGS_NAME_FOUND);
 563          } else {
 564              $setting_name  = $setting['@']['name'];
 565              $setting_value = $setting['@']['value'];
 566              $result->setInfo($setting_name);
 567  
 568              if ($setting_name == 'memory_limit') {
 569                  $current = ini_get('memory_limit');
 570                  if ($current == -1) {
 571                      $result->setStatus(true);
 572                  } else {
 573                      $current  = get_real_size($current);
 574                      $minlimit = get_real_size($setting_value);
 575                      if ($current < $minlimit) {
 576                          @ini_set('memory_limit', $setting_value);
 577                          $current = ini_get('memory_limit');
 578                          $current = get_real_size($current);
 579                      }
 580                      $result->setStatus($current >= $minlimit);
 581                  }
 582  
 583              } else {
 584                  $current = ini_get_bool($setting_name);
 585              /// The name exists. Just check if it's an installed extension
 586                  if ($current == $setting_value) {
 587                      $result->setStatus(true);
 588                  } else {
 589                      $result->setStatus(false);
 590                  }
 591              }
 592          }
 593  
 594      /// Do any actions defined in the XML file.
 595          process_environment_result($setting, $result);
 596  
 597      /// Add the result to the array of results
 598          $results[] = $result;
 599      }
 600  
 601  
 602      return $results;
 603  }
 604  
 605  /**
 606   * This function will do the custom checks.
 607   *
 608   * @global object
 609   * @uses CUSTOM_CHECK_FUNCTION_MISSING
 610   * @uses CUSTOM_CHECK_FILE_MISSING
 611   * @uses NO_CUSTOM_CHECK_FOUND
 612   * @param string $version xml version we are going to use to test this server.
 613   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 614   * @return array array of results encapsulated in environment_result objects.
 615   */
 616  function environment_custom_checks($version, $env_select) {
 617      global $CFG;
 618  
 619      $results = array();
 620  
 621  /// Get current Moodle version (release) for later compare
 622      $release = isset($CFG->release) ? $CFG->release : $version; /// In case $CFG fails (at install) use $version
 623      $current_version = normalize_version($release);
 624  
 625  /// Get the enviroment version we need
 626      if (!$data = get_environment_for_version($version, $env_select)) {
 627      /// Error. No version data found - but this will already have been reported.
 628          return $results;
 629      }
 630  
 631  /// Extract the CUSTOM_CHECKS part
 632      if (!isset($data['#']['CUSTOM_CHECKS']['0']['#']['CUSTOM_CHECK'])) {
 633      /// No custom checks found - not a problem
 634          return $results;
 635      }
 636  
 637  /// Iterate over extensions checking them and creating the needed environment_results
 638      foreach($data['#']['CUSTOM_CHECKS']['0']['#']['CUSTOM_CHECK'] as $check) {
 639          $result = new environment_results('custom_check');
 640  
 641      /// Check for level
 642          $level = get_level($check);
 643  
 644      /// Check for extension name
 645          if (isset($check['@']['file']) && isset($check['@']['function'])) {
 646              $file = $CFG->dirroot . '/' . $check['@']['file'];
 647              $function = $check['@']['function'];
 648              if (is_readable($file)) {
 649                  include_once($file);
 650                  if (function_exists($function)) {
 651                      $result->setLevel($level);
 652                      $result->setInfo($function);
 653                      $result = $function($result);
 654                  } else {
 655                  /// Only show error for current version (where function MUST exist)
 656                  /// else, we are performing custom checks against future versiosn
 657                  /// and function MAY not exist, so it doesn't cause error, just skip
 658                  /// custom check by returning null. MDL-15939
 659                      if (version_compare($current_version, $version, '>=')) {
 660                          $result->setStatus(false);
 661                          $result->setInfo($function);
 662                          $result->setErrorCode(CUSTOM_CHECK_FUNCTION_MISSING);
 663                      } else {
 664                          $result = null;
 665                      }
 666                  }
 667              } else {
 668              /// Only show error for current version (where function MUST exist)
 669              /// else, we are performing custom checks against future versiosn
 670              /// and function MAY not exist, so it doesn't cause error, just skip
 671              /// custom check by returning null. MDL-15939
 672                  if (version_compare($current_version, $version, '>=')) {
 673                      $result->setStatus(false);
 674                      $result->setInfo($function);
 675                      $result->setErrorCode(CUSTOM_CHECK_FILE_MISSING);
 676                  } else {
 677                      $result = null;
 678                  }
 679              }
 680          } else {
 681              $result->setStatus(false);
 682              $result->setErrorCode(NO_CUSTOM_CHECK_FOUND);
 683          }
 684  
 685          if (!is_null($result)) {
 686          /// Do any actions defined in the XML file.
 687              process_environment_result($check, $result);
 688  
 689          /// Add the result to the array of results
 690              $results[] = $result;
 691          }
 692      }
 693  
 694      return $results;
 695  }
 696  
 697  /**
 698   * This function will check if Moodle requirements are satisfied
 699   *
 700   * @uses NO_VERSION_DATA_FOUND
 701   * @param string $version xml version we are going to use to test this server
 702   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 703   * @return object results encapsulated in one environment_result object
 704   */
 705  function environment_check_moodle($version, $env_select) {
 706  
 707      $result = new environment_results('moodle');
 708  
 709  /// Get the enviroment version we need
 710      if (!$data = get_environment_for_version($version, $env_select)) {
 711      /// Error. No version data found
 712          $result->setStatus(false);
 713          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 714          return $result;
 715      }
 716  
 717  /// Extract the moodle part
 718      if (!isset($data['@']['requires'])) {
 719          $needed_version = '1.0'; /// Default to 1.0 if no moodle requires is found
 720      } else {
 721      /// Extract required moodle version
 722          $needed_version = $data['@']['requires'];
 723      }
 724  
 725  /// Now search the version we are using
 726      $release = get_config('', 'release');
 727      $current_version = normalize_version($release);
 728      if (strpos($release, 'dev') !== false) {
 729          // when final version is required, dev is NOT enough!
 730          $current_version = $current_version - 0.1;
 731      }
 732  
 733  /// And finally compare them, saving results
 734      if (version_compare($current_version, $needed_version, '>=')) {
 735          $result->setStatus(true);
 736      } else {
 737          $result->setStatus(false);
 738      }
 739      $result->setLevel('required');
 740      $result->setCurrentVersion($release);
 741      $result->setNeededVersion($needed_version);
 742  
 743      return $result;
 744  }
 745  
 746  /**
 747   * This function will check if php requirements are satisfied
 748   *
 749   * @uses NO_VERSION_DATA_FOUND
 750   * @uses NO_PHP_SECTION_FOUND
 751   * @uses NO_PHP_VERSION_FOUND
 752   * @param string $version xml version we are going to use to test this server
 753   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 754   * @return object results encapsulated in one environment_result object
 755   */
 756  function environment_check_php($version, $env_select) {
 757  
 758      $result = new environment_results('php');
 759  
 760  /// Get the enviroment version we need
 761      if (!$data = get_environment_for_version($version, $env_select)) {
 762      /// Error. No version data found
 763          $result->setStatus(false);
 764          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 765          return $result;
 766      }
 767  
 768  /// Extract the php part
 769      if (!isset($data['#']['PHP'])) {
 770      /// Error. No PHP section found
 771          $result->setStatus(false);
 772          $result->setErrorCode(NO_PHP_SECTION_FOUND);
 773          return $result;
 774      } else {
 775      /// Extract level and version
 776          $level = get_level($data['#']['PHP']['0']);
 777          if (!isset($data['#']['PHP']['0']['@']['version'])) {
 778              $result->setStatus(false);
 779              $result->setErrorCode(NO_PHP_VERSION_FOUND);
 780              return $result;
 781          } else {
 782              $needed_version = $data['#']['PHP']['0']['@']['version'];
 783          }
 784      }
 785  
 786  /// Now search the version we are using
 787      $current_version = normalize_version(phpversion());
 788  
 789  /// And finally compare them, saving results
 790      if (version_compare($current_version, $needed_version, '>=')) {
 791          $result->setStatus(true);
 792      } else {
 793          $result->setStatus(false);
 794      }
 795      $result->setLevel($level);
 796      $result->setCurrentVersion($current_version);
 797      $result->setNeededVersion($needed_version);
 798  
 799  /// Do any actions defined in the XML file.
 800      process_environment_result($data['#']['PHP'][0], $result);
 801  
 802      return $result;
 803  }
 804  
 805  /**
 806   * Looks for buggy PCRE implementation, we need unicode support in Moodle...
 807   * @param string $version xml version we are going to use to test this server
 808   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 809   * @return stdClass results encapsulated in one environment_result object, null if irrelevant
 810   */
 811  function environment_check_pcre_unicode($version, $env_select) {
 812      $result = new environment_results('pcreunicode');
 813  
 814      // Get the environment version we need
 815      if (!$data = get_environment_for_version($version, $env_select)) {
 816          // Error. No version data found!
 817          $result->setStatus(false);
 818          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 819          return $result;
 820      }
 821  
 822      if (!isset($data['#']['PCREUNICODE'])) {
 823          return null;
 824      }
 825  
 826      $level = get_level($data['#']['PCREUNICODE']['0']);
 827      $result->setLevel($level);
 828  
 829      if (!function_exists('preg_match')) {
 830          // The extension test fails instead.
 831          return null;
 832  
 833      } else if (@preg_match('/\pL/u', 'a') and @preg_match('/á/iu', 'Á')) {
 834          $result->setStatus(true);
 835  
 836      } else {
 837          $result->setStatus(false);
 838      }
 839  
 840      // Do any actions defined in the XML file.
 841      process_environment_result($data['#']['PCREUNICODE'][0], $result);
 842  
 843      return $result;
 844  }
 845  
 846  /**
 847   * This function will check if unicode database requirements are satisfied
 848   *
 849   * @global object
 850   * @uses NO_VERSION_DATA_FOUND
 851   * @uses NO_UNICODE_SECTION_FOUND
 852   * @param string $version xml version we are going to use to test this server
 853   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 854   * @return object results encapsulated in one environment_result object
 855   */
 856  function environment_check_unicode($version, $env_select) {
 857      global $DB;
 858  
 859      $result = new environment_results('unicode');
 860  
 861      /// Get the enviroment version we need
 862      if (!$data = get_environment_for_version($version, $env_select)) {
 863      /// Error. No version data found
 864          $result->setStatus(false);
 865          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 866          return $result;
 867      }
 868  
 869      /// Extract the unicode part
 870  
 871      if (!isset($data['#']['UNICODE'])) {
 872      /// Error. No UNICODE section found
 873          $result->setStatus(false);
 874          $result->setErrorCode(NO_UNICODE_SECTION_FOUND);
 875          return $result;
 876      } else {
 877      /// Extract level
 878          $level = get_level($data['#']['UNICODE']['0']);
 879      }
 880  
 881      if (!$unicodedb = $DB->setup_is_unicodedb()) {
 882          $result->setStatus(false);
 883      } else {
 884          $result->setStatus(true);
 885      }
 886  
 887      $result->setLevel($level);
 888  
 889  /// Do any actions defined in the XML file.
 890      process_environment_result($data['#']['UNICODE'][0], $result);
 891  
 892      return $result;
 893  }
 894  
 895  /**
 896   * This function will check if database requirements are satisfied
 897   *
 898   * @global object
 899   * @uses NO_VERSION_DATA_FOUND
 900   * @uses NO_DATABASE_SECTION_FOUND
 901   * @uses NO_DATABASE_VENDORS_FOUND
 902   * @uses NO_DATABASE_VENDOR_MYSQL_FOUND
 903   * @uses NO_DATABASE_VENDOR_POSTGRES_FOUND
 904   * @uses NO_DATABASE_VENDOR_VERSION_FOUND
 905   * @param string $version xml version we are going to use to test this server
 906   * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
 907   * @return object results encapsulated in one environment_result object
 908   */
 909  function environment_check_database($version, $env_select) {
 910  
 911      global $DB;
 912  
 913      $result = new environment_results('database');
 914  
 915      $vendors = array();  //Array of vendors in version
 916  
 917  /// Get the enviroment version we need
 918      if (!$data = get_environment_for_version($version, $env_select)) {
 919      /// Error. No version data found
 920          $result->setStatus(false);
 921          $result->setErrorCode(NO_VERSION_DATA_FOUND);
 922          return $result;
 923      }
 924  
 925  /// Extract the database part
 926      if (!isset($data['#']['DATABASE'])) {
 927      /// Error. No DATABASE section found
 928          $result->setStatus(false);
 929          $result->setErrorCode(NO_DATABASE_SECTION_FOUND);
 930          return $result;
 931      } else {
 932      /// Extract level
 933          $level = get_level($data['#']['DATABASE']['0']);
 934      }
 935  
 936  /// Extract DB vendors. At least 2 are mandatory (mysql & postgres)
 937      if (!isset($data['#']['DATABASE']['0']['#']['VENDOR'])) {
 938      /// Error. No VENDORS found
 939          $result->setStatus(false);
 940          $result->setErrorCode(NO_DATABASE_VENDORS_FOUND);
 941          return $result;
 942      } else {
 943      /// Extract vendors
 944          foreach ($data['#']['DATABASE']['0']['#']['VENDOR'] as $vendor) {
 945              if (isset($vendor['@']['name']) && isset($vendor['@']['version'])) {
 946                  $vendors[$vendor['@']['name']] = $vendor['@']['version'];
 947                  $vendorsxml[$vendor['@']['name']] = $vendor;
 948              }
 949          }
 950      }
 951  /// Check we have the mysql vendor version
 952      if (empty($vendors['mysql'])) {
 953          $result->setStatus(false);
 954          $result->setErrorCode(NO_DATABASE_VENDOR_MYSQL_FOUND);
 955          return $result;
 956      }
 957  /// Check we have the postgres vendor version
 958      if (empty($vendors['postgres'])) {
 959          $result->setStatus(false);
 960          $result->setErrorCode(NO_DATABASE_VENDOR_POSTGRES_FOUND);
 961          return $result;
 962      }
 963  
 964  /// Now search the version we are using (depending of vendor)
 965      $current_vendor = $DB->get_dbvendor();
 966  
 967      $dbinfo = $DB->get_server_info();
 968      $current_version = normalize_version($dbinfo['version']);
 969      $needed_version = $vendors[$current_vendor];
 970  
 971  /// Check we have a needed version
 972      if (!$needed_version) {
 973          $result->setStatus(false);
 974          $result->setErrorCode(NO_DATABASE_VENDOR_VERSION_FOUND);
 975          return $result;
 976      }
 977  
 978  /// And finally compare them, saving results
 979      if (version_compare($current_version, $needed_version, '>=')) {
 980          $result->setStatus(true);
 981      } else {
 982          $result->setStatus(false);
 983      }
 984      $result->setLevel($level);
 985      $result->setCurrentVersion($current_version);
 986      $result->setNeededVersion($needed_version);
 987      $result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')');
 988  
 989  /// Do any actions defined in the XML file.
 990      process_environment_result($vendorsxml[$current_vendor], $result);
 991  
 992      return $result;
 993  
 994  }
 995  
 996  /**
 997   * This function will post-process the result record by executing the specified
 998   * function, modifying it as necessary, also a custom message will be added
 999   * to the result object to be printed by the display layer.
1000   * Every bypass function must be defined in this file and it'll return
1001   * true/false to decide if the original test is bypassed or no. Also
1002   * such bypass functions are able to directly handling the result object
1003   * although it should be only under exceptional conditions.
1004   *
1005   * @param string xmldata containing the bypass data
1006   * @param object result object to be updated
1007   * @return void
1008   */
1009  function process_environment_bypass($xml, &$result) {
1010  
1011  /// Only try to bypass if we were in error and it was required
1012      if ($result->getStatus() || $result->getLevel() == 'optional') {
1013          return;
1014      }
1015  
1016  /// It there is bypass info (function and message)
1017      if (is_array($xml['#']) && isset($xml['#']['BYPASS'][0]['@']['function']) && isset($xml['#']['BYPASS'][0]['@']['message'])) {
1018          $function = $xml['#']['BYPASS'][0]['@']['function'];
1019          $message  = $xml['#']['BYPASS'][0]['@']['message'];
1020      /// Look for the function
1021          if (function_exists($function)) {
1022          /// Call it, and if bypass = true is returned, apply meesage
1023              if ($function($result)) {
1024              /// We only set the bypass message if the function itself hasn't defined it before
1025                  if (empty($result->getBypassStr)) {
1026                      $result->setBypassStr($message);
1027                  }
1028              }
1029          }
1030      }
1031  }
1032  
1033  /**
1034   * This function will post-process the result record by executing the specified
1035   * function, modifying it as necessary, also a custom message will be added
1036   * to the result object to be printed by the display layer.
1037   * Every restrict function must be defined in this file and it'll return
1038   * true/false to decide if the original test is restricted or no. Also
1039   * such restrict functions are able to directly handling the result object
1040   * although it should be only under exceptional conditions.
1041   *
1042   * @param string xmldata containing the restrict data
1043   * @param object result object to be updated
1044   * @return void
1045   */
1046  function process_environment_restrict($xml, &$result) {
1047  
1048  /// Only try to restrict if we were not in error and it was required
1049      if (!$result->getStatus() || $result->getLevel() == 'optional') {
1050          return;
1051      }
1052  /// It there is restrict info (function and message)
1053      if (is_array($xml['#']) && isset($xml['#']['RESTRICT'][0]['@']['function']) && isset($xml['#']['RESTRICT'][0]['@']['message'])) {
1054          $function = $xml['#']['RESTRICT'][0]['@']['function'];
1055          $message  = $xml['#']['RESTRICT'][0]['@']['message'];
1056      /// Look for the function
1057          if (function_exists($function)) {
1058          /// Call it, and if restrict = true is returned, apply meesage
1059              if ($function($result)) {
1060              /// We only set the restrict message if the function itself hasn't defined it before
1061                  if (empty($result->getRestrictStr)) {
1062                      $result->setRestrictStr($message);
1063                  }
1064              }
1065          }
1066      }
1067  }
1068  
1069  /**
1070   * This function will detect if there is some message available to be added to the
1071   * result in order to clarify enviromental details.
1072   *
1073   * @uses INCORRECT_FEEDBACK_FOR_REQUIRED
1074   * @uses INCORRECT_FEEDBACK_FOR_OPTIONAL
1075   * @param string xmldata containing the feedback data
1076   * @param object reult object to be updated
1077   */
1078  function process_environment_messages($xml, &$result) {
1079  
1080  /// If there is feedback info
1081      if (is_array($xml['#']) && isset($xml['#']['FEEDBACK'][0]['#'])) {
1082          $feedbackxml = $xml['#']['FEEDBACK'][0]['#'];
1083  
1084          // Detect some incorrect feedback combinations.
1085          if ($result->getLevel() == 'required' and isset($feedbackxml['ON_CHECK'])) {
1086              $result->setStatus(false);
1087              $result->setErrorCode(INCORRECT_FEEDBACK_FOR_REQUIRED);
1088          } else if ($result->getLevel() == 'optional' and isset($feedbackxml['ON_ERROR'])) {
1089              $result->setStatus(false);
1090              $result->setErrorCode(INCORRECT_FEEDBACK_FOR_OPTIONAL);
1091          }
1092  
1093          if (!$result->status and $result->getLevel() == 'required') {
1094              if (isset($feedbackxml['ON_ERROR'][0]['@']['message'])) {
1095                  $result->setFeedbackStr($feedbackxml['ON_ERROR'][0]['@']['message']);
1096              }
1097          } else if (!$result->status and $result->getLevel() == 'optional') {
1098              if (isset($feedbackxml['ON_CHECK'][0]['@']['message'])) {
1099                  $result->setFeedbackStr($feedbackxml['ON_CHECK'][0]['@']['message']);
1100              }
1101          } else {
1102              if (isset($feedbackxml['ON_OK'][0]['@']['message'])) {
1103                  $result->setFeedbackStr($feedbackxml['ON_OK'][0]['@']['message']);
1104              }
1105          }
1106      }
1107  }
1108  
1109  
1110  //--- Helper Class to return results to caller ---//
1111  
1112  
1113  /**
1114   * Helper Class to return results to caller
1115   *
1116   * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
1117   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1118   * @package moodlecore
1119   */
1120  class environment_results {
1121      /**
1122       * @var string Which are we checking (database, php, php_extension, php_extension)
1123       */
1124      var $part;
1125      /**
1126       * @var bool true means the test passed and all is OK. false means it failed.
1127       */
1128      var $status;
1129      /**
1130       * @var integer See constants at the beginning of the file
1131       */
1132      var $error_code;
1133      /**
1134       * @var string required/optional
1135       */
1136      var $level;
1137      /**
1138       * @var string current version detected
1139       */
1140      var $current_version;
1141      /**
1142       * @var string version needed
1143       */
1144      var $needed_version;
1145      /**
1146       * @var string Aux. info (DB vendor, library...)
1147       */
1148      var $info;
1149      /**
1150       * @var string String to show on error|on check|on ok
1151       */
1152      var $feedback_str;
1153      /**
1154       * @var string String to show if some bypass has happened
1155       */
1156      var $bypass_str;
1157      /**
1158       * @var string String to show if some restrict has happened
1159       */
1160      var $restrict_str;
1161  
1162      /**
1163       * Constructor of the environment_result class. Just set default values
1164       *
1165       * @param string $part
1166       */
1167      function environment_results($part) {
1168          $this->part=$part;
1169          $this->status=false;
1170          $this->error_code=NO_ERROR;
1171          $this->level='required';
1172          $this->current_version='';
1173          $this->needed_version='';
1174          $this->info='';
1175          $this->feedback_str='';
1176          $this->bypass_str='';
1177          $this->restrict_str='';
1178      }
1179  
1180      /**
1181       * Set the status
1182       *
1183       * @param bool $testpassed true means the test passed and all is OK. false means it failed.
1184       */
1185      function setStatus($testpassed) {
1186          $this->status = $testpassed;
1187          if ($testpassed) {
1188              $this->setErrorCode(NO_ERROR);
1189          }
1190      }
1191  
1192      /**
1193       * Set the error_code
1194       *
1195       * @param integer $error_code the error code (see constants above)
1196       */
1197      function setErrorCode($error_code) {
1198          $this->error_code=$error_code;
1199      }
1200  
1201      /**
1202       * Set the level
1203       *
1204       * @param string $level the level (required, optional)
1205       */
1206      function setLevel($level) {
1207          $this->level=$level;
1208      }
1209  
1210      /**
1211       * Set the current version
1212       *
1213       * @param string $current_version the current version
1214       */
1215      function setCurrentVersion($current_version) {
1216          $this->current_version=$current_version;
1217      }
1218  
1219      /**
1220       * Set the needed version
1221       *
1222       * @param string $needed_version the needed version
1223       */
1224      function setNeededVersion($needed_version) {
1225          $this->needed_version=$needed_version;
1226      }
1227  
1228      /**
1229       * Set the auxiliary info
1230       *
1231       * @param string $info the auxiliary info
1232       */
1233      function setInfo($info) {
1234          $this->info=$info;
1235      }
1236  
1237      /**
1238       * Set the feedback string
1239       *
1240       * @param mixed $str the feedback string that will be fetched from the admin lang file.
1241       *                  pass just the string or pass an array of params for get_string
1242       *                  You always should put your string in admin.php but a third param is useful
1243       *                  to pass an $a object / string to get_string
1244       */
1245      function setFeedbackStr($str) {
1246          $this->feedback_str=$str;
1247      }
1248  
1249  
1250      /**
1251       * Set the bypass string
1252       *
1253       * @param string $str the bypass string that will be fetched from the admin lang file.
1254       *                  pass just the string or pass an array of params for get_string
1255       *                  You always should put your string in admin.php but a third param is useful
1256       *                  to pass an $a object / string to get_string
1257       */
1258      function setBypassStr($str) {
1259          $this->bypass_str=$str;
1260      }
1261  
1262      /**
1263       * Set the restrict string
1264       *
1265       * @param string $str the restrict string that will be fetched from the admin lang file.
1266       *                  pass just the string or pass an array of params for get_string
1267       *                  You always should put your string in admin.php but a third param is useful
1268       *                  to pass an $a object / string to get_string
1269       */
1270      function setRestrictStr($str) {
1271          $this->restrict_str=$str;
1272      }
1273  
1274      /**
1275       * Get the status
1276       *
1277       * @return bool true means the test passed and all is OK. false means it failed.
1278       */
1279      function getStatus() {
1280          return $this->status;
1281      }
1282  
1283      /**
1284       * Get the error code
1285       *
1286       * @return integer error code
1287       */
1288      function getErrorCode() {
1289          return $this->error_code;
1290      }
1291  
1292      /**
1293       * Get the level
1294       *
1295       * @return string level
1296       */
1297      function getLevel() {
1298          return $this->level;
1299      }
1300  
1301      /**
1302       * Get the current version
1303       *
1304       * @return string current version
1305       */
1306      function getCurrentVersion() {
1307          return $this->current_version;
1308      }
1309  
1310      /**
1311       * Get the needed version
1312       *
1313       * @return string needed version
1314       */
1315      function getNeededVersion() {
1316          return $this->needed_version;
1317      }
1318  
1319      /**
1320       * Get the aux info
1321       *
1322       * @return string info
1323       */
1324      function getInfo() {
1325          return $this->info;
1326      }
1327  
1328      /**
1329       * Get the part this result belongs to
1330       *
1331       * @return string part
1332       */
1333      function getPart() {
1334          return $this->part;
1335      }
1336  
1337      /**
1338       * Get the feedback string
1339       *
1340       * @return mixed feedback string (can be an array of params for get_string or a single string to fetch from
1341       *                  admin.php lang file).
1342       */
1343      function getFeedbackStr() {
1344          return $this->feedback_str;
1345      }
1346  
1347      /**
1348       * Get the bypass string
1349       *
1350       * @return mixed bypass string (can be an array of params for get_string or a single string to fetch from
1351       *                  admin.php lang file).
1352       */
1353      function getBypassStr() {
1354          return $this->bypass_str;
1355      }
1356  
1357      /**
1358       * Get the restrict string
1359       *
1360       * @return mixed restrict string (can be an array of params for get_string or a single string to fetch from
1361       *                  admin.php lang file).
1362       */
1363      function getRestrictStr() {
1364          return $this->restrict_str;
1365      }
1366  
1367      /**
1368       * @todo Document this function
1369       *
1370       * @param mixed $string params for get_string, either a string to fetch from admin.php or an array of
1371       *                       params for get_string.
1372       * @param string $class css class(es) for message.
1373       * @return string feedback string fetched from lang file wrapped in p tag with class $class or returns
1374       *                              empty string if $string is empty.
1375       */
1376      function strToReport($string, $class){
1377          if (!empty($string)){
1378              if (is_array($string)){
1379                  $str = call_user_func_array('get_string', $string);
1380              } else {
1381                  $str = get_string($string, 'admin');
1382              }
1383              return '<p class="'.$class.'">'.$str.'</p>';
1384          } else {
1385              return '';
1386          }
1387      }
1388  }
1389  
1390  /// Here all the restrict functions are coded to be used by the environment
1391  /// checker. All those functions will receive the result object and will
1392  /// return it modified as needed (status and bypass string)
1393  
1394  /**
1395   * @param array $element the element from the environment.xml file that should have
1396   *      either a level="required" or level="optional" attribute.
1397   * @return string "required" or "optional".
1398   */
1399  function get_level($element) {
1400      $level = 'required';
1401      if (isset($element['@']['level'])) {
1402          $level = $element['@']['level'];
1403          if (!in_array($level, array('required', 'optional'))) {
1404              debugging('The level of a check in the environment.xml file must be "required" or "optional".', DEBUG_DEVELOPER);
1405              $level = 'required';
1406          }
1407      } else {
1408          debugging('Checks in the environment.xml file must have a level="required" or level="optional" attribute.', DEBUG_DEVELOPER);
1409      }
1410      return $level;
1411  }
1412  
1413  /**
1414   * Once the result has been determined, look in the XML for any
1415   * messages, or other things that should be done depending on the outcome.
1416   *
1417   * @param array $element the element from the environment.xml file which
1418   *      may have children defining what should be done with the outcome.
1419   * @param object $result the result of the test, which may be modified by
1420   *      this function as specified in the XML.
1421   */
1422  function process_environment_result($element, &$result) {
1423  /// Process messages, modifying the $result if needed.
1424      process_environment_messages($element, $result);
1425  /// Process bypass, modifying $result if needed.
1426      process_environment_bypass($element, $result);
1427  /// Process restrict, modifying $result if needed.
1428      process_environment_restrict($element, $result);
1429  }

title

Description

title

Description

title

Description

title

title

Body