diff --git a/public/admin/environment.xml b/public/admin/environment.xml index 719c7feb1b5..7cc7cefc313 100644 --- a/public/admin/environment.xml +++ b/public/admin/environment.xml @@ -5021,6 +5021,10 @@ + + + + diff --git a/public/admin/index.php b/public/admin/index.php index fc6dfac2473..d9a3a88125d 100644 --- a/public/admin/index.php +++ b/public/admin/index.php @@ -1,5 +1,4 @@ libdir.'/adminlib.php'); // various admin-only functions -require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions +require_once($CFG->libdir . '/adminlib.php'); // Various admin-only functions. +require_once($CFG->libdir . '/upgradelib.php'); // General upgrade/install related functions. $confirmupgrade = optional_param('confirmupgrade', 0, PARAM_BOOL); // Core upgrade confirmed? $confirmrelease = optional_param('confirmrelease', 0, PARAM_BOOL); // Core release info and server checks confirmed? @@ -148,11 +148,11 @@ $PAGE->set_url($url); unset($url); // Are we returning from an add-on installation request at moodle.org/plugins? -if ($newaddonreq and !$cache and empty($CFG->disableupdateautodeploy)) { - $target = new moodle_url('/admin/tool/installaddon/index.php', array( +if ($newaddonreq && !$cache && empty($CFG->disableupdateautodeploy)) { + $target = new moodle_url('/admin/tool/installaddon/index.php', [ 'installaddonrequest' => $newaddonreq, - 'confirm' => 0)); - if (!isloggedin() or isguestuser()) { + 'confirm' => 0]); + if (!isloggedin() || isguestuser()) { // Login and go the the add-on tool page. $SESSION->wantsurl = $target->out(); redirect(get_login_url()); @@ -160,27 +160,35 @@ if ($newaddonreq and !$cache and empty($CFG->disableupdateautodeploy)) { redirect($target); } -$PAGE->set_pagelayout('admin'); // Set a default pagelayout +$PAGE->set_pagelayout('admin'); // Set a default pagelayout. $documentationlink = 'Installation docs'; -// Check some PHP server settings +// Check some PHP server settings. if (ini_get_bool('session.auto_start')) { - throw new \moodle_exception('phpvaroff', 'debug', '', - (object)array('name' => 'session.auto_start', 'link' => $documentationlink)); + throw new \moodle_exception( + 'phpvaroff', + 'debug', + '', + (object)['name' => 'session.auto_start', 'link' => $documentationlink] + ); } if (!ini_get_bool('file_uploads')) { - throw new \moodle_exception('phpvaron', 'debug', '', - (object)array('name' => 'file_uploads', 'link' => $documentationlink)); + throw new \moodle_exception( + 'phpvaron', + 'debug', + '', + (object)['name' => 'file_uploads', 'link' => $documentationlink] + ); } if (is_float_problem()) { throw new \moodle_exception('phpfloatproblem', 'admin', '', $documentationlink); } -// Set some necessary variables during set-up to avoid PHP warnings later on this page +// Set some necessary variables during set-up to avoid PHP warnings later on this page. if (!isset($CFG->release)) { $CFG->release = ''; } @@ -194,10 +202,10 @@ if (!isset($CFG->branch)) { $version = null; $release = null; $branch = null; -require("$CFG->dirroot/version.php"); // defines $version, $release, $branch and $maturity -$CFG->target_release = $release; // used during installation and upgrades +require("$CFG->dirroot/version.php"); // Defines the $version, $release, $branch and $maturity variables. +$CFG->target_release = $release; // Used during installation and upgrades. -if (!$version or !$release) { +if (!$version || !$release) { throw new \moodle_exception('withoutversion', 'debug'); // Without version, stop. } @@ -205,12 +213,12 @@ if (!core_tables_exist()) { $PAGE->set_pagelayout('maintenance'); $PAGE->set_popup_notification_allowed(false); - // fake some settings + // Rake some settings. $CFG->docroot = 'http://docs.moodle.org'; $strinstallation = get_string('installation', 'install'); - // remove current session content completely + // Remove current session content completely. \core\session\manager::terminate_current(); if (empty($agreelicense)) { @@ -226,8 +234,8 @@ if (!core_tables_exist()) { die(); } if (empty($confirmrelease)) { - require_once($CFG->libdir.'/environmentlib.php'); - list($envstatus, $environmentresults) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE); + require_once($CFG->libdir . '/environmentlib.php'); + [$envstatus, $environmentresults] = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE); $strcurrentrelease = get_string('currentrelease'); $PAGE->navbar->add($strcurrentrelease); @@ -240,21 +248,21 @@ if (!core_tables_exist()) { die(); } - // check plugin dependencies - $failed = array(); + // Check plugin dependencies. + $failed = []; if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) { $PAGE->navbar->add(get_string('pluginscheck', 'admin')); $PAGE->set_title($strinstallation); $PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release); $output = $PAGE->get_renderer('core', 'admin'); - $url = new moodle_url($PAGE->url, array('agreelicense' => 1, 'confirmrelease' => 1, 'lang' => $CFG->lang)); + $url = new moodle_url($PAGE->url, ['agreelicense' => 1, 'confirmrelease' => 1, 'lang' => $CFG->lang]); echo $output->unsatisfied_dependencies_page($version, $failed, $url); die(); } unset($failed); - //TODO: add a page with list of non-standard plugins here + // TODO: add a page with list of non-standard plugins here. $strdatabasesetup = get_string('databasesetup'); upgrade_init_javascript(); @@ -269,7 +277,7 @@ if (!core_tables_exist()) { if (!$DB->setup_is_unicodedb()) { if (!$DB->change_db_encoding()) { - // If could not convert successfully, throw error, and prevent installation + // If could not convert successfully, throw error, and prevent installation. throw new \moodle_exception('unicoderequired', 'admin'); } } @@ -301,18 +309,17 @@ if (empty($CFG->version)) { $outagelessupgrade = !empty($DB->get_field('config', 'value', ['name' => 'outagelessupgrade'])); if (!$outagelessupgrade) { // Detect config cache inconsistency, this happens when you switch branches on dev servers. - if ($CFG->version != $DB->get_field('config', 'value', array('name' => 'version'))) { + if ($CFG->version != $DB->get_field('config', 'value', ['name' => 'version'])) { purge_all_caches(); redirect(new moodle_url($PAGE->url), 'Config cache inconsistency detected, resetting caches...'); } if (!$cache && $version > $CFG->version && !$outagelessupgrade) { // Upgrade. - - $PAGE->set_url(new moodle_url($PAGE->url, array( + $PAGE->set_url(new moodle_url($PAGE->url, [ 'confirmupgrade' => $confirmupgrade, 'confirmrelease' => $confirmrelease, 'confirmplugincheck' => $confirmplugins, - ))); + ])); check_upgrade_key($upgradekeyhash); @@ -353,8 +360,8 @@ if (!$outagelessupgrade) { if (empty($confirmupgrade)) { $a = new stdClass(); - $a->oldversion = "$CFG->release (".sprintf('%.2f', $CFG->version).")"; - $a->newversion = "$release (".sprintf('%.2f', $version).")"; + $a->oldversion = "$CFG->release (" . sprintf('%.2f', $CFG->version) . ")"; + $a->newversion = "$release (" . sprintf('%.2f', $version) . ")"; $strdatabasechecking = get_string('databasechecking', '', $a); $PAGE->set_title($stradministration); @@ -363,10 +370,9 @@ if (!$outagelessupgrade) { echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite); die(); - } else if (empty($confirmrelease)) { - require_once($CFG->libdir.'/environmentlib.php'); - list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE); + require_once($CFG->libdir . '/environmentlib.php'); + [$envstatus, $environmentresults] = check_moodle_environment($release, ENV_SELECT_RELEASE); $strcurrentrelease = get_string('currentrelease'); $PAGE->navbar->add($strcurrentrelease); @@ -376,7 +382,6 @@ if (!$outagelessupgrade) { echo $output->upgrade_environment_page($release, $envstatus, $environmentresults); die(); - } else if (empty($confirmplugins)) { $strplugincheck = get_string('plugincheck'); @@ -423,10 +428,10 @@ if (!$outagelessupgrade) { $pluginman->cancel_plugin_installation($abortinstall); redirect($PAGE->url); } else { - $continue = new moodle_url($PAGE->url, array('abortinstall' => $abortinstall, 'confirmabortinstall' => 1)); + $continue = new moodle_url($PAGE->url, ['abortinstall' => $abortinstall, 'confirmabortinstall' => 1]); $abortable = $pluginman->get_plugin_info($abortinstall); if ($pluginman->can_cancel_plugin_installation($abortable)) { - echo $output->upgrade_confirm_abort_install_page(array($abortable), $continue); + echo $output->upgrade_confirm_abort_install_page([$abortable], $continue); die(); } redirect($PAGE->url); @@ -438,9 +443,11 @@ if (!$outagelessupgrade) { // No sesskey support guaranteed here, because sessions might not work yet. $restorable = $pluginman->list_restorable_archives(); if ($restorable) { - upgrade_install_plugins($restorable, $confirmabortupgrade, + upgrade_install_plugins( + $restorable, + $confirmabortupgrade, get_string('cancelupgradehead', 'core_plugin'), - new moodle_url($PAGE->url, array('abortupgradex' => 1, 'confirmabortupgrade' => 1)) + new moodle_url($PAGE->url, ['abortupgradex' => 1, 'confirmabortupgrade' => 1]) ); } redirect($PAGE->url); @@ -451,10 +458,12 @@ if (!$outagelessupgrade) { // No sesskey support guaranteed here, because sessions might not work yet. $restorable = $pluginman->list_restorable_archives(); if (isset($restorable[$abortupgrade])) { - $restorable = array($restorable[$abortupgrade]); - upgrade_install_plugins($restorable, $confirmabortupgrade, + $restorable = [$restorable[$abortupgrade]]; + upgrade_install_plugins( + $restorable, + $confirmabortupgrade, get_string('cancelupgradehead', 'core_plugin'), - new moodle_url($PAGE->url, array('abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1)) + new moodle_url($PAGE->url, ['abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1]) ); } redirect($PAGE->url); @@ -464,9 +473,11 @@ if (!$outagelessupgrade) { if ($installdepx) { // No sesskey support guaranteed here, because sessions might not work yet. $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true)); - upgrade_install_plugins($installable, $confirminstalldep, + upgrade_install_plugins( + $installable, + $confirminstalldep, get_string('dependencyinstallhead', 'core_plugin'), - new moodle_url($PAGE->url, array('installdepx' => 1, 'confirminstalldep' => 1)) + new moodle_url($PAGE->url, ['installdepx' => 1, 'confirminstalldep' => 1]) ); } @@ -475,10 +486,12 @@ if (!$outagelessupgrade) { // No sesskey support guaranteed here, because sessions might not work yet. $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true)); if (!empty($installable[$installdep])) { - $installable = array($installable[$installdep]); - upgrade_install_plugins($installable, $confirminstalldep, + $installable = [$installable[$installdep]]; + upgrade_install_plugins( + $installable, + $confirminstalldep, get_string('dependencyinstallhead', 'core_plugin'), - new moodle_url($PAGE->url, array('installdep' => $installdep, 'confirminstalldep' => 1)) + new moodle_url($PAGE->url, ['installdep' => $installdep, 'confirminstalldep' => 1]) ); } } @@ -487,36 +500,46 @@ if (!$outagelessupgrade) { if ($installupdatex) { // No sesskey support guaranteed here, because sessions might not work yet. $installable = $pluginman->filter_installable($pluginman->available_updates()); - upgrade_install_plugins($installable, $confirminstallupdate, + upgrade_install_plugins( + $installable, + $confirminstallupdate, get_string('updateavailableinstallallhead', 'core_admin'), - new moodle_url($PAGE->url, array('installupdatex' => 1, 'confirminstallupdate' => 1)) + new moodle_url($PAGE->url, ['installupdatex' => 1, 'confirminstallupdate' => 1]) ); } // Install single available update. - if ($installupdate and $installupdateversion) { + if ($installupdate && $installupdateversion) { // No sesskey support guaranteed here, because sessions might not work yet. if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) { - $installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true)); - upgrade_install_plugins($installable, $confirminstallupdate, + $installable = [$pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true)]; + upgrade_install_plugins( + $installable, + $confirminstallupdate, get_string('updateavailableinstallallhead', 'core_admin'), - new moodle_url($PAGE->url, array('installupdate' => $installupdate, - 'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1) - ) + new moodle_url($PAGE->url, ['installupdate' => $installupdate, + 'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1]) ); } } - echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(), - $version, $showallplugins, $PAGE->url, new moodle_url($PAGE->url, array('confirmplugincheck' => 1))); + echo $output->upgrade_plugin_check_page( + core_plugin_manager::instance(), + \core\update\checker::instance(), + $version, + $showallplugins, + $PAGE->url, + new moodle_url($PAGE->url, ['confirmplugincheck' => 1]) + ); die(); - } else { // Always verify plugin dependencies! - $failed = array(); + $failed = []; if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) { - echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url, - array('confirmplugincheck' => 0))); + echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url( + $PAGE->url, + ['confirmplugincheck' => 0] + )); die(); } unset($failed); @@ -530,7 +553,7 @@ if (!$outagelessupgrade) { } // Updated human-readable release version if necessary. - if (!$cache && $release <> $CFG->release ) { // Update the release version. + if (!$cache && $release <> $CFG->release) { // Update the release version. set_config('release', $release); } @@ -539,11 +562,10 @@ if (!$outagelessupgrade) { } if (!$cache && moodle_needs_upgrading()) { - - $PAGE->set_url(new moodle_url($PAGE->url, array( + $PAGE->set_url(new moodle_url($PAGE->url, [ 'confirmrelease' => $confirmrelease, 'confirmplugincheck' => $confirmplugins, - ))); + ])); check_upgrade_key($upgradekeyhash); @@ -556,7 +578,7 @@ if (!$outagelessupgrade) { if (empty($confirmrelease)) { require_once($CFG->libdir . '/environmentlib.php'); - list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE); + [$envstatus, $environmentresults] = check_moodle_environment($release, ENV_SELECT_RELEASE); $strcurrentrelease = get_string('currentrelease'); $PAGE->navbar->add($strcurrentrelease); @@ -566,7 +588,6 @@ if (!$outagelessupgrade) { echo $output->upgrade_environment_page($release, $envstatus, $environmentresults); die(); - } else if (!$confirmplugins) { $strplugincheck = get_string('plugincheck'); @@ -596,8 +617,8 @@ if (!$outagelessupgrade) { } redirect($PAGE->url); } else { - $continue = new moodle_url($PAGE->url, array('abortinstallx' => $abortinstallx, - 'confirmabortinstall' => 1)); + $continue = new moodle_url($PAGE->url, ['abortinstallx' => $abortinstallx, + 'confirmabortinstall' => 1]); echo $output->upgrade_confirm_abort_install_page($abortables, $continue); die(); } @@ -612,10 +633,10 @@ if (!$outagelessupgrade) { $pluginman->cancel_plugin_installation($abortinstall); redirect($PAGE->url); } else { - $continue = new moodle_url($PAGE->url, array('abortinstall' => $abortinstall, 'confirmabortinstall' => 1)); + $continue = new moodle_url($PAGE->url, ['abortinstall' => $abortinstall, 'confirmabortinstall' => 1]); $abortable = $pluginman->get_plugin_info($abortinstall); if ($pluginman->can_cancel_plugin_installation($abortable)) { - echo $output->upgrade_confirm_abort_install_page(array($abortable), $continue); + echo $output->upgrade_confirm_abort_install_page([$abortable], $continue); die(); } redirect($PAGE->url); @@ -627,9 +648,11 @@ if (!$outagelessupgrade) { require_sesskey(); $restorable = $pluginman->list_restorable_archives(); if ($restorable) { - upgrade_install_plugins($restorable, $confirmabortupgrade, + upgrade_install_plugins( + $restorable, + $confirmabortupgrade, get_string('cancelupgradehead', 'core_plugin'), - new moodle_url($PAGE->url, array('abortupgradex' => 1, 'confirmabortupgrade' => 1)) + new moodle_url($PAGE->url, ['abortupgradex' => 1, 'confirmabortupgrade' => 1]) ); } redirect($PAGE->url); @@ -640,10 +663,12 @@ if (!$outagelessupgrade) { require_sesskey(); $restorable = $pluginman->list_restorable_archives(); if (isset($restorable[$abortupgrade])) { - $restorable = array($restorable[$abortupgrade]); - upgrade_install_plugins($restorable, $confirmabortupgrade, + $restorable = [$restorable[$abortupgrade]]; + upgrade_install_plugins( + $restorable, + $confirmabortupgrade, get_string('cancelupgradehead', 'core_plugin'), - new moodle_url($PAGE->url, array('abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1)) + new moodle_url($PAGE->url, ['abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1]) ); } redirect($PAGE->url); @@ -653,9 +678,11 @@ if (!$outagelessupgrade) { if ($installdepx) { require_sesskey(); $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true)); - upgrade_install_plugins($installable, $confirminstalldep, + upgrade_install_plugins( + $installable, + $confirminstalldep, get_string('dependencyinstallhead', 'core_plugin'), - new moodle_url($PAGE->url, array('installdepx' => 1, 'confirminstalldep' => 1)) + new moodle_url($PAGE->url, ['installdepx' => 1, 'confirminstalldep' => 1]) ); } @@ -664,10 +691,12 @@ if (!$outagelessupgrade) { require_sesskey(); $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true)); if (!empty($installable[$installdep])) { - $installable = array($installable[$installdep]); - upgrade_install_plugins($installable, $confirminstalldep, + $installable = [$installable[$installdep]]; + upgrade_install_plugins( + $installable, + $confirminstalldep, get_string('dependencyinstallhead', 'core_plugin'), - new moodle_url($PAGE->url, array('installdep' => $installdep, 'confirminstalldep' => 1)) + new moodle_url($PAGE->url, ['installdep' => $installdep, 'confirminstalldep' => 1]) ); } } @@ -676,9 +705,11 @@ if (!$outagelessupgrade) { if ($installupdatex) { require_sesskey(); $installable = $pluginman->filter_installable($pluginman->available_updates()); - upgrade_install_plugins($installable, $confirminstallupdate, + upgrade_install_plugins( + $installable, + $confirminstallupdate, get_string('updateavailableinstallallhead', 'core_admin'), - new moodle_url($PAGE->url, array('installupdatex' => 1, 'confirminstallupdate' => 1)) + new moodle_url($PAGE->url, ['installupdatex' => 1, 'confirminstallupdate' => 1]) ); } @@ -686,30 +717,37 @@ if (!$outagelessupgrade) { if ($installupdate && $installupdateversion) { require_sesskey(); if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) { - $installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true)); - upgrade_install_plugins($installable, $confirminstallupdate, + $installable = [$pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true)]; + upgrade_install_plugins( + $installable, + $confirminstallupdate, get_string('updateavailableinstallallhead', 'core_admin'), - new moodle_url($PAGE->url, array('installupdate' => $installupdate, - 'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1) - ) + new moodle_url($PAGE->url, ['installupdate' => $installupdate, + 'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1]) ); } } // Show plugins info. - echo $output->upgrade_plugin_check_page($pluginman, \core\update\checker::instance(), - $version, $showallplugins, - new moodle_url($PAGE->url), - new moodle_url($PAGE->url, array('confirmplugincheck' => 1, 'cache' => 0))); + echo $output->upgrade_plugin_check_page( + $pluginman, + \core\update\checker::instance(), + $version, + $showallplugins, + new moodle_url($PAGE->url), + new moodle_url($PAGE->url, ['confirmplugincheck' => 1, 'cache' => 0]) + ); die(); } // Make sure plugin dependencies are always checked. - $failed = array(); + $failed = []; if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) { $output = $PAGE->get_renderer('core', 'admin'); - echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url, - array('confirmplugincheck' => 0))); + echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url( + $PAGE->url, + ['confirmplugincheck' => 0] + )); die(); } unset($failed); @@ -772,11 +810,9 @@ if (!$outagelessupgrade) { $adminuser->newadminuser = 1; complete_user_login($adminuser); redirect("$CFG->wwwroot/user/editadvanced.php?id=$adminuser->id"); // Edit thyself. - } else { unset_config('adminsetuppending'); } - } else { // Just make sure upgrade logging is properly terminated. upgrade_finished('upgradesettings.php'); @@ -790,17 +826,17 @@ if (has_capability('moodle/site:config', context_system::instance())) { if ($updateschecker->enabled()) { $updateschecker->fetch(); } - redirect(new moodle_url('/admin/index.php', array('cache' => 0))); + redirect(new moodle_url('/admin/index.php', ['cache' => 0])); } } // Now we can be sure everything was upgraded and caches work fine, // redirect if necessary to make sure caching is enabled. if (!$cache) { - redirect(new moodle_url('/admin/index.php', array('cache' => 1))); + redirect(new moodle_url('/admin/index.php', ['cache' => 1])); } -// Check for valid admin user - no guest autologin +// Check for valid admin user - no guest autologin. require_login(0, false); if (isguestuser()) { // Login as real user! @@ -818,24 +854,24 @@ if (!has_capability('moodle/site:config', $context)) { exit; } -// check that site is properly customized +// Check that site is properly customized. $site = get_site(); if (empty($site->shortname)) { - // probably new installation - lets return to frontpage after this step - // remove settings that we want uninitialised + // Probably new installation - lets return to frontpage after this step + // remove settings that we want uninitialised. unset_config('registerauth'); unset_config('timezone'); // Force admin to select timezone! redirect('upgradesettings.php?return=site'); } -// setup critical warnings before printing admin tree block +// Setup critical warnings before printing admin tree block. $insecuredataroot = is_dataroot_insecure(true); -$SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR); +$SESSION->admin_critical_warning = ($insecuredataroot == INSECURE_DATAROOT_ERROR); $adminroot = admin_get_root(); $PAGE->set_primary_active_tab('siteadminnode'); -// Check if there are any new admin settings which have still yet to be set +// Check if there are any new admin settings which have still yet to be set. if (any_new_admin_settings($adminroot)) { redirect('upgradesettings.php'); } @@ -852,7 +888,7 @@ if (isset($SESSION->pluginuninstallreturn)) { // If site registration needs updating, redirect. \core\hub\registration::registration_reminder('/admin/index.php'); -// Everything should now be set up, and the user is an admin +// Everything should now be set up, and the user is an admin. // Print default admin page with notifications. $errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED'); @@ -868,36 +904,38 @@ $maintenancemode = !empty($CFG->maintenance_enabled); // Available updates for Moodle core. $updateschecker = \core\update\checker::instance(); -$availableupdates = array(); +$availableupdates = []; $availableupdatesfetch = null; if ($updateschecker->enabled()) { // Only compute the update information when it is going to be displayed to the user. - $availableupdates['core'] = $updateschecker->get_update_info('core', - array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds)); + $availableupdates['core'] = $updateschecker->get_update_info( + 'core', + ['minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds] + ); - // Available updates for contributed plugins + // Available updates for contributed plugins. $pluginman = core_plugin_manager::instance(); foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) { foreach ($plugintypeinstances as $pluginname => $plugininfo) { $pluginavailableupdates = $plugininfo->available_updates(); if (!empty($pluginavailableupdates)) { foreach ($pluginavailableupdates as $pluginavailableupdate) { - if (!isset($availableupdates[$plugintype.'_'.$pluginname])) { - $availableupdates[$plugintype.'_'.$pluginname] = array(); + if (!isset($availableupdates[$plugintype . '_' . $pluginname])) { + $availableupdates[$plugintype . '_' . $pluginname] = []; } - $availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate; + $availableupdates[$plugintype . '_' . $pluginname][] = $pluginavailableupdate; } } } } - // The timestamp of the most recent check for available updates + // The timestamp of the most recent check for available updates. $availableupdatesfetch = $updateschecker->get_last_timefetched(); } -$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€'); -//check if the site is registered on Moodle.org +$buggyiconvnomb = (!function_exists('mb_convert_encoding') && @iconv('UTF-8', 'UTF-8//IGNORE', '100' . chr(130) . '€') !== '100€'); +// Check if the site is registered on Moodle.org. $registered = \core\hub\registration::is_registered(); // Check if there are any cache warnings. $cachewarnings = cache_helper::warnings(); @@ -908,11 +946,26 @@ $mobileconfigured = !empty($CFG->enablemobilewebservice); $invalidforgottenpasswordurl = !empty($CFG->forgottenpasswordurl) && empty(clean_param($CFG->forgottenpasswordurl, PARAM_URL)); // Check if a directory with development libraries exists. -if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules'))) { - $devlibdir = true; -} else { - $devlibdir = false; +$devlibdir = false; +if (empty($CFG->disabledevlibdirscheck)) { + if (is_dir("{$CFG->root}/node_modules")) { + // The node_modules directory is used by Node.js packages, which are often used in development. + $devlibdir = true; + } + + if (is_dir("{$CFG->root}/vendor") && is_file("{$CFG->root}/vendor/composer/installed.php")) { + // The vendor directory is used by Composer packages, which are often used in development. + // These files may also be used for production code, so we need to read the installed.php file to determine + // if development dependencies are included. + $installed = include("{$CFG->root}/vendor/composer/installed.php"); + if (is_array($installed) && array_key_exists('root', $installed)) { + if ($installed['root']['dev']) { + $devlibdir = true; + } + } + } } + // Check if the site is being foced onto ssl. $overridetossl = !empty($CFG->overridetossl); @@ -935,9 +988,27 @@ admin_externalpage_setup('adminnotifications'); $output = $PAGE->get_renderer('core', 'admin'); -echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems, - $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb, - $registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir, - $mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent, - $showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent, - $xmlrpcwarning); +echo $output->admin_notifications_page( + $maturity, + $insecuredataroot, + $errorsdisplayed, + $cronoverdue, + $dbproblems, + $maintenancemode, + $availableupdates, + $availableupdatesfetch, + $buggyiconvnomb, + $registered, + $cachewarnings, + $eventshandlers, + $themedesignermode, + $devlibdir, + $mobileconfigured, + $overridetossl, + $invalidforgottenpasswordurl, + $croninfrequent, + $showcampaigncontent, + $showfeedbackencouragement, + $servicesandsupportcontent, + $xmlrpcwarning +); diff --git a/public/lang/en/admin.php b/public/lang/en/admin.php index fd11c7af64b..5f33a07f788 100644 --- a/public/lang/en/admin.php +++ b/public/lang/en/admin.php @@ -168,6 +168,10 @@ $string['commonactivitysettings'] = 'Common activity settings'; $string['commonfiltersettings'] = 'Common filter settings'; $string['commonsettings'] = 'Common settings'; $string['componentinstalled'] = 'Component installed'; +$string['composernotfound'] = 'Composer dependencies were not found. Please ensure that the "composer install --no-dev --classmap-authoritative" command has been run in the Moodle root directory. If you are not using Composer, please ensure that the vendor directory exists and contains the necessary files.'; +$string['composerdeveloperdependenciesinstalled'] = 'Composer Developer dependencies are installed. Please ensure that the "composer install --no-dev --classmap-authoritative" command has been run in the Moodle root directory.'; +$string['composeroptimisedindevmode'] = 'The Composer autoloader is currently running optimised whilst Moodle is in developer mode. This can cause issues in some cases. You may wish to run "composer install" without additional arguments.'; +$string['composernotoptimised'] = 'Moodle is running in production mode whilst the Composer autoloader is not optimised. You may wish to run "composer install --no-dev --classmap-authoritative" to optimise the autoloader.'; $string['computedfromlogs'] = 'Computed from logs since {$a}.'; $string['condifmodeditdefaults'] = 'Default values are used in the settings form when creating a new activity or resource.'; $string['confeditorhidebuttons'] = 'Select the buttons that should be hidden in the HTML editor.'; diff --git a/public/lib/classes/environment.php b/public/lib/classes/environment.php new file mode 100644 index 00000000000..c05e756ef4c --- /dev/null +++ b/public/lib/classes/environment.php @@ -0,0 +1,163 @@ +. + +namespace core; + +/** + * Class environment + * + * @package core + * @copyright Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class environment { + /** + * Ensure that Composer dependencies are installed and the necessary files are present. + * + * @param \environment_results $result + * @return \environment_results|null + */ + public static function check_composer_dependencies_installed(\environment_results $result): ?\environment_results { + // Check if the composer vendor directory exists. + $vendorpath = static::get_vendor_path(); + if (!is_dir($vendorpath)) { + $result->setInfo('Composer vendor directory not found'); + $result->setFeedbackStr('composernotfound'); + return $result; + } + + // Check if the composer autoload file exists. + $autoloadpath = "{$vendorpath}/autoload.php"; + if (!is_file($autoloadpath)) { + $result->setInfo('Composer autoload file not found'); + $result->setFeedbackStr('composernotfound'); + return $result; + } + + // Check if the installed.php file exists in the composer directory. + $installedpath = "{$vendorpath}/composer/installed.php"; + if (!is_file($installedpath)) { + $result->setInfo('Composer installed data not found'); + $result->setFeedbackStr('composernotfound'); + return $result; + } + + return null; + } + + /** + * Ensure that Composer developer dependencies are not installed. + * + * @param \environment_results $result + * @return \environment_results|null + */ + public static function check_composer_developer_dependencies_not_installed( + \environment_results $result + ): ?\environment_results { + if (static::is_developer_mode_enabled()) { + $result->setInfo('Developer mode is enabled, skipping check for developer dependencies'); + return null; // Skip this check in developer mode. + } + + $vendorpath = static::get_vendor_path(); + if (!is_dir($vendorpath)) { + return null; // No vendor directory, so no developer dependencies to check. + } + + // Check if the installed.php file exists in the composer directory. + $installedpath = "{$vendorpath}/composer/installed.php"; + if (!is_file($installedpath)) { + return null; // No installed file, so no developer dependencies to check. + } + + // Check if developer dependencies have been installed too. + $installed = include($installedpath); + if (is_array($installed) && array_key_exists('root', $installed)) { + if ($installed['root']['dev']) { + $result->setInfo('Composer Developer dependencies are installed'); + $result->setFeedbackStr('composerdeveloperdependenciesinstalled'); + return $result; + } + } + + return null; + } + + /** + * Ensure that Composer developer dependencies are optimised . + * + * @param \environment_results $result + * @return \environment_results|null + * @codeCoverageIgnore + */ + public static function check_composer_dependencies_optimised( + \environment_results $result + ): ?\environment_results { + $vendorpath = static::get_vendor_path(); + if (!is_dir($vendorpath)) { + return null; // No vendor directory, so no developer dependencies to check. + } + + $autoloader = require("{$vendorpath}/autoload.php"); + + if (static::is_developer_mode_enabled()) { + if ($autoloader->isClassMapAuthoritative()) { + $result->setInfo('Composer autoloader is optimised'); + $result->setFeedbackStr('composeroptimisedindevmode'); + + return $result; + } + + $result->setInfo('Developer mode is enabled, optimiser is correctly disabled.'); + + return null; + } + + if ($autoloader->isClassMapAuthoritative()) { + $result->setInfo('Autoloader is correctly optimised.'); + + return null; + } + + $result->setInfo('Composer autoloader is not optimised'); + $result->setFeedbackStr('composernotoptimised'); + + return $result; + } + + /** + * Get the path to the Composer vendor directory. + * + * @return string + */ + protected static function get_vendor_path(): string { + global $CFG; + + // Return the path to the vendor directory. + return "{$CFG->root}/vendor"; + } + + /** + * Check if developer mode is enabled. + * + * @return bool + */ + protected static function is_developer_mode_enabled(): bool { + global $CFG; + + return !empty($CFG->debugdeveloper); + } +} diff --git a/public/lib/tests/classes/environment.php b/public/lib/tests/classes/environment.php new file mode 100644 index 00000000000..025cfabee8b --- /dev/null +++ b/public/lib/tests/classes/environment.php @@ -0,0 +1,68 @@ +. + +namespace core\tests; + +/** + * Test helper for the \core\environment class. + * + * @package core + * @copyright Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class environment extends \core\environment { + /** @var string|null The path to the vendor dir if modified */ + protected static ?string $vendorpath; + + /** @var bool|null Whether developer mode is enabled, or defer to $CFG */ + protected static ?bool $devmode = null; + + /** + * Set the developer mode for testing purposes. + * + * @param bool $enabled + */ + public static function set_developer_mode(bool $enabled): void { + self::$devmode = $enabled; + } + + /** + * Set the vendor path for testing purposes. + * + * @param string $path + */ + public static function set_vendor_path(string $path): void { + self::$vendorpath = $path; + } + + #[\Override] + protected static function get_vendor_path(): string { + if (self::$vendorpath) { + return self::$vendorpath; + } + + return parent::get_vendor_path(); + } + + #[\Override] + protected static function is_developer_mode_enabled(): bool { + if (self::$devmode !== null) { + return self::$devmode; + } + + return parent::is_developer_mode_enabled(); + } +} diff --git a/public/lib/tests/environment_test.php b/public/lib/tests/environment_test.php index e80298737cb..fe8f946801e 100644 --- a/public/lib/tests/environment_test.php +++ b/public/lib/tests/environment_test.php @@ -16,232 +16,141 @@ namespace core; -use environment_results; +use core\tests\environment as environment_tester; /** - * Moodle environment test. + * Tests for the \core\environment class. * * @package core - * @category phpunit - * @copyright 2013 Petr Skoda {@link http://skodak.org} + * @category test + * @copyright Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +#[\PHPUnit\Framework\Attributes\CoversClass(environment::class)] final class environment_test extends \advanced_testcase { + #[\PHPUnit\Framework\Attributes\DataProvider('composer_error_states_provider')] + public function test_composer_not_installed_cases( + array $fs = [], + string $expectedfeedback = 'composernotfound' + ): void { + \org\bovigo\vfs\vfsStream::setup('root', null, $fs); + environment_tester::set_vendor_path(\org\bovigo\vfs\vfsStream::url('root/vendor')); - /** - * Test the environment check status. - */ - public function test_environment_check_status(): void { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_dependencies_installed($result); + $this->assertEquals($expectedfeedback, $result->getFeedbackStr()); - $results = check_moodle_environment(normalize_version($CFG->release), ENV_SELECT_RELEASE); - - // The first element of the results array contains the environment check status. - $status = reset($results); - $this->assertTrue($status); + // Check that the developer dependencies tests do not error in these conditions. + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_developer_dependencies_not_installed($result); + $this->assertNull($result); } /** - * Data provider for Moodle environment check tests. + * Data provider for test_composer_not_installed_cases. * - * @return array + * @return \Generator */ - public static function environment_provider(): array { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); - - $results = check_moodle_environment(normalize_version($CFG->release), ENV_SELECT_RELEASE); - // The second element of the results array contains the list of environment results. - $environmentresults = end($results); - return array_map(function($result) { - return [$result]; - }, $environmentresults); + public static function composer_error_states_provider(): \Generator { + yield 'composer vendor directory not found' => [ + 'fs' => [], + 'expectedfeedback' => 'composernotfound', + ]; + yield 'composer autoload file not found' => [ + 'fs' => [ + 'vendor' => [], + ], + 'expectedfeedback' => 'composernotfound', + ]; + yield 'composer installed data not found' => [ + 'fs' => [ + 'vendor' => [ + 'autoload.php' => '', + ], + ], + 'expectedfeedback' => 'composernotfound', + ]; } - /** - * Test the environment. - * - * @dataProvider environment_provider - * @param environment_results $result - */ - public function test_environment($result): void { - $sslmessages = ['ssl/tls configuration not supported', 'invalid ssl/tls configuration']; + public function test_composer_installed(): void { + \org\bovigo\vfs\vfsStream::setup('root', null, [ + 'vendor' => [ + 'autoload.php' => '', + 'composer' => [ + 'installed.php' => '', + ], + ], + ]); - if ($result->part === 'php_setting' - && $result->info === 'opcache.enable' - && $result->getLevel() === 'optional' - && $result->getStatus() === false) { - $this->markTestSkipped('OPCache extension is not necessary for unit testing.'); - } + environment_tester::set_vendor_path(\org\bovigo\vfs\vfsStream::url('root/vendor')); - if ($result->part === 'php_setting' - && $result->info === 'zend.exception_ignore_args' - && $result->getLevel() === 'optional' - && $result->getStatus() === false) { - $this->markTestSkipped('zend.exception_ignore_args is not necessary for unit testing.'); - } - - if ($result->part === 'php_extension' - && $result->getPluginName() !== '' - && $result->getLevel() === 'optional' - && $result->getStatus() === false) { - $this->markTestSkipped('Optional plugin extension is not necessary for unit testing.'); - } - - if ($result->part === 'custom_check' - && $result->getLevel() === 'optional' - && $result->getStatus() === false) { - if (in_array($result->info, $sslmessages)) { - $this->markTestSkipped('Up-to-date TLS libraries are not necessary for unit testing.'); - } - if ($result->info === 'php not 64 bits' && PHP_INT_SIZE == 4) { - // If we're on a 32-bit system, skip 64-bit check. 32-bit PHP has PHP_INT_SIZE set to 4. - $this->markTestSkipped('64-bit check is not necessary for unit testing.'); - } - } - $info = "{$result->part}:{$result->info}"; - $this->assertTrue($result->getStatus(), "Problem detected in environment ($info), fix all warnings and errors!"); + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_dependencies_installed($result); + $this->assertNull($result); } - /** - * Test the get_list_of_environment_versions() function. - */ - public function test_get_list_of_environment_versions(): void { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); - // Build a sample xmlised environment.xml. - $xml = << - - - - - - - - - - - - - - - - - - - - - - - - - - -END; - $environemt = (new \core\xml_parser())->parse($xml); - $versions = get_list_of_environment_versions($environemt); - $this->assertCount(5, $versions); - $this->assertContains('1.9', $versions); - $this->assertContains('2.5', $versions); - $this->assertContains('2.6', $versions); - $this->assertContains('2.7', $versions); - $this->assertContains('all', $versions); + public function test_composer_dev_installed(): void { + \org\bovigo\vfs\vfsStream::setup('root', null, [ + 'vendor' => [ + 'autoload.php' => '', + 'composer' => [ + 'installed.php' => ' ["dev" => true]];', + ], + ], + ]); + environment_tester::set_vendor_path(\org\bovigo\vfs\vfsStream::url('root/vendor')); + environment_tester::set_developer_mode(false); + + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_developer_dependencies_not_installed($result); + $this->assertEquals('composerdeveloperdependenciesinstalled', $result->getFeedbackStr()); + + // Check that the dependencies tests do not error in these conditions. + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_dependencies_installed($result); + $this->assertNull($result); } - /** - * Test the environment_verify_plugin() function. - */ - public function test_verify_plugin(): void { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); - $xmlparser = new \core\xml_parser(); - // Build sample xmlised environment file fragments. - $plugin1xml = << - - - - -END; - $plugin1 = $xmlparser->parse($plugin1xml); - $plugin2xml = << - - - - -END; - $plugin2 = $xmlparser->parse($plugin2xml); - $this->assertTrue(environment_verify_plugin('block_testcase', $plugin1['PLUGIN'])); - $this->assertFalse(environment_verify_plugin('block_testcase', $plugin2['PLUGIN'])); - $this->assertFalse(environment_verify_plugin('mod_someother', $plugin1['PLUGIN'])); - $this->assertFalse(environment_verify_plugin('mod_someother', $plugin2['PLUGIN'])); + public function test_composer_dev_installed_with_developer_mode(): void { + \org\bovigo\vfs\vfsStream::setup('root', null, [ + 'vendor' => [ + 'autoload.php' => '', + 'composer' => [ + 'installed.php' => ' ["dev" => true]];', + ], + ], + ]); + environment_tester::set_vendor_path(\org\bovigo\vfs\vfsStream::url('root/vendor')); + environment_tester::set_developer_mode(true); + + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_developer_dependencies_not_installed($result); + $this->assertNull($result); + + // Check that the dependencies tests do not error in these conditions. + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_dependencies_installed($result); + $this->assertNull($result); } - /** - * Test the restrict_php_version() function returns true if the current - * PHP version is greater than the restricted version - */ - public function test_restrict_php_version_greater_than_restricted_version(): void { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); + public function test_composer_dev_not_installed(): void { + \org\bovigo\vfs\vfsStream::setup('root', null, [ + 'vendor' => [ + 'autoload.php' => '', + 'composer' => [ + 'installed.php' => ' ["dev" => false]];', + ], + ], + ]); + environment_tester::set_vendor_path(\org\bovigo\vfs\vfsStream::url('root/vendor')); - $result = new environment_results('php'); - $delimiter = '.'; - // Get the current PHP version. - $currentversion = explode($delimiter, normalize_version(phpversion())); - // Lets drop back one major version to ensure we trip the restriction. - $currentversion[0]--; - $restrictedversion = implode($delimiter, $currentversion); + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_developer_dependencies_not_installed($result); + $this->assertNull($result); - // Make sure the status is true before the test to see it flip to false. - $result->setStatus(true); - - $this->assertTrue(restrict_php_version($result, $restrictedversion), - 'restrict_php_version returns true if the current version exceeds the restricted version'); - } - - /** - * Test the restrict_php_version() function returns true if the current - * PHP version is equal to the restricted version - */ - public function test_restrict_php_version_equal_to_restricted_version(): void { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); - - $result = new environment_results('php'); - // Get the current PHP version. - $currentversion = normalize_version(phpversion()); - - // Make sure the status is true before the test to see it flip to false. - $result->setStatus(true); - - $this->assertTrue(restrict_php_version($result, $currentversion), - 'restrict_php_version returns true if the current version is equal to the restricted version'); - } - - /** - * Test the restrict_php_version() function returns false if the current - * PHP version is less than the restricted version - */ - public function test_restrict_php_version_less_than_restricted_version(): void { - global $CFG; - require_once($CFG->libdir.'/environmentlib.php'); - - $result = new environment_results('php'); - $delimiter = '.'; - // Get the current PHP version. - $currentversion = explode($delimiter, normalize_version(phpversion())); - // Lets increase the major version to ensure don't trip the restriction. - $currentversion[0]++; - $restrictedversion = implode($delimiter, $currentversion); - - // Make sure the status is true before the test to see it flip to false. - $result->setStatus(true); - - $this->assertFalse(restrict_php_version($result, $restrictedversion), - 'restrict_php_version returns false if the current version is less than the restricted version'); + // Check that the dependencies tests do not error in these conditions. + $result = new \environment_results('custom_check'); + $result = environment_tester::check_composer_dependencies_installed($result); + $this->assertNull($result); } } diff --git a/public/lib/tests/environmentlib_test.php b/public/lib/tests/environmentlib_test.php new file mode 100644 index 00000000000..d32808514ca --- /dev/null +++ b/public/lib/tests/environmentlib_test.php @@ -0,0 +1,260 @@ +. + +namespace core; + +use environment_results; + +/** + * Moodle environment test. + * + * @package core + * @category test + * @copyright 2013 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +final class environmentlib_test extends \advanced_testcase { + /** + * Test the environment check status. + */ + public function test_environment_check_status(): void { + global $CFG; + require_once($CFG->libdir . '/environmentlib.php'); + + $results = check_moodle_environment(normalize_version($CFG->release), ENV_SELECT_RELEASE); + + // The first element of the results array contains the environment check status. + $status = reset($results); + $this->assertTrue($status); + } + + /** + * Data provider for Moodle environment check tests. + * + * @return array + */ + public static function environment_provider(): array { + global $CFG; + require_once($CFG->libdir . '/environmentlib.php'); + + $results = check_moodle_environment(normalize_version($CFG->release), ENV_SELECT_RELEASE); + // The second element of the results array contains the list of environment results. + $environmentresults = end($results); + return array_map(function ($result) { + return [$result]; + }, $environmentresults); + } + + /** + * Test the environment. + * + * @dataProvider environment_provider + * @param environment_results $result + */ + public function test_environment($result): void { + $sslmessages = ['ssl/tls configuration not supported', 'invalid ssl/tls configuration']; + + if ( + $result->part === 'php_setting' + && $result->info === 'opcache.enable' + && $result->getLevel() === 'optional' + && $result->getStatus() === false + ) { + $this->markTestSkipped('OPCache extension is not necessary for unit testing.'); + } + + if ( + $result->part === 'php_setting' + && $result->info === 'zend.exception_ignore_args' + && $result->getLevel() === 'optional' + && $result->getStatus() === false + ) { + $this->markTestSkipped('zend.exception_ignore_args is not necessary for unit testing.'); + } + + if ( + $result->part === 'php_extension' + && $result->getPluginName() !== '' + && $result->getLevel() === 'optional' + && $result->getStatus() === false + ) { + $this->markTestSkipped('Optional plugin extension is not necessary for unit testing.'); + } + + if ( + $result->part === 'custom_check' + && $result->getLevel() === 'optional' + && $result->getStatus() === false + ) { + if (in_array($result->info, $sslmessages)) { + $this->markTestSkipped('Up-to-date TLS libraries are not necessary for unit testing.'); + } + if ($result->info === 'php not 64 bits' && PHP_INT_SIZE == 4) { + // If we're on a 32-bit system, skip 64-bit check. 32-bit PHP has PHP_INT_SIZE set to 4. + $this->markTestSkipped('64-bit check is not necessary for unit testing.'); + } + } + $info = "{$result->part}:{$result->info}"; + $this->assertTrue($result->getStatus(), "Problem detected in environment ($info), fix all warnings and errors!"); + } + + /** + * Test the get_list_of_environment_versions() function. + */ + public function test_get_list_of_environment_versions(): void { + global $CFG; + require_once($CFG->libdir . '/environmentlib.php'); + // Build a sample xmlised environment.xml. + $xml = << + + + + + + + + + + + + + + + + + + + + + + + + + + +END; + $environemt = (new \core\xml_parser())->parse($xml); + $versions = get_list_of_environment_versions($environemt); + $this->assertCount(5, $versions); + $this->assertContains('1.9', $versions); + $this->assertContains('2.5', $versions); + $this->assertContains('2.6', $versions); + $this->assertContains('2.7', $versions); + $this->assertContains('all', $versions); + } + + /** + * Test the environment_verify_plugin() function. + */ + public function test_verify_plugin(): void { + global $CFG; + $xmlparser = new \core\xml_parser(); + require_once($CFG->libdir . '/environmentlib.php'); + // Build sample xmlised environment file fragments. + $plugin1xml = << + + + + +END; + $plugin1 = $xmlparser->parse($plugin1xml); + $plugin2xml = << + + + + +END; + $plugin2 = $xmlparser->parse($plugin2xml); + $this->assertTrue(environment_verify_plugin('block_testcase', $plugin1['PLUGIN'])); + $this->assertFalse(environment_verify_plugin('block_testcase', $plugin2['PLUGIN'])); + $this->assertFalse(environment_verify_plugin('mod_someother', $plugin1['PLUGIN'])); + $this->assertFalse(environment_verify_plugin('mod_someother', $plugin2['PLUGIN'])); + } + + /** + * Test the restrict_php_version() function returns true if the current + * PHP version is greater than the restricted version + */ + public function test_restrict_php_version_greater_than_restricted_version(): void { + global $CFG; + require_once($CFG->libdir . '/environmentlib.php'); + + $result = new environment_results('php'); + $delimiter = '.'; + // Get the current PHP version. + $currentversion = explode($delimiter, normalize_version(phpversion())); + // Lets drop back one major version to ensure we trip the restriction. + $currentversion[0]--; + $restrictedversion = implode($delimiter, $currentversion); + + // Make sure the status is true before the test to see it flip to false. + $result->setStatus(true); + + $this->assertTrue( + restrict_php_version($result, $restrictedversion), + 'restrict_php_version returns true if the current version exceeds the restricted version' + ); + } + + /** + * Test the restrict_php_version() function returns true if the current + * PHP version is equal to the restricted version + */ + public function test_restrict_php_version_equal_to_restricted_version(): void { + global $CFG; + require_once($CFG->libdir . '/environmentlib.php'); + + $result = new environment_results('php'); + // Get the current PHP version. + $currentversion = normalize_version(phpversion()); + + // Make sure the status is true before the test to see it flip to false. + $result->setStatus(true); + + $this->assertTrue( + restrict_php_version($result, $currentversion), + 'restrict_php_version returns true if the current version is equal to the restricted version' + ); + } + + /** + * Test the restrict_php_version() function returns false if the current + * PHP version is less than the restricted version + */ + public function test_restrict_php_version_less_than_restricted_version(): void { + global $CFG; + require_once($CFG->libdir . '/environmentlib.php'); + + $result = new environment_results('php'); + $delimiter = '.'; + // Get the current PHP version. + $currentversion = explode($delimiter, normalize_version(phpversion())); + // Lets increase the major version to ensure don't trip the restriction. + $currentversion[0]++; + $restrictedversion = implode($delimiter, $currentversion); + + // Make sure the status is true before the test to see it flip to false. + $result->setStatus(true); + + $this->assertFalse( + restrict_php_version($result, $restrictedversion), + 'restrict_php_version returns false if the current version is less than the restricted version' + ); + } +}