cfc8ea0f01ae2c0a5c49c0f5241c07547f3b8fec
[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 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
222                   );
223 foreach ($databases as $type=>$database) {
224     if ($database->driver_installed() !== true) {
225         unset($databases[$type]);
226     }
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
262     ),
263     array(
264         'h' => 'help'
265     )
266 );
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";
300     }
301     if ($default !== 'en') {
302         echo 'en - English (en)'."\n";
303     }
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 = '';
322             }
323         }
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 = '';
345         }
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));
353     }
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');
370     }
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 = '';
381         }
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));
389     }
391 $CFG->wwwroot       = $wwwroot;
392 $CFG->httpswwwroot  = $CFG->wwwroot;
394 //We need dataroot before lang download
395 $CFG->dataroot = $options['dataroot'];
396 if ($interactive) {
397     cli_separator();
398     $i=0;
399     while(is_dataroot_insecure()) {
400         $parrent = dirname($CFG->dataroot);
401         $i++;
402         if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) {
403             $CFG->dataroot = ''; //can not find secure location for dataroot
404             break;
405         }
406         $CFG->dataroot = dirname($parrent).'/moodledata';
407     }
408     cli_heading(get_string('dataroot', 'install'));
409     $error = '';
410     do {
411         if ($CFG->dataroot !== '') {
412             $prompt = get_string('clitypevaluedefault', 'admin', $CFG->dataroot);
413         } else {
414             $prompt = get_string('clitypevalue', 'admin');
415         }
416         echo $error;
417         $CFG->dataroot = cli_input($prompt, $CFG->dataroot);
418         if ($CFG->dataroot === '') {
419             $error = get_string('cliincorrectvalueretry', 'admin')."\n";
420         } else if (is_dataroot_insecure()) {
421             $CFG->dataroot = '';
422             $error = get_string('pathsunsecuredataroot', 'install')."\n";
423         } else {
424             if (install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
425                 $error = '';
426             } else {
427                 $a = (object)array('dataroot' => $CFG->dataroot);
428                 $error = get_string('pathserrcreatedataroot', 'install', $a)."\n";
429             }
430         }
432     } while ($error !== '');
434 } else {
435     if (is_dataroot_insecure()) {
436         cli_error(get_string('pathsunsecuredataroot', 'install'));
437     }
438     if (!install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
439         $a = (object)array('dataroot' => $CFG->dataroot);
440         cli_error(get_string('pathserrcreatedataroot', 'install', $a));
441     }
443 $CFG->tempdir       = $CFG->dataroot.'/temp';
444 $CFG->backuptempdir = $CFG->tempdir.'/backup';
445 $CFG->cachedir      = $CFG->dataroot.'/cache';
446 $CFG->localcachedir = $CFG->dataroot.'/localcache';
448 // download required lang packs
449 if ($CFG->lang !== 'en') {
450     $installer = new lang_installer($CFG->lang);
451     $results = $installer->run();
452     foreach ($results as $langcode => $langstatus) {
453         if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) {
454             $a       = new stdClass();
455             $a->url  = $installer->lang_pack_url($langcode);
456             $a->dest = $CFG->dataroot.'/lang';
457             cli_problem(get_string('remotedownloaderror', 'error', $a));
458         }
459     }
462 // switch the string_manager instance to stop using install/lang/
463 $CFG->early_install_lang = false;
464 $CFG->langotherroot      = $CFG->dataroot.'/lang';
465 $CFG->langlocalroot      = $CFG->dataroot.'/lang';
466 get_string_manager(true);
468 // make sure we are installing stable release or require a confirmation
469 if (isset($maturity)) {
470     if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) {
471         $maturitylevel = get_string('maturity'.$maturity, 'admin');
473         if ($interactive) {
474             cli_separator();
475             cli_heading(get_string('notice'));
476             echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL;
477             echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL;
478             echo get_string('continue') . PHP_EOL;
479             $prompt = get_string('cliyesnoprompt', 'admin');
480             $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
481             if ($input == get_string('clianswerno', 'admin')) {
482                 exit(1);
483             }
484         } else {
485             cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel));
486             cli_error(get_string('maturityallowunstable', 'admin'));
487         }
488     }
491 // ask for db type - show only drivers available
492 if ($interactive) {
493     $options['dbtype'] = strtolower($options['dbtype']);
494     cli_separator();
495     cli_heading(get_string('databasetypehead', 'install'));
496     foreach ($databases as $type=>$database) {
497         echo " $type \n";
498     }
499     if (!empty($databases[$options['dbtype']])) {
500         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbtype']);
501     } else {
502         $prompt = get_string('clitypevalue', 'admin');
503     }
504     $CFG->dbtype = cli_input($prompt, $options['dbtype'], array_keys($databases));
506 } else {
507     if (empty($databases[$options['dbtype']])) {
508         $a = (object)array('option'=>'dbtype', 'value'=>$options['dbtype']);
509         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
510     }
511     $CFG->dbtype = $options['dbtype'];
513 $database = $databases[$CFG->dbtype];
516 // We cannot do any validation until all DB connection data is provided.
517 $hintdatabase = '';
518 do {
519     echo $hintdatabase;
521     // Ask for db host.
522     if ($interactive) {
523         cli_separator();
524         cli_heading(get_string('databasehost', 'install'));
525         if ($options['dbhost'] !== '') {
526             $prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
527         } else {
528             $prompt = get_string('clitypevalue', 'admin');
529         }
530         $CFG->dbhost = cli_input($prompt, $options['dbhost']);
532     } else {
533         $CFG->dbhost = $options['dbhost'];
534     }
536     // Ask for db name.
537     if ($interactive) {
538         cli_separator();
539         cli_heading(get_string('databasename', 'install'));
540         if ($options['dbname'] !== '') {
541             $prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
542         } else {
543             $prompt = get_string('clitypevalue', 'admin');
544         }
545         $CFG->dbname = cli_input($prompt, $options['dbname']);
547     } else {
548         $CFG->dbname = $options['dbname'];
549     }
551     // Ask for db prefix.
552     if ($interactive) {
553         cli_separator();
554         cli_heading(get_string('dbprefix', 'install'));
555         //TODO: solve somehow the prefix trouble for oci.
556         if ($options['prefix'] !== '') {
557             $prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
558         } else {
559             $prompt = get_string('clitypevalue', 'admin');
560         }
561         $CFG->prefix = cli_input($prompt, $options['prefix']);
563     } else {
564         $CFG->prefix = $options['prefix'];
565     }
567     // Ask for db port.
568     if ($interactive) {
569         cli_separator();
570         cli_heading(get_string('databaseport', 'install'));
571         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
572         $CFG->dboptions['dbport'] = (int) cli_input($prompt, $options['dbport']);
574     } else {
575         $CFG->dboptions['dbport'] = (int) $options['dbport'];
576     }
577     if ($CFG->dboptions['dbport'] <= 0) {
578         $CFG->dboptions['dbport'] = '';
579     }
581     // Ask for db socket.
582     if ($CFG->ostype === 'WINDOWS') {
583         $CFG->dboptions['dbsocket'] = '';
585     } else if ($interactive and empty($CFG->dboptions['dbport'])) {
586         cli_separator();
587         cli_heading(get_string('databasesocket', 'install'));
588         $prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
589         $CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
591     } else {
592         $CFG->dboptions['dbsocket'] = $options['dbsocket'];
593     }
595     // Ask for db user.
596     if ($interactive) {
597         cli_separator();
598         cli_heading(get_string('databaseuser', 'install'));
599         if ($options['dbuser'] !== '') {
600             $prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
601         } else {
602             $prompt = get_string('clitypevalue', 'admin');
603         }
604         $CFG->dbuser = cli_input($prompt, $options['dbuser']);
606     } else {
607         $CFG->dbuser = $options['dbuser'];
608     }
610     // Ask for db password.
611     if ($interactive) {
612         cli_separator();
613         cli_heading(get_string('databasepass', 'install'));
615         if ($options['dbpass'] !== '') {
616             $prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
617         } else {
618             $prompt = get_string('clitypevalue', 'admin');
619         }
621         $CFG->dbpass = cli_input($prompt, $options['dbpass']);
622         if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation.
623             $distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
624                     array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']),
625                     $distro);
626         }
627         $hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
628                 array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
630     } else {
631         $CFG->dbpass = $options['dbpass'];
632         $hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
633                 array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
634         if ($hintdatabase !== '') {
635             cli_error(get_string('dbconnectionerror', 'install'));
636         }
637     }
638 } while ($hintdatabase !== '');
640 // ask for fullname
641 if ($interactive) {
642     cli_separator();
643     cli_heading(get_string('fullsitename', 'moodle'));
645     if ($options['fullname'] !== '') {
646         $prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
647     } else {
648         $prompt = get_string('clitypevalue', 'admin');
649     }
651     do {
652         $options['fullname'] = cli_input($prompt, $options['fullname']);
653     } while (empty($options['fullname']));
654 } else {
655     if (empty($options['fullname'])) {
656         $a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
657         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
658     }
661 // ask for shortname
662 if ($interactive) {
663     cli_separator();
664     cli_heading(get_string('shortsitename', 'moodle'));
666     if ($options['shortname'] !== '') {
667         $prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
668     } else {
669         $prompt = get_string('clitypevalue', 'admin');
670     }
672     do {
673         $options['shortname'] = cli_input($prompt, $options['shortname']);
674     } while (empty($options['shortname']));
675 } else {
676     if (empty($options['shortname'])) {
677         $a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
678         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
679     }
682 // ask for admin user name
683 if ($interactive) {
684     cli_separator();
685     cli_heading(get_string('cliadminusername', 'install'));
686     if (!empty($options['adminuser'])) {
687         $prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
688     } else {
689         $prompt = get_string('clitypevalue', 'admin');
690     }
691     do {
692         $options['adminuser'] = cli_input($prompt, $options['adminuser']);
693     } while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
694 } else {
695     if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
696         $a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
697         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
698     }
701 // ask for admin user password
702 if ($interactive) {
703     cli_separator();
704     cli_heading(get_string('cliadminpassword', 'install'));
705     $prompt = get_string('clitypevalue', 'admin');
706     do {
707         $options['adminpass'] = cli_input($prompt);
708     } while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
709 } else {
710     if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
711         $a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
712         cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
713     }
716 // Ask for the admin email address.
717 if ($interactive) {
718     cli_separator();
719     cli_heading(get_string('cliadminemail', 'install'));
720     $prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
721     $options['adminemail'] = cli_input($prompt, $options['adminemail']);
724 // Validate that the address provided was an e-mail address.
725 if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
726     $a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
727     cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
730 // Ask for the upgrade key.
731 if ($interactive) {
732     cli_separator();
733     cli_heading(get_string('upgradekeyset', 'admin'));
734     if ($options['upgradekey'] !== '') {
735         $prompt = get_string('clitypevaluedefault', 'admin', $options['upgradekey']);
736         $options['upgradekey'] = cli_input($prompt, $options['upgradekey']);
737     } else {
738         $prompt = get_string('clitypevalue', 'admin');
739         $options['upgradekey'] = cli_input($prompt);
740     }
743 // Set the upgrade key if it was provided.
744 if ($options['upgradekey'] !== '') {
745     $CFG->upgradekey = $options['upgradekey'];
748 if ($interactive) {
749     if (!$options['agree-license']) {
750         cli_separator();
751         cli_heading(get_string('copyrightnotice'));
752         echo "Moodle  - Modular Object-Oriented Dynamic Learning Environment\n";
753         echo get_string('gpl3')."\n\n";
754         echo get_string('doyouagree')."\n";
755         $prompt = get_string('cliyesnoprompt', 'admin');
756         $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
757         if ($input == get_string('clianswerno', 'admin')) {
758             exit(1);
759         }
760     }
761 } else {
762     if (!$options['agree-license']) {
763         cli_error(get_string('climustagreelicense', 'install'));
764     }
767 // Finally we have all info needed for config.php
768 $configphp = install_generate_configphp($database, $CFG);
769 umask(0137);
770 if (($fh = fopen($configfile, 'w')) !== false) {
771     fwrite($fh, $configphp);
772     fclose($fh);
775 if (!file_exists($configfile)) {
776     cli_error('Can not create config file.');
779 // remember selected language
780 $installlang = $CFG->lang;
781 // return back to original dir before executing setup.php which changes the dir again
782 chdir($olddir);
783 // We have config.php, it is a real php script from now on :-)
784 require($configfile);
786 // use selected language
787 $CFG->lang = $installlang;
788 $SESSION->lang = $CFG->lang;
790 require("$CFG->dirroot/version.php");
792 // Test environment first.
793 require_once($CFG->libdir . '/environmentlib.php');
794 list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
795 if (!$envstatus) {
796     $errors = environment_get_errors($environment_results);
797     cli_heading(get_string('environment', 'admin'));
798     foreach ($errors as $error) {
799         list($info, $report) = $error;
800         echo "!! $info !!\n$report\n\n";
801     }
802     exit(1);
805 // Test plugin dependencies.
806 $failed = array();
807 if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
808     cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
809     cli_error(get_string('pluginschecktodo', 'admin'));
812 if (!$options['skip-database']) {
813     install_cli_database($options, $interactive);
814     // This needs to happen at the end to ensure it occurs after all caches
815     // have been purged for the last time.
816     // This will build a cached version of the current theme for the user
817     // to immediately start browsing the site.
818     require_once($CFG->libdir.'/upgradelib.php');
819     upgrade_themes();
820 } else {
821     echo get_string('cliskipdatabase', 'install')."\n";
824 echo get_string('cliinstallfinished', 'install')."\n";
825 exit(0); // 0 means success