0b6c5cac392b191a8b6f44cbc06352478980252c
[moodle.git] / admin / cli / install.php
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.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * This script creates config.php file and prepares database.
20  *
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
25  *
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
30  */
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);
37 }
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();
43 }
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();
99     }
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";
112     }
114     if ($DB->get_manager()->table_exists('config')) {
115         cli_error(get_string('clialreadyinstalled', 'install'));
116     } else {
117         cli_error(get_string('clialreadyconfigured', 'install'));
118     }
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
150 if (version_compare(phpversion(), "5.6.5") < 0) {
151     $phpversion = phpversion();
152     // do NOT localise - lang strings would not work here and we CAN NOT move it after installib
153     fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
154     fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
155     exit(1);
158 // set up configuration
159 global $CFG;
160 $CFG = new stdClass();
161 $CFG->lang                 = 'en';
162 $CFG->dirroot              = dirname(dirname(__DIR__));
163 $CFG->libdir               = "$CFG->dirroot/lib";
164 $CFG->wwwroot              = "http://localhost";
165 $CFG->httpswwwroot         = $CFG->wwwroot;
166 $CFG->docroot              = 'http://docs.moodle.org';
167 $CFG->running_installer    = true;
168 $CFG->early_install_lang   = true;
169 $CFG->ostype               = (stristr(PHP_OS, 'win') && !stristr(PHP_OS, 'darwin')) ? 'WINDOWS' : 'UNIX';
170 $CFG->dboptions            = array();
171 $CFG->debug                = (E_ALL | E_STRICT);
172 $CFG->debugdisplay         = true;
173 $CFG->debugdeveloper       = true;
175 $parts = explode('/', str_replace('\\', '/', dirname(__DIR__)));
176 $CFG->admin                = array_pop($parts);
178 //point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else
179 //the problem is that we need specific version of quickforms and hacked excel files :-(
180 ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
182 require_once($CFG->libdir.'/classes/component.php');
183 require_once($CFG->libdir.'/classes/text.php');
184 require_once($CFG->libdir.'/classes/string_manager.php');
185 require_once($CFG->libdir.'/classes/string_manager_install.php');
186 require_once($CFG->libdir.'/classes/string_manager_standard.php');
187 require_once($CFG->libdir.'/installlib.php');
188 require_once($CFG->libdir.'/clilib.php');
189 require_once($CFG->libdir.'/setuplib.php');
190 require_once($CFG->libdir.'/weblib.php');
191 require_once($CFG->libdir.'/dmllib.php');
192 require_once($CFG->libdir.'/moodlelib.php');
193 require_once($CFG->libdir.'/deprecatedlib.php');
194 require_once($CFG->libdir.'/adminlib.php');
195 require_once($CFG->libdir.'/componentlib.class.php');
196 require_once($CFG->dirroot.'/cache/lib.php');
198 // Register our classloader, in theory somebody might want to replace it to load other hacked core classes.
199 // Required because the database checks below lead to session interaction which is going to lead us to requiring autoloaded classes.
200 if (defined('COMPONENT_CLASSLOADER')) {
201     spl_autoload_register(COMPONENT_CLASSLOADER);
202 } else {
203     spl_autoload_register('core_component::classloader');
206 require($CFG->dirroot.'/version.php');
207 $CFG->target_release = $release;
209 \core\session\manager::init_empty_session();
210 global $SESSION;
211 global $USER;
213 global $COURSE;
214 $COURSE = new stdClass();
215 $COURSE->id = 1;
217 global $SITE;
218 $SITE = $COURSE;
219 define('SITEID', 1);
221 //Database types
222 $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
223                    'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
224                    'pgsql'  => moodle_database::get_driver_instance('pgsql',  'native'),
225                    'oci'    => moodle_database::get_driver_instance('oci',    'native'),
226                    'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // MS SQL*Server PHP driver
227                    'mssql'  => moodle_database::get_driver_instance('mssql',  'native'), // FreeTDS driver
228                   );
229 foreach ($databases as $type=>$database) {
230     if ($database->driver_installed() !== true) {
231         unset($databases[$type]);
232     }
234 if (empty($databases)) {
235     $defaultdb = '';
236 } else {
237     reset($databases);
238     $defaultdb = key($databases);
241 // now get cli options
242 list($options, $unrecognized) = cli_get_params(
243     array(
244         'chmod'             => isset($distro->directorypermissions) ? sprintf('%04o',$distro->directorypermissions) : '2777', // let distros set dir permissions
245         'lang'              => $CFG->lang,
246         'wwwroot'           => '',
247         'dataroot'          => empty($distro->dataroot) ? str_replace('\\', '/', dirname(dirname(dirname(__DIR__))).'/moodledata'): $distro->dataroot, // initialised later after including libs or by distro
248         'dbtype'            => empty($distro->dbtype) ? $defaultdb : $distro->dbtype, // let distro skip dbtype selection
249         'dbhost'            => empty($distro->dbhost) ? 'localhost' : $distro->dbhost, // let distros set dbhost
250         'dbname'            => 'moodle',
251         'dbuser'            => empty($distro->dbuser) ? 'root' : $distro->dbuser, // let distros set dbuser
252         'dbpass'            => '',
253         'dbport'            => '',
254         'dbsocket'          => '',
255         'prefix'            => 'mdl_',
256         'fullname'          => '',
257         'shortname'         => '',
258         'summary'           => '',
259         'adminuser'         => 'admin',
260         'adminpass'         => '',
261         'adminemail'        => '',
262         'upgradekey'        => '',
263         'non-interactive'   => false,
264         'agree-license'     => false,
265         'allow-unstable'    => false,
266         'skip-database'     => false,
267         'help'              => false
268     ),
269     array(
270         'h' => 'help'
271     )
272 );
274 $interactive = empty($options['non-interactive']);
276 // set up language
277 $lang = clean_param($options['lang'], PARAM_SAFEDIR);
278 $languages = get_string_manager()->get_list_of_translations();
279 if (array_key_exists($lang, $languages)) {
280     $CFG->lang = $lang;
283 if ($unrecognized) {
284     $unrecognized = implode("\n  ", $unrecognized);
285     cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
288 if ($options['help']) {
289     echo $help;
290     die;
293 //Print header
294 cli_logo();
295 echo PHP_EOL;
296 echo get_string('cliinstallheader', 'install', $CFG->target_release)."\n";
298 //Fist select language
299 if ($interactive) {
300     cli_separator();
301     // Do not put the langs into columns because it is not compatible with RTL.
302     $default = $CFG->lang;
303     cli_heading(get_string('chooselanguagehead', 'install'));
304     if (array_key_exists($default, $languages)) {
305         echo $default.' - '.$languages[$default]."\n";
306     }
307     if ($default !== 'en') {
308         echo 'en - English (en)'."\n";
309     }
310     echo '? - '.get_string('availablelangs', 'install')."\n";
311     $prompt = get_string('clitypevaluedefault', 'admin', $CFG->lang);
312     $error = '';
313     do {
314         echo $error;
315         $input = cli_input($prompt, $default);
317         if ($input === '?') {
318             echo implode("\n", $languages)."\n";
319             $error = "\n";
321         } else {
322             $input = clean_param($input, PARAM_SAFEDIR);
324             if (!array_key_exists($input, $languages)) {
325                 $error = get_string('cliincorrectvalueretry', 'admin')."\n";
326             } else {
327                 $error = '';
328             }
329         }
330     } while ($error !== '');
331     $CFG->lang = $input;
332 } else {
333     // already selected and verified
336 // Set directorypermissions first
337 $chmod = octdec(clean_param($options['chmod'], PARAM_INT));
338 if ($interactive) {
339     cli_separator();
340     cli_heading(get_string('datarootpermission', 'install'));
341     $prompt = get_string('clitypevaluedefault', 'admin', decoct($chmod));
342     $error = '';
343     do {
344         echo $error;
345         $input = cli_input($prompt, decoct($chmod));
346         $input = octdec(clean_param($input, PARAM_INT));
347         if (empty($input)) {
348             $error = get_string('cliincorrectvalueretry', 'admin')."\n";
349         } else {
350             $error = '';
351         }
352     } while ($error !== '');
353     $chmod = $input;
355 } else {
356     if (empty($chmod)) {
357         $a = (object)array('option' => 'chmod', 'value' => decoct($chmod));
358         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
359     }
361 $CFG->directorypermissions = $chmod;
362 $CFG->filepermissions      = ($CFG->directorypermissions & 0666);
363 $CFG->umaskpermissions     = (($CFG->directorypermissions & 0777) ^ 0777);
365 //We need wwwroot before we test dataroot
366 $wwwroot = clean_param($options['wwwroot'], PARAM_URL);
367 $wwwroot = trim($wwwroot, '/');
368 if ($interactive) {
369     cli_separator();
370     cli_heading(get_string('wwwroot', 'install'));
371     if (strpos($wwwroot, 'http') === 0) {
372         $prompt = get_string('clitypevaluedefault', 'admin', $wwwroot);
373     } else {
374         $wwwroot = null;
375         $prompt = get_string('clitypevalue', 'admin');
376     }
377     $error = '';
378     do {
379         echo $error;
380         $input = cli_input($prompt, $wwwroot);
381         $input = clean_param($input, PARAM_URL);
382         $input = trim($input, '/');
383         if (strpos($input, 'http') !== 0) {
384             $error = get_string('cliincorrectvalueretry', 'admin')."\n";
385         } else {
386             $error = '';
387         }
388     } while ($error !== '');
389     $wwwroot = $input;
391 } else {
392     if (strpos($wwwroot, 'http') !== 0) {
393         $a = (object)array('option'=>'wwwroot', 'value'=>$wwwroot);
394         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
395     }
397 $CFG->wwwroot       = $wwwroot;
398 $CFG->httpswwwroot  = $CFG->wwwroot;
401 //We need dataroot before lang download
402 $CFG->dataroot = $options['dataroot'];
403 if ($interactive) {
404     cli_separator();
405     $i=0;
406     while(is_dataroot_insecure()) {
407         $parrent = dirname($CFG->dataroot);
408         $i++;
409         if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) {
410             $CFG->dataroot = ''; //can not find secure location for dataroot
411             break;
412         }
413         $CFG->dataroot = dirname($parrent).'/moodledata';
414     }
415     cli_heading(get_string('dataroot', 'install'));
416     $error = '';
417     do {
418         if ($CFG->dataroot !== '') {
419             $prompt = get_string('clitypevaluedefault', 'admin', $CFG->dataroot);
420         } else {
421             $prompt = get_string('clitypevalue', 'admin');
422         }
423         echo $error;
424         $CFG->dataroot = cli_input($prompt, $CFG->dataroot);
425         if ($CFG->dataroot === '') {
426             $error = get_string('cliincorrectvalueretry', 'admin')."\n";
427         } else if (is_dataroot_insecure()) {
428             $CFG->dataroot = '';
429             $error = get_string('pathsunsecuredataroot', 'install')."\n";
430         } else {
431             if (install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
432                 $error = '';
433             } else {
434                 $a = (object)array('dataroot' => $CFG->dataroot);
435                 $error = get_string('pathserrcreatedataroot', 'install', $a)."\n";
436             }
437         }
439     } while ($error !== '');
441 } else {
442     if (is_dataroot_insecure()) {
443         cli_error(get_string('pathsunsecuredataroot', 'install'));
444     }
445     if (!install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
446         $a = (object)array('dataroot' => $CFG->dataroot);
447         cli_error(get_string('pathserrcreatedataroot', 'install', $a));
448     }
450 $CFG->tempdir       = $CFG->dataroot.'/temp';
451 $CFG->cachedir      = $CFG->dataroot.'/cache';
452 $CFG->localcachedir = $CFG->dataroot.'/localcache';
454 // download required lang packs
455 if ($CFG->lang !== 'en') {
456     $installer = new lang_installer($CFG->lang);
457     $results = $installer->run();
458     foreach ($results as $langcode => $langstatus) {
459         if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) {
460             $a       = new stdClass();
461             $a->url  = $installer->lang_pack_url($langcode);
462             $a->dest = $CFG->dataroot.'/lang';
463             cli_problem(get_string('remotedownloaderror', 'error', $a));
464         }
465     }
468 // switch the string_manager instance to stop using install/lang/
469 $CFG->early_install_lang = false;
470 $CFG->langotherroot      = $CFG->dataroot.'/lang';
471 $CFG->langlocalroot      = $CFG->dataroot.'/lang';
472 get_string_manager(true);
474 // make sure we are installing stable release or require a confirmation
475 if (isset($maturity)) {
476     if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) {
477         $maturitylevel = get_string('maturity'.$maturity, 'admin');
479         if ($interactive) {
480             cli_separator();
481             cli_heading(get_string('notice'));
482             echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL;
483             echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL;
484             echo get_string('continue') . PHP_EOL;
485             $prompt = get_string('cliyesnoprompt', 'admin');
486             $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
487             if ($input == get_string('clianswerno', 'admin')) {
488                 exit(1);
489             }
490         } else {
491             cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel));
492             cli_error(get_string('maturityallowunstable', 'admin'));
493         }
494     }
497 // ask for db type - show only drivers available
498 if ($interactive) {
499     $options['dbtype'] = strtolower($options['dbtype']);
500     cli_separator();
501     cli_heading(get_string('databasetypehead', 'install'));
502     foreach ($databases as $type=>$database) {
503         echo " $type \n";
504     }
505     if (!empty($databases[$options['dbtype']])) {
506         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbtype']);
507     } else {
508         $prompt = get_string('clitypevalue', 'admin');
509     }
510     $CFG->dbtype = cli_input($prompt, $options['dbtype'], array_keys($databases));
512 } else {
513     if (empty($databases[$options['dbtype']])) {
514         $a = (object)array('option'=>'dbtype', 'value'=>$options['dbtype']);
515         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
516     }
517     $CFG->dbtype = $options['dbtype'];
519 $database = $databases[$CFG->dbtype];
522 // ask for db host
523 if ($interactive) {
524     cli_separator();
525     cli_heading(get_string('databasehost', 'install'));
526     if ($options['dbhost'] !== '') {
527         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
528     } else {
529         $prompt = get_string('clitypevalue', 'admin');
530     }
531     $CFG->dbhost = cli_input($prompt, $options['dbhost']);
533 } else {
534     $CFG->dbhost = $options['dbhost'];
537 // ask for db name
538 if ($interactive) {
539     cli_separator();
540     cli_heading(get_string('databasename', 'install'));
541     if ($options['dbname'] !== '') {
542         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
543     } else {
544         $prompt = get_string('clitypevalue', 'admin');
545     }
546     $CFG->dbname = cli_input($prompt, $options['dbname']);
548 } else {
549     $CFG->dbname = $options['dbname'];
552 // ask for db prefix
553 if ($interactive) {
554     cli_separator();
555     cli_heading(get_string('dbprefix', 'install'));
556     //TODO: solve somehow the prefix trouble for oci
557     if ($options['prefix'] !== '') {
558         $prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
559     } else {
560         $prompt = get_string('clitypevalue', 'admin');
561     }
562     $CFG->prefix = cli_input($prompt, $options['prefix']);
564 } else {
565     $CFG->prefix = $options['prefix'];
568 // ask for db port
569 if ($interactive) {
570     cli_separator();
571     cli_heading(get_string('databaseport', 'install'));
572     $prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
573     $CFG->dboptions['dbport'] = (int)cli_input($prompt, $options['dbport']);
575 } else {
576     $CFG->dboptions['dbport'] = (int)$options['dbport'];
578 if ($CFG->dboptions['dbport'] <= 0) {
579     $CFG->dboptions['dbport'] = '';
582 // ask for db socket
583 if ($CFG->ostype === 'WINDOWS') {
584     $CFG->dboptions['dbsocket'] = '';
586 } else if ($interactive and empty($CFG->dboptions['dbport'])) {
587     cli_separator();
588     cli_heading(get_string('databasesocket', 'install'));
589     $prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
590     $CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
592 } else {
593     $CFG->dboptions['dbsocket'] = $options['dbsocket'];
596 // ask for db user
597 if ($interactive) {
598     cli_separator();
599     cli_heading(get_string('databaseuser', 'install'));
600     if ($options['dbuser'] !== '') {
601         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
602     } else {
603         $prompt = get_string('clitypevalue', 'admin');
604     }
605     $CFG->dbuser = cli_input($prompt, $options['dbuser']);
607 } else {
608     $CFG->dbuser = $options['dbuser'];
611 // ask for db password
612 if ($interactive) {
613     cli_separator();
614     cli_heading(get_string('databasepass', 'install'));
615     do {
616         if ($options['dbpass'] !== '') {
617             $prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
618         } else {
619             $prompt = get_string('clitypevalue', 'admin');
620         }
622         $CFG->dbpass = cli_input($prompt, $options['dbpass']);
623         if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation
624             $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);
625         }
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     } while ($hint_database !== '');
629 } else {
630     $CFG->dbpass = $options['dbpass'];
631     $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']));
632     if ($hint_database !== '') {
633         cli_error(get_string('dbconnectionerror', 'install'));
634     }
637 // ask for fullname
638 if ($interactive) {
639     cli_separator();
640     cli_heading(get_string('fullsitename', 'moodle'));
642     if ($options['fullname'] !== '') {
643         $prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
644     } else {
645         $prompt = get_string('clitypevalue', 'admin');
646     }
648     do {
649         $options['fullname'] = cli_input($prompt, $options['fullname']);
650     } while (empty($options['fullname']));
651 } else {
652     if (empty($options['fullname'])) {
653         $a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
654         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
655     }
658 // ask for shortname
659 if ($interactive) {
660     cli_separator();
661     cli_heading(get_string('shortsitename', 'moodle'));
663     if ($options['shortname'] !== '') {
664         $prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
665     } else {
666         $prompt = get_string('clitypevalue', 'admin');
667     }
669     do {
670         $options['shortname'] = cli_input($prompt, $options['shortname']);
671     } while (empty($options['shortname']));
672 } else {
673     if (empty($options['shortname'])) {
674         $a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
675         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
676     }
679 // ask for admin user name
680 if ($interactive) {
681     cli_separator();
682     cli_heading(get_string('cliadminusername', 'install'));
683     if (!empty($options['adminuser'])) {
684         $prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
685     } else {
686         $prompt = get_string('clitypevalue', 'admin');
687     }
688     do {
689         $options['adminuser'] = cli_input($prompt, $options['adminuser']);
690     } while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
691 } else {
692     if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
693         $a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
694         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
695     }
698 // ask for admin user password
699 if ($interactive) {
700     cli_separator();
701     cli_heading(get_string('cliadminpassword', 'install'));
702     $prompt = get_string('clitypevalue', 'admin');
703     do {
704         $options['adminpass'] = cli_input($prompt);
705     } while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
706 } else {
707     if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
708         $a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
709         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
710     }
713 // Ask for the admin email address.
714 if ($interactive) {
715     cli_separator();
716     cli_heading(get_string('cliadminemail', 'install'));
717     $prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
718     $options['adminemail'] = cli_input($prompt);
721 // Validate that the address provided was an e-mail address.
722 if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
723     $a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
724     cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
727 // Ask for the upgrade key.
728 if ($interactive) {
729     cli_separator();
730     cli_heading(get_string('upgradekeyset', 'admin'));
731     if ($options['upgradekey'] !== '') {
732         $prompt = get_string('clitypevaluedefault', 'admin', $options['upgradekey']);
733         $options['upgradekey'] = cli_input($prompt, $options['upgradekey']);
734     } else {
735         $prompt = get_string('clitypevalue', 'admin');
736         $options['upgradekey'] = cli_input($prompt);
737     }
740 // Set the upgrade key if it was provided.
741 if ($options['upgradekey'] !== '') {
742     $CFG->upgradekey = $options['upgradekey'];
745 if ($interactive) {
746     if (!$options['agree-license']) {
747         cli_separator();
748         cli_heading(get_string('copyrightnotice'));
749         echo "Moodle  - Modular Object-Oriented Dynamic Learning Environment\n";
750         echo get_string('gpl3')."\n\n";
751         echo get_string('doyouagree')."\n";
752         $prompt = get_string('cliyesnoprompt', 'admin');
753         $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
754         if ($input == get_string('clianswerno', 'admin')) {
755             exit(1);
756         }
757     }
758 } else {
759     if (!$options['agree-license']) {
760         cli_error(get_string('climustagreelicense', 'install'));
761     }
764 // Finally we have all info needed for config.php
765 $configphp = install_generate_configphp($database, $CFG);
766 umask(0137);
767 if (($fh = fopen($configfile, 'w')) !== false) {
768     fwrite($fh, $configphp);
769     fclose($fh);
772 if (!file_exists($configfile)) {
773     cli_error('Can not create config file.');
776 // remember selected language
777 $installlang = $CFG->lang;
778 // return back to original dir before executing setup.php which changes the dir again
779 chdir($olddir);
780 // We have config.php, it is a real php script from now on :-)
781 require($configfile);
783 // use selected language
784 $CFG->lang = $installlang;
785 $SESSION->lang = $CFG->lang;
787 require("$CFG->dirroot/version.php");
789 // Test environment first.
790 require_once($CFG->libdir . '/environmentlib.php');
791 list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
792 if (!$envstatus) {
793     $errors = environment_get_errors($environment_results);
794     cli_heading(get_string('environment', 'admin'));
795     foreach ($errors as $error) {
796         list($info, $report) = $error;
797         echo "!! $info !!\n$report\n\n";
798     }
799     exit(1);
802 // Test plugin dependencies.
803 $failed = array();
804 if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
805     cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
806     cli_error(get_string('pluginschecktodo', 'admin'));
809 if (!$options['skip-database']) {
810     install_cli_database($options, $interactive);
811 } else {
812     echo get_string('cliskipdatabase', 'install')."\n";
815 echo get_string('cliinstallfinished', 'install')."\n";
816 exit(0); // 0 means success