MDL-23590 refactoring cli install before adding install_database.php + fixing problem...
[moodle.git] / lib / installlib.php
CommitLineData
95feaf96 1<?php
2
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/>.
2f13f94c 17
2f13f94c 18/**
9d068cd6 19 * Functions to support installation process
95feaf96 20 *
b7315f35 21 * @package core
95feaf96 22 * @subpackage install
23 * @copyright 2009 Petr Skoda (http://skodak.org)
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2f13f94c 25 */
2f13f94c 26
460ebd6c
PS
27defined('MOODLE_INTERNAL') || die();
28
226617ea 29/** INSTALL_WELCOME = 0 */
3b093310 30define('INSTALL_WELCOME', 0);
226617ea 31/** INSTALL_ENVIRONMENT = 1 */
64c368e3 32define('INSTALL_ENVIRONMENT', 1);
226617ea 33/** INSTALL_PATHS = 2 */
64c368e3 34define('INSTALL_PATHS', 2);
226617ea 35/** INSTALL_DOWNLOADLANG = 3 */
64c368e3 36define('INSTALL_DOWNLOADLANG', 3);
226617ea 37/** INSTALL_DATABASETYPE = 4 */
64c368e3 38define('INSTALL_DATABASETYPE', 4);
226617ea 39/** INSTALL_DATABASE = 5 */
64c368e3 40define('INSTALL_DATABASE', 5);
226617ea 41/** INSTALL_SAVE = 6 */
64c368e3 42define('INSTALL_SAVE', 6);
3b093310 43
11e7b506 44/**
226617ea 45 * Tries to detect the right www root setting.
11e7b506 46 * @return string detected www root
47 */
48function install_guess_wwwroot() {
49 $wwwroot = '';
50 if (empty($_SERVER['HTTPS']) or $_SERVER['HTTPS'] == 'off') {
51 $wwwroot .= 'http://';
52 } else {
53 $wwwroot .= 'https://';
54 }
55 $hostport = explode(':', $_SERVER['HTTP_HOST']);
56 $wwwroot .= reset($hostport);
57 if ($_SERVER['SERVER_PORT'] != 80 and $_SERVER['SERVER_PORT'] != '443') {
58 $wwwroot .= ':'.$_SERVER['SERVER_PORT'];
59 }
60 $wwwroot .= $_SERVER['SCRIPT_NAME'];
61
62 list($wwwroot, $xtra) = explode('/install.php', $wwwroot);
63
64 return $wwwroot;
65}
66
95feaf96 67/**
68 * Copy of @see{ini_get_bool()}
69 * @param string $ini_get_arg
70 * @return bool
71 */
3b093310 72function install_ini_get_bool($ini_get_arg) {
73 $temp = ini_get($ini_get_arg);
74
75 if ($temp == '1' or strtolower($temp) == 'on') {
76 return true;
77 }
78 return false;
79}
80
95feaf96 81/**
82 * Print help button
83 * @param string $url
84 * @param string $titel
85 * @return void
86 */
3b093310 87function install_helpbutton($url, $title='') {
88 if ($title == '') {
89 $title = get_string('help');
90 }
91 echo "<a href=\"javascript:void(0)\" ";
92 echo "onclick=\"return window.open('$url','Help','menubar=0,location=0,scrollbars,resizable,width=500,height=400')\"";
93 echo ">";
94 echo "<img src=\"pix/help.gif\" class=\"iconhelp\" alt=\"$title\" title=\"$title\"/>";
95 echo "</a>\n";
96}
97
95feaf96 98/**
99 * This is in function because we want the /install.php to parse in PHP4
226617ea 100 *
101 * @param object $database
102 * @param string $dbhsot
103 * @param string $dbuser
104 * @param string $dbpass
105 * @param string $dbname
106 * @param string $prefix
107 * @param mixed $dboptions
108 * @return string
95feaf96 109 */
768408e8 110function install_db_validate($database, $dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions) {
3b093310 111 try {
112 try {
113 $database->connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
114 } catch (moodle_exception $e) {
115 // let's try to create new database
116 if ($database->create_database($dbhost, $dbuser, $dbpass, $dbname, $dboptions)) {
117 $database->connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
118 } else {
119 throw $e;
120 }
121 }
122 return '';
123 } catch (dml_exception $ex) {
124 return get_string($ex->errorcode, $ex->module, $ex->a).'<br />'.$ex->debuginfo;
125 }
126}
127
dc47d704 128/**
129 * Returns content of config.php file.
6189e63d
DM
130 *
131 * Uses PHP_EOL for generating proper end of lines for the given platform.
132 *
dc47d704 133 * @param moodle_database $database database instance
134 * @param object $cfg copy of $CFG
dc47d704 135 * @return string
136 */
3b5ff37f 137function install_generate_configphp($database, $cfg) {
59ba2bb0 138 $configphp = '<?php // Moodle configuration file' . PHP_EOL . PHP_EOL;
dc47d704 139
6189e63d
DM
140 $configphp .= 'unset($CFG);' . PHP_EOL;
141 $configphp .= '$CFG = new stdClass();' . PHP_EOL . PHP_EOL; // prevent PHP5 strict warnings
dc47d704 142
143 $dbconfig = $database->export_dbconfig();
144
145 foreach ($dbconfig as $key=>$value) {
146 $key = str_pad($key, 9);
6189e63d 147 $configphp .= '$CFG->'.$key.' = '.var_export($value, true) . ';' . PHP_EOL;
dc47d704 148 }
6189e63d 149 $configphp .= PHP_EOL;
dc47d704 150
6189e63d 151 $configphp .= '$CFG->wwwroot = '.var_export($cfg->wwwroot, true) . ';' . PHP_EOL ;
dc47d704 152
3b5ff37f 153 $configphp .= '$CFG->dataroot = '.var_export($cfg->dataroot, true) . ';' . PHP_EOL;
dc47d704 154
6189e63d 155 $configphp .= '$CFG->admin = '.var_export($cfg->admin, true) . ';' . PHP_EOL . PHP_EOL;
dc47d704 156
7be67681
DM
157 if (empty($cfg->directorypermissions)) {
158 $chmod = '02777';
159 } else {
160 $chmod = '0' . decoct($cfg->directorypermissions);
161 }
162 $configphp .= '$CFG->directorypermissions = ' . $chmod . ';' . PHP_EOL . PHP_EOL;
dc47d704 163
6189e63d 164 $configphp .= '$CFG->passwordsaltmain = '.var_export(complex_random_string(), true) . ';' . PHP_EOL . PHP_EOL;
4c1ba3ff 165
3b5ff37f 166 $configphp .= 'require_once(dirname(__FILE__) . \'/lib/setup.php\');' . PHP_EOL . PHP_EOL;
6189e63d
DM
167 $configphp .= '// There is no php closing tag in this file,' . PHP_EOL;
168 $configphp .= '// it is intentional because it prevents trailing whitespace problems!' . PHP_EOL;
dc47d704 169
170 return $configphp;
171}
172
95feaf96 173/**
174 * Prints complete help page used during installation.
175 * Does not return.
226617ea 176 *
177 * @global object
95feaf96 178 * @param string $help
179 */
3b093310 180function install_print_help_page($help) {
3a915b06 181 global $CFG, $OUTPUT; //TODO: MUST NOT USE $OUTPUT HERE!!!
3b093310 182
183 @header('Content-Type: text/html; charset=UTF-8');
184 @header('Cache-Control: no-store, no-cache, must-revalidate');
185 @header('Cache-Control: post-check=0, pre-check=0', false);
186 @header('Pragma: no-cache');
187 @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
188 @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
189
190 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
191 echo '<html dir="'.(right_to_left() ? 'rtl' : 'ltr').'">
192 <head>
78946b9b 193 <link rel="shortcut icon" href="theme/standard/pix/favicon.ico" />
3b093310 194 <link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.'/install.php?css=1" />
195 <title>'.get_string('installation','install').'</title>
196 <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
197 <meta http-equiv="pragma" content="no-cache" />
198 <meta http-equiv="expires" content="0" />';
199
200 echo '</head><body>';
201 switch ($help) {
202 case 'phpversionhelp':
203 print_string($help, 'install', phpversion());
204 break;
205 case 'memorylimithelp':
206 print_string($help, 'install', get_memory_limit());
207 break;
208 default:
209 print_string($help, 'install');
2f13f94c 210 }
3a915b06 211 echo $OUTPUT->close_window_button(); //TODO: MUST NOT USE $OUTPUT HERE!!!
3b093310 212 echo '</body></html>';
213 die;
2f13f94c 214}
215
95feaf96 216/**
8bb70111 217 * Prints installation page header, we can no use weblib yet in installer.
226617ea 218 *
219 * @global object
95feaf96 220 * @param array $config
221 * @param string $stagename
222 * @param string $heading
223 * @param string $stagetext
224 * @return void
225 */
3b093310 226function install_print_header($config, $stagename, $heading, $stagetext) {
227 global $CFG;
2f13f94c 228
3b093310 229 @header('Content-Type: text/html; charset=UTF-8');
230 @header('Cache-Control: no-store, no-cache, must-revalidate');
231 @header('Cache-Control: post-check=0, pre-check=0', false);
232 @header('Pragma: no-cache');
233 @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
234 @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
235
236 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
237 echo '<html dir="'.(right_to_left() ? 'rtl' : 'ltr').'">
238 <head>
78946b9b 239 <link rel="shortcut icon" href="theme/standard/pix/favicon.ico" />';
3b093310 240
90723839 241 $sheets = array('pagelayout','core');
3b093310 242 $csss = array();
243 foreach ($sheets as $sheet) {
90723839 244 $csss[] = $CFG->wwwroot.'/theme/base/style/'.$sheet.'.css';
3b093310 245 }
90723839 246 $sheets = array('core', 'css3');
3b093310 247 foreach ($sheets as $sheet) {
90723839 248 $csss[] = $CFG->wwwroot.'/theme/standard/style/'.$sheet.'.css';
2f13f94c 249 }
3b093310 250 foreach ($csss as $css) {
251 echo '<link rel="stylesheet" type="text/css" href="'.$css.'" />'."\n";
252 }
253
254 echo '<link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.'/install.php?css=1" />
9ace5094 255 <title>'.get_string('installation','install').' - Moodle '.$CFG->target_release.'</title>
3b093310 256 <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
257 <meta http-equiv="pragma" content="no-cache" />
258 <meta http-equiv="expires" content="0" />';
259
260 echo '</head><body class="notloggedin">
261 <div id="page" class="stage'.$config->stage.'">
90723839
SH
262 <div id="page-header">
263 <div id="header" class=" clearfix">
264 <h1 class="headermain">'.get_string('installation','install').'</h1>
265 <div class="headermenu">&nbsp;</div>
266 </div>
267 <div class="navbar clearfix">
268 <div class="breadcrumb">
269 <ul><li class="first">'.$stagename.'</li></ul>
270 </div>
271 <div class="navbutton">&nbsp;</div>
3b093310 272 </div>
3b093310 273 </div>
274 <!-- END OF HEADER -->
275 <div id="installdiv">';
2f13f94c 276
3b093310 277 echo '<h2>'.$heading.'</h2>';
278
279 if ($stagetext !== '') {
280 echo '<div class="stage generalbox box">';
281 echo $stagetext;
282 echo '</div>';
283 }
284 // main
285 echo '<form id="installform" method="post" action="install.php"><fieldset>';
286 foreach ($config as $name=>$value) {
287 echo '<input type="hidden" name="'.$name.'" value="'.s($value).'" />';
288 }
2f13f94c 289}
290
95feaf96 291/**
292 * Prints installation page header, we can no use weblib yet in isntaller.
226617ea 293 *
294 * @global object
95feaf96 295 * @param array $config
296 * @param bool $reload print reload button instead of next
297 * @return void
298 */
3b093310 299function install_print_footer($config, $reload=false) {
300 global $CFG;
301
302 if ($config->stage > INSTALL_WELCOME) {
4d928665 303 $first = '<input type="submit" id="previousbutton" name="previous" value="&laquo; '.s(get_string('previous')).'" />';
3b093310 304 } else {
85ed076b 305 $first = '<input type="submit" id="previousbutton" name="next" value="'.s(get_string('reload')).'" />';
4d928665 306 $first .= '<script type="text/javascript">
307//<![CDATA[
308 var first = document.getElementById("previousbutton");
309 first.style.visibility = "hidden";
310//]]>
311</script>
312';
3b093310 313 }
314
315 if ($reload) {
85ed076b 316 $next = '<input type="submit" id="nextbutton" name="next" value="'.s(get_string('reload')).'" />';
3b093310 317 } else {
4d928665 318 $next = '<input type="submit" id="nextbutton" name="next" value="'.s(get_string('next')).' &raquo;" />';
3b093310 319 }
320
321 echo '</fieldset><fieldset id="nav_buttons">'.$first.$next.'</fieldset>';
322
323 $homelink = '<div class="sitelink">'.
9ace5094 324 '<a title="Moodle '. $CFG->target_release .'" href="http://docs.moodle.org/en/Administrator_documentation" onclick="this.target=\'_blank\'">'.
3b093310 325 '<img style="width:100px;height:30px" src="pix/moodlelogo.gif" alt="moodlelogo" /></a></div>';
326
327 echo '</form></div>';
328 echo '<div id="footer"><hr />'.$homelink.'</div>';
329 echo '</div></body></html>';
330}
331
332
95feaf96 333/**
334 * Prints css needed on installation page, tries to look like the rest of installation.
335 * Does not return.
226617ea 336 *
337 * @global object
95feaf96 338 */
3b093310 339function install_css_styles() {
340 global $CFG;
341
342 @header('Content-type: text/css'); // Correct MIME type
343 @header('Cache-Control: no-store, no-cache, must-revalidate');
344 @header('Cache-Control: post-check=0, pre-check=0', false);
345 @header('Pragma: no-cache');
346 @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
347 @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
348
da0c0e25 349//TODO: add rtl support here, make it match new default theme MDL-21149
3b093310 350
351 echo '
352
353h2 {
354 text-align:center;
355}
356
357#installdiv {
358 width: 800px;
359 margin-left:auto;
360 margin-right:auto;
361}
362
363#installdiv dt {
364 font-weight: bold;
365}
366
367#installdiv dd {
368 padding-bottom: 0.5em;
369}
370
371.stage {
372 margin-top: 2em;
373 margin-bottom: 2em;
374 width: 100%;
375 padding:25px;
376}
377
378#installform {
379 width: 100%;
380}
381
382#nav_buttons input {
383 margin: 5px;
384}
385
386#envresult {
387 text-align:left;
388 width: auto;
389 margin-left:10em;
390}
391
392#envresult dd {
393 color: red;
394}
395
396.formrow {
397 clear:both;
398 text-align:left;
399 padding: 8px;
400}
401
402.formrow label.formlabel {
403 display:block;
404 float:left;
405 width: 260px;
406 margin-right:5px;
407 text-align:right;
408}
409
410.formrow .forminput {
411 display:block;
412 float:left;
413}
414
415fieldset {
416 text-align:center;
417 border:none;
418}
419
420.hint {
421 display:block;
422 clear:both;
423 padding-left: 265px;
424 color: red;
425}
426
427.configphp {
428 text-align:left;
429 background-color:white;
430 padding:1em;
431 width:95%;
432}
433
64c368e3 434.stage6 .stage {
3b093310 435 font-weight: bold;
436 color: red;
437}
438
439';
440
441 die;
2f13f94c 442}
b7315f35
PS
443
444/**
445 * Install Moodle DB,
446 * config.php must exist, there must not be any tables in db yet.
447 *
448 * @param array $options adminpass is mandatory
449 * @param bool $interactive
450 * @return void
451 */
452function install_cli_database(array $options, $interactive) {
453 global $CFG, $DB;
454 require_once($CFG->libdir.'/environmentlib.php');
455 require_once($CFG->libdir.'/upgradelib.php');
456
457 // show as much debug as possible
458 @error_reporting(1023);
459 @ini_set('display_errors', '1');
460 $CFG->debug = 38911;
461 $CFG->debugdisplay = true;
462
463 $CFG->version = '';
464 $CFG->release = '';
465
466 // read $version and $release
467 require($CFG->dirroot.'/version.php');
468
469 if ($DB->get_tables() ) {
470 cli_error(get_string('clitablesexist', 'install'));
471 }
472
473 if (empty($options['adminpass'])) {
474 cli_error('Missing required admin password');
475 }
476
477 // test environment first
478 if (!check_moodle_environment($version, $environment_results, false, ENV_SELECT_RELEASE)) {
479 $errors = environment_get_errors($environment_results);
480 cli_heading(get_string('environment', 'admin'));
481 foreach ($errors as $error) {
482 list($info, $report) = $error;
483 echo "!! $info !!\n$report\n\n";
484 }
485 //remove config.php, we do not want half finished upgrades!
486 unlink($configfile);
487 exit(1);
488 }
489
490 if (!$DB->setup_is_unicodedb()) {
491 if (!$DB->change_db_encoding()) {
492 // If could not convert successfully, throw error, and prevent installation
493 cli_error(get_string('unicoderequired', 'admin'));
494 }
495 }
496
497 if ($interactive) {
498 cli_separator();
499 cli_heading(get_string('databasesetup'));
500 }
501
502 // install core
503 install_core($version, true);
504 set_config('release', $release);
505
506 // install all plugins types, local, etc.
507 upgrade_noncore(true);
508
509 // set up admin user password
510 $DB->set_field('user', 'password', hash_internal_user_password($options['adminpass']), array('username' => 'admin'));
511
512 // rename admin username if needed
513 if (isset($options['adminuser']) and $options['adminuser'] !== 'admin' and $options['adminuser'] !== 'guest') {
514 $DB->set_field('user', 'username', $options['adminuser'], array('username' => 'admin'));
515 }
516
517 // indicate that this site is fully configured
518 set_config('rolesactive', 1);
519 upgrade_finished();
520
521 // log in as admin - we need do anything when applying defaults
522 $admins = get_admins();
523 $admin = reset($admins);
524 session_set_user($admin);
525 message_set_default_message_preferences($admin);
526
527 // apply all default settings, do it twice to fill all defaults - some settings depend on other setting
528 admin_apply_default_settings(NULL, true);
529 admin_apply_default_settings(NULL, true);
530 set_config('registerauth', '');
531
532}