mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 06:18:28 +01:00
450 lines
15 KiB
PHP
450 lines
15 KiB
PHP
|
<?php //$Ia:d$
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// NOTICE OF COPYRIGHT //
|
||
|
// //
|
||
|
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
|
||
|
// http://moodle.com //
|
||
|
// //
|
||
|
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
|
||
|
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
|
||
|
// //
|
||
|
// This program 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 2 of the License, or //
|
||
|
// (at your option) any later version. //
|
||
|
// //
|
||
|
// This program 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: //
|
||
|
// //
|
||
|
// http://www.gnu.org/copyleft/gpl.html //
|
||
|
// //
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// This file includes all the necessary stuff to execute some standard
|
||
|
// test of required versions and libraries to run Moodle. It can be
|
||
|
// invoked from the admin interface, and both at install and upgrade.
|
||
|
//
|
||
|
// All the info is stored in the environment.xml file
|
||
|
|
||
|
require_once($CFG->libdir.'/xmlize.php');
|
||
|
|
||
|
define(NO_ERROR, 0);
|
||
|
define(NO_VERSION_DATA_FOUND, 1);
|
||
|
define(NO_DATABASE_SECTION_FOUND, 2);
|
||
|
define(NO_DATABASE_VENDORS_FOUND, 3);
|
||
|
define(NO_DATABASE_VENDOR_MYSQL_FOUND, 4);
|
||
|
define(NO_DATABASE_VENDOR_POSTGRES_FOUND, 5);
|
||
|
define(DATABASE_OLD_VERSION, 6);
|
||
|
define(NO_PHP_SECTION_FOUND, 7);
|
||
|
define(NO_PHP_VERSION_FOUND, 8);
|
||
|
define(PHP_OLD_VERSION, 9);
|
||
|
define(NO_PHP_EXTENSIONS_SECTION_FOUND, 10);
|
||
|
define(NO_PHP_EXTENSIONS_NAME_FOUND, 11);
|
||
|
define(NO_PHP_EXTENSION_WITH_NAME, 12);
|
||
|
|
||
|
/**
|
||
|
* 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) {
|
||
|
/// 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
|
||
|
* @return mixed the xmlized structure or false on error
|
||
|
*/
|
||
|
function load_environment_xml() {
|
||
|
|
||
|
global $CFG;
|
||
|
|
||
|
static $data; //Only load and xmlize once by request
|
||
|
|
||
|
if (!empty($data)) {
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/// First of all, take a look inside $CFG->moodledata/environment/environment.xml
|
||
|
$file = $CFG->moodledata.'/environment/environment.xml';
|
||
|
if (!is_file($file) || !is_readable($file) || !$contents = file_get_contents($file)) {
|
||
|
/// Fallback to fixed admin/environment.xml
|
||
|
$file = $CFG->dirroot.'/admin/environment.xml';
|
||
|
if (!is_file($file) || !is_readable($file) || !$contents = file_get_contents($file)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
/// XML the whole file
|
||
|
$data = xmlize($contents);
|
||
|
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function will return the list of Moodle versions available
|
||
|
* @return mixed array of versions. False on error.
|
||
|
*/
|
||
|
function get_list_of_environment_versions ($contents) {
|
||
|
|
||
|
static $versions = array();
|
||
|
|
||
|
if (!empty($versions)) {
|
||
|
return $versions;
|
||
|
}
|
||
|
|
||
|
if (isset($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'])) {
|
||
|
foreach ($contents['COMPATIBILITY_MATRIX']['#']['MOODLE'] as $version) {
|
||
|
$versions[] = $version['@']['version'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $versions;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function will return the xmlized data belonging to one Moodle version
|
||
|
* @return mixed the xmlized structure or false on error
|
||
|
*/
|
||
|
function get_environment_for_version($version) {
|
||
|
|
||
|
/// Load xml file
|
||
|
if (!$contents = load_environment_xml()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/// Detect available versions
|
||
|
if (!$versions = get_list_of_environment_versions($contents)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/// If the version requested is available
|
||
|
if (!in_array($version, $versions)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/// We now we have it. Extract from full contents.
|
||
|
$fl_arr = array_flip($versions);
|
||
|
|
||
|
return $contents['COMPATIBILITY_MATRIX']['#']['MOODLE'][$fl_arr[$version]];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function will check for everything (DB, PHP and PHP extensions for now)
|
||
|
* returning an array of environment_result objects.
|
||
|
* @param string $version xml version we are going to use to test this server
|
||
|
* @return array array of results encapsulated in one environment_result object
|
||
|
*/
|
||
|
function environment_check($version) {
|
||
|
|
||
|
$results = array(); //To store all the results
|
||
|
|
||
|
$results[] = environment_check_database($version);
|
||
|
$results[] = environment_check_php($version);
|
||
|
|
||
|
$phpext_results = environment_check_php_extensions($version);
|
||
|
|
||
|
$results = array_merge ($results, $phpext_results);
|
||
|
|
||
|
return $results;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function will check if php extensions requirements are satisfied
|
||
|
* @param string $version xml version we are going to use to test this server
|
||
|
* @return array array of results encapsulated in one environment_result object
|
||
|
*/
|
||
|
function environment_check_php_extensions($version) {
|
||
|
|
||
|
$results = array();
|
||
|
|
||
|
/// Get the enviroment version we need
|
||
|
if (!$data = get_environment_for_version($version)) {
|
||
|
/// Error. No version data found
|
||
|
$result->setStatus(false);
|
||
|
$result->setErrorCode(NO_VERSION_DATA_FOUND);
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/// Extract the php_extension part
|
||
|
if (!isset($data['#']['PHP_EXTENSIONS']['0']['#']['PHP_EXTENSION'])) {
|
||
|
/// Error. No PHP section found
|
||
|
$result->setStatus(false);
|
||
|
$result->setErrorCode(NO_PHP_EXTENSIONS_SECTION_FOUND);
|
||
|
return $result;
|
||
|
} else {
|
||
|
/// 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_extensions');
|
||
|
/// Check for level
|
||
|
if (isset($extension['@']['level'])) {
|
||
|
$level = $extension['@']['level'];
|
||
|
if ($level != 'recommended') {
|
||
|
$level = 'required';
|
||
|
}
|
||
|
}
|
||
|
/// 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);
|
||
|
$result->setErrorCode(NO_PHP_EXTENSION_WITH_NAME);
|
||
|
} else {
|
||
|
$result->setStatus(true);
|
||
|
}
|
||
|
$result->setLevel($level);
|
||
|
$result->setInfo($extension_name);
|
||
|
}
|
||
|
/// Add the result to the array of results
|
||
|
$results[] = $result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $results;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function will check if php requirements are satisfied
|
||
|
* @param string $version xml version we are going to use to test this server
|
||
|
* @return object results encapsulated in one environment_result object
|
||
|
*/
|
||
|
function environment_check_php($version) {
|
||
|
|
||
|
$result = new environment_results('php');
|
||
|
|
||
|
/// Get the enviroment version we need
|
||
|
if (!$data = get_environment_for_version($version)) {
|
||
|
/// 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
|
||
|
if (isset($data['#']['PHP']['0']['@']['level'])) {
|
||
|
$level = $data['#']['PHP']['0']['level'];
|
||
|
if ($level != 'recommended') {
|
||
|
$level = 'required';
|
||
|
}
|
||
|
}
|
||
|
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->setErrorCode(PHP_OLD_VERSION);
|
||
|
}
|
||
|
$result->setLevel($level);
|
||
|
$result->setCurrentVersion($current_version);
|
||
|
$result->setNeededVersion($needed_version);
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function will check if database requirements are satisfied
|
||
|
* @param string $version xml version we are going to use to test this server
|
||
|
* @return object results encapsulated in one environment_result object
|
||
|
*/
|
||
|
function environment_check_database($version) {
|
||
|
|
||
|
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)) {
|
||
|
/// 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
|
||
|
if (isset($data['#']['DATABASE']['0']['@']['level'])) {
|
||
|
$level = $data['#']['DATABASE']['0']['level'];
|
||
|
if ($level != 'recommended') {
|
||
|
$level = 'required';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// 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'];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/// 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->databaseType;
|
||
|
$dbinfo = $db->ServerInfo();
|
||
|
$current_version = normalize_version($dbinfo['version']);
|
||
|
$needed_version = $vendors[$current_vendor];
|
||
|
|
||
|
/// And finally compare them, saving results
|
||
|
if (version_compare($current_version, $needed_version, '>=')) {
|
||
|
$result->setStatus(true);
|
||
|
} else {
|
||
|
$result->setStatus(false);
|
||
|
$result->setErrorCode(DATABASE_OLD_VERSION);
|
||
|
}
|
||
|
$result->setLevel($level);
|
||
|
$result->setCurrentVersion($current_version);
|
||
|
$result->setNeededVersion($needed_version);
|
||
|
$result->setInfo($current_vendor);
|
||
|
|
||
|
return $result;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//--- Helper Class to return results to caller ---//
|
||
|
|
||
|
/**
|
||
|
* This class is used to return the results of the environment
|
||
|
* main functions (environment_check_xxxx)
|
||
|
*/
|
||
|
class environment_results {
|
||
|
|
||
|
var $result; //true/false
|
||
|
var $error_code; //integer. See constants at the beginning of the file
|
||
|
var $level; //required/recommended
|
||
|
var $current_version; //current version detected
|
||
|
var $needed_version; //version needed
|
||
|
var $info; //Aux. info (DB vendor, library...)
|
||
|
|
||
|
/**
|
||
|
* Constructor of the environment_result class. Just set default values
|
||
|
*/
|
||
|
function environment_results($part) {
|
||
|
$this->part=$part;
|
||
|
$this->result=false;
|
||
|
$this->error_code=NOTHING_CHECKED_YET;
|
||
|
$this->level='required';
|
||
|
$this->current_version='';
|
||
|
$this->needed_version='';
|
||
|
$this->info=array();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the result
|
||
|
* @param boolean the result (true/false)
|
||
|
*/
|
||
|
function setStatus($result) {
|
||
|
$this->result=$result;
|
||
|
if (result) {
|
||
|
$this->setErrorCode(NO_ERROR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the error_code
|
||
|
* @param integer the error code (see constants above)
|
||
|
*/
|
||
|
function setErrorCode($error_code) {
|
||
|
$this->error_code=$error_code;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the level
|
||
|
* @param string the level (required, recommended)
|
||
|
*/
|
||
|
function setLevel($level) {
|
||
|
$this->level=$level;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the current version
|
||
|
* @param string the current version
|
||
|
*/
|
||
|
function setCurrentVersion($current_version) {
|
||
|
$this->current_version=$current_version;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the needed version
|
||
|
* @param string the needed version
|
||
|
*/
|
||
|
function setNeededVersion($needed_version) {
|
||
|
$this->needed_version=$needed_version;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the auxiliary info
|
||
|
* @param string the auxiliary info
|
||
|
*/
|
||
|
function setInfo($info) {
|
||
|
$this->info[]=$info;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
?>
|