See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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 * @param string $version version to check. 90 * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. Default ENV_SELECT_NEWER (BC) 91 * @return array with two elements. The first element true/false, depending on 92 * on whether the check passed. The second element is an array of environment_results 93 * objects that has detailed information about the checks and which ones passed. 94 */ 95 function check_moodle_environment($version, $env_select = ENV_SELECT_NEWER) { 96 if ($env_select != ENV_SELECT_NEWER and $env_select != ENV_SELECT_DATAROOT and $env_select != ENV_SELECT_RELEASE) { 97 throw new coding_exception('Incorrect value of $env_select parameter'); 98 } 99 100 /// Get the more recent version before the requested 101 if (!$version = get_latest_version_available($version, $env_select)) { 102 return array(false, array()); 103 } 104 105 /// Perform all the checks 106 if (!$environment_results = environment_check($version, $env_select)) { 107 return array(false, array()); 108 } 109 110 /// Iterate over all the results looking for some error in required items 111 /// or some error_code 112 $result = true; 113 foreach ($environment_results as $environment_result) { 114 if (!$environment_result->getStatus() && $environment_result->getLevel() == 'required' 115 && !$environment_result->getBypassStr()) { 116 $result = false; // required item that is not bypased 117 } else if ($environment_result->getStatus() && $environment_result->getLevel() == 'required' 118 && $environment_result->getRestrictStr()) { 119 $result = false; // required item that is restricted 120 } else if ($environment_result->getErrorCode()) { 121 $result = false; 122 } 123 } 124 125 return array($result, $environment_results); 126 } 127 128 129 /** 130 * Returns array of critical errors in plain text format 131 * @param array $environment_results array of results gathered 132 * @return array errors 133 */ 134 function environment_get_errors($environment_results) { 135 global $CFG; 136 $errors = array(); 137 138 // Iterate over each environment_result 139 foreach ($environment_results as $environment_result) { 140 $type = $environment_result->getPart(); 141 $info = $environment_result->getInfo(); 142 $status = $environment_result->getStatus(); 143 $plugin = $environment_result->getPluginName(); 144 $error_code = $environment_result->getErrorCode(); 145 146 $a = new stdClass(); 147 if ($error_code) { 148 $a->error_code = $error_code; 149 $errors[] = array($info, get_string('environmentxmlerror', 'admin', $a)); 150 return $errors; 151 } 152 153 /// Calculate the status value 154 if ($environment_result->getBypassStr() != '') { 155 // not interesting 156 continue; 157 } else if ($environment_result->getRestrictStr() != '') { 158 // error 159 } else { 160 if ($status) { 161 // ok 162 continue; 163 } else { 164 if ($environment_result->getLevel() == 'optional') { 165 // just a warning 166 continue; 167 } else { 168 // error 169 } 170 } 171 } 172 173 // We are comparing versions 174 $rec = new stdClass(); 175 if ($rec->needed = $environment_result->getNeededVersion()) { 176 $rec->current = $environment_result->getCurrentVersion(); 177 if ($environment_result->getLevel() == 'required') { 178 $stringtouse = 'environmentrequireversion'; 179 } else { 180 $stringtouse = 'environmentrecommendversion'; 181 } 182 // We are checking installed & enabled things 183 } else if ($environment_result->getPart() == 'custom_check') { 184 if ($environment_result->getLevel() == 'required') { 185 $stringtouse = 'environmentrequirecustomcheck'; 186 } else { 187 $stringtouse = 'environmentrecommendcustomcheck'; 188 } 189 } else if ($environment_result->getPart() == 'php_setting') { 190 if ($status) { 191 $stringtouse = 'environmentsettingok'; 192 } else if ($environment_result->getLevel() == 'required') { 193 $stringtouse = 'environmentmustfixsetting'; 194 } else { 195 $stringtouse = 'environmentshouldfixsetting'; 196 } 197 } else { 198 if ($environment_result->getLevel() == 'required') { 199 $stringtouse = 'environmentrequireinstall'; 200 } else { 201 $stringtouse = 'environmentrecommendinstall'; 202 } 203 } 204 $report = get_string($stringtouse, 'admin', $rec); 205 206 // Here we'll store all the feedback found 207 $feedbacktext = ''; 208 // Append the feedback if there is some 209 $feedbacktext .= $environment_result->strToReport($environment_result->getFeedbackStr(), 'error'); 210 // Append the restrict if there is some 211 $feedbacktext .= $environment_result->strToReport($environment_result->getRestrictStr(), 'error'); 212 213 if ($plugin === '') { 214 $report = '[' . get_string('coresystem') . '] ' . $report; 215 } else { 216 $report = '[' . $plugin . '] ' . $report; 217 } 218 219 $report .= ' - ' . html_to_text($feedbacktext); 220 221 if ($environment_result->getPart() == 'custom_check'){ 222 $errors[] = array($info, $report); 223 } else { 224 $errors[] = array(($info !== '' ? "$type $info" : $type), $report); 225 } 226 } 227 228 return $errors; 229 } 230 231 232 /** 233 * This function will normalize any version to just a serie of numbers 234 * separated by dots. Everything else will be removed. 235 * 236 * @param string $version the original version 237 * @return string the normalized version 238 */ 239 function normalize_version($version) { 240 241 /// 1.9 Beta 2 should be read 1.9 on enviromental checks, not 1.9.2 242 /// we can discard everything after the first space 243 $version = trim($version); 244 $versionarr = explode(" ",$version); 245 if (!empty($versionarr)) { 246 $version = $versionarr[0]; 247 } 248 /// Replace everything but numbers and dots by dots 249 $version = preg_replace('/[^\.\d]/', '.', $version); 250 /// Combine multiple dots in one 251 $version = preg_replace('/(\.{2,})/', '.', $version); 252 /// Trim possible leading and trailing dots 253 $version = trim($version, '.'); 254 255 return $version; 256 } 257 258 259 /** 260 * This function will load the environment.xml file and xmlize it 261 * 262 * @staticvar array $data 263 * @uses ENV_SELECT_NEWER 264 * @uses ENV_SELECT_DATAROOT 265 * @uses ENV_SELECT_RELEASE 266 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 267 * @return mixed the xmlized structure or false on error 268 */ 269 function load_environment_xml($env_select=ENV_SELECT_NEWER) { 270 271 global $CFG; 272 273 static $data = array(); // Only load and xmlize once by request. 274 275 if (isset($data[$env_select])) { 276 return $data[$env_select]; 277 } 278 $contents = false; 279 280 if (is_numeric($env_select)) { 281 $file = $CFG->dataroot.'/environment/environment.xml'; 282 $internalfile = $CFG->dirroot.'/'.$CFG->admin.'/environment.xml'; 283 switch ($env_select) { 284 case ENV_SELECT_NEWER: 285 if (!is_file($file) || !is_readable($file) || filemtime($file) < filemtime($internalfile) || 286 !$contents = file_get_contents($file)) { 287 /// Fallback to fixed $CFG->admin/environment.xml 288 if (!is_file($internalfile) || !is_readable($internalfile) || !$contents = file_get_contents($internalfile)) { 289 $contents = false; 290 } 291 } 292 break; 293 case ENV_SELECT_DATAROOT: 294 if (!is_file($file) || !is_readable($file) || !$contents = file_get_contents($file)) { 295 $contents = false; 296 } 297 break; 298 case ENV_SELECT_RELEASE: 299 if (!is_file($internalfile) || !is_readable($internalfile) || !$contents = file_get_contents($internalfile)) { 300 $contents = false; 301 } 302 break; 303 } 304 } else { 305 if ($plugindir = core_component::get_component_directory($env_select)) { 306 $pluginfile = "$plugindir/environment.xml"; 307 if (!is_file($pluginfile) || !is_readable($pluginfile) || !$contents = file_get_contents($pluginfile)) { 308 $contents = false; 309 } 310 } 311 } 312 // XML the whole file. 313 if ($contents !== false) { 314 $contents = xmlize($contents); 315 } 316 317 $data[$env_select] = $contents; 318 319 return $data[$env_select]; 320 } 321 322 323 /** 324 * This function will return the list of Moodle versions available 325 * 326 * @return array of versions 327 */ 328 function get_list_of_environment_versions($contents) { 329 $versions = array(); 330 331 if (isset($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'])) { 332 foreach ($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'] as $version) { 333 $versions[] = $version['@']['version']; 334 } 335 } 336 337 if (isset($contents['COMPATIBILITY_MATRIX']['#']['PLUGIN'])) { 338 $versions[] = 'all'; 339 } 340 341 return $versions; 342 } 343 344 345 /** 346 * This function will return the most recent version in the environment.xml 347 * file previous or equal to the version requested 348 * 349 * @param string $version top version from which we start to look backwards 350 * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. 351 * @return string|bool string more recent version or false if not found 352 */ 353 function get_latest_version_available($version, $env_select) { 354 if ($env_select != ENV_SELECT_NEWER and $env_select != ENV_SELECT_DATAROOT and $env_select != ENV_SELECT_RELEASE) { 355 throw new coding_exception('Incorrect value of $env_select parameter'); 356 } 357 358 /// Normalize the version requested 359 $version = normalize_version($version); 360 361 /// Load xml file 362 if (!$contents = load_environment_xml($env_select)) { 363 return false; 364 } 365 366 /// Detect available versions 367 if (!$versions = get_list_of_environment_versions($contents)) { 368 return false; 369 } 370 /// First we look for exact version 371 if (in_array($version, $versions)) { 372 return $version; 373 } else { 374 $found_version = false; 375 /// Not exact match, so we are going to iterate over the list searching 376 /// for the latest version before the requested one 377 foreach ($versions as $arrversion) { 378 if (version_compare($arrversion, $version, '<')) { 379 $found_version = $arrversion; 380 } 381 } 382 } 383 384 return $found_version; 385 } 386 387 388 /** 389 * This function will return the xmlized data belonging to one Moodle version 390 * 391 * @param string $version top version from which we start to look backwards 392 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 393 * @return mixed the xmlized structure or false on error 394 */ 395 function get_environment_for_version($version, $env_select) { 396 397 /// Normalize the version requested 398 $version = normalize_version($version); 399 400 /// Load xml file 401 if (!$contents = load_environment_xml($env_select)) { 402 return false; 403 } 404 405 /// Detect available versions 406 if (!$versions = get_list_of_environment_versions($contents)) { 407 return false; 408 } 409 410 // If $env_select is not numeric then this is being called on a plugin, and not the core environment.xml 411 // If a version of 'all' is in the arry is also means that the new <PLUGIN> tag was found, this should 412 // be matched against any version of Moodle. 413 if (!is_numeric($env_select) && in_array('all', $versions) 414 && environment_verify_plugin($env_select, $contents['COMPATIBILITY_MATRIX']['#']['PLUGIN'][0])) { 415 return $contents['COMPATIBILITY_MATRIX']['#']['PLUGIN'][0]; 416 } 417 418 /// If the version requested is available 419 if (!in_array($version, $versions)) { 420 return false; 421 } 422 423 /// We now we have it. Extract from full contents. 424 $fl_arr = array_flip($versions); 425 426 return $contents['COMPATIBILITY_MATRIX']['#']['MOODLE'][$fl_arr[$version]]; 427 } 428 429 /** 430 * Checks if a plugin tag has a name attribute and it matches the plugin being tested. 431 * 432 * @param string $plugin the name of the plugin. 433 * @param array $pluginxml the xmlised structure for the plugin tag being tested. 434 * @return boolean true if the name attribute exists and matches the plugin being tested. 435 */ 436 function environment_verify_plugin($plugin, $pluginxml) { 437 if (!isset($pluginxml['@']['name']) || $pluginxml['@']['name'] != $plugin) { 438 return false; 439 } 440 return true; 441 } 442 443 /** 444 * This function will check for everything (DB, PHP and PHP extensions for now) 445 * returning an array of environment_result objects. 446 * 447 * @global object 448 * @param string $version xml version we are going to use to test this server 449 * @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. 450 * @return environment_results[] array of results encapsulated in one environment_result object 451 */ 452 function environment_check($version, $env_select) { 453 global $CFG; 454 455 if ($env_select != ENV_SELECT_NEWER and $env_select != ENV_SELECT_DATAROOT and $env_select != ENV_SELECT_RELEASE) { 456 throw new coding_exception('Incorrect value of $env_select parameter'); 457 } 458 459 /// Normalize the version requested 460 $version = normalize_version($version); 461 462 $results = array(); //To store all the results 463 464 /// Only run the moodle versions checker on upgrade, not on install 465 if (!empty($CFG->version)) { 466 $results[] = environment_check_moodle($version, $env_select); 467 } 468 $results[] = environment_check_unicode($version, $env_select); 469 $results[] = environment_check_database($version, $env_select); 470 $results[] = environment_check_php($version, $env_select); 471 472 if ($result = environment_check_pcre_unicode($version, $env_select)) { 473 $results[] = $result; 474 } 475 476 $phpext_results = environment_check_php_extensions($version, $env_select); 477 $results = array_merge($results, $phpext_results); 478 479 $phpsetting_results = environment_check_php_settings($version, $env_select); 480 $results = array_merge($results, $phpsetting_results); 481 482 $custom_results = environment_custom_checks($version, $env_select); 483 $results = array_merge($results, $custom_results); 484 485 // Always use the plugin directory version of environment.xml, 486 // add-on developers need to keep those up-to-date with future info. 487 foreach (core_component::get_plugin_types() as $plugintype => $unused) { 488 foreach (core_component::get_plugin_list_with_file($plugintype, 'environment.xml') as $pluginname => $unused) { 489 $plugin = $plugintype . '_' . $pluginname; 490 491 $result = environment_check_database($version, $plugin); 492 if ($result->error_code != NO_VERSION_DATA_FOUND 493 and $result->error_code != NO_DATABASE_SECTION_FOUND 494 and $result->error_code != NO_DATABASE_VENDORS_FOUND) { 495 496 $result->plugin = $plugin; 497 $results[] = $result; 498 } 499 500 $result = environment_check_php($version, $plugin); 501 if ($result->error_code != NO_VERSION_DATA_FOUND 502 and $result->error_code != NO_PHP_SECTION_FOUND 503 and $result->error_code != NO_PHP_VERSION_FOUND) { 504 505 $result->plugin = $plugin; 506 $results[] = $result; 507 } 508 509 $pluginresults = environment_check_php_extensions($version, $plugin); 510 foreach ($pluginresults as $result) { 511 if ($result->error_code != NO_VERSION_DATA_FOUND 512 and $result->error_code != NO_PHP_EXTENSIONS_SECTION_FOUND) { 513 514 $result->plugin = $plugin; 515 $results[] = $result; 516 } 517 } 518 519 $pluginresults = environment_check_php_settings($version, $plugin); 520 foreach ($pluginresults as $result) { 521 if ($result->error_code != NO_VERSION_DATA_FOUND) { 522 $result->plugin = $plugin; 523 $results[] = $result; 524 } 525 } 526 527 $pluginresults = environment_custom_checks($version, $plugin); 528 foreach ($pluginresults as $result) { 529 if ($result->error_code != NO_VERSION_DATA_FOUND) { 530 $result->plugin = $plugin; 531 $results[] = $result; 532 } 533 } 534 } 535 } 536 537 return $results; 538 } 539 540 541 /** 542 * This function will check if php extensions requirements are satisfied 543 * 544 * @uses NO_VERSION_DATA_FOUND 545 * @uses NO_PHP_EXTENSIONS_SECTION_FOUND 546 * @uses NO_PHP_EXTENSIONS_NAME_FOUND 547 * @param string $version xml version we are going to use to test this server 548 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 549 * @return array array of results encapsulated in one environment_result object 550 */ 551 function environment_check_php_extensions($version, $env_select) { 552 553 $results = array(); 554 555 /// Get the enviroment version we need 556 if (!$data = get_environment_for_version($version, $env_select)) { 557 /// Error. No version data found 558 $result = new environment_results('php_extension'); 559 $result->setStatus(false); 560 $result->setErrorCode(NO_VERSION_DATA_FOUND); 561 return array($result); 562 } 563 564 /// Extract the php_extension part 565 if (!isset($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'])) { 566 /// Error. No PHP section found 567 $result = new environment_results('php_extension'); 568 $result->setStatus(false); 569 $result->setErrorCode(NO_PHP_EXTENSIONS_SECTION_FOUND); 570 return array($result); 571 } 572 /// Iterate over extensions checking them and creating the needed environment_results 573 foreach($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'] as $extension) { 574 $result = new environment_results('php_extension'); 575 /// Check for level 576 $level = get_level($extension); 577 /// Check for extension name 578 if (!isset($extension['@']['name'])) { 579 $result->setStatus(false); 580 $result->setErrorCode(NO_PHP_EXTENSIONS_NAME_FOUND); 581 } else { 582 $extension_name = $extension['@']['name']; 583 /// The name exists. Just check if it's an installed extension 584 if (!extension_loaded($extension_name)) { 585 $result->setStatus(false); 586 } else { 587 $result->setStatus(true); 588 } 589 $result->setLevel($level); 590 $result->setInfo($extension_name); 591 } 592 593 /// Do any actions defined in the XML file. 594 process_environment_result($extension, $result); 595 596 /// Add the result to the array of results 597 $results[] = $result; 598 } 599 600 601 return $results; 602 } 603 604 /** 605 * This function will check if php extensions requirements are satisfied 606 * 607 * @uses NO_VERSION_DATA_FOUND 608 * @uses NO_PHP_SETTINGS_NAME_FOUND 609 * @param string $version xml version we are going to use to test this server 610 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 611 * @return array array of results encapsulated in one environment_result object 612 */ 613 function environment_check_php_settings($version, $env_select) { 614 615 $results = array(); 616 617 /// Get the enviroment version we need 618 if (!$data = get_environment_for_version($version, $env_select)) { 619 /// Error. No version data found 620 $result = new environment_results('php_setting'); 621 $result->setStatus(false); 622 $result->setErrorCode(NO_VERSION_DATA_FOUND); 623 $results[] = $result; 624 return $results; 625 } 626 627 /// Extract the php_setting part 628 if (!isset($data['#']['PHP_SETTINGS']['0']['#']['PHP_SETTING'])) { 629 /// No PHP section found - ignore 630 return $results; 631 } 632 /// Iterate over settings checking them and creating the needed environment_results 633 foreach($data['#']['PHP_SETTINGS']['0']['#']['PHP_SETTING'] as $setting) { 634 $result = new environment_results('php_setting'); 635 /// Check for level 636 $level = get_level($setting); 637 $result->setLevel($level); 638 /// Check for extension name 639 if (!isset($setting['@']['name'])) { 640 $result->setStatus(false); 641 $result->setErrorCode(NO_PHP_SETTINGS_NAME_FOUND); 642 } else { 643 $setting_name = $setting['@']['name']; 644 $setting_value = $setting['@']['value']; 645 $result->setInfo($setting_name); 646 647 if ($setting_name == 'memory_limit') { 648 $current = ini_get('memory_limit'); 649 if ($current == -1) { 650 $result->setStatus(true); 651 } else { 652 $current = get_real_size($current); 653 $minlimit = get_real_size($setting_value); 654 if ($current < $minlimit) { 655 @ini_set('memory_limit', $setting_value); 656 $current = ini_get('memory_limit'); 657 $current = get_real_size($current); 658 } 659 $result->setStatus($current >= $minlimit); 660 } 661 662 } else { 663 $current = ini_get_bool($setting_name); 664 /// The name exists. Just check if it's an installed extension 665 if ($current == $setting_value) { 666 $result->setStatus(true); 667 } else { 668 $result->setStatus(false); 669 } 670 } 671 } 672 673 /// Do any actions defined in the XML file. 674 process_environment_result($setting, $result); 675 676 /// Add the result to the array of results 677 $results[] = $result; 678 } 679 680 681 return $results; 682 } 683 684 /** 685 * This function will do the custom checks. 686 * 687 * @uses CUSTOM_CHECK_FUNCTION_MISSING 688 * @uses CUSTOM_CHECK_FILE_MISSING 689 * @uses NO_CUSTOM_CHECK_FOUND 690 * @param string $version xml version we are going to use to test this server. 691 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 692 * @return array array of results encapsulated in environment_result objects. 693 */ 694 function environment_custom_checks($version, $env_select) { 695 global $CFG; 696 697 $results = array(); 698 699 /// Get current Moodle version (release) for later compare 700 $release = isset($CFG->release) ? $CFG->release : $version; /// In case $CFG fails (at install) use $version 701 $current_version = normalize_version($release); 702 703 /// Get the enviroment version we need 704 if (!$data = get_environment_for_version($version, $env_select)) { 705 /// Error. No version data found - but this will already have been reported. 706 return $results; 707 } 708 709 /// Extract the CUSTOM_CHECKS part 710 if (!isset($data['#']['CUSTOM_CHECKS']['0']['#']['CUSTOM_CHECK'])) { 711 /// No custom checks found - not a problem 712 return $results; 713 } 714 715 /// Iterate over extensions checking them and creating the needed environment_results 716 foreach($data['#']['CUSTOM_CHECKS']['0']['#']['CUSTOM_CHECK'] as $check) { 717 $result = new environment_results('custom_check'); 718 719 /// Check for level 720 $level = get_level($check); 721 722 /// Check for extension name 723 if (isset($check['@']['function'])) { 724 $function = $check['@']['function']; 725 $file = null; 726 if (isset($check['@']['file'])) { 727 $file = $CFG->dirroot . '/' . $check['@']['file']; 728 if (is_readable($file)) { 729 include_once($file); 730 } 731 } 732 733 if (is_callable($function)) { 734 $result->setLevel($level); 735 $result->setInfo($function); 736 $result = call_user_func($function, $result); 737 } else if (!$file or is_readable($file)) { 738 /// Only show error for current version (where function MUST exist) 739 /// else, we are performing custom checks against future versiosn 740 /// and function MAY not exist, so it doesn't cause error, just skip 741 /// custom check by returning null. MDL-15939 742 if (version_compare($current_version, $version, '>=')) { 743 $result->setStatus(false); 744 $result->setInfo($function); 745 $result->setErrorCode(CUSTOM_CHECK_FUNCTION_MISSING); 746 } else { 747 $result = null; 748 } 749 } else { 750 /// Only show error for current version (where function MUST exist) 751 /// else, we are performing custom checks against future versiosn 752 /// and function MAY not exist, so it doesn't cause error, just skip 753 /// custom check by returning null. MDL-15939 754 if (version_compare($current_version, $version, '>=')) { 755 $result->setStatus(false); 756 $result->setInfo($function); 757 $result->setErrorCode(CUSTOM_CHECK_FILE_MISSING); 758 } else { 759 $result = null; 760 } 761 } 762 } else { 763 $result->setStatus(false); 764 $result->setErrorCode(NO_CUSTOM_CHECK_FOUND); 765 } 766 767 if (!is_null($result)) { 768 /// Do any actions defined in the XML file. 769 process_environment_result($check, $result); 770 771 /// Add the result to the array of results 772 $results[] = $result; 773 } 774 } 775 776 return $results; 777 } 778 779 /** 780 * This function will check if Moodle requirements are satisfied 781 * 782 * @uses NO_VERSION_DATA_FOUND 783 * @param string $version xml version we are going to use to test this server 784 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 785 * @return object results encapsulated in one environment_result object 786 */ 787 function environment_check_moodle($version, $env_select) { 788 789 $result = new environment_results('moodle'); 790 791 /// Get the enviroment version we need 792 if (!$data = get_environment_for_version($version, $env_select)) { 793 /// Error. No version data found 794 $result->setStatus(false); 795 $result->setErrorCode(NO_VERSION_DATA_FOUND); 796 return $result; 797 } 798 799 /// Extract the moodle part 800 if (!isset($data['@']['requires'])) { 801 $needed_version = '1.0'; /// Default to 1.0 if no moodle requires is found 802 } else { 803 /// Extract required moodle version 804 $needed_version = $data['@']['requires']; 805 } 806 807 /// Now search the version we are using 808 $release = get_config('', 'release'); 809 $current_version = normalize_version($release); 810 if (strpos($release, 'dev') !== false) { 811 // when final version is required, dev is NOT enough! 812 $current_version = $current_version - 0.1; 813 } 814 815 /// And finally compare them, saving results 816 if (version_compare($current_version, $needed_version, '>=')) { 817 $result->setStatus(true); 818 } else { 819 $result->setStatus(false); 820 } 821 $result->setLevel('required'); 822 $result->setCurrentVersion($release); 823 $result->setNeededVersion($needed_version); 824 825 return $result; 826 } 827 828 /** 829 * This function will check if php requirements are satisfied 830 * 831 * @uses NO_VERSION_DATA_FOUND 832 * @uses NO_PHP_SECTION_FOUND 833 * @uses NO_PHP_VERSION_FOUND 834 * @param string $version xml version we are going to use to test this server 835 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 836 * @return object results encapsulated in one environment_result object 837 */ 838 function environment_check_php($version, $env_select) { 839 840 $result = new environment_results('php'); 841 842 /// Get the enviroment version we need 843 if (!$data = get_environment_for_version($version, $env_select)) { 844 /// Error. No version data found 845 $result->setStatus(false); 846 $result->setErrorCode(NO_VERSION_DATA_FOUND); 847 return $result; 848 } 849 850 /// Extract the php part 851 if (!isset($data['#']['PHP'])) { 852 /// Error. No PHP section found 853 $result->setStatus(false); 854 $result->setErrorCode(NO_PHP_SECTION_FOUND); 855 return $result; 856 } else { 857 /// Extract level and version 858 $level = get_level($data['#']['PHP']['0']); 859 if (!isset($data['#']['PHP']['0']['@']['version'])) { 860 $result->setStatus(false); 861 $result->setErrorCode(NO_PHP_VERSION_FOUND); 862 return $result; 863 } else { 864 $needed_version = $data['#']['PHP']['0']['@']['version']; 865 } 866 } 867 868 /// Now search the version we are using 869 $current_version = normalize_version(phpversion()); 870 871 /// And finally compare them, saving results 872 if (version_compare($current_version, $needed_version, '>=')) { 873 $result->setStatus(true); 874 } else { 875 $result->setStatus(false); 876 } 877 $result->setLevel($level); 878 $result->setCurrentVersion($current_version); 879 $result->setNeededVersion($needed_version); 880 881 /// Do any actions defined in the XML file. 882 process_environment_result($data['#']['PHP'][0], $result); 883 884 return $result; 885 } 886 887 /** 888 * Looks for buggy PCRE implementation, we need unicode support in Moodle... 889 * @param string $version xml version we are going to use to test this server 890 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 891 * @return stdClass results encapsulated in one environment_result object, null if irrelevant 892 */ 893 function environment_check_pcre_unicode($version, $env_select) { 894 $result = new environment_results('pcreunicode'); 895 896 // Get the environment version we need 897 if (!$data = get_environment_for_version($version, $env_select)) { 898 // Error. No version data found! 899 $result->setStatus(false); 900 $result->setErrorCode(NO_VERSION_DATA_FOUND); 901 return $result; 902 } 903 904 if (!isset($data['#']['PCREUNICODE'])) { 905 return null; 906 } 907 908 $level = get_level($data['#']['PCREUNICODE']['0']); 909 $result->setLevel($level); 910 911 if (!function_exists('preg_match')) { 912 // The extension test fails instead. 913 return null; 914 915 } else if (@preg_match('/\pL/u', 'a') and @preg_match('/á/iu', 'Á')) { 916 $result->setStatus(true); 917 918 } else { 919 $result->setStatus(false); 920 } 921 922 // Do any actions defined in the XML file. 923 process_environment_result($data['#']['PCREUNICODE'][0], $result); 924 925 return $result; 926 } 927 928 /** 929 * This function will check if unicode database requirements are satisfied 930 * 931 * @uses NO_VERSION_DATA_FOUND 932 * @uses NO_UNICODE_SECTION_FOUND 933 * @param string $version xml version we are going to use to test this server 934 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 935 * @return object results encapsulated in one environment_result object 936 */ 937 function environment_check_unicode($version, $env_select) { 938 global $DB; 939 940 $result = new environment_results('unicode'); 941 942 /// Get the enviroment version we need 943 if (!$data = get_environment_for_version($version, $env_select)) { 944 /// Error. No version data found 945 $result->setStatus(false); 946 $result->setErrorCode(NO_VERSION_DATA_FOUND); 947 return $result; 948 } 949 950 /// Extract the unicode part 951 952 if (!isset($data['#']['UNICODE'])) { 953 /// Error. No UNICODE section found 954 $result->setStatus(false); 955 $result->setErrorCode(NO_UNICODE_SECTION_FOUND); 956 return $result; 957 } else { 958 /// Extract level 959 $level = get_level($data['#']['UNICODE']['0']); 960 } 961 962 if (!$unicodedb = $DB->setup_is_unicodedb()) { 963 $result->setStatus(false); 964 } else { 965 $result->setStatus(true); 966 } 967 968 $result->setLevel($level); 969 970 /// Do any actions defined in the XML file. 971 process_environment_result($data['#']['UNICODE'][0], $result); 972 973 return $result; 974 } 975 976 /** 977 * This function will check if database requirements are satisfied 978 * 979 * @uses NO_VERSION_DATA_FOUND 980 * @uses NO_DATABASE_SECTION_FOUND 981 * @uses NO_DATABASE_VENDORS_FOUND 982 * @uses NO_DATABASE_VENDOR_MYSQL_FOUND 983 * @uses NO_DATABASE_VENDOR_POSTGRES_FOUND 984 * @uses NO_DATABASE_VENDOR_VERSION_FOUND 985 * @param string $version xml version we are going to use to test this server 986 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 987 * @return object results encapsulated in one environment_result object 988 */ 989 function environment_check_database($version, $env_select) { 990 991 global $DB; 992 993 $result = new environment_results('database'); 994 995 $vendors = array(); //Array of vendors in version 996 997 /// Get the enviroment version we need 998 if (!$data = get_environment_for_version($version, $env_select)) { 999 /// Error. No version data found 1000 $result->setStatus(false); 1001 $result->setErrorCode(NO_VERSION_DATA_FOUND); 1002 return $result; 1003 } 1004 1005 /// Extract the database part 1006 if (!isset($data['#']['DATABASE'])) { 1007 /// Error. No DATABASE section found 1008 $result->setStatus(false); 1009 $result->setErrorCode(NO_DATABASE_SECTION_FOUND); 1010 return $result; 1011 } else { 1012 /// Extract level 1013 $level = get_level($data['#']['DATABASE']['0']); 1014 } 1015 1016 /// Extract DB vendors. At least 2 are mandatory (mysql & postgres) 1017 if (!isset($data['#']['DATABASE']['0']['#']['VENDOR'])) { 1018 /// Error. No VENDORS found 1019 $result->setStatus(false); 1020 $result->setErrorCode(NO_DATABASE_VENDORS_FOUND); 1021 return $result; 1022 } else { 1023 /// Extract vendors 1024 foreach ($data['#']['DATABASE']['0']['#']['VENDOR'] as $vendor) { 1025 if (isset($vendor['@']['name']) && isset($vendor['@']['version'])) { 1026 $vendors[$vendor['@']['name']] = $vendor['@']['version']; 1027 $vendorsxml[$vendor['@']['name']] = $vendor; 1028 } 1029 } 1030 } 1031 /// Check we have the mysql vendor version 1032 if (empty($vendors['mysql'])) { 1033 $result->setStatus(false); 1034 $result->setErrorCode(NO_DATABASE_VENDOR_MYSQL_FOUND); 1035 return $result; 1036 } 1037 /// Check we have the postgres vendor version 1038 if (empty($vendors['postgres'])) { 1039 $result->setStatus(false); 1040 $result->setErrorCode(NO_DATABASE_VENDOR_POSTGRES_FOUND); 1041 return $result; 1042 } 1043 1044 /// Now search the version we are using (depending of vendor) 1045 $current_vendor = $DB->get_dbvendor(); 1046 1047 $dbinfo = $DB->get_server_info(); 1048 $current_version = normalize_version($dbinfo['version']); 1049 $needed_version = $vendors[$current_vendor]; 1050 1051 /// Check we have a needed version 1052 if (!$needed_version) { 1053 $result->setStatus(false); 1054 $result->setErrorCode(NO_DATABASE_VENDOR_VERSION_FOUND); 1055 return $result; 1056 } 1057 1058 // Check if the DB Vendor has been properly configured. 1059 // Hack: this is required when playing with MySQL and MariaDB since they share the same PHP module and base DB classes, 1060 // whilst they are slowly evolving using separate directions though MariaDB is still an "almost" drop-in replacement. 1061 $dbvendorismysql = ($current_vendor === 'mysql'); 1062 $dbtypeismariadb = (stripos($dbinfo['description'], 'mariadb') !== false); 1063 if ($dbvendorismysql && $dbtypeismariadb) { 1064 $result->setStatus(false); 1065 $result->setLevel($level); 1066 $result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')'); 1067 $result->setFeedbackStr('environmentmariadbwrongdbtype'); 1068 return $result; 1069 } 1070 1071 /// And finally compare them, saving results 1072 if (version_compare($current_version, $needed_version, '>=')) { 1073 $result->setStatus(true); 1074 } else { 1075 $result->setStatus(false); 1076 } 1077 $result->setLevel($level); 1078 $result->setCurrentVersion($current_version); 1079 $result->setNeededVersion($needed_version); 1080 $result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')'); 1081 1082 /// Do any actions defined in the XML file. 1083 process_environment_result($vendorsxml[$current_vendor], $result); 1084 1085 return $result; 1086 1087 } 1088 1089 /** 1090 * This function will post-process the result record by executing the specified 1091 * function, modifying it as necessary, also a custom message will be added 1092 * to the result object to be printed by the display layer. 1093 * Every bypass function must be defined in this file and it'll return 1094 * true/false to decide if the original test is bypassed or no. Also 1095 * such bypass functions are able to directly handling the result object 1096 * although it should be only under exceptional conditions. 1097 * 1098 * @param string xmldata containing the bypass data 1099 * @param object result object to be updated 1100 * @return void 1101 */ 1102 function process_environment_bypass($xml, &$result) { 1103 1104 /// Only try to bypass if we were in error and it was required 1105 if ($result->getStatus() || $result->getLevel() == 'optional') { 1106 return; 1107 } 1108 1109 /// It there is bypass info (function and message) 1110 if (is_array($xml['#']) && isset($xml['#']['BYPASS'][0]['@']['function']) && isset($xml['#']['BYPASS'][0]['@']['message'])) { 1111 $function = $xml['#']['BYPASS'][0]['@']['function']; 1112 $message = $xml['#']['BYPASS'][0]['@']['message']; 1113 /// Look for the function 1114 if (function_exists($function)) { 1115 /// Call it, and if bypass = true is returned, apply meesage 1116 if ($function($result)) { 1117 /// We only set the bypass message if the function itself hasn't defined it before 1118 if (empty($result->getBypassStr)) { 1119 if (isset($xml['#']['BYPASS'][0]['@']['plugin'])) { 1120 $result->setBypassStr(array($message, $xml['#']['BYPASS'][0]['@']['plugin'])); 1121 } else { 1122 $result->setBypassStr($message); 1123 } 1124 } 1125 } 1126 } 1127 } 1128 } 1129 1130 /** 1131 * This function will post-process the result record by executing the specified 1132 * function, modifying it as necessary, also a custom message will be added 1133 * to the result object to be printed by the display layer. 1134 * Every restrict function must be defined in this file and it'll return 1135 * true/false to decide if the original test is restricted or no. Also 1136 * such restrict functions are able to directly handling the result object 1137 * although it should be only under exceptional conditions. 1138 * 1139 * @param string xmldata containing the restrict data 1140 * @param object result object to be updated 1141 * @return void 1142 */ 1143 function process_environment_restrict($xml, &$result) { 1144 1145 /// Only try to restrict if we were not in error and it was required 1146 if (!$result->getStatus() || $result->getLevel() == 'optional') { 1147 return; 1148 } 1149 /// It there is restrict info (function and message) 1150 if (is_array($xml['#']) && isset($xml['#']['RESTRICT'][0]['@']['function']) && isset($xml['#']['RESTRICT'][0]['@']['message'])) { 1151 $function = $xml['#']['RESTRICT'][0]['@']['function']; 1152 $message = $xml['#']['RESTRICT'][0]['@']['message']; 1153 /// Look for the function 1154 if (function_exists($function)) { 1155 /// Call it, and if restrict = true is returned, apply meesage 1156 if ($function($result)) { 1157 /// We only set the restrict message if the function itself hasn't defined it before 1158 if (empty($result->getRestrictStr)) { 1159 if (isset($xml['#']['RESTRICT'][0]['@']['plugin'])) { 1160 $result->setRestrictStr(array($message, $xml['#']['RESTRICT'][0]['@']['plugin'])); 1161 } else { 1162 $result->setRestrictStr($message); 1163 } 1164 } 1165 } 1166 } 1167 } 1168 } 1169 1170 /** 1171 * This function will detect if there is some message available to be added to the 1172 * result in order to clarify enviromental details. 1173 * 1174 * @uses INCORRECT_FEEDBACK_FOR_REQUIRED 1175 * @uses INCORRECT_FEEDBACK_FOR_OPTIONAL 1176 * @param string xmldata containing the feedback data 1177 * @param object reult object to be updated 1178 */ 1179 function process_environment_messages($xml, &$result) { 1180 1181 /// If there is feedback info 1182 if (is_array($xml['#']) && isset($xml['#']['FEEDBACK'][0]['#'])) { 1183 $feedbackxml = $xml['#']['FEEDBACK'][0]['#']; 1184 1185 // Detect some incorrect feedback combinations. 1186 if ($result->getLevel() == 'required' and isset($feedbackxml['ON_CHECK'])) { 1187 $result->setStatus(false); 1188 $result->setErrorCode(INCORRECT_FEEDBACK_FOR_REQUIRED); 1189 } else if ($result->getLevel() == 'optional' and isset($feedbackxml['ON_ERROR'])) { 1190 $result->setStatus(false); 1191 $result->setErrorCode(INCORRECT_FEEDBACK_FOR_OPTIONAL); 1192 } 1193 1194 if (!$result->status and $result->getLevel() == 'required') { 1195 if (isset($feedbackxml['ON_ERROR'][0]['@']['message'])) { 1196 if (isset($feedbackxml['ON_ERROR'][0]['@']['plugin'])) { 1197 $result->setFeedbackStr(array($feedbackxml['ON_ERROR'][0]['@']['message'], $feedbackxml['ON_ERROR'][0]['@']['plugin'])); 1198 } else { 1199 $result->setFeedbackStr($feedbackxml['ON_ERROR'][0]['@']['message']); 1200 } 1201 } 1202 } else if (!$result->status and $result->getLevel() == 'optional') { 1203 if (isset($feedbackxml['ON_CHECK'][0]['@']['message'])) { 1204 if (isset($feedbackxml['ON_CHECK'][0]['@']['plugin'])) { 1205 $result->setFeedbackStr(array($feedbackxml['ON_CHECK'][0]['@']['message'], $feedbackxml['ON_CHECK'][0]['@']['plugin'])); 1206 } else { 1207 $result->setFeedbackStr($feedbackxml['ON_CHECK'][0]['@']['message']); 1208 } 1209 } 1210 } else { 1211 if (isset($feedbackxml['ON_OK'][0]['@']['message'])) { 1212 if (isset($feedbackxml['ON_OK'][0]['@']['plugin'])) { 1213 $result->setFeedbackStr(array($feedbackxml['ON_OK'][0]['@']['message'], $feedbackxml['ON_OK'][0]['@']['plugin'])); 1214 } else { 1215 $result->setFeedbackStr($feedbackxml['ON_OK'][0]['@']['message']); 1216 } 1217 } 1218 } 1219 } 1220 } 1221 1222 1223 //--- Helper Class to return results to caller ---// 1224 1225 1226 /** 1227 * Helper Class to return results to caller 1228 * 1229 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 1230 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 1231 * @package moodlecore 1232 */ 1233 class environment_results { 1234 /** 1235 * @var string Which are we checking (database, php, php_extension, php_extension) 1236 */ 1237 var $part; 1238 /** 1239 * @var bool true means the test passed and all is OK. false means it failed. 1240 */ 1241 var $status; 1242 /** 1243 * @var integer See constants at the beginning of the file 1244 */ 1245 var $error_code; 1246 /** 1247 * @var string required/optional 1248 */ 1249 var $level; 1250 /** 1251 * @var string current version detected 1252 */ 1253 var $current_version; 1254 /** 1255 * @var string version needed 1256 */ 1257 var $needed_version; 1258 /** 1259 * @var string Aux. info (DB vendor, library...) 1260 */ 1261 var $info; 1262 /** 1263 * @var string String to show on error|on check|on ok 1264 */ 1265 var $feedback_str; 1266 /** 1267 * @var string String to show if some bypass has happened 1268 */ 1269 var $bypass_str; 1270 /** 1271 * @var string String to show if some restrict has happened 1272 */ 1273 var $restrict_str; 1274 /** 1275 * @var string|null full plugin name or null if main environment 1276 */ 1277 var $plugin = null; 1278 /** 1279 * Constructor of the environment_result class. Just set default values 1280 * 1281 * @param string $part 1282 */ 1283 public function __construct($part) { 1284 $this->part=$part; 1285 $this->status=false; 1286 $this->error_code=NO_ERROR; 1287 $this->level='required'; 1288 $this->current_version=''; 1289 $this->needed_version=''; 1290 $this->info=''; 1291 $this->feedback_str=''; 1292 $this->bypass_str=''; 1293 $this->restrict_str=''; 1294 } 1295 1296 /** 1297 * Old syntax of class constructor. Deprecated in PHP7. 1298 * 1299 * @deprecated since Moodle 3.1 1300 */ 1301 public function environment_results($part) { 1302 debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); 1303 self::__construct($part); 1304 } 1305 1306 /** 1307 * Set the status 1308 * 1309 * @param bool $testpassed true means the test passed and all is OK. false means it failed. 1310 */ 1311 function setStatus($testpassed) { 1312 $this->status = $testpassed; 1313 if ($testpassed) { 1314 $this->setErrorCode(NO_ERROR); 1315 } 1316 } 1317 1318 /** 1319 * Set the error_code 1320 * 1321 * @param integer $error_code the error code (see constants above) 1322 */ 1323 function setErrorCode($error_code) { 1324 $this->error_code=$error_code; 1325 } 1326 1327 /** 1328 * Set the level 1329 * 1330 * @param string $level the level (required, optional) 1331 */ 1332 function setLevel($level) { 1333 $this->level=$level; 1334 } 1335 1336 /** 1337 * Set the current version 1338 * 1339 * @param string $current_version the current version 1340 */ 1341 function setCurrentVersion($current_version) { 1342 $this->current_version=$current_version; 1343 } 1344 1345 /** 1346 * Set the needed version 1347 * 1348 * @param string $needed_version the needed version 1349 */ 1350 function setNeededVersion($needed_version) { 1351 $this->needed_version=$needed_version; 1352 } 1353 1354 /** 1355 * Set the auxiliary info 1356 * 1357 * @param string $info the auxiliary info 1358 */ 1359 function setInfo($info) { 1360 $this->info=$info; 1361 } 1362 1363 /** 1364 * Set the feedback string 1365 * 1366 * @param mixed $str the feedback string that will be fetched from the admin lang file. 1367 * pass just the string or pass an array of params for get_string 1368 * You always should put your string in admin.php but a third param is useful 1369 * to pass an $a object / string to get_string 1370 */ 1371 function setFeedbackStr($str) { 1372 $this->feedback_str=$str; 1373 } 1374 1375 1376 /** 1377 * Set the bypass string 1378 * 1379 * @param string $str the bypass string that will be fetched from the admin lang file. 1380 * pass just the string or pass an array of params for get_string 1381 * You always should put your string in admin.php but a third param is useful 1382 * to pass an $a object / string to get_string 1383 */ 1384 function setBypassStr($str) { 1385 $this->bypass_str=$str; 1386 } 1387 1388 /** 1389 * Set the restrict string 1390 * 1391 * @param string $str the restrict string that will be fetched from the admin lang file. 1392 * pass just the string or pass an array of params for get_string 1393 * You always should put your string in admin.php but a third param is useful 1394 * to pass an $a object / string to get_string 1395 */ 1396 function setRestrictStr($str) { 1397 $this->restrict_str=$str; 1398 } 1399 1400 /** 1401 * Get the status 1402 * 1403 * @return bool true means the test passed and all is OK. false means it failed. 1404 */ 1405 function getStatus() { 1406 return $this->status; 1407 } 1408 1409 /** 1410 * Get the error code 1411 * 1412 * @return integer error code 1413 */ 1414 function getErrorCode() { 1415 return $this->error_code; 1416 } 1417 1418 /** 1419 * Get the level 1420 * 1421 * @return string level 1422 */ 1423 function getLevel() { 1424 return $this->level; 1425 } 1426 1427 /** 1428 * Get the current version 1429 * 1430 * @return string current version 1431 */ 1432 function getCurrentVersion() { 1433 return $this->current_version; 1434 } 1435 1436 /** 1437 * Get the needed version 1438 * 1439 * @return string needed version 1440 */ 1441 function getNeededVersion() { 1442 return $this->needed_version; 1443 } 1444 1445 /** 1446 * Get the aux info 1447 * 1448 * @return string info 1449 */ 1450 function getInfo() { 1451 return $this->info; 1452 } 1453 1454 /** 1455 * Get the part this result belongs to 1456 * 1457 * @return string part 1458 */ 1459 function getPart() { 1460 return $this->part; 1461 } 1462 1463 /** 1464 * Get the feedback string 1465 * 1466 * @return mixed feedback string (can be an array of params for get_string or a single string to fetch from 1467 * admin.php lang file). 1468 */ 1469 function getFeedbackStr() { 1470 return $this->feedback_str; 1471 } 1472 1473 /** 1474 * Get the bypass string 1475 * 1476 * @return mixed bypass string (can be an array of params for get_string or a single string to fetch from 1477 * admin.php lang file). 1478 */ 1479 function getBypassStr() { 1480 return $this->bypass_str; 1481 } 1482 1483 /** 1484 * Get the restrict string 1485 * 1486 * @return mixed restrict string (can be an array of params for get_string or a single string to fetch from 1487 * admin.php lang file). 1488 */ 1489 function getRestrictStr() { 1490 return $this->restrict_str; 1491 } 1492 1493 /** 1494 * @todo Document this function 1495 * 1496 * @param mixed $string params for get_string, either a string to fetch from admin.php or an array of 1497 * params for get_string. 1498 * @param string $class css class(es) for message. 1499 * @return string feedback string fetched from lang file wrapped in p tag with class $class or returns 1500 * empty string if $string is empty. 1501 */ 1502 function strToReport($string, $class){ 1503 if (!empty($string)){ 1504 if (is_array($string)){ 1505 $str = call_user_func_array('get_string', $string); 1506 } else { 1507 $str = get_string($string, 'admin'); 1508 } 1509 return '<p class="'.$class.'">'.$str.'</p>'; 1510 } else { 1511 return ''; 1512 } 1513 } 1514 1515 /** 1516 * Get plugin name. 1517 * 1518 * @return string plugin name 1519 */ 1520 function getPluginName() { 1521 if ($this->plugin) { 1522 $manager = core_plugin_manager::instance(); 1523 list($plugintype, $pluginname) = core_component::normalize_component($this->plugin); 1524 return $manager->plugintype_name($plugintype) . ' / ' . $manager->plugin_name($this->plugin); 1525 } else { 1526 return ''; 1527 } 1528 } 1529 } 1530 1531 /// Here all the restrict functions are coded to be used by the environment 1532 /// checker. All those functions will receive the result object and will 1533 /// return it modified as needed (status and bypass string) 1534 1535 /** 1536 * @param array $element the element from the environment.xml file that should have 1537 * either a level="required" or level="optional" attribute. 1538 * @return string "required" or "optional". 1539 */ 1540 function get_level($element) { 1541 $level = 'required'; 1542 if (isset($element['@']['level'])) { 1543 $level = $element['@']['level']; 1544 if (!in_array($level, array('required', 'optional'))) { 1545 debugging('The level of a check in the environment.xml file must be "required" or "optional".', DEBUG_DEVELOPER); 1546 $level = 'required'; 1547 } 1548 } else { 1549 debugging('Checks in the environment.xml file must have a level="required" or level="optional" attribute.', DEBUG_DEVELOPER); 1550 } 1551 return $level; 1552 } 1553 1554 /** 1555 * Once the result has been determined, look in the XML for any 1556 * messages, or other things that should be done depending on the outcome. 1557 * 1558 * @param array $element the element from the environment.xml file which 1559 * may have children defining what should be done with the outcome. 1560 * @param object $result the result of the test, which may be modified by 1561 * this function as specified in the XML. 1562 */ 1563 function process_environment_result($element, &$result) { 1564 /// Process messages, modifying the $result if needed. 1565 process_environment_messages($element, $result); 1566 /// Process bypass, modifying $result if needed. 1567 process_environment_bypass($element, $result); 1568 /// Process restrict, modifying $result if needed. 1569 process_environment_restrict($element, $result); 1570 } 1571 1572 /** 1573 * Check if the current PHP version is greater than or equal to 1574 * PHP version 7. 1575 * 1576 * @param object $result an environment_results instance 1577 * @return bool result of version check 1578 */ 1579 function restrict_php_version_7(&$result) { 1580 return restrict_php_version($result, '7'); 1581 } 1582 1583 /** 1584 * Check if the current PHP version is greater than or equal to an 1585 * unsupported version. 1586 * 1587 * @param object $result an environment_results instance 1588 * @param string $version the version of PHP that can't be used 1589 * @return bool result of version check 1590 */ 1591 function restrict_php_version(&$result, $version) { 1592 1593 // Get the current PHP version. 1594 $currentversion = normalize_version(phpversion()); 1595 1596 // Confirm we're using a supported PHP version. 1597 if (version_compare($currentversion, $version, '<')) { 1598 // Everything is ok, the restriction doesn't apply. 1599 return false; 1600 } else { 1601 // We're using an unsupported PHP version, apply restriction. 1602 return true; 1603 } 1604 } 1605 1606 /** 1607 * Check if the current PHP version is greater than or equal to 1608 * PHP version 7.1. 1609 * 1610 * @param object $result an environment_results instance 1611 * @return bool result of version check 1612 */ 1613 function restrict_php_version_71(&$result) { 1614 return restrict_php_version($result, '7.1'); 1615 } 1616 1617 /** 1618 * Check if the current PHP version is greater than or equal to 1619 * PHP version 7.2. 1620 * 1621 * @param object $result an environment_results instance 1622 * @return bool result of version check 1623 */ 1624 function restrict_php_version_72(&$result) { 1625 return restrict_php_version($result, '7.2'); 1626 } 1627 1628 /** 1629 * Check if the current PHP version is greater than or equal to 1630 * PHP version 7.3. 1631 * 1632 * @param object $result an environment_results instance 1633 * @return bool result of version check 1634 */ 1635 function restrict_php_version_73(&$result) { 1636 return restrict_php_version($result, '7.3'); 1637 } 1638 1639 /** 1640 * Check if the current PHP version is greater than or equal to 1641 * PHP version 7.4. 1642 * 1643 * @param object $result an environment_results instance 1644 * @return bool result of version check 1645 */ 1646 function restrict_php_version_74(&$result) { 1647 return restrict_php_version($result, '7.4'); 1648 } 1649 1650 /** 1651 * Check if the current PHP version is greater than or equal to 1652 * PHP version 8.0 1653 * 1654 * @param object $result an environment_results instance 1655 * @return bool result of version check 1656 */ 1657 function restrict_php_version_80($result) { 1658 return restrict_php_version($result, '8.0'); 1659 } 1660 1661 /** 1662 * Check if the current PHP version is greater than or equal to 1663 * PHP version 8.1 1664 * 1665 * @param object $result an environment_results instance 1666 * @return bool result of version check 1667 */ 1668 function restrict_php_version_81($result) { 1669 return restrict_php_version($result, '8.1'); 1670 } 1671 1672 /** 1673 * Check if the current PHP version is greater than or equal to 1674 * PHP version 8.2 1675 * 1676 * @param object $result an environment_results instance 1677 * @return bool result of version check 1678 */ 1679 function restrict_php_version_82($result) { 1680 return restrict_php_version($result, '8.2'); 1681 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body