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