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