Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
  • /admin/ -> index.php (source)

    Differences Between: [Versions 310 and 34] [Versions 310 and 35] [Versions 310 and 36] [Versions 310 and 37] [Versions 310 and 38] [Versions 34 and 310] [Versions 35 and 310] [Versions 36 and 310] [Versions 37 and 310] [Versions 38 and 310]

       1  <?php
       2  
       3  // This file is part of Moodle - http://moodle.org/
       4  //
       5  // Moodle is free software: you can redistribute it and/or modify
       6  // it under the terms of the GNU General Public License as published by
       7  // the Free Software Foundation, either version 3 of the License, or
       8  // (at your option) any later version.
       9  //
      10  // Moodle is distributed in the hope that it will be useful,
      11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13  // GNU General Public License for more details.
      14  //
      15  // You should have received a copy of the GNU General Public License
      16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
      17  
      18  /**
      19   * Main administration script.
      20   *
      21   * @package    core
      22   * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
      23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      24   */
      25  
      26  // Check that config.php exists, if not then call the install script
      27  if (!file_exists('../config.php')) {
      28      header('Location: ../install.php');
      29      die();
      30  }
      31  
      32  // Check that PHP is of a sufficient version as soon as possible.
      33  require_once (__DIR__.'/../lib/phpminimumversionlib.php');
      34  moodle_require_minimum_php_version();
      35  
      36  // make sure iconv is available and actually works
      37  if (!function_exists('iconv')) {
      38      // this should not happen, this must be very borked install
      39      echo 'Moodle requires the iconv PHP extension. Please install or enable the iconv extension.';
      40      die();
      41  }
      42  
      43  // Make sure php5-json is available.
      44  if (!function_exists('json_encode') || !function_exists('json_decode')) {
      45      // This also shouldn't happen.
      46      echo 'Moodle requires the json PHP extension. Please install or enable the json extension.';
      47      die();
      48  }
      49  
      50  // Make sure xml extension is available.
      51  if (!extension_loaded('xml')) {
      52      echo 'Moodle requires the xml PHP extension. Please install or enable the xml extension.';
      53      die();
      54  }
      55  
      56  define('NO_OUTPUT_BUFFERING', true);
      57  
      58  if (isset($_POST['upgradekey'])) {
      59      // Before you start reporting issues about the collision attacks against
      60      // SHA-1, you should understand that we are not actually attempting to do
      61      // any cryptography here. This is hashed purely so that the key is not
      62      // that apparent in the address bar itself. Anyone who catches the HTTP
      63      // traffic can immediately use it as a valid admin key.
      64      header('Location: index.php?cache=0&upgradekeyhash='.sha1($_POST['upgradekey']));
      65      die();
      66  }
      67  
      68  if ((isset($_GET['cache']) and $_GET['cache'] === '0')
      69          or (isset($_POST['cache']) and $_POST['cache'] === '0')
      70          or (!isset($_POST['cache']) and !isset($_GET['cache']) and empty($_GET['sesskey']) and empty($_POST['sesskey']))) {
      71      // Prevent caching at all cost when visiting this page directly,
      72      // we redirect to self once we known no upgrades are necessary.
      73      // Note: $_GET and $_POST are used here intentionally because our param cleaning is not loaded yet.
      74      // Note2: the sesskey is present in all block editing hacks, we can not redirect there, so enable caching.
      75      define('CACHE_DISABLE_ALL', true);
      76  
      77      // Force OPcache reset if used, we do not want any stale caches
      78      // when detecting if upgrade necessary or when running upgrade.
      79      if (function_exists('opcache_reset')) {
      80          opcache_reset();
      81      }
      82      $cache = 0;
      83  
      84  } else {
      85      $cache = 1;
      86  }
      87  
      88  require('../config.php');
      89  
      90  // Invalidate the cache of version.php in any circumstances to help core_component
      91  // detecting if the version has changed and component cache should be reset.
      92  if (function_exists('opcache_invalidate')) {
      93      opcache_invalidate($CFG->dirroot . '/version.php', true);
      94  }
      95  // Make sure the component cache gets rebuilt if necessary, any method that
      96  // indirectly calls the protected init() method is good here.
      97  core_component::get_core_subsystems();
      98  
      99  if (is_major_upgrade_required() && isloggedin()) {
     100      // A major upgrade is required.
     101      // Terminate the session and redirect back here before anything DB-related happens.
     102      redirect_if_major_upgrade_required();
     103  }
     104  
     105  require_once($CFG->libdir.'/adminlib.php');    // various admin-only functions
     106  require_once($CFG->libdir.'/upgradelib.php');  // general upgrade/install related functions
     107  
     108  $confirmupgrade = optional_param('confirmupgrade', 0, PARAM_BOOL); // Core upgrade confirmed?
     109  $confirmrelease = optional_param('confirmrelease', 0, PARAM_BOOL); // Core release info and server checks confirmed?
     110  $confirmplugins = optional_param('confirmplugincheck', 0, PARAM_BOOL); // Plugins check page confirmed?
     111  $showallplugins = optional_param('showallplugins', 0, PARAM_BOOL); // Show all plugins on the plugins check page?
     112  $agreelicense = optional_param('agreelicense', 0, PARAM_BOOL); // GPL license confirmed for installation?
     113  $fetchupdates = optional_param('fetchupdates', 0, PARAM_BOOL); // Should check for available updates?
     114  $newaddonreq = optional_param('installaddonrequest', null, PARAM_RAW); // Plugin installation requested at moodle.org/plugins.
     115  $upgradekeyhash = optional_param('upgradekeyhash', null, PARAM_ALPHANUM); // Hash of provided upgrade key.
     116  $installdep = optional_param('installdep', null, PARAM_COMPONENT); // Install given missing dependency (required plugin).
     117  $installdepx = optional_param('installdepx', false, PARAM_BOOL); // Install all missing dependencies.
     118  $confirminstalldep = optional_param('confirminstalldep', false, PARAM_BOOL); // Installing dependencies confirmed.
     119  $abortinstall = optional_param('abortinstall', null, PARAM_COMPONENT); // Cancel installation of the given new plugin.
     120  $abortinstallx = optional_param('abortinstallx', null, PARAM_BOOL); // Cancel installation of all new plugins.
     121  $confirmabortinstall = optional_param('confirmabortinstall', false, PARAM_BOOL); // Installation cancel confirmed.
     122  $abortupgrade = optional_param('abortupgrade', null, PARAM_COMPONENT); // Cancel upgrade of the given existing plugin.
     123  $abortupgradex = optional_param('abortupgradex', null, PARAM_BOOL); // Cancel upgrade of all upgradable plugins.
     124  $confirmabortupgrade = optional_param('confirmabortupgrade', false, PARAM_BOOL); // Upgrade cancel confirmed.
     125  $installupdate = optional_param('installupdate', null, PARAM_COMPONENT); // Install given available update.
     126  $installupdateversion = optional_param('installupdateversion', null, PARAM_INT); // Version of the available update to install.
     127  $installupdatex = optional_param('installupdatex', false, PARAM_BOOL); // Install all available plugin updates.
     128  $confirminstallupdate = optional_param('confirminstallupdate', false, PARAM_BOOL); // Available update(s) install confirmed?
     129  
     130  if (!empty($CFG->disableupdateautodeploy)) {
     131      // Invalidate all requests to install plugins via the admin UI.
     132      $newaddonreq = null;
     133      $installdep = null;
     134      $installdepx = false;
     135      $abortupgrade = null;
     136      $abortupgradex = null;
     137      $installupdate = null;
     138      $installupdateversion = null;
     139      $installupdatex = false;
     140  }
     141  
     142  // Set up PAGE.
     143  $url = new moodle_url('/admin/index.php');
     144  $url->param('cache', $cache);
     145  if (isset($upgradekeyhash)) {
     146      $url->param('upgradekeyhash', $upgradekeyhash);
     147  }
     148  $PAGE->set_url($url);
     149  unset($url);
     150  
     151  // Are we returning from an add-on installation request at moodle.org/plugins?
     152  if ($newaddonreq and !$cache and empty($CFG->disableupdateautodeploy)) {
     153      $target = new moodle_url('/admin/tool/installaddon/index.php', array(
     154          'installaddonrequest' => $newaddonreq,
     155          'confirm' => 0));
     156      if (!isloggedin() or isguestuser()) {
     157          // Login and go the the add-on tool page.
     158          $SESSION->wantsurl = $target->out();
     159          redirect(get_login_url());
     160      }
     161      redirect($target);
     162  }
     163  
     164  $PAGE->set_pagelayout('admin'); // Set a default pagelayout
     165  
     166  $documentationlink = '<a href="http://docs.moodle.org/en/Installation">Installation docs</a>';
     167  
     168  // Check some PHP server settings
     169  
     170  if (ini_get_bool('session.auto_start')) {
     171      print_error('phpvaroff', 'debug', '', (object)array('name'=>'session.auto_start', 'link'=>$documentationlink));
     172  }
     173  
     174  if (!ini_get_bool('file_uploads')) {
     175      print_error('phpvaron', 'debug', '', (object)array('name'=>'file_uploads', 'link'=>$documentationlink));
     176  }
     177  
     178  if (is_float_problem()) {
     179      print_error('phpfloatproblem', 'admin', '', $documentationlink);
     180  }
     181  
     182  // Set some necessary variables during set-up to avoid PHP warnings later on this page
     183  if (!isset($CFG->release)) {
     184      $CFG->release = '';
     185  }
     186  if (!isset($CFG->version)) {
     187      $CFG->version = '';
     188  }
     189  if (!isset($CFG->branch)) {
     190      $CFG->branch = '';
     191  }
     192  
     193  $version = null;
     194  $release = null;
     195  $branch = null;
     196  require("$CFG->dirroot/version.php");       // defines $version, $release, $branch and $maturity
     197  $CFG->target_release = $release;            // used during installation and upgrades
     198  
     199  if (!$version or !$release) {
     200      print_error('withoutversion', 'debug'); // without version, stop
     201  }
     202  
     203  if (!core_tables_exist()) {
     204      $PAGE->set_pagelayout('maintenance');
     205      $PAGE->set_popup_notification_allowed(false);
     206  
     207      // fake some settings
     208      $CFG->docroot = 'http://docs.moodle.org';
     209  
     210      $strinstallation = get_string('installation', 'install');
     211  
     212      // remove current session content completely
     213      \core\session\manager::terminate_current();
     214  
     215      if (empty($agreelicense)) {
     216          $strlicense = get_string('license');
     217  
     218          $PAGE->navbar->add($strlicense);
     219          $PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release);
     220          $PAGE->set_heading($strinstallation);
     221          $PAGE->set_cacheable(false);
     222  
     223          $output = $PAGE->get_renderer('core', 'admin');
     224          echo $output->install_licence_page();
     225          die();
     226      }
     227      if (empty($confirmrelease)) {
     228          require_once($CFG->libdir.'/environmentlib.php');
     229          list($envstatus, $environmentresults) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
     230          $strcurrentrelease = get_string('currentrelease');
     231  
     232          $PAGE->navbar->add($strcurrentrelease);
     233          $PAGE->set_title($strinstallation);
     234          $PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release);
     235          $PAGE->set_cacheable(false);
     236  
     237          $output = $PAGE->get_renderer('core', 'admin');
     238          echo $output->install_environment_page($maturity, $envstatus, $environmentresults, $release);
     239          die();
     240      }
     241  
     242      // check plugin dependencies
     243      $failed = array();
     244      if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
     245          $PAGE->navbar->add(get_string('pluginscheck', 'admin'));
     246          $PAGE->set_title($strinstallation);
     247          $PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release);
     248  
     249          $output = $PAGE->get_renderer('core', 'admin');
     250          $url = new moodle_url($PAGE->url, array('agreelicense' => 1, 'confirmrelease' => 1, 'lang' => $CFG->lang));
     251          echo $output->unsatisfied_dependencies_page($version, $failed, $url);
     252          die();
     253      }
     254      unset($failed);
     255  
     256      //TODO: add a page with list of non-standard plugins here
     257  
     258      $strdatabasesetup = get_string('databasesetup');
     259      upgrade_init_javascript();
     260  
     261      $PAGE->navbar->add($strdatabasesetup);
     262      $PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release);
     263      $PAGE->set_heading($strinstallation);
     264      $PAGE->set_cacheable(false);
     265  
     266      $output = $PAGE->get_renderer('core', 'admin');
     267      echo $output->header();
     268  
     269      if (!$DB->setup_is_unicodedb()) {
     270          if (!$DB->change_db_encoding()) {
     271              // If could not convert successfully, throw error, and prevent installation
     272              print_error('unicoderequired', 'admin');
     273          }
     274      }
     275  
     276      install_core($version, true);
     277  }
     278  
     279  
     280  // Check version of Moodle code on disk compared with database
     281  // and upgrade if possible.
     282  
     283  if (!$cache) {
     284      // Do not try to do anything fancy in non-cached mode,
     285      // this prevents themes from fetching data from non-existent tables.
     286      $PAGE->set_pagelayout('maintenance');
     287      $PAGE->set_popup_notification_allowed(false);
     288  }
     289  
     290  $stradministration = get_string('administration');
     291  $PAGE->set_context(context_system::instance());
     292  
     293  if (empty($CFG->version)) {
     294      print_error('missingconfigversion', 'debug');
     295  }
     296  
     297  // Detect config cache inconsistency, this happens when you switch branches on dev servers.
     298  if ($CFG->version != $DB->get_field('config', 'value', array('name'=>'version'))) {
     299      purge_all_caches();
     300      redirect(new moodle_url($PAGE->url), 'Config cache inconsistency detected, resetting caches...');
     301  }
     302  
     303  if (!$cache and $version > $CFG->version) {  // upgrade
     304  
     305      $PAGE->set_url(new moodle_url($PAGE->url, array(
     306          'confirmupgrade' => $confirmupgrade,
     307          'confirmrelease' => $confirmrelease,
     308          'confirmplugincheck' => $confirmplugins,
     309      )));
     310  
     311      check_upgrade_key($upgradekeyhash);
     312  
     313      // Warning about upgrading a test site.
     314      $testsite = false;
     315      if (defined('BEHAT_SITE_RUNNING')) {
     316          $testsite = 'behat';
     317      }
     318  
     319      if (isset($CFG->themerev)) {
     320          // Store the themerev to restore after purging caches.
     321          $themerev = $CFG->themerev;
     322      }
     323  
     324      // We purge all of MUC's caches here.
     325      // Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
     326      // This ensures a real config object is loaded and the stores will be purged.
     327      // This is the only way we can purge custom caches such as memcache or APC.
     328      // Note: all other calls to caches will still used the disabled API.
     329      cache_helper::purge_all(true);
     330      // We then purge the regular caches.
     331      purge_all_caches();
     332  
     333      if (isset($themerev)) {
     334          // Restore the themerev
     335          set_config('themerev', $themerev);
     336      }
     337  
     338      $output = $PAGE->get_renderer('core', 'admin');
     339  
     340      if (upgrade_stale_php_files_present()) {
     341          $PAGE->set_title($stradministration);
     342          $PAGE->set_cacheable(false);
     343  
     344          echo $output->upgrade_stale_php_files_page();
     345          die();
     346      }
     347  
     348      if (empty($confirmupgrade)) {
     349          $a = new stdClass();
     350          $a->oldversion = "$CFG->release (".sprintf('%.2f', $CFG->version).")";
     351          $a->newversion = "$release (".sprintf('%.2f', $version).")";
     352          $strdatabasechecking = get_string('databasechecking', '', $a);
     353  
     354          $PAGE->set_title($stradministration);
     355          $PAGE->set_heading($strdatabasechecking);
     356          $PAGE->set_cacheable(false);
     357  
     358          echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
     359          die();
     360  
     361      } else if (empty($confirmrelease)) {
     362          require_once($CFG->libdir.'/environmentlib.php');
     363          list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
     364          $strcurrentrelease = get_string('currentrelease');
     365  
     366          $PAGE->navbar->add($strcurrentrelease);
     367          $PAGE->set_title($strcurrentrelease);
     368          $PAGE->set_heading($strcurrentrelease);
     369          $PAGE->set_cacheable(false);
     370  
     371          echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
     372          die();
     373  
     374      } else if (empty($confirmplugins)) {
     375          $strplugincheck = get_string('plugincheck');
     376  
     377          $PAGE->navbar->add($strplugincheck);
     378          $PAGE->set_title($strplugincheck);
     379          $PAGE->set_heading($strplugincheck);
     380          $PAGE->set_cacheable(false);
     381  
     382          $pluginman = core_plugin_manager::instance();
     383  
     384          // Check for available updates.
     385          if ($fetchupdates) {
     386              // No sesskey support guaranteed here, because sessions might not work yet.
     387              $updateschecker = \core\update\checker::instance();
     388              if ($updateschecker->enabled()) {
     389                  $updateschecker->fetch();
     390              }
     391              redirect($PAGE->url);
     392          }
     393  
     394          // Cancel all plugin installations.
     395          if ($abortinstallx) {
     396              // No sesskey support guaranteed here, because sessions might not work yet.
     397              $abortables = $pluginman->list_cancellable_installations();
     398              if ($abortables) {
     399                  if ($confirmabortinstall) {
     400                      foreach ($abortables as $plugin) {
     401                          $pluginman->cancel_plugin_installation($plugin->component);
     402                      }
     403                      redirect($PAGE->url);
     404                  } else {
     405                      $continue = new moodle_url($PAGE->url, array('abortinstallx' => $abortinstallx, 'confirmabortinstall' => 1));
     406                      echo $output->upgrade_confirm_abort_install_page($abortables, $continue);
     407                      die();
     408                  }
     409              }
     410              redirect($PAGE->url);
     411          }
     412  
     413          // Cancel single plugin installation.
     414          if ($abortinstall) {
     415              // No sesskey support guaranteed here, because sessions might not work yet.
     416              if ($confirmabortinstall) {
     417                  $pluginman->cancel_plugin_installation($abortinstall);
     418                  redirect($PAGE->url);
     419              } else {
     420                  $continue = new moodle_url($PAGE->url, array('abortinstall' => $abortinstall, 'confirmabortinstall' => 1));
     421                  $abortable = $pluginman->get_plugin_info($abortinstall);
     422                  if ($pluginman->can_cancel_plugin_installation($abortable)) {
     423                      echo $output->upgrade_confirm_abort_install_page(array($abortable), $continue);
     424                      die();
     425                  }
     426                  redirect($PAGE->url);
     427              }
     428          }
     429  
     430          // Cancel all plugins upgrades (that is, restore archived versions).
     431          if ($abortupgradex) {
     432              // No sesskey support guaranteed here, because sessions might not work yet.
     433              $restorable = $pluginman->list_restorable_archives();
     434              if ($restorable) {
     435                  upgrade_install_plugins($restorable, $confirmabortupgrade,
     436                      get_string('cancelupgradehead', 'core_plugin'),
     437                      new moodle_url($PAGE->url, array('abortupgradex' => 1, 'confirmabortupgrade' => 1))
     438                  );
     439              }
     440              redirect($PAGE->url);
     441          }
     442  
     443          // Cancel single plugin upgrade (that is, install the archived version).
     444          if ($abortupgrade) {
     445              // No sesskey support guaranteed here, because sessions might not work yet.
     446              $restorable = $pluginman->list_restorable_archives();
     447              if (isset($restorable[$abortupgrade])) {
     448                  $restorable = array($restorable[$abortupgrade]);
     449                  upgrade_install_plugins($restorable, $confirmabortupgrade,
     450                      get_string('cancelupgradehead', 'core_plugin'),
     451                      new moodle_url($PAGE->url, array('abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1))
     452                  );
     453              }
     454              redirect($PAGE->url);
     455          }
     456  
     457          // Install all available missing dependencies.
     458          if ($installdepx) {
     459              // No sesskey support guaranteed here, because sessions might not work yet.
     460              $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
     461              upgrade_install_plugins($installable, $confirminstalldep,
     462                  get_string('dependencyinstallhead', 'core_plugin'),
     463                  new moodle_url($PAGE->url, array('installdepx' => 1, 'confirminstalldep' => 1))
     464              );
     465          }
     466  
     467          // Install single available missing dependency.
     468          if ($installdep) {
     469              // No sesskey support guaranteed here, because sessions might not work yet.
     470              $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
     471              if (!empty($installable[$installdep])) {
     472                  $installable = array($installable[$installdep]);
     473                  upgrade_install_plugins($installable, $confirminstalldep,
     474                      get_string('dependencyinstallhead', 'core_plugin'),
     475                      new moodle_url($PAGE->url, array('installdep' => $installdep, 'confirminstalldep' => 1))
     476                  );
     477              }
     478          }
     479  
     480          // Install all available updates.
     481          if ($installupdatex) {
     482              // No sesskey support guaranteed here, because sessions might not work yet.
     483              $installable = $pluginman->filter_installable($pluginman->available_updates());
     484              upgrade_install_plugins($installable, $confirminstallupdate,
     485                  get_string('updateavailableinstallallhead', 'core_admin'),
     486                  new moodle_url($PAGE->url, array('installupdatex' => 1, 'confirminstallupdate' => 1))
     487              );
     488          }
     489  
     490          // Install single available update.
     491          if ($installupdate and $installupdateversion) {
     492              // No sesskey support guaranteed here, because sessions might not work yet.
     493              if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) {
     494                  $installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true));
     495                  upgrade_install_plugins($installable, $confirminstallupdate,
     496                      get_string('updateavailableinstallallhead', 'core_admin'),
     497                      new moodle_url($PAGE->url, array('installupdate' => $installupdate,
     498                          'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1)
     499                      )
     500                  );
     501              }
     502          }
     503  
     504          echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
     505                  $version, $showallplugins, $PAGE->url, new moodle_url($PAGE->url, array('confirmplugincheck' => 1)));
     506          die();
     507  
     508      } else {
     509          // Always verify plugin dependencies!
     510          $failed = array();
     511          if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
     512              echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
     513                  array('confirmplugincheck' => 0)));
     514              die();
     515          }
     516          unset($failed);
     517  
     518          // Launch main upgrade.
     519          upgrade_core($version, true);
     520      }
     521  } else if ($version < $CFG->version) {
     522      // better stop here, we can not continue with plugin upgrades or anything else
     523      throw new moodle_exception('downgradedcore', 'error', new moodle_url('/admin/'));
     524  }
     525  
     526  // Updated human-readable release version if necessary
     527  if (!$cache and $release <> $CFG->release) {  // Update the release version
     528      set_config('release', $release);
     529  }
     530  
     531  if (!$cache and $branch <> $CFG->branch) {  // Update the branch
     532      set_config('branch', $branch);
     533  }
     534  
     535  if (!$cache and moodle_needs_upgrading()) {
     536  
     537      $PAGE->set_url(new moodle_url($PAGE->url, array(
     538          'confirmrelease' => $confirmrelease,
     539          'confirmplugincheck' => $confirmplugins,
     540      )));
     541  
     542      check_upgrade_key($upgradekeyhash);
     543  
     544      if (!$PAGE->headerprinted) {
     545          // means core upgrade or installation was not already done
     546  
     547          $pluginman = core_plugin_manager::instance();
     548          $output = $PAGE->get_renderer('core', 'admin');
     549  
     550          if (empty($confirmrelease)) {
     551              require_once($CFG->libdir . '/environmentlib.php');
     552  
     553              list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
     554              $strcurrentrelease = get_string('currentrelease');
     555  
     556              $PAGE->navbar->add($strcurrentrelease);
     557              $PAGE->set_title($strcurrentrelease);
     558              $PAGE->set_heading($strcurrentrelease);
     559              $PAGE->set_cacheable(false);
     560  
     561              echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
     562              die();
     563  
     564          } else if (!$confirmplugins) {
     565              $strplugincheck = get_string('plugincheck');
     566  
     567              $PAGE->navbar->add($strplugincheck);
     568              $PAGE->set_title($strplugincheck);
     569              $PAGE->set_heading($strplugincheck);
     570              $PAGE->set_cacheable(false);
     571  
     572              // Check for available updates.
     573              if ($fetchupdates) {
     574                  require_sesskey();
     575                  $updateschecker = \core\update\checker::instance();
     576                  if ($updateschecker->enabled()) {
     577                      $updateschecker->fetch();
     578                  }
     579                  redirect($PAGE->url);
     580              }
     581  
     582              // Cancel all plugin installations.
     583              if ($abortinstallx) {
     584                  require_sesskey();
     585                  $abortables = $pluginman->list_cancellable_installations();
     586                  if ($abortables) {
     587                      if ($confirmabortinstall) {
     588                          foreach ($abortables as $plugin) {
     589                              $pluginman->cancel_plugin_installation($plugin->component);
     590                          }
     591                          redirect($PAGE->url);
     592                      } else {
     593                          $continue = new moodle_url($PAGE->url, array('abortinstallx' => $abortinstallx,
     594                              'confirmabortinstall' => 1));
     595                          echo $output->upgrade_confirm_abort_install_page($abortables, $continue);
     596                          die();
     597                      }
     598                  }
     599                  redirect($PAGE->url);
     600              }
     601  
     602              // Cancel single plugin installation.
     603              if ($abortinstall) {
     604                  require_sesskey();
     605                  if ($confirmabortinstall) {
     606                      $pluginman->cancel_plugin_installation($abortinstall);
     607                      redirect($PAGE->url);
     608                  } else {
     609                      $continue = new moodle_url($PAGE->url, array('abortinstall' => $abortinstall, 'confirmabortinstall' => 1));
     610                      $abortable = $pluginman->get_plugin_info($abortinstall);
     611                      if ($pluginman->can_cancel_plugin_installation($abortable)) {
     612                          echo $output->upgrade_confirm_abort_install_page(array($abortable), $continue);
     613                          die();
     614                      }
     615                      redirect($PAGE->url);
     616                  }
     617              }
     618  
     619              // Cancel all plugins upgrades (that is, restore archived versions).
     620              if ($abortupgradex) {
     621                  require_sesskey();
     622                  $restorable = $pluginman->list_restorable_archives();
     623                  if ($restorable) {
     624                      upgrade_install_plugins($restorable, $confirmabortupgrade,
     625                          get_string('cancelupgradehead', 'core_plugin'),
     626                          new moodle_url($PAGE->url, array('abortupgradex' => 1, 'confirmabortupgrade' => 1))
     627                      );
     628                  }
     629                  redirect($PAGE->url);
     630              }
     631  
     632              // Cancel single plugin upgrade (that is, install the archived version).
     633              if ($abortupgrade) {
     634                  require_sesskey();
     635                  $restorable = $pluginman->list_restorable_archives();
     636                  if (isset($restorable[$abortupgrade])) {
     637                      $restorable = array($restorable[$abortupgrade]);
     638                      upgrade_install_plugins($restorable, $confirmabortupgrade,
     639                          get_string('cancelupgradehead', 'core_plugin'),
     640                          new moodle_url($PAGE->url, array('abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1))
     641                      );
     642                  }
     643                  redirect($PAGE->url);
     644              }
     645  
     646              // Install all available missing dependencies.
     647              if ($installdepx) {
     648                  require_sesskey();
     649                  $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
     650                  upgrade_install_plugins($installable, $confirminstalldep,
     651                      get_string('dependencyinstallhead', 'core_plugin'),
     652                      new moodle_url($PAGE->url, array('installdepx' => 1, 'confirminstalldep' => 1))
     653                  );
     654              }
     655  
     656              // Install single available missing dependency.
     657              if ($installdep) {
     658                  require_sesskey();
     659                  $installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
     660                  if (!empty($installable[$installdep])) {
     661                      $installable = array($installable[$installdep]);
     662                      upgrade_install_plugins($installable, $confirminstalldep,
     663                          get_string('dependencyinstallhead', 'core_plugin'),
     664                          new moodle_url($PAGE->url, array('installdep' => $installdep, 'confirminstalldep' => 1))
     665                      );
     666                  }
     667              }
     668  
     669              // Install all available updates.
     670              if ($installupdatex) {
     671                  require_sesskey();
     672                  $installable = $pluginman->filter_installable($pluginman->available_updates());
     673                  upgrade_install_plugins($installable, $confirminstallupdate,
     674                      get_string('updateavailableinstallallhead', 'core_admin'),
     675                      new moodle_url($PAGE->url, array('installupdatex' => 1, 'confirminstallupdate' => 1))
     676                  );
     677              }
     678  
     679              // Install single available update.
     680              if ($installupdate and $installupdateversion) {
     681                  require_sesskey();
     682                  if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) {
     683                      $installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true));
     684                      upgrade_install_plugins($installable, $confirminstallupdate,
     685                          get_string('updateavailableinstallallhead', 'core_admin'),
     686                          new moodle_url($PAGE->url, array('installupdate' => $installupdate,
     687                              'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1)
     688                          )
     689                      );
     690                  }
     691              }
     692  
     693              // Show plugins info.
     694              echo $output->upgrade_plugin_check_page($pluginman, \core\update\checker::instance(),
     695                      $version, $showallplugins,
     696                      new moodle_url($PAGE->url),
     697                      new moodle_url($PAGE->url, array('confirmplugincheck' => 1, 'cache' => 0)));
     698              die();
     699          }
     700  
     701          // Make sure plugin dependencies are always checked.
     702          $failed = array();
     703          if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
     704              $output = $PAGE->get_renderer('core', 'admin');
     705              echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
     706                  array('confirmplugincheck' => 0)));
     707              die();
     708          }
     709          unset($failed);
     710      }
     711  
     712      // install/upgrade all plugins and other parts
     713      upgrade_noncore(true);
     714  }
     715  
     716  // If this is the first install, indicate that this site is fully configured
     717  // except the admin password
     718  if (during_initial_install()) {
     719      set_config('rolesactive', 1); // after this, during_initial_install will return false.
     720      set_config('adminsetuppending', 1);
     721      set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
     722      // we need this redirect to setup proper session
     723      upgrade_finished("index.php?sessionstarted=1&amp;lang=$CFG->lang");
     724  }
     725  
     726  // make sure admin user is created - this is the last step because we need
     727  // session to be working properly in order to edit admin account
     728   if (!empty($CFG->adminsetuppending)) {
     729      $sessionstarted = optional_param('sessionstarted', 0, PARAM_BOOL);
     730      if (!$sessionstarted) {
     731          redirect("index.php?sessionstarted=1&lang=$CFG->lang");
     732      } else {
     733          $sessionverify = optional_param('sessionverify', 0, PARAM_BOOL);
     734          if (!$sessionverify) {
     735              $SESSION->sessionverify = 1;
     736              redirect("index.php?sessionstarted=1&sessionverify=1&lang=$CFG->lang");
     737          } else {
     738              if (empty($SESSION->sessionverify)) {
     739                  print_error('installsessionerror', 'admin', "index.php?sessionstarted=1&lang=$CFG->lang");
     740              }
     741              unset($SESSION->sessionverify);
     742          }
     743      }
     744  
     745      // Cleanup SESSION to make sure other code does not complain in the future.
     746      unset($SESSION->has_timed_out);
     747      unset($SESSION->wantsurl);
     748  
     749      // at this stage there can be only one admin unless more were added by install - users may change username, so do not rely on that
     750      $adminids = explode(',', $CFG->siteadmins);
     751      $adminuser = get_complete_user_data('id', reset($adminids));
     752  
     753      if ($adminuser->password === 'adminsetuppending') {
     754          // prevent installation hijacking
     755          if ($adminuser->lastip !== getremoteaddr()) {
     756              print_error('installhijacked', 'admin');
     757          }
     758          // login user and let him set password and admin details
     759          $adminuser->newadminuser = 1;
     760          complete_user_login($adminuser);
     761          redirect("$CFG->wwwroot/user/editadvanced.php?id=$adminuser->id"); // Edit thyself
     762  
     763      } else {
     764          unset_config('adminsetuppending');
     765      }
     766  
     767  } else {
     768      // just make sure upgrade logging is properly terminated
     769      upgrade_finished('upgradesettings.php');
     770  }
     771  
     772  if (has_capability('moodle/site:config', context_system::instance())) {
     773      if ($fetchupdates) {
     774          require_sesskey();
     775          $updateschecker = \core\update\checker::instance();
     776          if ($updateschecker->enabled()) {
     777              $updateschecker->fetch();
     778          }
     779          redirect(new moodle_url('/admin/index.php', array('cache' => 0)));
     780      }
     781  }
     782  
     783  // Now we can be sure everything was upgraded and caches work fine,
     784  // redirect if necessary to make sure caching is enabled.
     785  if (!$cache) {
     786      redirect(new moodle_url('/admin/index.php', array('cache' => 1)));
     787  }
     788  
     789  // Check for valid admin user - no guest autologin
     790  require_login(0, false);
     791  if (isguestuser()) {
     792      // Login as real user!
     793      $SESSION->wantsurl = (string)new moodle_url('/admin/index.php');
     794      redirect(get_login_url());
     795  }
     796  $context = context_system::instance();
     797  
     798  if (!has_capability('moodle/site:config', $context)) {
     799      // Do not throw exception display an empty page with administration menu if visible for current user.
     800      $PAGE->set_title($SITE->fullname);
     801      $PAGE->set_heading($SITE->fullname);
     802      echo $OUTPUT->header();
     803      echo $OUTPUT->footer();
     804      exit;
     805  }
     806  
     807  // check that site is properly customized
     808  $site = get_site();
     809  if (empty($site->shortname)) {
     810      // probably new installation - lets return to frontpage after this step
     811      // remove settings that we want uninitialised
     812      unset_config('registerauth');
     813      unset_config('timezone'); // Force admin to select timezone!
     814      redirect('upgradesettings.php?return=site');
     815  }
     816  
     817  // setup critical warnings before printing admin tree block
     818  $insecuredataroot = is_dataroot_insecure(true);
     819  $SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
     820  
     821  $adminroot = admin_get_root();
     822  
     823  // Check if there are any new admin settings which have still yet to be set
     824  if (any_new_admin_settings($adminroot)) {
     825      redirect('upgradesettings.php');
     826  }
     827  
     828  // Return to original page that started the plugin uninstallation if necessary.
     829  if (isset($SESSION->pluginuninstallreturn)) {
     830      $return = $SESSION->pluginuninstallreturn;
     831      unset($SESSION->pluginuninstallreturn);
     832      if ($return) {
     833          redirect($return);
     834      }
     835  }
     836  
     837  // If site registration needs updating, redirect.
     838  \core\hub\registration::registration_reminder('/admin/index.php');
     839  
     840  // Everything should now be set up, and the user is an admin
     841  
     842  // Print default admin page with notifications.
     843  $errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED');
     844  
     845  $lastcron = get_config('tool_task', 'lastcronstart');
     846  $cronoverdue = ($lastcron < time() - 3600 * 24);
     847  $lastcroninterval = get_config('tool_task', 'lastcroninterval');
     848  
     849  $expectedfrequency = $CFG->expectedcronfrequency ?? MINSECS;
     850  $croninfrequent = !$cronoverdue && ($lastcroninterval > ($expectedfrequency + MINSECS) || $lastcron < time() - $expectedfrequency);
     851  $dbproblems = $DB->diagnose();
     852  $maintenancemode = !empty($CFG->maintenance_enabled);
     853  
     854  // Available updates for Moodle core.
     855  $updateschecker = \core\update\checker::instance();
     856  $availableupdates = array();
     857  $availableupdatesfetch = null;
     858  
     859  if ($updateschecker->enabled()) {
     860      // Only compute the update information when it is going to be displayed to the user.
     861      $availableupdates['core'] = $updateschecker->get_update_info('core',
     862          array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
     863  
     864      // Available updates for contributed plugins
     865      $pluginman = core_plugin_manager::instance();
     866      foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
     867          foreach ($plugintypeinstances as $pluginname => $plugininfo) {
     868              $pluginavailableupdates = $plugininfo->available_updates();
     869              if (!empty($pluginavailableupdates)) {
     870                  foreach ($pluginavailableupdates as $pluginavailableupdate) {
     871                      if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
     872                          $availableupdates[$plugintype.'_'.$pluginname] = array();
     873                      }
     874                      $availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
     875                  }
     876              }
     877          }
     878      }
     879  
     880      // The timestamp of the most recent check for available updates
     881      $availableupdatesfetch = $updateschecker->get_last_timefetched();
     882  }
     883  
     884  $buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
     885  //check if the site is registered on Moodle.org
     886  $registered = \core\hub\registration::is_registered();
     887  // Check if there are any cache warnings.
     888  $cachewarnings = cache_helper::warnings();
     889  // Check if there are events 1 API handlers.
     890  $eventshandlers = $DB->get_records_sql('SELECT DISTINCT component FROM {events_handlers}');
     891  $themedesignermode = !empty($CFG->themedesignermode);
     892  $mobileconfigured = !empty($CFG->enablemobilewebservice);
     893  $invalidforgottenpasswordurl = !empty($CFG->forgottenpasswordurl) && empty(clean_param($CFG->forgottenpasswordurl, PARAM_URL));
     894  
     895  // Check if a directory with development libraries exists.
     896  if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules'))) {
     897      $devlibdir = true;
     898  } else {
     899      $devlibdir = false;
     900  }
     901  // Check if the site is being foced onto ssl.
     902  $overridetossl = !empty($CFG->overridetossl);
     903  
     904  // Check if moodle campaign content setting is enabled or not.
     905  $showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaigncontent;
     906  
     907  // Encourage admins to enable the user feedback feature if it is not enabled already.
     908  $showfeedbackencouragement = empty($CFG->enableuserfeedback);
     909  
     910  admin_externalpage_setup('adminnotifications');
     911  
     912  $output = $PAGE->get_renderer('core', 'admin');
     913  
     914  echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
     915                                         $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
     916                                         $registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
     917                                         $mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
     918                                         $showcampaigncontent, $showfeedbackencouragement);