PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/admin/cli/install.php

https://bitbucket.org/moodle/moodle
PHP | 835 lines | 663 code | 88 blank | 84 comment | 149 complexity | 915abc5cde77136e4bcc80952d8fd34f MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  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. * This script creates config.php file and prepares database.
  18. *
  19. * This script is not intended for beginners!
  20. * Potential problems:
  21. * - su to apache account or sudo before execution
  22. * - not compatible with Windows platform
  23. *
  24. * @package core
  25. * @subpackage cli
  26. * @copyright 2009 Petr Skoda (http://skodak.org)
  27. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28. */
  29. define('CLI_SCRIPT', true);
  30. // extra execution prevention - we can not just require config.php here
  31. if (isset($_SERVER['REMOTE_ADDR'])) {
  32. exit(1);
  33. }
  34. // Force OPcache reset if used, we do not want any stale caches
  35. // when preparing test environment.
  36. if (function_exists('opcache_reset')) {
  37. opcache_reset();
  38. }
  39. $help =
  40. "Command line Moodle installer, creates config.php and initializes database.
  41. Please note you must execute this script with the same uid as apache
  42. or use chmod/chown after installation.
  43. Site defaults may be changed via local/defaults.php.
  44. Options:
  45. --chmod=OCTAL-MODE Permissions of new directories created within dataroot.
  46. Default is 2777. You may want to change it to 2770
  47. or 2750 or 750. See chmod man page for details.
  48. --lang=CODE Installation and default site language.
  49. --wwwroot=URL Web address for the Moodle site,
  50. required in non-interactive mode.
  51. --dataroot=DIR Location of the moodle data folder,
  52. must not be web accessible. Default is moodledata
  53. in the parent directory.
  54. --dbtype=TYPE Database type. Default is mysqli
  55. --dbhost=HOST Database host. Default is localhost
  56. --dbname=NAME Database name. Default is moodle
  57. --dbuser=USERNAME Database user. Default is root
  58. --dbpass=PASSWORD Database password. Default is blank
  59. --dbport=NUMBER Use database port.
  60. --dbsocket=PATH Use database socket, 1 means default. Available for some databases only.
  61. --prefix=STRING Table prefix for above database tables. Default is mdl_
  62. --fullname=STRING The fullname of the site
  63. --shortname=STRING The shortname of the site
  64. --summary=STRING The summary to be displayed on the front page
  65. --adminuser=USERNAME Username for the moodle admin account. Default is admin
  66. --adminpass=PASSWORD Password for the moodle admin account,
  67. required in non-interactive mode.
  68. --adminemail=STRING Email address for the moodle admin account.
  69. --upgradekey=STRING The upgrade key to be set in the config.php, leave empty to not set it.
  70. --non-interactive No interactive questions, installation fails if any
  71. problem encountered.
  72. --agree-license Indicates agreement with software license,
  73. required in non-interactive mode.
  74. --allow-unstable Install even if the version is not marked as stable yet,
  75. required in non-interactive mode.
  76. --skip-database Stop the installation before installing the database.
  77. -h, --help Print out this help
  78. Example:
  79. \$sudo -u www-data /usr/bin/php admin/cli/install.php --lang=cs
  80. "; //TODO: localize, mark as needed in install - to be translated later when everything is finished
  81. // distro specific customisation
  82. $distrolibfile = __DIR__.'/../../install/distrolib.php';
  83. $distro = null;
  84. if (file_exists($distrolibfile)) {
  85. require_once($distrolibfile);
  86. if (function_exists('distro_get_config')) {
  87. $distro = distro_get_config();
  88. }
  89. }
  90. // Nothing to do if config.php exists
  91. $configfile = __DIR__.'/../../config.php';
  92. if (file_exists($configfile)) {
  93. require($configfile);
  94. require_once($CFG->libdir.'/clilib.php');
  95. list($options, $unrecognized) = cli_get_params(array('help'=>false), array('h'=>'help'));
  96. if ($options['help']) {
  97. echo $help;
  98. echo "\n\n";
  99. }
  100. if ($DB->get_manager()->table_exists('config')) {
  101. cli_error(get_string('clialreadyinstalled', 'install'));
  102. } else {
  103. cli_error(get_string('clialreadyconfigured', 'install'));
  104. }
  105. }
  106. $olddir = getcwd();
  107. // change directory so that includes below work properly
  108. chdir(dirname($_SERVER['argv'][0]));
  109. // Servers should define a default timezone in php.ini, but if they don't then make sure something is defined.
  110. if (!function_exists('date_default_timezone_set') or !function_exists('date_default_timezone_get')) {
  111. fwrite(STDERR, "Timezone functions are not available.\n");
  112. exit(1);
  113. }
  114. date_default_timezone_set(@date_default_timezone_get());
  115. // make sure PHP errors are displayed - helps with diagnosing of problems
  116. @error_reporting(E_ALL);
  117. @ini_set('display_errors', '1');
  118. // we need a lot of memory
  119. @ini_set('memory_limit', '128M');
  120. /** Used by library scripts to check they are being called by Moodle */
  121. define('MOODLE_INTERNAL', true);
  122. // Disables all caching.
  123. define('CACHE_DISABLE_ALL', true);
  124. define('PHPUNIT_TEST', false);
  125. define('IGNORE_COMPONENT_CACHE', true);
  126. // Check that PHP is of a sufficient version as soon as possible.
  127. require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
  128. moodle_require_minimum_php_version();
  129. // set up configuration
  130. global $CFG;
  131. $CFG = new stdClass();
  132. $CFG->lang = 'en';
  133. $CFG->dirroot = dirname(dirname(__DIR__));
  134. $CFG->libdir = "$CFG->dirroot/lib";
  135. $CFG->wwwroot = "http://localhost";
  136. $CFG->httpswwwroot = $CFG->wwwroot;
  137. $CFG->docroot = 'http://docs.moodle.org';
  138. $CFG->running_installer = true;
  139. $CFG->early_install_lang = true;
  140. $CFG->ostype = (stristr(PHP_OS, 'win') && !stristr(PHP_OS, 'darwin')) ? 'WINDOWS' : 'UNIX';
  141. $CFG->dboptions = array();
  142. $CFG->debug = (E_ALL | E_STRICT);
  143. $CFG->debugdisplay = true;
  144. $CFG->debugdeveloper = true;
  145. $parts = explode('/', str_replace('\\', '/', dirname(__DIR__)));
  146. $CFG->admin = array_pop($parts);
  147. //point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else
  148. //the problem is that we need specific version of quickforms and hacked excel files :-(
  149. ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
  150. require_once($CFG->libdir.'/classes/component.php');
  151. require_once($CFG->libdir.'/classes/text.php');
  152. require_once($CFG->libdir.'/classes/string_manager.php');
  153. require_once($CFG->libdir.'/classes/string_manager_install.php');
  154. require_once($CFG->libdir.'/classes/string_manager_standard.php');
  155. require_once($CFG->libdir.'/installlib.php');
  156. require_once($CFG->libdir.'/clilib.php');
  157. require_once($CFG->libdir.'/setuplib.php');
  158. require_once($CFG->libdir.'/weblib.php');
  159. require_once($CFG->libdir.'/dmllib.php');
  160. require_once($CFG->libdir.'/moodlelib.php');
  161. require_once($CFG->libdir.'/deprecatedlib.php');
  162. require_once($CFG->libdir.'/adminlib.php');
  163. require_once($CFG->libdir.'/componentlib.class.php');
  164. require_once($CFG->dirroot.'/cache/lib.php');
  165. // Register our classloader, in theory somebody might want to replace it to load other hacked core classes.
  166. // Required because the database checks below lead to session interaction which is going to lead us to requiring autoloaded classes.
  167. if (defined('COMPONENT_CLASSLOADER')) {
  168. spl_autoload_register(COMPONENT_CLASSLOADER);
  169. } else {
  170. spl_autoload_register('core_component::classloader');
  171. }
  172. require($CFG->dirroot.'/version.php');
  173. $CFG->target_release = $release;
  174. \core\session\manager::init_empty_session();
  175. global $SESSION;
  176. global $USER;
  177. global $COURSE;
  178. $COURSE = new stdClass();
  179. $COURSE->id = 1;
  180. global $SITE;
  181. $SITE = $COURSE;
  182. define('SITEID', 1);
  183. //Database types
  184. $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
  185. 'auroramysql' => moodle_database::get_driver_instance('auroramysql', 'native'),
  186. 'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
  187. 'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'),
  188. 'oci' => moodle_database::get_driver_instance('oci', 'native'),
  189. 'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // MS SQL*Server PHP driver
  190. );
  191. foreach ($databases as $type=>$database) {
  192. if ($database->driver_installed() !== true) {
  193. unset($databases[$type]);
  194. }
  195. }
  196. if (empty($databases)) {
  197. $defaultdb = '';
  198. } else {
  199. reset($databases);
  200. $defaultdb = key($databases);
  201. }
  202. // now get cli options
  203. list($options, $unrecognized) = cli_get_params(
  204. array(
  205. 'chmod' => isset($distro->directorypermissions) ? sprintf('%04o',$distro->directorypermissions) : '2777', // let distros set dir permissions
  206. 'lang' => $CFG->lang,
  207. 'wwwroot' => '',
  208. 'dataroot' => empty($distro->dataroot) ? str_replace('\\', '/', dirname(dirname(dirname(__DIR__))).'/moodledata'): $distro->dataroot, // initialised later after including libs or by distro
  209. 'dbtype' => empty($distro->dbtype) ? $defaultdb : $distro->dbtype, // let distro skip dbtype selection
  210. 'dbhost' => empty($distro->dbhost) ? 'localhost' : $distro->dbhost, // let distros set dbhost
  211. 'dbname' => 'moodle',
  212. 'dbuser' => empty($distro->dbuser) ? 'root' : $distro->dbuser, // let distros set dbuser
  213. 'dbpass' => '',
  214. 'dbport' => '',
  215. 'dbsocket' => '',
  216. 'prefix' => 'mdl_',
  217. 'fullname' => '',
  218. 'shortname' => '',
  219. 'summary' => '',
  220. 'adminuser' => 'admin',
  221. 'adminpass' => '',
  222. 'adminemail' => '',
  223. 'upgradekey' => '',
  224. 'non-interactive' => false,
  225. 'agree-license' => false,
  226. 'allow-unstable' => false,
  227. 'skip-database' => false,
  228. 'help' => false
  229. ),
  230. array(
  231. 'h' => 'help'
  232. )
  233. );
  234. $interactive = empty($options['non-interactive']);
  235. $skipdatabase = $options['skip-database'];
  236. // set up language
  237. $lang = clean_param($options['lang'], PARAM_SAFEDIR);
  238. $languages = get_string_manager()->get_list_of_translations();
  239. if (array_key_exists($lang, $languages)) {
  240. $CFG->lang = $lang;
  241. }
  242. if ($unrecognized) {
  243. $unrecognized = implode("\n ", $unrecognized);
  244. cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
  245. }
  246. if ($options['help']) {
  247. echo $help;
  248. die;
  249. }
  250. //Print header
  251. cli_logo();
  252. echo PHP_EOL;
  253. echo get_string('cliinstallheader', 'install', $CFG->target_release)."\n";
  254. //Fist select language
  255. if ($interactive) {
  256. cli_separator();
  257. // Do not put the langs into columns because it is not compatible with RTL.
  258. $default = $CFG->lang;
  259. cli_heading(get_string('chooselanguagehead', 'install'));
  260. if (array_key_exists($default, $languages)) {
  261. echo $default.' - '.$languages[$default]."\n";
  262. }
  263. if ($default !== 'en') {
  264. echo 'en - English (en)'."\n";
  265. }
  266. echo '? - '.get_string('availablelangs', 'install')."\n";
  267. $prompt = get_string('clitypevaluedefault', 'admin', $CFG->lang);
  268. $error = '';
  269. do {
  270. echo $error;
  271. $input = cli_input($prompt, $default);
  272. if ($input === '?') {
  273. echo implode("\n", $languages)."\n";
  274. $error = "\n";
  275. } else {
  276. $input = clean_param($input, PARAM_SAFEDIR);
  277. if (!array_key_exists($input, $languages)) {
  278. $error = get_string('cliincorrectvalueretry', 'admin')."\n";
  279. } else {
  280. $error = '';
  281. }
  282. }
  283. } while ($error !== '');
  284. $CFG->lang = $input;
  285. } else {
  286. // already selected and verified
  287. }
  288. // Set directorypermissions first
  289. $chmod = octdec(clean_param($options['chmod'], PARAM_INT));
  290. if ($interactive) {
  291. cli_separator();
  292. cli_heading(get_string('datarootpermission', 'install'));
  293. $prompt = get_string('clitypevaluedefault', 'admin', decoct($chmod));
  294. $error = '';
  295. do {
  296. echo $error;
  297. $input = cli_input($prompt, decoct($chmod));
  298. $input = octdec(clean_param($input, PARAM_INT));
  299. if (empty($input)) {
  300. $error = get_string('cliincorrectvalueretry', 'admin')."\n";
  301. } else {
  302. $error = '';
  303. }
  304. } while ($error !== '');
  305. $chmod = $input;
  306. } else {
  307. if (empty($chmod)) {
  308. $a = (object)array('option' => 'chmod', 'value' => decoct($chmod));
  309. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  310. }
  311. }
  312. $CFG->directorypermissions = $chmod;
  313. $CFG->filepermissions = ($CFG->directorypermissions & 0666);
  314. $CFG->umaskpermissions = (($CFG->directorypermissions & 0777) ^ 0777);
  315. //We need wwwroot before we test dataroot
  316. $wwwroot = clean_param($options['wwwroot'], PARAM_URL);
  317. $wwwroot = trim($wwwroot, '/');
  318. if ($interactive) {
  319. cli_separator();
  320. cli_heading(get_string('wwwroot', 'install'));
  321. if (strpos($wwwroot, 'http') === 0) {
  322. $prompt = get_string('clitypevaluedefault', 'admin', $wwwroot);
  323. } else {
  324. $wwwroot = null;
  325. $prompt = get_string('clitypevalue', 'admin');
  326. }
  327. $error = '';
  328. do {
  329. echo $error;
  330. $input = cli_input($prompt, $wwwroot);
  331. $input = clean_param($input, PARAM_URL);
  332. $input = trim($input, '/');
  333. if (strpos($input, 'http') !== 0) {
  334. $error = get_string('cliincorrectvalueretry', 'admin')."\n";
  335. } else {
  336. $error = '';
  337. }
  338. } while ($error !== '');
  339. $wwwroot = $input;
  340. } else {
  341. if (strpos($wwwroot, 'http') !== 0) {
  342. $a = (object)array('option'=>'wwwroot', 'value'=>$wwwroot);
  343. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  344. }
  345. }
  346. $CFG->wwwroot = $wwwroot;
  347. $CFG->httpswwwroot = $CFG->wwwroot;
  348. //We need dataroot before lang download
  349. $CFG->dataroot = $options['dataroot'];
  350. if ($interactive) {
  351. cli_separator();
  352. $i=0;
  353. while(is_dataroot_insecure()) {
  354. $parrent = dirname($CFG->dataroot);
  355. $i++;
  356. if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) {
  357. $CFG->dataroot = ''; //can not find secure location for dataroot
  358. break;
  359. }
  360. $CFG->dataroot = dirname($parrent).'/moodledata';
  361. }
  362. cli_heading(get_string('dataroot', 'install'));
  363. $error = '';
  364. do {
  365. if ($CFG->dataroot !== '') {
  366. $prompt = get_string('clitypevaluedefault', 'admin', $CFG->dataroot);
  367. } else {
  368. $prompt = get_string('clitypevalue', 'admin');
  369. }
  370. echo $error;
  371. $CFG->dataroot = cli_input($prompt, $CFG->dataroot);
  372. if ($CFG->dataroot === '') {
  373. $error = get_string('cliincorrectvalueretry', 'admin')."\n";
  374. } else if (is_dataroot_insecure()) {
  375. $CFG->dataroot = '';
  376. $error = get_string('pathsunsecuredataroot', 'install')."\n";
  377. } else {
  378. if (install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
  379. $error = '';
  380. } else {
  381. $a = (object)array('dataroot' => $CFG->dataroot);
  382. $error = get_string('pathserrcreatedataroot', 'install', $a)."\n";
  383. }
  384. }
  385. } while ($error !== '');
  386. } else {
  387. if (is_dataroot_insecure()) {
  388. cli_error(get_string('pathsunsecuredataroot', 'install'));
  389. }
  390. if (!install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
  391. $a = (object)array('dataroot' => $CFG->dataroot);
  392. cli_error(get_string('pathserrcreatedataroot', 'install', $a));
  393. }
  394. }
  395. $CFG->tempdir = $CFG->dataroot.'/temp';
  396. $CFG->backuptempdir = $CFG->tempdir.'/backup';
  397. $CFG->cachedir = $CFG->dataroot.'/cache';
  398. $CFG->localcachedir = $CFG->dataroot.'/localcache';
  399. // download required lang packs
  400. if ($CFG->lang !== 'en') {
  401. $installer = new lang_installer($CFG->lang);
  402. $results = $installer->run();
  403. foreach ($results as $langcode => $langstatus) {
  404. if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) {
  405. $a = new stdClass();
  406. $a->url = $installer->lang_pack_url($langcode);
  407. $a->dest = $CFG->dataroot.'/lang';
  408. cli_problem(get_string('remotedownloaderror', 'error', $a));
  409. }
  410. }
  411. }
  412. // switch the string_manager instance to stop using install/lang/
  413. $CFG->early_install_lang = false;
  414. $CFG->langotherroot = $CFG->dataroot.'/lang';
  415. $CFG->langlocalroot = $CFG->dataroot.'/lang';
  416. get_string_manager(true);
  417. // make sure we are installing stable release or require a confirmation
  418. if (isset($maturity)) {
  419. if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) {
  420. $maturitylevel = get_string('maturity'.$maturity, 'admin');
  421. if ($interactive) {
  422. cli_separator();
  423. cli_heading(get_string('notice'));
  424. echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL;
  425. echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL;
  426. echo get_string('continue') . PHP_EOL;
  427. $prompt = get_string('cliyesnoprompt', 'admin');
  428. $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
  429. if ($input == get_string('clianswerno', 'admin')) {
  430. exit(1);
  431. }
  432. } else {
  433. cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel));
  434. cli_error(get_string('maturityallowunstable', 'admin'));
  435. }
  436. }
  437. }
  438. // ask for db type - show only drivers available
  439. if ($interactive) {
  440. $options['dbtype'] = strtolower($options['dbtype']);
  441. cli_separator();
  442. cli_heading(get_string('databasetypehead', 'install'));
  443. foreach ($databases as $type=>$database) {
  444. echo " $type \n";
  445. }
  446. if (!empty($databases[$options['dbtype']])) {
  447. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbtype']);
  448. } else {
  449. $prompt = get_string('clitypevalue', 'admin');
  450. }
  451. $CFG->dbtype = cli_input($prompt, $options['dbtype'], array_keys($databases));
  452. } else {
  453. if (empty($databases[$options['dbtype']])) {
  454. $a = (object)array('option'=>'dbtype', 'value'=>$options['dbtype']);
  455. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  456. }
  457. $CFG->dbtype = $options['dbtype'];
  458. }
  459. $database = $databases[$CFG->dbtype];
  460. // We cannot do any validation until all DB connection data is provided.
  461. $hintdatabase = '';
  462. do {
  463. echo $hintdatabase;
  464. // Ask for db host.
  465. if ($interactive) {
  466. cli_separator();
  467. cli_heading(get_string('databasehost', 'install'));
  468. if ($options['dbhost'] !== '') {
  469. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
  470. } else {
  471. $prompt = get_string('clitypevalue', 'admin');
  472. }
  473. $CFG->dbhost = cli_input($prompt, $options['dbhost']);
  474. } else {
  475. $CFG->dbhost = $options['dbhost'];
  476. }
  477. // Ask for db name.
  478. if ($interactive) {
  479. cli_separator();
  480. cli_heading(get_string('databasename', 'install'));
  481. if ($options['dbname'] !== '') {
  482. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
  483. } else {
  484. $prompt = get_string('clitypevalue', 'admin');
  485. }
  486. $CFG->dbname = cli_input($prompt, $options['dbname']);
  487. } else {
  488. $CFG->dbname = $options['dbname'];
  489. }
  490. // Ask for db prefix.
  491. if ($interactive) {
  492. cli_separator();
  493. cli_heading(get_string('dbprefix', 'install'));
  494. //TODO: solve somehow the prefix trouble for oci.
  495. if ($options['prefix'] !== '') {
  496. $prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
  497. } else {
  498. $prompt = get_string('clitypevalue', 'admin');
  499. }
  500. $CFG->prefix = cli_input($prompt, $options['prefix']);
  501. } else {
  502. $CFG->prefix = $options['prefix'];
  503. }
  504. // Ask for db port.
  505. if ($interactive) {
  506. cli_separator();
  507. cli_heading(get_string('databaseport', 'install'));
  508. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
  509. $CFG->dboptions['dbport'] = (int) cli_input($prompt, $options['dbport']);
  510. } else {
  511. $CFG->dboptions['dbport'] = (int) $options['dbport'];
  512. }
  513. if ($CFG->dboptions['dbport'] <= 0) {
  514. $CFG->dboptions['dbport'] = '';
  515. }
  516. // Ask for db socket.
  517. if ($CFG->ostype === 'WINDOWS') {
  518. $CFG->dboptions['dbsocket'] = '';
  519. } else if ($interactive and empty($CFG->dboptions['dbport'])) {
  520. cli_separator();
  521. cli_heading(get_string('databasesocket', 'install'));
  522. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
  523. $CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
  524. } else {
  525. $CFG->dboptions['dbsocket'] = $options['dbsocket'];
  526. }
  527. // Ask for db user.
  528. if ($interactive) {
  529. cli_separator();
  530. cli_heading(get_string('databaseuser', 'install'));
  531. if ($options['dbuser'] !== '') {
  532. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
  533. } else {
  534. $prompt = get_string('clitypevalue', 'admin');
  535. }
  536. $CFG->dbuser = cli_input($prompt, $options['dbuser']);
  537. } else {
  538. $CFG->dbuser = $options['dbuser'];
  539. }
  540. // Ask for db password.
  541. if ($interactive) {
  542. cli_separator();
  543. cli_heading(get_string('databasepass', 'install'));
  544. if ($options['dbpass'] !== '') {
  545. $prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
  546. } else {
  547. $prompt = get_string('clitypevalue', 'admin');
  548. }
  549. $CFG->dbpass = cli_input($prompt, $options['dbpass']);
  550. if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation.
  551. $distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
  552. array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']),
  553. $distro);
  554. }
  555. $hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
  556. array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
  557. } else {
  558. $CFG->dbpass = $options['dbpass'];
  559. $hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
  560. array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
  561. if ($hintdatabase !== '') {
  562. cli_error(get_string('dbconnectionerror', 'install'));
  563. }
  564. }
  565. } while ($hintdatabase !== '');
  566. // If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
  567. // These fields will be requested during the database install part.
  568. if (!$skipdatabase) {
  569. // Ask for fullname.
  570. if ($interactive) {
  571. cli_separator();
  572. cli_heading(get_string('fullsitename', 'moodle'));
  573. if ($options['fullname'] !== '') {
  574. $prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
  575. } else {
  576. $prompt = get_string('clitypevalue', 'admin');
  577. }
  578. do {
  579. $options['fullname'] = cli_input($prompt, $options['fullname']);
  580. } while (empty($options['fullname']));
  581. } else {
  582. if (empty($options['fullname'])) {
  583. $a = (object)['option' => 'fullname', 'value' => $options['fullname']];
  584. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  585. }
  586. }
  587. // Ask for shortname.
  588. if ($interactive) {
  589. cli_separator();
  590. cli_heading(get_string('shortsitename', 'moodle'));
  591. if ($options['shortname'] !== '') {
  592. $prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
  593. } else {
  594. $prompt = get_string('clitypevalue', 'admin');
  595. }
  596. do {
  597. $options['shortname'] = cli_input($prompt, $options['shortname']);
  598. } while (empty($options['shortname']));
  599. } else {
  600. if (empty($options['shortname'])) {
  601. $a = (object)['option' => 'shortname', 'value' => $options['shortname']];
  602. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  603. }
  604. }
  605. // Ask for admin user name.
  606. if ($interactive) {
  607. cli_separator();
  608. cli_heading(get_string('cliadminusername', 'install'));
  609. if (!empty($options['adminuser'])) {
  610. $prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
  611. } else {
  612. $prompt = get_string('clitypevalue', 'admin');
  613. }
  614. do {
  615. $options['adminuser'] = cli_input($prompt, $options['adminuser']);
  616. } while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
  617. } else {
  618. if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
  619. $a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
  620. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  621. }
  622. }
  623. // Ask for admin user password.
  624. if ($interactive) {
  625. cli_separator();
  626. cli_heading(get_string('cliadminpassword', 'install'));
  627. $prompt = get_string('clitypevalue', 'admin');
  628. do {
  629. $options['adminpass'] = cli_input($prompt);
  630. } while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
  631. } else {
  632. if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
  633. $a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
  634. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  635. }
  636. }
  637. // Ask for the admin email address.
  638. if ($interactive) {
  639. cli_separator();
  640. cli_heading(get_string('cliadminemail', 'install'));
  641. $prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
  642. $options['adminemail'] = cli_input($prompt, $options['adminemail']);
  643. }
  644. // Validate that the address provided was an e-mail address.
  645. if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
  646. $a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
  647. cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
  648. }
  649. }
  650. // Ask for the upgrade key.
  651. if ($interactive) {
  652. cli_separator();
  653. cli_heading(get_string('upgradekeyset', 'admin'));
  654. if ($options['upgradekey'] !== '') {
  655. $prompt = get_string('clitypevaluedefault', 'admin', $options['upgradekey']);
  656. $options['upgradekey'] = cli_input($prompt, $options['upgradekey']);
  657. } else {
  658. $prompt = get_string('clitypevalue', 'admin');
  659. $options['upgradekey'] = cli_input($prompt);
  660. }
  661. }
  662. // Set the upgrade key if it was provided.
  663. if ($options['upgradekey'] !== '') {
  664. $CFG->upgradekey = $options['upgradekey'];
  665. }
  666. // The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
  667. // the license again in the database install part.
  668. if (!$skipdatabase) {
  669. if ($interactive) {
  670. if (!$options['agree-license']) {
  671. cli_separator();
  672. cli_heading(get_string('copyrightnotice'));
  673. echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
  674. echo get_string('gpl3')."\n\n";
  675. echo get_string('doyouagree')."\n";
  676. $prompt = get_string('cliyesnoprompt', 'admin');
  677. $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
  678. if ($input == get_string('clianswerno', 'admin')) {
  679. exit(1);
  680. }
  681. }
  682. } else {
  683. if (!$options['agree-license'] && !$skipdatabase) {
  684. cli_error(get_string('climustagreelicense', 'install'));
  685. }
  686. }
  687. }
  688. // Finally we have all info needed for config.php
  689. $configphp = install_generate_configphp($database, $CFG);
  690. umask(0137);
  691. if (($fh = fopen($configfile, 'w')) !== false) {
  692. fwrite($fh, $configphp);
  693. fclose($fh);
  694. }
  695. if (!file_exists($configfile)) {
  696. cli_error('Can not create config file.');
  697. }
  698. // remember selected language
  699. $installlang = $CFG->lang;
  700. // return back to original dir before executing setup.php which changes the dir again
  701. chdir($olddir);
  702. // We have config.php, it is a real php script from now on :-)
  703. require($configfile);
  704. // use selected language
  705. $CFG->lang = $installlang;
  706. $SESSION->lang = $CFG->lang;
  707. require("$CFG->dirroot/version.php");
  708. // Test environment first.
  709. require_once($CFG->libdir . '/environmentlib.php');
  710. list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
  711. if (!$envstatus) {
  712. $errors = environment_get_errors($environment_results);
  713. cli_heading(get_string('environment', 'admin'));
  714. foreach ($errors as $error) {
  715. list($info, $report) = $error;
  716. echo "!! $info !!\n$report\n\n";
  717. }
  718. exit(1);
  719. }
  720. // Test plugin dependencies.
  721. $failed = array();
  722. if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
  723. cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
  724. cli_error(get_string('pluginschecktodo', 'admin'));
  725. }
  726. if (!$skipdatabase) {
  727. install_cli_database($options, $interactive);
  728. // This needs to happen at the end to ensure it occurs after all caches
  729. // have been purged for the last time.
  730. // This will build a cached version of the current theme for the user
  731. // to immediately start browsing the site.
  732. require_once($CFG->libdir.'/upgradelib.php');
  733. upgrade_themes();
  734. } else {
  735. echo get_string('cliskipdatabase', 'install')."\n";
  736. }
  737. echo get_string('cliinstallfinished', 'install')."\n";
  738. exit(0); // 0 means success