index.php 36 KB

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