Differences Between: [Versions 310 and 403] [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, true)) { 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, true)) { 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 so, at all effects 812 // it's like we are running the previous version. 813 $versionarr = explode('.', $current_version); 814 if (isset($versionarr[1]) and $versionarr[1] > 0) { 815 $versionarr[1]--; 816 $current_version = implode('.', $versionarr); 817 } else { 818 $current_version = $current_version - 0.1; 819 } 820 } 821 822 /// And finally compare them, saving results 823 if (version_compare($current_version, $needed_version, '>=')) { 824 $result->setStatus(true); 825 } else { 826 $result->setStatus(false); 827 } 828 $result->setLevel('required'); 829 $result->setCurrentVersion($release); 830 $result->setNeededVersion($needed_version); 831 832 return $result; 833 } 834 835 /** 836 * This function will check if php requirements are satisfied 837 * 838 * @uses NO_VERSION_DATA_FOUND 839 * @uses NO_PHP_SECTION_FOUND 840 * @uses NO_PHP_VERSION_FOUND 841 * @param string $version xml version we are going to use to test this server 842 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 843 * @return object results encapsulated in one environment_result object 844 */ 845 function environment_check_php($version, $env_select) { 846 847 $result = new environment_results('php'); 848 849 /// Get the enviroment version we need 850 if (!$data = get_environment_for_version($version, $env_select)) { 851 /// Error. No version data found 852 $result->setStatus(false); 853 $result->setErrorCode(NO_VERSION_DATA_FOUND); 854 return $result; 855 } 856 857 /// Extract the php part 858 if (!isset($data['#']['PHP'])) { 859 /// Error. No PHP section found 860 $result->setStatus(false); 861 $result->setErrorCode(NO_PHP_SECTION_FOUND); 862 return $result; 863 } else { 864 /// Extract level and version 865 $level = get_level($data['#']['PHP']['0']); 866 if (!isset($data['#']['PHP']['0']['@']['version'])) { 867 $result->setStatus(false); 868 $result->setErrorCode(NO_PHP_VERSION_FOUND); 869 return $result; 870 } else { 871 $needed_version = $data['#']['PHP']['0']['@']['version']; 872 } 873 } 874 875 /// Now search the version we are using 876 $current_version = normalize_version(phpversion()); 877 878 /// And finally compare them, saving results 879 if (version_compare($current_version, $needed_version, '>=')) { 880 $result->setStatus(true); 881 } else { 882 $result->setStatus(false); 883 } 884 $result->setLevel($level); 885 $result->setCurrentVersion($current_version); 886 $result->setNeededVersion($needed_version); 887 888 /// Do any actions defined in the XML file. 889 process_environment_result($data['#']['PHP'][0], $result); 890 891 return $result; 892 } 893 894 /** 895 * Looks for buggy PCRE implementation, we need unicode support in Moodle... 896 * @param string $version xml version we are going to use to test this server 897 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 898 * @return stdClass results encapsulated in one environment_result object, null if irrelevant 899 */ 900 function environment_check_pcre_unicode($version, $env_select) { 901 $result = new environment_results('pcreunicode'); 902 903 // Get the environment version we need 904 if (!$data = get_environment_for_version($version, $env_select)) { 905 // Error. No version data found! 906 $result->setStatus(false); 907 $result->setErrorCode(NO_VERSION_DATA_FOUND); 908 return $result; 909 } 910 911 if (!isset($data['#']['PCREUNICODE'])) { 912 return null; 913 } 914 915 $level = get_level($data['#']['PCREUNICODE']['0']); 916 $result->setLevel($level); 917 918 if (!function_exists('preg_match')) { 919 // The extension test fails instead. 920 return null; 921 922 } else if (@preg_match('/\pL/u', 'a') and @preg_match('/á/iu', 'Á')) { 923 $result->setStatus(true); 924 925 } else { 926 $result->setStatus(false); 927 } 928 929 // Do any actions defined in the XML file. 930 process_environment_result($data['#']['PCREUNICODE'][0], $result); 931 932 return $result; 933 } 934 935 /** 936 * This function will check if unicode database requirements are satisfied 937 * 938 * @uses NO_VERSION_DATA_FOUND 939 * @uses NO_UNICODE_SECTION_FOUND 940 * @param string $version xml version we are going to use to test this server 941 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 942 * @return object results encapsulated in one environment_result object 943 */ 944 function environment_check_unicode($version, $env_select) { 945 global $DB; 946 947 $result = new environment_results('unicode'); 948 949 /// Get the enviroment version we need 950 if (!$data = get_environment_for_version($version, $env_select)) { 951 /// Error. No version data found 952 $result->setStatus(false); 953 $result->setErrorCode(NO_VERSION_DATA_FOUND); 954 return $result; 955 } 956 957 /// Extract the unicode part 958 959 if (!isset($data['#']['UNICODE'])) { 960 /// Error. No UNICODE section found 961 $result->setStatus(false); 962 $result->setErrorCode(NO_UNICODE_SECTION_FOUND); 963 return $result; 964 } else { 965 /// Extract level 966 $level = get_level($data['#']['UNICODE']['0']); 967 } 968 969 if (!$unicodedb = $DB->setup_is_unicodedb()) { 970 $result->setStatus(false); 971 } else { 972 $result->setStatus(true); 973 } 974 975 $result->setLevel($level); 976 977 /// Do any actions defined in the XML file. 978 process_environment_result($data['#']['UNICODE'][0], $result); 979 980 return $result; 981 } 982 983 /** 984 * This function will check if database requirements are satisfied 985 * 986 * @uses NO_VERSION_DATA_FOUND 987 * @uses NO_DATABASE_SECTION_FOUND 988 * @uses NO_DATABASE_VENDORS_FOUND 989 * @uses NO_DATABASE_VENDOR_MYSQL_FOUND 990 * @uses NO_DATABASE_VENDOR_POSTGRES_FOUND 991 * @uses NO_DATABASE_VENDOR_VERSION_FOUND 992 * @param string $version xml version we are going to use to test this server 993 * @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name. 994 * @return object results encapsulated in one environment_result object 995 */ 996 function environment_check_database($version, $env_select) { 997 998 global $DB; 999 1000 $result = new environment_results('database'); 1001 1002 $vendors = array(); //Array of vendors in version 1003 1004 /// Get the enviroment version we need 1005 if (!$data = get_environment_for_version($version, $env_select)) { 1006 /// Error. No version data found 1007 $result->setStatus(false); 1008 $result->setErrorCode(NO_VERSION_DATA_FOUND); 1009 return $result; 1010 } 1011 1012 /// Extract the database part 1013 if (!isset($data['#']['DATABASE'])) { 1014 /// Error. No DATABASE section found 1015 $result->setStatus(false); 1016 $result->setErrorCode(NO_DATABASE_SECTION_FOUND); 1017 return $result; 1018 } else { 1019 /// Extract level 1020 $level = get_level($data['#']['DATABASE']['0']); 1021 } 1022 1023 /// Extract DB vendors. At least 2 are mandatory (mysql & postgres) 1024 if (!isset($data['#']['DATABASE']['0']['#']['VENDOR'])) { 1025 /// Error. No VENDORS found 1026 $result->setStatus(false); 1027 $result->setErrorCode(NO_DATABASE_VENDORS_FOUND); 1028 return $result; 1029 } else { 1030 /// Extract vendors 1031 foreach ($data['#']['DATABASE']['0']['#']['VENDOR'] as $vendor) { 1032 if (isset($vendor['@']['name']) && isset($vendor['@']['version'])) { 1033 $vendors[$vendor['@']['name']] = $vendor['@']['version']; 1034 $vendorsxml[$vendor['@']['name']] = $vendor; 1035 } 1036 } 1037 } 1038 /// Check we have the mysql vendor version 1039 if (empty($vendors['mysql'])) { 1040 $result->setStatus(false); 1041 $result->setErrorCode(NO_DATABASE_VENDOR_MYSQL_FOUND); 1042 return $result; 1043 } 1044 /// Check we have the postgres vendor version 1045 if (empty($vendors['postgres'])) { 1046 $result->setStatus(false); 1047 $result->setErrorCode(NO_DATABASE_VENDOR_POSTGRES_FOUND); 1048 return $result; 1049 } 1050 1051 /// Now search the version we are using (depending of vendor) 1052 $current_vendor = $DB->get_dbvendor(); 1053 1054 $dbinfo = $DB->get_server_info(); 1055 $current_version = normalize_version($dbinfo['version']); 1056 $needed_version = $vendors[$current_vendor]; 1057 1058 /// Check we have a needed version 1059 if (!$needed_version) { 1060 $result->setStatus(false); 1061 $result->setErrorCode(NO_DATABASE_VENDOR_VERSION_FOUND); 1062 return $result; 1063 } 1064 1065 // Check if the DB Vendor has been properly configured. 1066 // Hack: this is required when playing with MySQL and MariaDB since they share the same PHP module and base DB classes, 1067 // whilst they are slowly evolving using separate directions though MariaDB is still an "almost" drop-in replacement. 1068 $dbvendorismysql = ($current_vendor === 'mysql'); 1069 $dbtypeismariadb = (stripos($dbinfo['description'], 'mariadb') !== false); 1070 if ($dbvendorismysql && $dbtypeismariadb) { 1071 $result->setStatus(false); 1072 $result->setLevel($level); 1073 $result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')'); 1074 $result->setFeedbackStr('environmentmariadbwrongdbtype'); 1075 return $result; 1076 } 1077 1078 /// And finally compare them, saving results 1079 if (version_compare($current_version, $needed_version, '>=')) { 1080 $result->setStatus(true); 1081 } else { 1082 $result->setStatus(false); 1083 } 1084 $result->setLevel($level); 1085 $result->setCurrentVersion($current_version); 1086 $result->setNeededVersion($needed_version); 1087 $result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')'); 1088 1089 /// Do any actions defined in the XML file. 1090 process_environment_result($vendorsxml[$current_vendor], $result); 1091 1092 return $result; 1093 1094 } 1095 1096 /** 1097 * This function will post-process the result record by executing the specified 1098 * function, modifying it as necessary, also a custom message will be added 1099 * to the result object to be printed by the display layer. 1100 * Every bypass function must be defined in this file and it'll return 1101 * true/false to decide if the original test is bypassed or no. Also 1102 * such bypass functions are able to directly handling the result object 1103 * although it should be only under exceptional conditions. 1104 * 1105 * @param string xmldata containing the bypass data 1106 * @param object result object to be updated 1107 * @return void 1108 */ 1109 function process_environment_bypass($xml, &$result) { 1110 1111 /// Only try to bypass if we were in error and it was required 1112 if ($result->getStatus() || $result->getLevel() == 'optional') { 1113 return; 1114 } 1115 1116 /// It there is bypass info (function and message) 1117 if (is_array($xml['#']) && isset($xml['#']['BYPASS'][0]['@']['function']) && isset($xml['#']['BYPASS'][0]['@']['message'])) { 1118 $function = $xml['#']['BYPASS'][0]['@']['function']; 1119 $message = $xml['#']['BYPASS'][0]['@']['message']; 1120 /// Look for the function 1121 if (function_exists($function)) { 1122 /// Call it, and if bypass = true is returned, apply meesage 1123 if ($function($result)) { 1124 /// We only set the bypass message if the function itself hasn't defined it before 1125 if (empty($result->getBypassStr)) { 1126 if (isset($xml['#']['BYPASS'][0]['@']['plugin'])) { 1127 $result->setBypassStr(array($message, $xml['#']['BYPASS'][0]['@']['plugin'])); 1128 } else { 1129 $result->setBypassStr($message); 1130 } 1131 } 1132 } 1133 } 1134 } 1135 } 1136 1137 /** 1138 * This function will post-process the result record by executing the specified 1139 * function, modifying it as necessary, also a custom message will be added 1140 * to the result object to be printed by the display layer. 1141 * Every restrict function must be defined in this file and it'll return 1142 * true/false to decide if the original test is restricted or no. Also 1143 * such restrict functions are able to directly handling the result object 1144 * although it should be only under exceptional conditions. 1145 * 1146 * @param string xmldata containing the restrict data 1147 * @param object result object to be updated 1148 * @return void 1149 */ 1150 function process_environment_restrict($xml, &$result) { 1151 1152 /// Only try to restrict if we were not in error and it was required 1153 if (!$result->getStatus() || $result->getLevel() == 'optional') { 1154 return; 1155 } 1156 /// It there is restrict info (function and message) 1157 if (is_array($xml['#']) && isset($xml['#']['RESTRICT'][0]['@']['function']) && isset($xml['#']['RESTRICT'][0]['@']['message'])) { 1158 $function = $xml['#']['RESTRICT'][0]['@']['function']; 1159 $message = $xml['#']['RESTRICT'][0]['@']['message']; 1160 /// Look for the function 1161 if (function_exists($function)) { 1162 /// Call it, and if restrict = true is returned, apply meesage 1163 if ($function($result)) { 1164 /// We only set the restrict message if the function itself hasn't defined it before 1165 if (empty($result->getRestrictStr)) { 1166 if (isset($xml['#']['RESTRICT'][0]['@']['plugin'])) { 1167 $result->setRestrictStr(array($message, $xml['#']['RESTRICT'][0]['@']['plugin'])); 1168 } else { 1169 $result->setRestrictStr($message); 1170 } 1171 } 1172 } 1173 } 1174 } 1175 } 1176 1177 /** 1178 * This function will detect if there is some message available to be added to the 1179 * result in order to clarify enviromental details. 1180 * 1181 * @uses INCORRECT_FEEDBACK_FOR_REQUIRED 1182 * @uses INCORRECT_FEEDBACK_FOR_OPTIONAL 1183 * @param string xmldata containing the feedback data 1184 * @param object reult object to be updated 1185 */ 1186 function process_environment_messages($xml, &$result) { 1187 1188 /// If there is feedback info 1189 if (is_array($xml['#']) && isset($xml['#']['FEEDBACK'][0]['#'])) { 1190 $feedbackxml = $xml['#']['FEEDBACK'][0]['#']; 1191 1192 // Detect some incorrect feedback combinations. 1193 if ($result->getLevel() == 'required' and isset($feedbackxml['ON_CHECK'])) { 1194 $result->setStatus(false); 1195 $result->setErrorCode(INCORRECT_FEEDBACK_FOR_REQUIRED); 1196 } else if ($result->getLevel() == 'optional' and isset($feedbackxml['ON_ERROR'])) { 1197 $result->setStatus(false); 1198 $result->setErrorCode(INCORRECT_FEEDBACK_FOR_OPTIONAL); 1199 } 1200 1201 if (!$result->status and $result->getLevel() == 'required') { 1202 if (isset($feedbackxml['ON_ERROR'][0]['@']['message'])) { 1203 if (isset($feedbackxml['ON_ERROR'][0]['@']['plugin'])) { 1204 $result->setFeedbackStr(array($feedbackxml['ON_ERROR'][0]['@']['message'], $feedbackxml['ON_ERROR'][0]['@']['plugin'])); 1205 } else { 1206 $result->setFeedbackStr($feedbackxml['ON_ERROR'][0]['@']['message']); 1207 } 1208 } 1209 } else if (!$result->status and $result->getLevel() == 'optional') { 1210 if (isset($feedbackxml['ON_CHECK'][0]['@']['message'])) { 1211 if (isset($feedbackxml['ON_CHECK'][0]['@']['plugin'])) { 1212 $result->setFeedbackStr(array($feedbackxml['ON_CHECK'][0]['@']['message'], $feedbackxml['ON_CHECK'][0]['@']['plugin'])); 1213 } else { 1214 $result->setFeedbackStr($feedbackxml['ON_CHECK'][0]['@']['message']); 1215 } 1216 } 1217 } else { 1218 if (isset($feedbackxml['ON_OK'][0]['@']['message'])) { 1219 if (isset($feedbackxml['ON_OK'][0]['@']['plugin'])) { 1220 $result->setFeedbackStr(array($feedbackxml['ON_OK'][0]['@']['message'], $feedbackxml['ON_OK'][0]['@']['plugin'])); 1221 } else { 1222 $result->setFeedbackStr($feedbackxml['ON_OK'][0]['@']['message']); 1223 } 1224 } 1225 } 1226 } 1227 } 1228 1229 1230 //--- Helper Class to return results to caller ---// 1231 1232 1233 /** 1234 * Helper Class to return results to caller 1235 * 1236 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 1237 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 1238 * @package moodlecore 1239 */ 1240 class environment_results { 1241 /** 1242 * @var string Which are we checking (database, php, php_extension, php_extension) 1243 */ 1244 var $part; 1245 /** 1246 * @var bool true means the test passed and all is OK. false means it failed. 1247 */ 1248 var $status; 1249 /** 1250 * @var integer See constants at the beginning of the file 1251 */ 1252 var $error_code; 1253 /** 1254 * @var string required/optional 1255 */ 1256 var $level; 1257 /** 1258 * @var string current version detected 1259 */ 1260 var $current_version; 1261 /** 1262 * @var string version needed 1263 */ 1264 var $needed_version; 1265 /** 1266 * @var string Aux. info (DB vendor, library...) 1267 */ 1268 var $info; 1269 /** 1270 * @var string String to show on error|on check|on ok 1271 */ 1272 var $feedback_str; 1273 /** 1274 * @var string String to show if some bypass has happened 1275 */ 1276 var $bypass_str; 1277 /** 1278 * @var string String to show if some restrict has happened 1279 */ 1280 var $restrict_str; 1281 /** 1282 * @var string|null full plugin name or null if main environment 1283 */ 1284 var $plugin = null; 1285 /** 1286 * Constructor of the environment_result class. Just set default values 1287 * 1288 * @param string $part 1289 */ 1290 public function __construct($part) { 1291 $this->part=$part; 1292 $this->status=false; 1293 $this->error_code=NO_ERROR; 1294 $this->level='required'; 1295 $this->current_version=''; 1296 $this->needed_version=''; 1297 $this->info=''; 1298 $this->feedback_str=''; 1299 $this->bypass_str=''; 1300 $this->restrict_str=''; 1301 } 1302 1303 /** 1304 * Old syntax of class constructor. Deprecated in PHP7. 1305 * 1306 * @deprecated since Moodle 3.1 1307 */ 1308 public function environment_results($part) { 1309 debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); 1310 self::__construct($part); 1311 } 1312 1313 /** 1314 * Set the status 1315 * 1316 * @param bool $testpassed true means the test passed and all is OK. false means it failed. 1317 */ 1318 function setStatus($testpassed) { 1319 $this->status = $testpassed; 1320 if ($testpassed) { 1321 $this->setErrorCode(NO_ERROR); 1322 } 1323 } 1324 1325 /** 1326 * Set the error_code 1327 * 1328 * @param integer $error_code the error code (see constants above) 1329 */ 1330 function setErrorCode($error_code) { 1331 $this->error_code=$error_code; 1332 } 1333 1334 /** 1335 * Set the level 1336 * 1337 * @param string $level the level (required, optional) 1338 */ 1339 function setLevel($level) { 1340 $this->level=$level; 1341 } 1342 1343 /** 1344 * Set the current version 1345 * 1346 * @param string $current_version the current version 1347 */ 1348 function setCurrentVersion($current_version) { 1349 $this->current_version=$current_version; 1350 } 1351 1352 /** 1353 * Set the needed version 1354 * 1355 * @param string $needed_version the needed version 1356 */ 1357 function setNeededVersion($needed_version) { 1358 $this->needed_version=$needed_version; 1359 } 1360 1361 /** 1362 * Set the auxiliary info 1363 * 1364 * @param string $info the auxiliary info 1365 */ 1366 function setInfo($info) { 1367 $this->info=$info; 1368 } 1369 1370 /** 1371 * Set the feedback string 1372 * 1373 * @param mixed $str the feedback string that will be fetched from the admin lang file. 1374 * pass just the string or pass an array of params for get_string 1375 * You always should put your string in admin.php but a third param is useful 1376 * to pass an $a object / string to get_string 1377 */ 1378 function setFeedbackStr($str) { 1379 $this->feedback_str=$str; 1380 } 1381 1382 1383 /** 1384 * Set the bypass string 1385 * 1386 * @param string $str the bypass string that will be fetched from the admin lang file. 1387 * pass just the string or pass an array of params for get_string 1388 * You always should put your string in admin.php but a third param is useful 1389 * to pass an $a object / string to get_string 1390 */ 1391 function setBypassStr($str) { 1392 $this->bypass_str=$str; 1393 } 1394 1395 /** 1396 * Set the restrict string 1397 * 1398 * @param string $str the restrict string that will be fetched from the admin lang file. 1399 * pass just the string or pass an array of params for get_string 1400 * You always should put your string in admin.php but a third param is useful 1401 * to pass an $a object / string to get_string 1402 */ 1403 function setRestrictStr($str) { 1404 $this->restrict_str=$str; 1405 } 1406 1407 /** 1408 * Get the status 1409 * 1410 * @return bool true means the test passed and all is OK. false means it failed. 1411 */ 1412 function getStatus() { 1413 return $this->status; 1414 } 1415 1416 /** 1417 * Get the error code 1418 * 1419 * @return integer error code 1420 */ 1421 function getErrorCode() { 1422 return $this->error_code; 1423 } 1424 1425 /** 1426 * Get the level 1427 * 1428 * @return string level 1429 */ 1430 function getLevel() { 1431 return $this->level; 1432 } 1433 1434 /** 1435 * Get the current version 1436 * 1437 * @return string current version 1438 */ 1439 function getCurrentVersion() { 1440 return $this->current_version; 1441 } 1442 1443 /** 1444 * Get the needed version 1445 * 1446 * @return string needed version 1447 */ 1448 function getNeededVersion() { 1449 return $this->needed_version; 1450 } 1451 1452 /** 1453 * Get the aux info 1454 * 1455 * @return string info 1456 */ 1457 function getInfo() { 1458 return $this->info; 1459 } 1460 1461 /** 1462 * Get the part this result belongs to 1463 * 1464 * @return string part 1465 */ 1466 function getPart() { 1467 return $this->part; 1468 } 1469 1470 /** 1471 * Get the feedback string 1472 * 1473 * @return mixed feedback string (can be an array of params for get_string or a single string to fetch from 1474 * admin.php lang file). 1475 */ 1476 function getFeedbackStr() { 1477 return $this->feedback_str; 1478 } 1479 1480 /** 1481 * Get the bypass string 1482 * 1483 * @return mixed bypass string (can be an array of params for get_string or a single string to fetch from 1484 * admin.php lang file). 1485 */ 1486 function getBypassStr() { 1487 return $this->bypass_str; 1488 } 1489 1490 /** 1491 * Get the restrict string 1492 * 1493 * @return mixed restrict string (can be an array of params for get_string or a single string to fetch from 1494 * admin.php lang file). 1495 */ 1496 function getRestrictStr() { 1497 return $this->restrict_str; 1498 } 1499 1500 /** 1501 * @todo Document this function 1502 * 1503 * @param mixed $string params for get_string, either a string to fetch from admin.php or an array of 1504 * params for get_string. 1505 * @param string $class css class(es) for message. 1506 * @return string feedback string fetched from lang file wrapped in p tag with class $class or returns 1507 * empty string if $string is empty. 1508 */ 1509 function strToReport($string, $class){ 1510 if (!empty($string)){ 1511 if (is_array($string)){ 1512 $str = call_user_func_array('get_string', $string); 1513 } else { 1514 $str = get_string($string, 'admin'); 1515 } 1516 return '<p class="'.$class.'">'.$str.'</p>'; 1517 } else { 1518 return ''; 1519 } 1520 } 1521 1522 /** 1523 * Get plugin name. 1524 * 1525 * @return string plugin name 1526 */ 1527 function getPluginName() { 1528 if ($this->plugin) { 1529 $manager = core_plugin_manager::instance(); 1530 list($plugintype, $pluginname) = core_component::normalize_component($this->plugin); 1531 return $manager->plugintype_name($plugintype) . ' / ' . $manager->plugin_name($this->plugin); 1532 } else { 1533 return ''; 1534 } 1535 } 1536 } 1537 1538 /// Here all the restrict functions are coded to be used by the environment 1539 /// checker. All those functions will receive the result object and will 1540 /// return it modified as needed (status and bypass string) 1541 1542 /** 1543 * @param array $element the element from the environment.xml file that should have 1544 * either a level="required" or level="optional" attribute. 1545 * @return string "required" or "optional". 1546 */ 1547 function get_level($element) { 1548 $level = 'required'; 1549 if (isset($element['@']['level'])) { 1550 $level = $element['@']['level']; 1551 if (!in_array($level, array('required', 'optional'))) { 1552 debugging('The level of a check in the environment.xml file must be "required" or "optional".', DEBUG_DEVELOPER); 1553 $level = 'required'; 1554 } 1555 } else { 1556 debugging('Checks in the environment.xml file must have a level="required" or level="optional" attribute.', DEBUG_DEVELOPER); 1557 } 1558 return $level; 1559 } 1560 1561 /** 1562 * Once the result has been determined, look in the XML for any 1563 * messages, or other things that should be done depending on the outcome. 1564 * 1565 * @param array $element the element from the environment.xml file which 1566 * may have children defining what should be done with the outcome. 1567 * @param object $result the result of the test, which may be modified by 1568 * this function as specified in the XML. 1569 */ 1570 function process_environment_result($element, &$result) { 1571 /// Process messages, modifying the $result if needed. 1572 process_environment_messages($element, $result); 1573 /// Process bypass, modifying $result if needed. 1574 process_environment_bypass($element, $result); 1575 /// Process restrict, modifying $result if needed. 1576 process_environment_restrict($element, $result); 1577 } 1578 1579 /** 1580 * Check if the current PHP version is greater than or equal to 1581 * PHP version 7. 1582 * 1583 * @param object $result an environment_results instance 1584 * @return bool result of version check 1585 */ 1586 function restrict_php_version_7(&$result) { 1587 return restrict_php_version($result, '7'); 1588 } 1589 1590 /** 1591 * Check if the current PHP version is greater than or equal to an 1592 * unsupported version. 1593 * 1594 * @param object $result an environment_results instance 1595 * @param string $version the version of PHP that can't be used 1596 * @return bool result of version check 1597 */ 1598 function restrict_php_version(&$result, $version) { 1599 1600 // Get the current PHP version. 1601 $currentversion = normalize_version(phpversion()); 1602 1603 // Confirm we're using a supported PHP version. 1604 if (version_compare($currentversion, $version, '<')) { 1605 // Everything is ok, the restriction doesn't apply. 1606 return false; 1607 } else { 1608 // We're using an unsupported PHP version, apply restriction. 1609 return true; 1610 } 1611 } 1612 1613 /** 1614 * Check if the current PHP version is greater than or equal to 1615 * PHP version 7.1. 1616 * 1617 * @param object $result an environment_results instance 1618 * @return bool result of version check 1619 */ 1620 function restrict_php_version_71(&$result) { 1621 return restrict_php_version($result, '7.1'); 1622 } 1623 1624 /** 1625 * Check if the current PHP version is greater than or equal to 1626 * PHP version 7.2. 1627 * 1628 * @param object $result an environment_results instance 1629 * @return bool result of version check 1630 */ 1631 function restrict_php_version_72(&$result) { 1632 return restrict_php_version($result, '7.2'); 1633 } 1634 1635 /** 1636 * Check if the current PHP version is greater than or equal to 1637 * PHP version 7.3. 1638 * 1639 * @param object $result an environment_results instance 1640 * @return bool result of version check 1641 */ 1642 function restrict_php_version_73(&$result) { 1643 return restrict_php_version($result, '7.3'); 1644 } 1645 1646 /** 1647 * Check if the current PHP version is greater than or equal to 1648 * PHP version 7.4. 1649 * 1650 * @param object $result an environment_results instance 1651 * @return bool result of version check 1652 */ 1653 function restrict_php_version_74(&$result) { 1654 return restrict_php_version($result, '7.4'); 1655 } 1656 1657 /** 1658 * Check if the current PHP version is greater than or equal to 1659 * PHP version 8.0 1660 * 1661 * @param object $result an environment_results instance 1662 * @return bool result of version check 1663 */ 1664 function restrict_php_version_80($result) { 1665 return restrict_php_version($result, '8.0'); 1666 } 1667 1668 /** 1669 * Check if the current PHP version is greater than or equal to 1670 * PHP version 8.1 1671 * 1672 * @param object $result an environment_results instance 1673 * @return bool result of version check 1674 */ 1675 function restrict_php_version_81($result) { 1676 return restrict_php_version($result, '8.1'); 1677 } 1678 1679 /** 1680 * Check if the current PHP version is greater than or equal to 1681 * PHP version 8.2 1682 * 1683 * @param object $result an environment_results instance 1684 * @return bool result of version check 1685 */ 1686 function restrict_php_version_82($result) { 1687 return restrict_php_version($result, '8.2'); 1688 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body