[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/ -> environmentlib.php (source)

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


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7