mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 06:18:28 +01:00
afe68a65cb
This commit adds an additional environment check for the unsupported PHP 8.1 version to Moodle 3.9.x, 3.11.x and 4.0.x. It also updates the lang string for unsupported PHP version. Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
1678 lines
58 KiB
PHP
1678 lines
58 KiB
PHP
<?php
|
|
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* This library includes all the necessary stuff to execute some standard
|
|
* tests of required versions and libraries to run Moodle. It can be
|
|
* used from the admin interface, and both at install and upgrade.
|
|
*
|
|
* All the info is stored in the admin/environment.xml file,
|
|
* supporting to have an updated version in dataroot/environment
|
|
*
|
|
* @copyright (C) 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
* @package core
|
|
* @subpackage admin
|
|
*/
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
/// Add required files
|
|
/**
|
|
* Include the necessary
|
|
*/
|
|
require_once($CFG->libdir.'/xmlize.php');
|
|
|
|
/// Define a bunch of XML processing errors
|
|
/** XML Processing Error */
|
|
define('NO_ERROR', 0);
|
|
/** XML Processing Error */
|
|
define('NO_VERSION_DATA_FOUND', 1);
|
|
/** XML Processing Error */
|
|
define('NO_DATABASE_SECTION_FOUND', 2);
|
|
/** XML Processing Error */
|
|
define('NO_DATABASE_VENDORS_FOUND', 3);
|
|
/** XML Processing Error */
|
|
define('NO_DATABASE_VENDOR_MYSQL_FOUND', 4);
|
|
/** XML Processing Error */
|
|
define('NO_DATABASE_VENDOR_POSTGRES_FOUND', 5);
|
|
/** XML Processing Error */
|
|
define('NO_PHP_SECTION_FOUND', 6);
|
|
/** XML Processing Error */
|
|
define('NO_PHP_VERSION_FOUND', 7);
|
|
/** XML Processing Error */
|
|
define('NO_PHP_EXTENSIONS_SECTION_FOUND', 8);
|
|
/** XML Processing Error */
|
|
define('NO_PHP_EXTENSIONS_NAME_FOUND', 9);
|
|
/** XML Processing Error */
|
|
define('NO_DATABASE_VENDOR_VERSION_FOUND', 10);
|
|
/** XML Processing Error */
|
|
define('NO_UNICODE_SECTION_FOUND', 11);
|
|
/** XML Processing Error */
|
|
define('NO_CUSTOM_CHECK_FOUND', 12);
|
|
/** XML Processing Error */
|
|
define('CUSTOM_CHECK_FILE_MISSING', 13);
|
|
/** XML Processing Error */
|
|
define('CUSTOM_CHECK_FUNCTION_MISSING', 14);
|
|
/** XML Processing Error */
|
|
define('NO_PHP_SETTINGS_NAME_FOUND', 15);
|
|
/** XML Processing Error */
|
|
define('INCORRECT_FEEDBACK_FOR_REQUIRED', 16);
|
|
/** XML Processing Error */
|
|
define('INCORRECT_FEEDBACK_FOR_OPTIONAL', 17);
|
|
|
|
/// Define algorithm used to select the xml file
|
|
/** To select the newer file available to perform checks */
|
|
define('ENV_SELECT_NEWER', 0);
|
|
/** To enforce the use of the file under dataroot */
|
|
define('ENV_SELECT_DATAROOT', 1);
|
|
/** To enforce the use of the file under admin (release) */
|
|
define('ENV_SELECT_RELEASE', 2);
|
|
|
|
/**
|
|
* This function checks all the requirements defined in environment.xml.
|
|
*
|
|
* @param string $version version to check.
|
|
* @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. Default ENV_SELECT_NEWER (BC)
|
|
* @return array with two elements. The first element true/false, depending on
|
|
* on whether the check passed. The second element is an array of environment_results
|
|
* objects that has detailed information about the checks and which ones passed.
|
|
*/
|
|
function check_moodle_environment($version, $env_select = ENV_SELECT_NEWER) {
|
|
if ($env_select != ENV_SELECT_NEWER and $env_select != ENV_SELECT_DATAROOT and $env_select != ENV_SELECT_RELEASE) {
|
|
throw new coding_exception('Incorrect value of $env_select parameter');
|
|
}
|
|
|
|
/// Get the more recent version before the requested
|
|
if (!$version = get_latest_version_available($version, $env_select)) {
|
|
return array(false, array());
|
|
}
|
|
|
|
/// Perform all the checks
|
|
if (!$environment_results = environment_check($version, $env_select)) {
|
|
return array(false, array());
|
|
}
|
|
|
|
/// Iterate over all the results looking for some error in required items
|
|
/// or some error_code
|
|
$result = true;
|
|
foreach ($environment_results as $environment_result) {
|
|
if (!$environment_result->getStatus() && $environment_result->getLevel() == 'required'
|
|
&& !$environment_result->getBypassStr()) {
|
|
$result = false; // required item that is not bypased
|
|
} else if ($environment_result->getStatus() && $environment_result->getLevel() == 'required'
|
|
&& $environment_result->getRestrictStr()) {
|
|
$result = false; // required item that is restricted
|
|
} else if ($environment_result->getErrorCode()) {
|
|
$result = false;
|
|
}
|
|
}
|
|
|
|
return array($result, $environment_results);
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns array of critical errors in plain text format
|
|
* @param array $environment_results array of results gathered
|
|
* @return array errors
|
|
*/
|
|
function environment_get_errors($environment_results) {
|
|
global $CFG;
|
|
$errors = array();
|
|
|
|
// Iterate over each environment_result
|
|
foreach ($environment_results as $environment_result) {
|
|
$type = $environment_result->getPart();
|
|
$info = $environment_result->getInfo();
|
|
$status = $environment_result->getStatus();
|
|
$plugin = $environment_result->getPluginName();
|
|
$error_code = $environment_result->getErrorCode();
|
|
|
|
$a = new stdClass();
|
|
if ($error_code) {
|
|
$a->error_code = $error_code;
|
|
$errors[] = array($info, get_string('environmentxmlerror', 'admin', $a));
|
|
return $errors;
|
|
}
|
|
|
|
/// Calculate the status value
|
|
if ($environment_result->getBypassStr() != '') {
|
|
// not interesting
|
|
continue;
|
|
} else if ($environment_result->getRestrictStr() != '') {
|
|
// error
|
|
} else {
|
|
if ($status) {
|
|
// ok
|
|
continue;
|
|
} else {
|
|
if ($environment_result->getLevel() == 'optional') {
|
|
// just a warning
|
|
continue;
|
|
} else {
|
|
// error
|
|
}
|
|
}
|
|
}
|
|
|
|
// We are comparing versions
|
|
$rec = new stdClass();
|
|
if ($rec->needed = $environment_result->getNeededVersion()) {
|
|
$rec->current = $environment_result->getCurrentVersion();
|
|
if ($environment_result->getLevel() == 'required') {
|
|
$stringtouse = 'environmentrequireversion';
|
|
} else {
|
|
$stringtouse = 'environmentrecommendversion';
|
|
}
|
|
// We are checking installed & enabled things
|
|
} else if ($environment_result->getPart() == 'custom_check') {
|
|
if ($environment_result->getLevel() == 'required') {
|
|
$stringtouse = 'environmentrequirecustomcheck';
|
|
} else {
|
|
$stringtouse = 'environmentrecommendcustomcheck';
|
|
}
|
|
} else if ($environment_result->getPart() == 'php_setting') {
|
|
if ($status) {
|
|
$stringtouse = 'environmentsettingok';
|
|
} else if ($environment_result->getLevel() == 'required') {
|
|
$stringtouse = 'environmentmustfixsetting';
|
|
} else {
|
|
$stringtouse = 'environmentshouldfixsetting';
|
|
}
|
|
} else {
|
|
if ($environment_result->getLevel() == 'required') {
|
|
$stringtouse = 'environmentrequireinstall';
|
|
} else {
|
|
$stringtouse = 'environmentrecommendinstall';
|
|
}
|
|
}
|
|
$report = get_string($stringtouse, 'admin', $rec);
|
|
|
|
// Here we'll store all the feedback found
|
|
$feedbacktext = '';
|
|
// Append the feedback if there is some
|
|
$feedbacktext .= $environment_result->strToReport($environment_result->getFeedbackStr(), 'error');
|
|
// Append the restrict if there is some
|
|
$feedbacktext .= $environment_result->strToReport($environment_result->getRestrictStr(), 'error');
|
|
|
|
if ($plugin === '') {
|
|
$report = '[' . get_string('coresystem') . '] ' . $report;
|
|
} else {
|
|
$report = '[' . $plugin . '] ' . $report;
|
|
}
|
|
|
|
$report .= ' - ' . html_to_text($feedbacktext);
|
|
|
|
if ($environment_result->getPart() == 'custom_check'){
|
|
$errors[] = array($info, $report);
|
|
} else {
|
|
$errors[] = array(($info !== '' ? "$type $info" : $type), $report);
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
|
|
/**
|
|
* This function will normalize any version to just a serie of numbers
|
|
* separated by dots. Everything else will be removed.
|
|
*
|
|
* @param string $version the original version
|
|
* @return string the normalized version
|
|
*/
|
|
function normalize_version($version) {
|
|
|
|
/// 1.9 Beta 2 should be read 1.9 on enviromental checks, not 1.9.2
|
|
/// we can discard everything after the first space
|
|
$version = trim($version);
|
|
$versionarr = explode(" ",$version);
|
|
if (!empty($versionarr)) {
|
|
$version = $versionarr[0];
|
|
}
|
|
/// Replace everything but numbers and dots by dots
|
|
$version = preg_replace('/[^\.\d]/', '.', $version);
|
|
/// Combine multiple dots in one
|
|
$version = preg_replace('/(\.{2,})/', '.', $version);
|
|
/// Trim possible leading and trailing dots
|
|
$version = trim($version, '.');
|
|
|
|
return $version;
|
|
}
|
|
|
|
|
|
/**
|
|
* This function will load the environment.xml file and xmlize it
|
|
*
|
|
* @staticvar array $data
|
|
* @uses ENV_SELECT_NEWER
|
|
* @uses ENV_SELECT_DATAROOT
|
|
* @uses ENV_SELECT_RELEASE
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return mixed the xmlized structure or false on error
|
|
*/
|
|
function load_environment_xml($env_select=ENV_SELECT_NEWER) {
|
|
|
|
global $CFG;
|
|
|
|
static $data = array(); // Only load and xmlize once by request.
|
|
|
|
if (isset($data[$env_select])) {
|
|
return $data[$env_select];
|
|
}
|
|
$contents = false;
|
|
|
|
if (is_numeric($env_select)) {
|
|
$file = $CFG->dataroot.'/environment/environment.xml';
|
|
$internalfile = $CFG->dirroot.'/'.$CFG->admin.'/environment.xml';
|
|
switch ($env_select) {
|
|
case ENV_SELECT_NEWER:
|
|
if (!is_file($file) || !is_readable($file) || filemtime($file) < filemtime($internalfile) ||
|
|
!$contents = file_get_contents($file)) {
|
|
/// Fallback to fixed $CFG->admin/environment.xml
|
|
if (!is_file($internalfile) || !is_readable($internalfile) || !$contents = file_get_contents($internalfile)) {
|
|
$contents = false;
|
|
}
|
|
}
|
|
break;
|
|
case ENV_SELECT_DATAROOT:
|
|
if (!is_file($file) || !is_readable($file) || !$contents = file_get_contents($file)) {
|
|
$contents = false;
|
|
}
|
|
break;
|
|
case ENV_SELECT_RELEASE:
|
|
if (!is_file($internalfile) || !is_readable($internalfile) || !$contents = file_get_contents($internalfile)) {
|
|
$contents = false;
|
|
}
|
|
break;
|
|
}
|
|
} else {
|
|
if ($plugindir = core_component::get_component_directory($env_select)) {
|
|
$pluginfile = "$plugindir/environment.xml";
|
|
if (!is_file($pluginfile) || !is_readable($pluginfile) || !$contents = file_get_contents($pluginfile)) {
|
|
$contents = false;
|
|
}
|
|
}
|
|
}
|
|
// XML the whole file.
|
|
if ($contents !== false) {
|
|
$contents = xmlize($contents);
|
|
}
|
|
|
|
$data[$env_select] = $contents;
|
|
|
|
return $data[$env_select];
|
|
}
|
|
|
|
|
|
/**
|
|
* This function will return the list of Moodle versions available
|
|
*
|
|
* @return array of versions
|
|
*/
|
|
function get_list_of_environment_versions($contents) {
|
|
$versions = array();
|
|
|
|
if (isset($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'])) {
|
|
foreach ($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'] as $version) {
|
|
$versions[] = $version['@']['version'];
|
|
}
|
|
}
|
|
|
|
if (isset($contents['COMPATIBILITY_MATRIX']['#']['PLUGIN'])) {
|
|
$versions[] = 'all';
|
|
}
|
|
|
|
return $versions;
|
|
}
|
|
|
|
|
|
/**
|
|
* This function will return the most recent version in the environment.xml
|
|
* file previous or equal to the version requested
|
|
*
|
|
* @param string $version top version from which we start to look backwards
|
|
* @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
|
|
* @return string|bool string more recent version or false if not found
|
|
*/
|
|
function get_latest_version_available($version, $env_select) {
|
|
if ($env_select != ENV_SELECT_NEWER and $env_select != ENV_SELECT_DATAROOT and $env_select != ENV_SELECT_RELEASE) {
|
|
throw new coding_exception('Incorrect value of $env_select parameter');
|
|
}
|
|
|
|
/// Normalize the version requested
|
|
$version = normalize_version($version);
|
|
|
|
/// Load xml file
|
|
if (!$contents = load_environment_xml($env_select)) {
|
|
return false;
|
|
}
|
|
|
|
/// Detect available versions
|
|
if (!$versions = get_list_of_environment_versions($contents)) {
|
|
return false;
|
|
}
|
|
/// First we look for exact version
|
|
if (in_array($version, $versions, true)) {
|
|
return $version;
|
|
} else {
|
|
$found_version = false;
|
|
/// Not exact match, so we are going to iterate over the list searching
|
|
/// for the latest version before the requested one
|
|
foreach ($versions as $arrversion) {
|
|
if (version_compare($arrversion, $version, '<')) {
|
|
$found_version = $arrversion;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $found_version;
|
|
}
|
|
|
|
|
|
/**
|
|
* This function will return the xmlized data belonging to one Moodle version
|
|
*
|
|
* @param string $version top version from which we start to look backwards
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return mixed the xmlized structure or false on error
|
|
*/
|
|
function get_environment_for_version($version, $env_select) {
|
|
|
|
/// Normalize the version requested
|
|
$version = normalize_version($version);
|
|
|
|
/// Load xml file
|
|
if (!$contents = load_environment_xml($env_select)) {
|
|
return false;
|
|
}
|
|
|
|
/// Detect available versions
|
|
if (!$versions = get_list_of_environment_versions($contents)) {
|
|
return false;
|
|
}
|
|
|
|
// If $env_select is not numeric then this is being called on a plugin, and not the core environment.xml
|
|
// If a version of 'all' is in the arry is also means that the new <PLUGIN> tag was found, this should
|
|
// be matched against any version of Moodle.
|
|
if (!is_numeric($env_select) && in_array('all', $versions)
|
|
&& environment_verify_plugin($env_select, $contents['COMPATIBILITY_MATRIX']['#']['PLUGIN'][0])) {
|
|
return $contents['COMPATIBILITY_MATRIX']['#']['PLUGIN'][0];
|
|
}
|
|
|
|
/// If the version requested is available
|
|
if (!in_array($version, $versions, true)) {
|
|
return false;
|
|
}
|
|
|
|
/// We now we have it. Extract from full contents.
|
|
$fl_arr = array_flip($versions);
|
|
|
|
return $contents['COMPATIBILITY_MATRIX']['#']['MOODLE'][$fl_arr[$version]];
|
|
}
|
|
|
|
/**
|
|
* Checks if a plugin tag has a name attribute and it matches the plugin being tested.
|
|
*
|
|
* @param string $plugin the name of the plugin.
|
|
* @param array $pluginxml the xmlised structure for the plugin tag being tested.
|
|
* @return boolean true if the name attribute exists and matches the plugin being tested.
|
|
*/
|
|
function environment_verify_plugin($plugin, $pluginxml) {
|
|
if (!isset($pluginxml['@']['name']) || $pluginxml['@']['name'] != $plugin) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* This function will check for everything (DB, PHP and PHP extensions for now)
|
|
* returning an array of environment_result objects.
|
|
*
|
|
* @global object
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use.
|
|
* @return environment_results[] array of results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check($version, $env_select) {
|
|
global $CFG;
|
|
|
|
if ($env_select != ENV_SELECT_NEWER and $env_select != ENV_SELECT_DATAROOT and $env_select != ENV_SELECT_RELEASE) {
|
|
throw new coding_exception('Incorrect value of $env_select parameter');
|
|
}
|
|
|
|
/// Normalize the version requested
|
|
$version = normalize_version($version);
|
|
|
|
$results = array(); //To store all the results
|
|
|
|
/// Only run the moodle versions checker on upgrade, not on install
|
|
if (!empty($CFG->version)) {
|
|
$results[] = environment_check_moodle($version, $env_select);
|
|
}
|
|
$results[] = environment_check_unicode($version, $env_select);
|
|
$results[] = environment_check_database($version, $env_select);
|
|
$results[] = environment_check_php($version, $env_select);
|
|
|
|
if ($result = environment_check_pcre_unicode($version, $env_select)) {
|
|
$results[] = $result;
|
|
}
|
|
|
|
$phpext_results = environment_check_php_extensions($version, $env_select);
|
|
$results = array_merge($results, $phpext_results);
|
|
|
|
$phpsetting_results = environment_check_php_settings($version, $env_select);
|
|
$results = array_merge($results, $phpsetting_results);
|
|
|
|
$custom_results = environment_custom_checks($version, $env_select);
|
|
$results = array_merge($results, $custom_results);
|
|
|
|
// Always use the plugin directory version of environment.xml,
|
|
// add-on developers need to keep those up-to-date with future info.
|
|
foreach (core_component::get_plugin_types() as $plugintype => $unused) {
|
|
foreach (core_component::get_plugin_list_with_file($plugintype, 'environment.xml') as $pluginname => $unused) {
|
|
$plugin = $plugintype . '_' . $pluginname;
|
|
|
|
$result = environment_check_database($version, $plugin);
|
|
if ($result->error_code != NO_VERSION_DATA_FOUND
|
|
and $result->error_code != NO_DATABASE_SECTION_FOUND
|
|
and $result->error_code != NO_DATABASE_VENDORS_FOUND) {
|
|
|
|
$result->plugin = $plugin;
|
|
$results[] = $result;
|
|
}
|
|
|
|
$result = environment_check_php($version, $plugin);
|
|
if ($result->error_code != NO_VERSION_DATA_FOUND
|
|
and $result->error_code != NO_PHP_SECTION_FOUND
|
|
and $result->error_code != NO_PHP_VERSION_FOUND) {
|
|
|
|
$result->plugin = $plugin;
|
|
$results[] = $result;
|
|
}
|
|
|
|
$pluginresults = environment_check_php_extensions($version, $plugin);
|
|
foreach ($pluginresults as $result) {
|
|
if ($result->error_code != NO_VERSION_DATA_FOUND
|
|
and $result->error_code != NO_PHP_EXTENSIONS_SECTION_FOUND) {
|
|
|
|
$result->plugin = $plugin;
|
|
$results[] = $result;
|
|
}
|
|
}
|
|
|
|
$pluginresults = environment_check_php_settings($version, $plugin);
|
|
foreach ($pluginresults as $result) {
|
|
if ($result->error_code != NO_VERSION_DATA_FOUND) {
|
|
$result->plugin = $plugin;
|
|
$results[] = $result;
|
|
}
|
|
}
|
|
|
|
$pluginresults = environment_custom_checks($version, $plugin);
|
|
foreach ($pluginresults as $result) {
|
|
if ($result->error_code != NO_VERSION_DATA_FOUND) {
|
|
$result->plugin = $plugin;
|
|
$results[] = $result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
|
|
/**
|
|
* This function will check if php extensions requirements are satisfied
|
|
*
|
|
* @uses NO_VERSION_DATA_FOUND
|
|
* @uses NO_PHP_EXTENSIONS_SECTION_FOUND
|
|
* @uses NO_PHP_EXTENSIONS_NAME_FOUND
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return array array of results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check_php_extensions($version, $env_select) {
|
|
|
|
$results = array();
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found
|
|
$result = new environment_results('php_extension');
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
return array($result);
|
|
}
|
|
|
|
/// Extract the php_extension part
|
|
if (!isset($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'])) {
|
|
/// Error. No PHP section found
|
|
$result = new environment_results('php_extension');
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_PHP_EXTENSIONS_SECTION_FOUND);
|
|
return array($result);
|
|
}
|
|
/// Iterate over extensions checking them and creating the needed environment_results
|
|
foreach($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'] as $extension) {
|
|
$result = new environment_results('php_extension');
|
|
/// Check for level
|
|
$level = get_level($extension);
|
|
/// Check for extension name
|
|
if (!isset($extension['@']['name'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_PHP_EXTENSIONS_NAME_FOUND);
|
|
} else {
|
|
$extension_name = $extension['@']['name'];
|
|
/// The name exists. Just check if it's an installed extension
|
|
if (!extension_loaded($extension_name)) {
|
|
$result->setStatus(false);
|
|
} else {
|
|
$result->setStatus(true);
|
|
}
|
|
$result->setLevel($level);
|
|
$result->setInfo($extension_name);
|
|
}
|
|
|
|
/// Do any actions defined in the XML file.
|
|
process_environment_result($extension, $result);
|
|
|
|
/// Add the result to the array of results
|
|
$results[] = $result;
|
|
}
|
|
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* This function will check if php extensions requirements are satisfied
|
|
*
|
|
* @uses NO_VERSION_DATA_FOUND
|
|
* @uses NO_PHP_SETTINGS_NAME_FOUND
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return array array of results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check_php_settings($version, $env_select) {
|
|
|
|
$results = array();
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found
|
|
$result = new environment_results('php_setting');
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
$results[] = $result;
|
|
return $results;
|
|
}
|
|
|
|
/// Extract the php_setting part
|
|
if (!isset($data['#']['PHP_SETTINGS']['0']['#']['PHP_SETTING'])) {
|
|
/// No PHP section found - ignore
|
|
return $results;
|
|
}
|
|
/// Iterate over settings checking them and creating the needed environment_results
|
|
foreach($data['#']['PHP_SETTINGS']['0']['#']['PHP_SETTING'] as $setting) {
|
|
$result = new environment_results('php_setting');
|
|
/// Check for level
|
|
$level = get_level($setting);
|
|
$result->setLevel($level);
|
|
/// Check for extension name
|
|
if (!isset($setting['@']['name'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_PHP_SETTINGS_NAME_FOUND);
|
|
} else {
|
|
$setting_name = $setting['@']['name'];
|
|
$setting_value = $setting['@']['value'];
|
|
$result->setInfo($setting_name);
|
|
|
|
if ($setting_name == 'memory_limit') {
|
|
$current = ini_get('memory_limit');
|
|
if ($current == -1) {
|
|
$result->setStatus(true);
|
|
} else {
|
|
$current = get_real_size($current);
|
|
$minlimit = get_real_size($setting_value);
|
|
if ($current < $minlimit) {
|
|
@ini_set('memory_limit', $setting_value);
|
|
$current = ini_get('memory_limit');
|
|
$current = get_real_size($current);
|
|
}
|
|
$result->setStatus($current >= $minlimit);
|
|
}
|
|
|
|
} else {
|
|
$current = ini_get_bool($setting_name);
|
|
/// The name exists. Just check if it's an installed extension
|
|
if ($current == $setting_value) {
|
|
$result->setStatus(true);
|
|
} else {
|
|
$result->setStatus(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Do any actions defined in the XML file.
|
|
process_environment_result($setting, $result);
|
|
|
|
/// Add the result to the array of results
|
|
$results[] = $result;
|
|
}
|
|
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* This function will do the custom checks.
|
|
*
|
|
* @uses CUSTOM_CHECK_FUNCTION_MISSING
|
|
* @uses CUSTOM_CHECK_FILE_MISSING
|
|
* @uses NO_CUSTOM_CHECK_FOUND
|
|
* @param string $version xml version we are going to use to test this server.
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return array array of results encapsulated in environment_result objects.
|
|
*/
|
|
function environment_custom_checks($version, $env_select) {
|
|
global $CFG;
|
|
|
|
$results = array();
|
|
|
|
/// Get current Moodle version (release) for later compare
|
|
$release = isset($CFG->release) ? $CFG->release : $version; /// In case $CFG fails (at install) use $version
|
|
$current_version = normalize_version($release);
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found - but this will already have been reported.
|
|
return $results;
|
|
}
|
|
|
|
/// Extract the CUSTOM_CHECKS part
|
|
if (!isset($data['#']['CUSTOM_CHECKS']['0']['#']['CUSTOM_CHECK'])) {
|
|
/// No custom checks found - not a problem
|
|
return $results;
|
|
}
|
|
|
|
/// Iterate over extensions checking them and creating the needed environment_results
|
|
foreach($data['#']['CUSTOM_CHECKS']['0']['#']['CUSTOM_CHECK'] as $check) {
|
|
$result = new environment_results('custom_check');
|
|
|
|
/// Check for level
|
|
$level = get_level($check);
|
|
|
|
/// Check for extension name
|
|
if (isset($check['@']['function'])) {
|
|
$function = $check['@']['function'];
|
|
$file = null;
|
|
if (isset($check['@']['file'])) {
|
|
$file = $CFG->dirroot . '/' . $check['@']['file'];
|
|
if (is_readable($file)) {
|
|
include_once($file);
|
|
}
|
|
}
|
|
|
|
if (is_callable($function)) {
|
|
$result->setLevel($level);
|
|
$result->setInfo($function);
|
|
$result = call_user_func($function, $result);
|
|
} else if (!$file or is_readable($file)) {
|
|
/// Only show error for current version (where function MUST exist)
|
|
/// else, we are performing custom checks against future versiosn
|
|
/// and function MAY not exist, so it doesn't cause error, just skip
|
|
/// custom check by returning null. MDL-15939
|
|
if (version_compare($current_version, $version, '>=')) {
|
|
$result->setStatus(false);
|
|
$result->setInfo($function);
|
|
$result->setErrorCode(CUSTOM_CHECK_FUNCTION_MISSING);
|
|
} else {
|
|
$result = null;
|
|
}
|
|
} else {
|
|
/// Only show error for current version (where function MUST exist)
|
|
/// else, we are performing custom checks against future versiosn
|
|
/// and function MAY not exist, so it doesn't cause error, just skip
|
|
/// custom check by returning null. MDL-15939
|
|
if (version_compare($current_version, $version, '>=')) {
|
|
$result->setStatus(false);
|
|
$result->setInfo($function);
|
|
$result->setErrorCode(CUSTOM_CHECK_FILE_MISSING);
|
|
} else {
|
|
$result = null;
|
|
}
|
|
}
|
|
} else {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_CUSTOM_CHECK_FOUND);
|
|
}
|
|
|
|
if (!is_null($result)) {
|
|
/// Do any actions defined in the XML file.
|
|
process_environment_result($check, $result);
|
|
|
|
/// Add the result to the array of results
|
|
$results[] = $result;
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* This function will check if Moodle requirements are satisfied
|
|
*
|
|
* @uses NO_VERSION_DATA_FOUND
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return object results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check_moodle($version, $env_select) {
|
|
|
|
$result = new environment_results('moodle');
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
/// Extract the moodle part
|
|
if (!isset($data['@']['requires'])) {
|
|
$needed_version = '1.0'; /// Default to 1.0 if no moodle requires is found
|
|
} else {
|
|
/// Extract required moodle version
|
|
$needed_version = $data['@']['requires'];
|
|
}
|
|
|
|
/// Now search the version we are using
|
|
$release = get_config('', 'release');
|
|
$current_version = normalize_version($release);
|
|
if (strpos($release, 'dev') !== false) {
|
|
// When final version is required, dev is NOT enough so, at all effects
|
|
// it's like we are running the previous version.
|
|
$versionarr = explode('.', $current_version);
|
|
if (isset($versionarr[1]) and $versionarr[1] > 0) {
|
|
$versionarr[1]--;
|
|
$current_version = implode('.', $versionarr);
|
|
} else {
|
|
$current_version = $current_version - 0.1;
|
|
}
|
|
}
|
|
|
|
/// And finally compare them, saving results
|
|
if (version_compare($current_version, $needed_version, '>=')) {
|
|
$result->setStatus(true);
|
|
} else {
|
|
$result->setStatus(false);
|
|
}
|
|
$result->setLevel('required');
|
|
$result->setCurrentVersion($release);
|
|
$result->setNeededVersion($needed_version);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* This function will check if php requirements are satisfied
|
|
*
|
|
* @uses NO_VERSION_DATA_FOUND
|
|
* @uses NO_PHP_SECTION_FOUND
|
|
* @uses NO_PHP_VERSION_FOUND
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return object results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check_php($version, $env_select) {
|
|
|
|
$result = new environment_results('php');
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
/// Extract the php part
|
|
if (!isset($data['#']['PHP'])) {
|
|
/// Error. No PHP section found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_PHP_SECTION_FOUND);
|
|
return $result;
|
|
} else {
|
|
/// Extract level and version
|
|
$level = get_level($data['#']['PHP']['0']);
|
|
if (!isset($data['#']['PHP']['0']['@']['version'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_PHP_VERSION_FOUND);
|
|
return $result;
|
|
} else {
|
|
$needed_version = $data['#']['PHP']['0']['@']['version'];
|
|
}
|
|
}
|
|
|
|
/// Now search the version we are using
|
|
$current_version = normalize_version(phpversion());
|
|
|
|
/// And finally compare them, saving results
|
|
if (version_compare($current_version, $needed_version, '>=')) {
|
|
$result->setStatus(true);
|
|
} else {
|
|
$result->setStatus(false);
|
|
}
|
|
$result->setLevel($level);
|
|
$result->setCurrentVersion($current_version);
|
|
$result->setNeededVersion($needed_version);
|
|
|
|
/// Do any actions defined in the XML file.
|
|
process_environment_result($data['#']['PHP'][0], $result);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Looks for buggy PCRE implementation, we need unicode support in Moodle...
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return stdClass results encapsulated in one environment_result object, null if irrelevant
|
|
*/
|
|
function environment_check_pcre_unicode($version, $env_select) {
|
|
$result = new environment_results('pcreunicode');
|
|
|
|
// Get the environment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
// Error. No version data found!
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
if (!isset($data['#']['PCREUNICODE'])) {
|
|
return null;
|
|
}
|
|
|
|
$level = get_level($data['#']['PCREUNICODE']['0']);
|
|
$result->setLevel($level);
|
|
|
|
if (!function_exists('preg_match')) {
|
|
// The extension test fails instead.
|
|
return null;
|
|
|
|
} else if (@preg_match('/\pL/u', 'a') and @preg_match('/á/iu', 'Á')) {
|
|
$result->setStatus(true);
|
|
|
|
} else {
|
|
$result->setStatus(false);
|
|
}
|
|
|
|
// Do any actions defined in the XML file.
|
|
process_environment_result($data['#']['PCREUNICODE'][0], $result);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* This function will check if unicode database requirements are satisfied
|
|
*
|
|
* @uses NO_VERSION_DATA_FOUND
|
|
* @uses NO_UNICODE_SECTION_FOUND
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return object results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check_unicode($version, $env_select) {
|
|
global $DB;
|
|
|
|
$result = new environment_results('unicode');
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
/// Extract the unicode part
|
|
|
|
if (!isset($data['#']['UNICODE'])) {
|
|
/// Error. No UNICODE section found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_UNICODE_SECTION_FOUND);
|
|
return $result;
|
|
} else {
|
|
/// Extract level
|
|
$level = get_level($data['#']['UNICODE']['0']);
|
|
}
|
|
|
|
if (!$unicodedb = $DB->setup_is_unicodedb()) {
|
|
$result->setStatus(false);
|
|
} else {
|
|
$result->setStatus(true);
|
|
}
|
|
|
|
$result->setLevel($level);
|
|
|
|
/// Do any actions defined in the XML file.
|
|
process_environment_result($data['#']['UNICODE'][0], $result);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* This function will check if database requirements are satisfied
|
|
*
|
|
* @uses NO_VERSION_DATA_FOUND
|
|
* @uses NO_DATABASE_SECTION_FOUND
|
|
* @uses NO_DATABASE_VENDORS_FOUND
|
|
* @uses NO_DATABASE_VENDOR_MYSQL_FOUND
|
|
* @uses NO_DATABASE_VENDOR_POSTGRES_FOUND
|
|
* @uses NO_DATABASE_VENDOR_VERSION_FOUND
|
|
* @param string $version xml version we are going to use to test this server
|
|
* @param int|string $env_select one of ENV_SELECT_NEWER | ENV_SELECT_DATAROOT | ENV_SELECT_RELEASE decide xml to use. String means plugin name.
|
|
* @return object results encapsulated in one environment_result object
|
|
*/
|
|
function environment_check_database($version, $env_select) {
|
|
|
|
global $DB;
|
|
|
|
$result = new environment_results('database');
|
|
|
|
$vendors = array(); //Array of vendors in version
|
|
|
|
/// Get the enviroment version we need
|
|
if (!$data = get_environment_for_version($version, $env_select)) {
|
|
/// Error. No version data found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
/// Extract the database part
|
|
if (!isset($data['#']['DATABASE'])) {
|
|
/// Error. No DATABASE section found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_DATABASE_SECTION_FOUND);
|
|
return $result;
|
|
} else {
|
|
/// Extract level
|
|
$level = get_level($data['#']['DATABASE']['0']);
|
|
}
|
|
|
|
/// Extract DB vendors. At least 2 are mandatory (mysql & postgres)
|
|
if (!isset($data['#']['DATABASE']['0']['#']['VENDOR'])) {
|
|
/// Error. No VENDORS found
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_DATABASE_VENDORS_FOUND);
|
|
return $result;
|
|
} else {
|
|
/// Extract vendors
|
|
foreach ($data['#']['DATABASE']['0']['#']['VENDOR'] as $vendor) {
|
|
if (isset($vendor['@']['name']) && isset($vendor['@']['version'])) {
|
|
$vendors[$vendor['@']['name']] = $vendor['@']['version'];
|
|
$vendorsxml[$vendor['@']['name']] = $vendor;
|
|
}
|
|
}
|
|
}
|
|
/// Check we have the mysql vendor version
|
|
if (empty($vendors['mysql'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_DATABASE_VENDOR_MYSQL_FOUND);
|
|
return $result;
|
|
}
|
|
/// Check we have the postgres vendor version
|
|
if (empty($vendors['postgres'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_DATABASE_VENDOR_POSTGRES_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
/// Now search the version we are using (depending of vendor)
|
|
$current_vendor = $DB->get_dbvendor();
|
|
|
|
$dbinfo = $DB->get_server_info();
|
|
$current_version = normalize_version($dbinfo['version']);
|
|
$needed_version = $vendors[$current_vendor];
|
|
|
|
/// Check we have a needed version
|
|
if (!$needed_version) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(NO_DATABASE_VENDOR_VERSION_FOUND);
|
|
return $result;
|
|
}
|
|
|
|
// Check if the DB Vendor has been properly configured.
|
|
// Hack: this is required when playing with MySQL and MariaDB since they share the same PHP module and base DB classes,
|
|
// whilst they are slowly evolving using separate directions though MariaDB is still an "almost" drop-in replacement.
|
|
$dbvendorismysql = ($current_vendor === 'mysql');
|
|
$dbtypeismariadb = (stripos($dbinfo['description'], 'mariadb') !== false);
|
|
if ($dbvendorismysql && $dbtypeismariadb) {
|
|
$result->setStatus(false);
|
|
$result->setLevel($level);
|
|
$result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')');
|
|
$result->setFeedbackStr('environmentmariadbwrongdbtype');
|
|
return $result;
|
|
}
|
|
|
|
/// And finally compare them, saving results
|
|
if (version_compare($current_version, $needed_version, '>=')) {
|
|
$result->setStatus(true);
|
|
} else {
|
|
$result->setStatus(false);
|
|
}
|
|
$result->setLevel($level);
|
|
$result->setCurrentVersion($current_version);
|
|
$result->setNeededVersion($needed_version);
|
|
$result->setInfo($current_vendor . ' (' . $dbinfo['description'] . ')');
|
|
|
|
/// Do any actions defined in the XML file.
|
|
process_environment_result($vendorsxml[$current_vendor], $result);
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
/**
|
|
* This function will post-process the result record by executing the specified
|
|
* function, modifying it as necessary, also a custom message will be added
|
|
* to the result object to be printed by the display layer.
|
|
* Every bypass function must be defined in this file and it'll return
|
|
* true/false to decide if the original test is bypassed or no. Also
|
|
* such bypass functions are able to directly handling the result object
|
|
* although it should be only under exceptional conditions.
|
|
*
|
|
* @param string xmldata containing the bypass data
|
|
* @param object result object to be updated
|
|
* @return void
|
|
*/
|
|
function process_environment_bypass($xml, &$result) {
|
|
|
|
/// Only try to bypass if we were in error and it was required
|
|
if ($result->getStatus() || $result->getLevel() == 'optional') {
|
|
return;
|
|
}
|
|
|
|
/// It there is bypass info (function and message)
|
|
if (is_array($xml['#']) && isset($xml['#']['BYPASS'][0]['@']['function']) && isset($xml['#']['BYPASS'][0]['@']['message'])) {
|
|
$function = $xml['#']['BYPASS'][0]['@']['function'];
|
|
$message = $xml['#']['BYPASS'][0]['@']['message'];
|
|
/// Look for the function
|
|
if (function_exists($function)) {
|
|
/// Call it, and if bypass = true is returned, apply meesage
|
|
if ($function($result)) {
|
|
/// We only set the bypass message if the function itself hasn't defined it before
|
|
if (empty($result->getBypassStr)) {
|
|
if (isset($xml['#']['BYPASS'][0]['@']['plugin'])) {
|
|
$result->setBypassStr(array($message, $xml['#']['BYPASS'][0]['@']['plugin']));
|
|
} else {
|
|
$result->setBypassStr($message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function will post-process the result record by executing the specified
|
|
* function, modifying it as necessary, also a custom message will be added
|
|
* to the result object to be printed by the display layer.
|
|
* Every restrict function must be defined in this file and it'll return
|
|
* true/false to decide if the original test is restricted or no. Also
|
|
* such restrict functions are able to directly handling the result object
|
|
* although it should be only under exceptional conditions.
|
|
*
|
|
* @param string xmldata containing the restrict data
|
|
* @param object result object to be updated
|
|
* @return void
|
|
*/
|
|
function process_environment_restrict($xml, &$result) {
|
|
|
|
/// Only try to restrict if we were not in error and it was required
|
|
if (!$result->getStatus() || $result->getLevel() == 'optional') {
|
|
return;
|
|
}
|
|
/// It there is restrict info (function and message)
|
|
if (is_array($xml['#']) && isset($xml['#']['RESTRICT'][0]['@']['function']) && isset($xml['#']['RESTRICT'][0]['@']['message'])) {
|
|
$function = $xml['#']['RESTRICT'][0]['@']['function'];
|
|
$message = $xml['#']['RESTRICT'][0]['@']['message'];
|
|
/// Look for the function
|
|
if (function_exists($function)) {
|
|
/// Call it, and if restrict = true is returned, apply meesage
|
|
if ($function($result)) {
|
|
/// We only set the restrict message if the function itself hasn't defined it before
|
|
if (empty($result->getRestrictStr)) {
|
|
if (isset($xml['#']['RESTRICT'][0]['@']['plugin'])) {
|
|
$result->setRestrictStr(array($message, $xml['#']['RESTRICT'][0]['@']['plugin']));
|
|
} else {
|
|
$result->setRestrictStr($message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function will detect if there is some message available to be added to the
|
|
* result in order to clarify enviromental details.
|
|
*
|
|
* @uses INCORRECT_FEEDBACK_FOR_REQUIRED
|
|
* @uses INCORRECT_FEEDBACK_FOR_OPTIONAL
|
|
* @param string xmldata containing the feedback data
|
|
* @param object reult object to be updated
|
|
*/
|
|
function process_environment_messages($xml, &$result) {
|
|
|
|
/// If there is feedback info
|
|
if (is_array($xml['#']) && isset($xml['#']['FEEDBACK'][0]['#'])) {
|
|
$feedbackxml = $xml['#']['FEEDBACK'][0]['#'];
|
|
|
|
// Detect some incorrect feedback combinations.
|
|
if ($result->getLevel() == 'required' and isset($feedbackxml['ON_CHECK'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(INCORRECT_FEEDBACK_FOR_REQUIRED);
|
|
} else if ($result->getLevel() == 'optional' and isset($feedbackxml['ON_ERROR'])) {
|
|
$result->setStatus(false);
|
|
$result->setErrorCode(INCORRECT_FEEDBACK_FOR_OPTIONAL);
|
|
}
|
|
|
|
if (!$result->status and $result->getLevel() == 'required') {
|
|
if (isset($feedbackxml['ON_ERROR'][0]['@']['message'])) {
|
|
if (isset($feedbackxml['ON_ERROR'][0]['@']['plugin'])) {
|
|
$result->setFeedbackStr(array($feedbackxml['ON_ERROR'][0]['@']['message'], $feedbackxml['ON_ERROR'][0]['@']['plugin']));
|
|
} else {
|
|
$result->setFeedbackStr($feedbackxml['ON_ERROR'][0]['@']['message']);
|
|
}
|
|
}
|
|
} else if (!$result->status and $result->getLevel() == 'optional') {
|
|
if (isset($feedbackxml['ON_CHECK'][0]['@']['message'])) {
|
|
if (isset($feedbackxml['ON_CHECK'][0]['@']['plugin'])) {
|
|
$result->setFeedbackStr(array($feedbackxml['ON_CHECK'][0]['@']['message'], $feedbackxml['ON_CHECK'][0]['@']['plugin']));
|
|
} else {
|
|
$result->setFeedbackStr($feedbackxml['ON_CHECK'][0]['@']['message']);
|
|
}
|
|
}
|
|
} else {
|
|
if (isset($feedbackxml['ON_OK'][0]['@']['message'])) {
|
|
if (isset($feedbackxml['ON_OK'][0]['@']['plugin'])) {
|
|
$result->setFeedbackStr(array($feedbackxml['ON_OK'][0]['@']['message'], $feedbackxml['ON_OK'][0]['@']['plugin']));
|
|
} else {
|
|
$result->setFeedbackStr($feedbackxml['ON_OK'][0]['@']['message']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--- Helper Class to return results to caller ---//
|
|
|
|
|
|
/**
|
|
* Helper Class to return results to caller
|
|
*
|
|
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
* @package moodlecore
|
|
*/
|
|
class environment_results {
|
|
/**
|
|
* @var string Which are we checking (database, php, php_extension, php_extension)
|
|
*/
|
|
var $part;
|
|
/**
|
|
* @var bool true means the test passed and all is OK. false means it failed.
|
|
*/
|
|
var $status;
|
|
/**
|
|
* @var integer See constants at the beginning of the file
|
|
*/
|
|
var $error_code;
|
|
/**
|
|
* @var string required/optional
|
|
*/
|
|
var $level;
|
|
/**
|
|
* @var string current version detected
|
|
*/
|
|
var $current_version;
|
|
/**
|
|
* @var string version needed
|
|
*/
|
|
var $needed_version;
|
|
/**
|
|
* @var string Aux. info (DB vendor, library...)
|
|
*/
|
|
var $info;
|
|
/**
|
|
* @var string String to show on error|on check|on ok
|
|
*/
|
|
var $feedback_str;
|
|
/**
|
|
* @var string String to show if some bypass has happened
|
|
*/
|
|
var $bypass_str;
|
|
/**
|
|
* @var string String to show if some restrict has happened
|
|
*/
|
|
var $restrict_str;
|
|
/**
|
|
* @var string|null full plugin name or null if main environment
|
|
*/
|
|
var $plugin = null;
|
|
/**
|
|
* Constructor of the environment_result class. Just set default values
|
|
*
|
|
* @param string $part
|
|
*/
|
|
public function __construct($part) {
|
|
$this->part=$part;
|
|
$this->status=false;
|
|
$this->error_code=NO_ERROR;
|
|
$this->level='required';
|
|
$this->current_version='';
|
|
$this->needed_version='';
|
|
$this->info='';
|
|
$this->feedback_str='';
|
|
$this->bypass_str='';
|
|
$this->restrict_str='';
|
|
}
|
|
|
|
/**
|
|
* Old syntax of class constructor. Deprecated in PHP7.
|
|
*
|
|
* @deprecated since Moodle 3.1
|
|
*/
|
|
public function environment_results($part) {
|
|
debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
|
|
self::__construct($part);
|
|
}
|
|
|
|
/**
|
|
* Set the status
|
|
*
|
|
* @param bool $testpassed true means the test passed and all is OK. false means it failed.
|
|
*/
|
|
function setStatus($testpassed) {
|
|
$this->status = $testpassed;
|
|
if ($testpassed) {
|
|
$this->setErrorCode(NO_ERROR);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the error_code
|
|
*
|
|
* @param integer $error_code the error code (see constants above)
|
|
*/
|
|
function setErrorCode($error_code) {
|
|
$this->error_code=$error_code;
|
|
}
|
|
|
|
/**
|
|
* Set the level
|
|
*
|
|
* @param string $level the level (required, optional)
|
|
*/
|
|
function setLevel($level) {
|
|
$this->level=$level;
|
|
}
|
|
|
|
/**
|
|
* Set the current version
|
|
*
|
|
* @param string $current_version the current version
|
|
*/
|
|
function setCurrentVersion($current_version) {
|
|
$this->current_version=$current_version;
|
|
}
|
|
|
|
/**
|
|
* Set the needed version
|
|
*
|
|
* @param string $needed_version the needed version
|
|
*/
|
|
function setNeededVersion($needed_version) {
|
|
$this->needed_version=$needed_version;
|
|
}
|
|
|
|
/**
|
|
* Set the auxiliary info
|
|
*
|
|
* @param string $info the auxiliary info
|
|
*/
|
|
function setInfo($info) {
|
|
$this->info=$info;
|
|
}
|
|
|
|
/**
|
|
* Set the feedback string
|
|
*
|
|
* @param mixed $str the feedback string that will be fetched from the admin lang file.
|
|
* pass just the string or pass an array of params for get_string
|
|
* You always should put your string in admin.php but a third param is useful
|
|
* to pass an $a object / string to get_string
|
|
*/
|
|
function setFeedbackStr($str) {
|
|
$this->feedback_str=$str;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the bypass string
|
|
*
|
|
* @param string $str the bypass string that will be fetched from the admin lang file.
|
|
* pass just the string or pass an array of params for get_string
|
|
* You always should put your string in admin.php but a third param is useful
|
|
* to pass an $a object / string to get_string
|
|
*/
|
|
function setBypassStr($str) {
|
|
$this->bypass_str=$str;
|
|
}
|
|
|
|
/**
|
|
* Set the restrict string
|
|
*
|
|
* @param string $str the restrict string that will be fetched from the admin lang file.
|
|
* pass just the string or pass an array of params for get_string
|
|
* You always should put your string in admin.php but a third param is useful
|
|
* to pass an $a object / string to get_string
|
|
*/
|
|
function setRestrictStr($str) {
|
|
$this->restrict_str=$str;
|
|
}
|
|
|
|
/**
|
|
* Get the status
|
|
*
|
|
* @return bool true means the test passed and all is OK. false means it failed.
|
|
*/
|
|
function getStatus() {
|
|
return $this->status;
|
|
}
|
|
|
|
/**
|
|
* Get the error code
|
|
*
|
|
* @return integer error code
|
|
*/
|
|
function getErrorCode() {
|
|
return $this->error_code;
|
|
}
|
|
|
|
/**
|
|
* Get the level
|
|
*
|
|
* @return string level
|
|
*/
|
|
function getLevel() {
|
|
return $this->level;
|
|
}
|
|
|
|
/**
|
|
* Get the current version
|
|
*
|
|
* @return string current version
|
|
*/
|
|
function getCurrentVersion() {
|
|
return $this->current_version;
|
|
}
|
|
|
|
/**
|
|
* Get the needed version
|
|
*
|
|
* @return string needed version
|
|
*/
|
|
function getNeededVersion() {
|
|
return $this->needed_version;
|
|
}
|
|
|
|
/**
|
|
* Get the aux info
|
|
*
|
|
* @return string info
|
|
*/
|
|
function getInfo() {
|
|
return $this->info;
|
|
}
|
|
|
|
/**
|
|
* Get the part this result belongs to
|
|
*
|
|
* @return string part
|
|
*/
|
|
function getPart() {
|
|
return $this->part;
|
|
}
|
|
|
|
/**
|
|
* Get the feedback string
|
|
*
|
|
* @return mixed feedback string (can be an array of params for get_string or a single string to fetch from
|
|
* admin.php lang file).
|
|
*/
|
|
function getFeedbackStr() {
|
|
return $this->feedback_str;
|
|
}
|
|
|
|
/**
|
|
* Get the bypass string
|
|
*
|
|
* @return mixed bypass string (can be an array of params for get_string or a single string to fetch from
|
|
* admin.php lang file).
|
|
*/
|
|
function getBypassStr() {
|
|
return $this->bypass_str;
|
|
}
|
|
|
|
/**
|
|
* Get the restrict string
|
|
*
|
|
* @return mixed restrict string (can be an array of params for get_string or a single string to fetch from
|
|
* admin.php lang file).
|
|
*/
|
|
function getRestrictStr() {
|
|
return $this->restrict_str;
|
|
}
|
|
|
|
/**
|
|
* @todo Document this function
|
|
*
|
|
* @param mixed $string params for get_string, either a string to fetch from admin.php or an array of
|
|
* params for get_string.
|
|
* @param string $class css class(es) for message.
|
|
* @return string feedback string fetched from lang file wrapped in p tag with class $class or returns
|
|
* empty string if $string is empty.
|
|
*/
|
|
function strToReport($string, $class){
|
|
if (!empty($string)){
|
|
if (is_array($string)){
|
|
$str = call_user_func_array('get_string', $string);
|
|
} else {
|
|
$str = get_string($string, 'admin');
|
|
}
|
|
return '<p class="'.$class.'">'.$str.'</p>';
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get plugin name.
|
|
*
|
|
* @return string plugin name
|
|
*/
|
|
function getPluginName() {
|
|
if ($this->plugin) {
|
|
$manager = core_plugin_manager::instance();
|
|
list($plugintype, $pluginname) = core_component::normalize_component($this->plugin);
|
|
return $manager->plugintype_name($plugintype) . ' / ' . $manager->plugin_name($this->plugin);
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Here all the restrict functions are coded to be used by the environment
|
|
/// checker. All those functions will receive the result object and will
|
|
/// return it modified as needed (status and bypass string)
|
|
|
|
/**
|
|
* @param array $element the element from the environment.xml file that should have
|
|
* either a level="required" or level="optional" attribute.
|
|
* @return string "required" or "optional".
|
|
*/
|
|
function get_level($element) {
|
|
$level = 'required';
|
|
if (isset($element['@']['level'])) {
|
|
$level = $element['@']['level'];
|
|
if (!in_array($level, array('required', 'optional'))) {
|
|
debugging('The level of a check in the environment.xml file must be "required" or "optional".', DEBUG_DEVELOPER);
|
|
$level = 'required';
|
|
}
|
|
} else {
|
|
debugging('Checks in the environment.xml file must have a level="required" or level="optional" attribute.', DEBUG_DEVELOPER);
|
|
}
|
|
return $level;
|
|
}
|
|
|
|
/**
|
|
* Once the result has been determined, look in the XML for any
|
|
* messages, or other things that should be done depending on the outcome.
|
|
*
|
|
* @param array $element the element from the environment.xml file which
|
|
* may have children defining what should be done with the outcome.
|
|
* @param object $result the result of the test, which may be modified by
|
|
* this function as specified in the XML.
|
|
*/
|
|
function process_environment_result($element, &$result) {
|
|
/// Process messages, modifying the $result if needed.
|
|
process_environment_messages($element, $result);
|
|
/// Process bypass, modifying $result if needed.
|
|
process_environment_bypass($element, $result);
|
|
/// Process restrict, modifying $result if needed.
|
|
process_environment_restrict($element, $result);
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 7.
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_7(&$result) {
|
|
return restrict_php_version($result, '7');
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to an
|
|
* unsupported version.
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @param string $version the version of PHP that can't be used
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version(&$result, $version) {
|
|
|
|
// Get the current PHP version.
|
|
$currentversion = normalize_version(phpversion());
|
|
|
|
// Confirm we're using a supported PHP version.
|
|
if (version_compare($currentversion, $version, '<')) {
|
|
// Everything is ok, the restriction doesn't apply.
|
|
return false;
|
|
} else {
|
|
// We're using an unsupported PHP version, apply restriction.
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 7.1.
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_71(&$result) {
|
|
return restrict_php_version($result, '7.1');
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 7.2.
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_72(&$result) {
|
|
return restrict_php_version($result, '7.2');
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 7.3.
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_73(&$result) {
|
|
return restrict_php_version($result, '7.3');
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 7.4.
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_74(&$result) {
|
|
return restrict_php_version($result, '7.4');
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 8.0
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_80($result) {
|
|
return restrict_php_version($result, '8.0');
|
|
}
|
|
|
|
/**
|
|
* Check if the current PHP version is greater than or equal to
|
|
* PHP version 8.1
|
|
*
|
|
* @param object $result an environment_results instance
|
|
* @return bool result of version check
|
|
*/
|
|
function restrict_php_version_81($result) {
|
|
return restrict_php_version($result, '8.1');
|
|
}
|