Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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/>.
  17  
  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   */
  31  
  32  define('CLI_SCRIPT', true);
  33  
  34  // extra execution prevention - we can not just require config.php here
  35  if (isset($_SERVER['REMOTE_ADDR'])) {
  36      exit(1);
  37  }
  38  
  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  }
  44  
  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.
  49  
  50  Site defaults may be changed via local/defaults.php.
  51  
  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
  86  
  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
  90  
  91  
  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      }
 100  }
 101  
 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'));
 108  
 109      if ($options['help']) {
 110          echo $help;
 111          echo "\n\n";
 112      }
 113  
 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      }
 119  }
 120  
 121  $olddir = getcwd();
 122  
 123  // change directory so that includes below work properly
 124  chdir(dirname($_SERVER['argv'][0]));
 125  
 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);
 130  }
 131  date_default_timezone_set(@date_default_timezone_get());
 132  
 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');
 138  
 139  /** Used by library scripts to check they are being called by Moodle */
 140  define('MOODLE_INTERNAL', true);
 141  
 142  // Disables all caching.
 143  define('CACHE_DISABLE_ALL', true);
 144  
 145  define('PHPUNIT_TEST', false);
 146  
 147  define('IGNORE_COMPONENT_CACHE', true);
 148  
 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();
 152  
 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;
 169  
 170  $parts = explode('/', str_replace('\\', '/', dirname(__DIR__)));
 171  $CFG->admin                = array_pop($parts);
 172  
 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'));
 176  
 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');
 192  
 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');
 199  }
 200  
 201  require($CFG->dirroot.'/version.php');
 202  $CFG->target_release = $release;
 203  
 204  \core\session\manager::init_empty_session();
 205  global $SESSION;
 206  global $USER;
 207  
 208  global $COURSE;
 209  $COURSE = new stdClass();
 210  $COURSE->id = 1;
 211  
 212  global $SITE;
 213  $SITE = $COURSE;
 214  define('SITEID', 1);
 215  
 216  //Database types
 217  $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
 218                     'auroramysql' => moodle_database::get_driver_instance('auroramysql', 'native'),
 219                     'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
 220                     'pgsql'  => moodle_database::get_driver_instance('pgsql',  'native'),
 221                     'oci'    => moodle_database::get_driver_instance('oci',    'native'),
 222                     'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // MS SQL*Server PHP driver
 223                    );
 224  foreach ($databases as $type=>$database) {
 225      if ($database->driver_installed() !== true) {
 226          unset($databases[$type]);
 227      }
 228  }
 229  if (empty($databases)) {
 230      $defaultdb = '';
 231  } else {
 232      reset($databases);
 233      $defaultdb = key($databases);
 234  }
 235  
 236  // now get cli options
 237  list($options, $unrecognized) = cli_get_params(
 238      array(
 239          'chmod'             => isset($distro->directorypermissions) ? sprintf('%04o',$distro->directorypermissions) : '2777', // let distros set dir permissions
 240          'lang'              => $CFG->lang,
 241          'wwwroot'           => '',
 242          'dataroot'          => empty($distro->dataroot) ? str_replace('\\', '/', dirname(dirname(dirname(__DIR__))).'/moodledata'): $distro->dataroot, // initialised later after including libs or by distro
 243          'dbtype'            => empty($distro->dbtype) ? $defaultdb : $distro->dbtype, // let distro skip dbtype selection
 244          'dbhost'            => empty($distro->dbhost) ? 'localhost' : $distro->dbhost, // let distros set dbhost
 245          'dbname'            => 'moodle',
 246          'dbuser'            => empty($distro->dbuser) ? 'root' : $distro->dbuser, // let distros set dbuser
 247          'dbpass'            => '',
 248          'dbport'            => '',
 249          'dbsocket'          => '',
 250          'prefix'            => 'mdl_',
 251          'fullname'          => '',
 252          'shortname'         => '',
 253          'summary'           => '',
 254          'adminuser'         => 'admin',
 255          'adminpass'         => '',
 256          'adminemail'        => '',
 257          'upgradekey'        => '',
 258          'non-interactive'   => false,
 259          'agree-license'     => false,
 260          'allow-unstable'    => false,
 261          'skip-database'     => false,
 262          'help'              => false
 263      ),
 264      array(
 265          'h' => 'help'
 266      )
 267  );
 268  
 269  $interactive = empty($options['non-interactive']);
 270  $skipdatabase = $options['skip-database'];
 271  
 272  // set up language
 273  $lang = clean_param($options['lang'], PARAM_SAFEDIR);
 274  $languages = get_string_manager()->get_list_of_translations();
 275  if (array_key_exists($lang, $languages)) {
 276      $CFG->lang = $lang;
 277  }
 278  
 279  if ($unrecognized) {
 280      $unrecognized = implode("\n  ", $unrecognized);
 281      cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
 282  }
 283  
 284  if ($options['help']) {
 285      echo $help;
 286      die;
 287  }
 288  
 289  //Print header
 290  cli_logo();
 291  echo PHP_EOL;
 292  echo get_string('cliinstallheader', 'install', $CFG->target_release)."\n";
 293  
 294  //Fist select language
 295  if ($interactive) {
 296      cli_separator();
 297      // Do not put the langs into columns because it is not compatible with RTL.
 298      $default = $CFG->lang;
 299      cli_heading(get_string('chooselanguagehead', 'install'));
 300      if (array_key_exists($default, $languages)) {
 301          echo $default.' - '.$languages[$default]."\n";
 302      }
 303      if ($default !== 'en') {
 304          echo 'en - English (en)'."\n";
 305      }
 306      echo '? - '.get_string('availablelangs', 'install')."\n";
 307      $prompt = get_string('clitypevaluedefault', 'admin', $CFG->lang);
 308      $error = '';
 309      do {
 310          echo $error;
 311          $input = cli_input($prompt, $default);
 312  
 313          if ($input === '?') {
 314              echo implode("\n", $languages)."\n";
 315              $error = "\n";
 316  
 317          } else {
 318              $input = clean_param($input, PARAM_SAFEDIR);
 319  
 320              if (!array_key_exists($input, $languages)) {
 321                  $error = get_string('cliincorrectvalueretry', 'admin')."\n";
 322              } else {
 323                  $error = '';
 324              }
 325          }
 326      } while ($error !== '');
 327      $CFG->lang = $input;
 328  } else {
 329      // already selected and verified
 330  }
 331  
 332  // Set directorypermissions first
 333  $chmod = octdec(clean_param($options['chmod'], PARAM_INT));
 334  if ($interactive) {
 335      cli_separator();
 336      cli_heading(get_string('datarootpermission', 'install'));
 337      $prompt = get_string('clitypevaluedefault', 'admin', decoct($chmod));
 338      $error = '';
 339      do {
 340          echo $error;
 341          $input = cli_input($prompt, decoct($chmod));
 342          $input = octdec(clean_param($input, PARAM_INT));
 343          if (empty($input)) {
 344              $error = get_string('cliincorrectvalueretry', 'admin')."\n";
 345          } else {
 346              $error = '';
 347          }
 348      } while ($error !== '');
 349      $chmod = $input;
 350  
 351  } else {
 352      if (empty($chmod)) {
 353          $a = (object)array('option' => 'chmod', 'value' => decoct($chmod));
 354          cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 355      }
 356  }
 357  $CFG->directorypermissions = $chmod;
 358  $CFG->filepermissions      = ($CFG->directorypermissions & 0666);
 359  $CFG->umaskpermissions     = (($CFG->directorypermissions & 0777) ^ 0777);
 360  
 361  //We need wwwroot before we test dataroot
 362  $wwwroot = clean_param($options['wwwroot'], PARAM_URL);
 363  $wwwroot = trim($wwwroot, '/');
 364  if ($interactive) {
 365      cli_separator();
 366      cli_heading(get_string('wwwroot', 'install'));
 367      if (strpos($wwwroot, 'http') === 0) {
 368          $prompt = get_string('clitypevaluedefault', 'admin', $wwwroot);
 369      } else {
 370          $wwwroot = null;
 371          $prompt = get_string('clitypevalue', 'admin');
 372      }
 373      $error = '';
 374      do {
 375          echo $error;
 376          $input = cli_input($prompt, $wwwroot);
 377          $input = clean_param($input, PARAM_URL);
 378          $input = trim($input, '/');
 379          if (strpos($input, 'http') !== 0) {
 380              $error = get_string('cliincorrectvalueretry', 'admin')."\n";
 381          } else {
 382              $error = '';
 383          }
 384      } while ($error !== '');
 385      $wwwroot = $input;
 386  
 387  } else {
 388      if (strpos($wwwroot, 'http') !== 0) {
 389          $a = (object)array('option'=>'wwwroot', 'value'=>$wwwroot);
 390          cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 391      }
 392  }
 393  $CFG->wwwroot       = $wwwroot;
 394  $CFG->httpswwwroot  = $CFG->wwwroot;
 395  
 396  //We need dataroot before lang download
 397  $CFG->dataroot = $options['dataroot'];
 398  if ($interactive) {
 399      cli_separator();
 400      $i=0;
 401      while(is_dataroot_insecure()) {
 402          $parrent = dirname($CFG->dataroot);
 403          $i++;
 404          if ($parrent == '/' or $parrent == '.' or preg_match('/^[a-z]:\\\?$/i', $parrent) or ($i > 100)) {
 405              $CFG->dataroot = ''; //can not find secure location for dataroot
 406              break;
 407          }
 408          $CFG->dataroot = dirname($parrent).'/moodledata';
 409      }
 410      cli_heading(get_string('dataroot', 'install'));
 411      $error = '';
 412      do {
 413          if ($CFG->dataroot !== '') {
 414              $prompt = get_string('clitypevaluedefault', 'admin', $CFG->dataroot);
 415          } else {
 416              $prompt = get_string('clitypevalue', 'admin');
 417          }
 418          echo $error;
 419          $CFG->dataroot = cli_input($prompt, $CFG->dataroot);
 420          if ($CFG->dataroot === '') {
 421              $error = get_string('cliincorrectvalueretry', 'admin')."\n";
 422          } else if (is_dataroot_insecure()) {
 423              $CFG->dataroot = '';
 424              $error = get_string('pathsunsecuredataroot', 'install')."\n";
 425          } else {
 426              if (install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
 427                  $error = '';
 428              } else {
 429                  $a = (object)array('dataroot' => $CFG->dataroot);
 430                  $error = get_string('pathserrcreatedataroot', 'install', $a)."\n";
 431              }
 432          }
 433  
 434      } while ($error !== '');
 435  
 436  } else {
 437      if (is_dataroot_insecure()) {
 438          cli_error(get_string('pathsunsecuredataroot', 'install'));
 439      }
 440      if (!install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
 441          $a = (object)array('dataroot' => $CFG->dataroot);
 442          cli_error(get_string('pathserrcreatedataroot', 'install', $a));
 443      }
 444  }
 445  $CFG->tempdir       = $CFG->dataroot.'/temp';
 446  $CFG->backuptempdir = $CFG->tempdir.'/backup';
 447  $CFG->cachedir      = $CFG->dataroot.'/cache';
 448  $CFG->localcachedir = $CFG->dataroot.'/localcache';
 449  
 450  // download required lang packs
 451  if ($CFG->lang !== 'en') {
 452      $installer = new lang_installer($CFG->lang);
 453      $results = $installer->run();
 454      foreach ($results as $langcode => $langstatus) {
 455          if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) {
 456              $a       = new stdClass();
 457              $a->url  = $installer->lang_pack_url($langcode);
 458              $a->dest = $CFG->dataroot.'/lang';
 459              cli_problem(get_string('remotedownloaderror', 'error', $a));
 460          }
 461      }
 462  }
 463  
 464  // switch the string_manager instance to stop using install/lang/
 465  $CFG->early_install_lang = false;
 466  $CFG->langotherroot      = $CFG->dataroot.'/lang';
 467  $CFG->langlocalroot      = $CFG->dataroot.'/lang';
 468  get_string_manager(true);
 469  
 470  // make sure we are installing stable release or require a confirmation
 471  if (isset($maturity)) {
 472      if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) {
 473          $maturitylevel = get_string('maturity'.$maturity, 'admin');
 474  
 475          if ($interactive) {
 476              cli_separator();
 477              cli_heading(get_string('notice'));
 478              echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL;
 479              echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL;
 480              echo get_string('continue') . PHP_EOL;
 481              $prompt = get_string('cliyesnoprompt', 'admin');
 482              $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
 483              if ($input == get_string('clianswerno', 'admin')) {
 484                  exit(1);
 485              }
 486          } else {
 487              cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel));
 488              cli_error(get_string('maturityallowunstable', 'admin'));
 489          }
 490      }
 491  }
 492  
 493  // ask for db type - show only drivers available
 494  if ($interactive) {
 495      $options['dbtype'] = strtolower($options['dbtype']);
 496      cli_separator();
 497      cli_heading(get_string('databasetypehead', 'install'));
 498      foreach ($databases as $type=>$database) {
 499          echo " $type \n";
 500      }
 501      if (!empty($databases[$options['dbtype']])) {
 502          $prompt = get_string('clitypevaluedefault', 'admin', $options['dbtype']);
 503      } else {
 504          $prompt = get_string('clitypevalue', 'admin');
 505      }
 506      $CFG->dbtype = cli_input($prompt, $options['dbtype'], array_keys($databases));
 507  
 508  } else {
 509      if (empty($databases[$options['dbtype']])) {
 510          $a = (object)array('option'=>'dbtype', 'value'=>$options['dbtype']);
 511          cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 512      }
 513      $CFG->dbtype = $options['dbtype'];
 514  }
 515  $database = $databases[$CFG->dbtype];
 516  
 517  
 518  // We cannot do any validation until all DB connection data is provided.
 519  $hintdatabase = '';
 520  do {
 521      echo $hintdatabase;
 522  
 523      // Ask for db host.
 524      if ($interactive) {
 525          cli_separator();
 526          cli_heading(get_string('databasehost', 'install'));
 527          if ($options['dbhost'] !== '') {
 528              $prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
 529          } else {
 530              $prompt = get_string('clitypevalue', 'admin');
 531          }
 532          $CFG->dbhost = cli_input($prompt, $options['dbhost']);
 533  
 534      } else {
 535          $CFG->dbhost = $options['dbhost'];
 536      }
 537  
 538      // Ask for db name.
 539      if ($interactive) {
 540          cli_separator();
 541          cli_heading(get_string('databasename', 'install'));
 542          if ($options['dbname'] !== '') {
 543              $prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
 544          } else {
 545              $prompt = get_string('clitypevalue', 'admin');
 546          }
 547          $CFG->dbname = cli_input($prompt, $options['dbname']);
 548  
 549      } else {
 550          $CFG->dbname = $options['dbname'];
 551      }
 552  
 553      // Ask for db prefix.
 554      if ($interactive) {
 555          cli_separator();
 556          cli_heading(get_string('dbprefix', 'install'));
 557          //TODO: solve somehow the prefix trouble for oci.
 558          if ($options['prefix'] !== '') {
 559              $prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
 560          } else {
 561              $prompt = get_string('clitypevalue', 'admin');
 562          }
 563          $CFG->prefix = cli_input($prompt, $options['prefix']);
 564  
 565      } else {
 566          $CFG->prefix = $options['prefix'];
 567      }
 568  
 569      // Ask for db port.
 570      if ($interactive) {
 571          cli_separator();
 572          cli_heading(get_string('databaseport', 'install'));
 573          $prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
 574          $CFG->dboptions['dbport'] = (int) cli_input($prompt, $options['dbport']);
 575  
 576      } else {
 577          $CFG->dboptions['dbport'] = (int) $options['dbport'];
 578      }
 579      if ($CFG->dboptions['dbport'] <= 0) {
 580          $CFG->dboptions['dbport'] = '';
 581      }
 582  
 583      // Ask for db socket.
 584      if ($CFG->ostype === 'WINDOWS') {
 585          $CFG->dboptions['dbsocket'] = '';
 586  
 587      } else if ($interactive and empty($CFG->dboptions['dbport'])) {
 588          cli_separator();
 589          cli_heading(get_string('databasesocket', 'install'));
 590          $prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
 591          $CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
 592  
 593      } else {
 594          $CFG->dboptions['dbsocket'] = $options['dbsocket'];
 595      }
 596  
 597      // Ask for db user.
 598      if ($interactive) {
 599          cli_separator();
 600          cli_heading(get_string('databaseuser', 'install'));
 601          if ($options['dbuser'] !== '') {
 602              $prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
 603          } else {
 604              $prompt = get_string('clitypevalue', 'admin');
 605          }
 606          $CFG->dbuser = cli_input($prompt, $options['dbuser']);
 607  
 608      } else {
 609          $CFG->dbuser = $options['dbuser'];
 610      }
 611  
 612      // Ask for db password.
 613      if ($interactive) {
 614          cli_separator();
 615          cli_heading(get_string('databasepass', 'install'));
 616  
 617          if ($options['dbpass'] !== '') {
 618              $prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
 619          } else {
 620              $prompt = get_string('clitypevalue', 'admin');
 621          }
 622  
 623          $CFG->dbpass = cli_input($prompt, $options['dbpass']);
 624          if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation.
 625              $distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
 626                      array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']),
 627                      $distro);
 628          }
 629          $hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
 630                  array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
 631  
 632      } else {
 633          $CFG->dbpass = $options['dbpass'];
 634          $hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
 635                  array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
 636          if ($hintdatabase !== '') {
 637              cli_error(get_string('dbconnectionerror', 'install'));
 638          }
 639      }
 640  } while ($hintdatabase !== '');
 641  
 642  // If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
 643  // These fields will be requested during the database install part.
 644  if (!$skipdatabase) {
 645      // Ask for fullname.
 646      if ($interactive) {
 647          cli_separator();
 648          cli_heading(get_string('fullsitename', 'moodle'));
 649  
 650          if ($options['fullname'] !== '') {
 651              $prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
 652          } else {
 653              $prompt = get_string('clitypevalue', 'admin');
 654          }
 655  
 656          do {
 657              $options['fullname'] = cli_input($prompt, $options['fullname']);
 658          } while (empty($options['fullname']));
 659      } else {
 660          if (empty($options['fullname'])) {
 661              $a = (object)['option' => 'fullname', 'value' => $options['fullname']];
 662              cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 663          }
 664      }
 665  
 666      // Ask for shortname.
 667      if ($interactive) {
 668          cli_separator();
 669          cli_heading(get_string('shortsitename', 'moodle'));
 670  
 671          if ($options['shortname'] !== '') {
 672              $prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
 673          } else {
 674              $prompt = get_string('clitypevalue', 'admin');
 675          }
 676  
 677          do {
 678              $options['shortname'] = cli_input($prompt, $options['shortname']);
 679          } while (empty($options['shortname']));
 680      } else {
 681          if (empty($options['shortname'])) {
 682              $a = (object)['option' => 'shortname', 'value' => $options['shortname']];
 683              cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 684          }
 685      }
 686  
 687      // Ask for admin user name.
 688      if ($interactive) {
 689          cli_separator();
 690          cli_heading(get_string('cliadminusername', 'install'));
 691          if (!empty($options['adminuser'])) {
 692              $prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
 693          } else {
 694              $prompt = get_string('clitypevalue', 'admin');
 695          }
 696          do {
 697              $options['adminuser'] = cli_input($prompt, $options['adminuser']);
 698          } while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
 699      } else {
 700          if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
 701              $a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
 702              cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 703          }
 704      }
 705  
 706      // Ask for admin user password.
 707      if ($interactive) {
 708          cli_separator();
 709          cli_heading(get_string('cliadminpassword', 'install'));
 710          $prompt = get_string('clitypevalue', 'admin');
 711          do {
 712              $options['adminpass'] = cli_input($prompt);
 713          } while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
 714      } else {
 715          if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
 716              $a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
 717              cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 718          }
 719      }
 720  
 721      // Ask for the admin email address.
 722      if ($interactive) {
 723          cli_separator();
 724          cli_heading(get_string('cliadminemail', 'install'));
 725          $prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
 726          $options['adminemail'] = cli_input($prompt, $options['adminemail']);
 727      }
 728  
 729      // Validate that the address provided was an e-mail address.
 730      if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
 731          $a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
 732          cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
 733      }
 734  }
 735  
 736  // Ask for the upgrade key.
 737  if ($interactive) {
 738      cli_separator();
 739      cli_heading(get_string('upgradekeyset', 'admin'));
 740      if ($options['upgradekey'] !== '') {
 741          $prompt = get_string('clitypevaluedefault', 'admin', $options['upgradekey']);
 742          $options['upgradekey'] = cli_input($prompt, $options['upgradekey']);
 743      } else {
 744          $prompt = get_string('clitypevalue', 'admin');
 745          $options['upgradekey'] = cli_input($prompt);
 746      }
 747  }
 748  
 749  // Set the upgrade key if it was provided.
 750  if ($options['upgradekey'] !== '') {
 751      $CFG->upgradekey = $options['upgradekey'];
 752  }
 753  
 754  // The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
 755  // the license again in the database install part.
 756  if (!$skipdatabase) {
 757      if ($interactive) {
 758          if (!$options['agree-license']) {
 759              cli_separator();
 760              cli_heading(get_string('copyrightnotice'));
 761              echo "Moodle  - Modular Object-Oriented Dynamic Learning Environment\n";
 762              echo get_string('gpl3')."\n\n";
 763              echo get_string('doyouagree')."\n";
 764              $prompt = get_string('cliyesnoprompt', 'admin');
 765              $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
 766              if ($input == get_string('clianswerno', 'admin')) {
 767                  exit(1);
 768              }
 769          }
 770      } else {
 771          if (!$options['agree-license'] && !$skipdatabase) {
 772              cli_error(get_string('climustagreelicense', 'install'));
 773          }
 774      }
 775  }
 776  
 777  // Finally we have all info needed for config.php
 778  $configphp = install_generate_configphp($database, $CFG);
 779  umask(0137);
 780  if (($fh = fopen($configfile, 'w')) !== false) {
 781      fwrite($fh, $configphp);
 782      fclose($fh);
 783  }
 784  
 785  if (!file_exists($configfile)) {
 786      cli_error('Can not create config file.');
 787  }
 788  
 789  // remember selected language
 790  $installlang = $CFG->lang;
 791  // return back to original dir before executing setup.php which changes the dir again
 792  chdir($olddir);
 793  // We have config.php, it is a real php script from now on :-)
 794  require($configfile);
 795  
 796  // use selected language
 797  $CFG->lang = $installlang;
 798  $SESSION->lang = $CFG->lang;
 799  
 800  require("$CFG->dirroot/version.php");
 801  
 802  // Test environment first.
 803  require_once($CFG->libdir . '/environmentlib.php');
 804  list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
 805  if (!$envstatus) {
 806      $errors = environment_get_errors($environment_results);
 807      cli_heading(get_string('environment', 'admin'));
 808      foreach ($errors as $error) {
 809          list($info, $report) = $error;
 810          echo "!! $info !!\n$report\n\n";
 811      }
 812      exit(1);
 813  }
 814  
 815  // Test plugin dependencies.
 816  $failed = array();
 817  if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
 818      cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
 819      cli_error(get_string('pluginschecktodo', 'admin'));
 820  }
 821  
 822  if (!$skipdatabase) {
 823      install_cli_database($options, $interactive);
 824      // This needs to happen at the end to ensure it occurs after all caches
 825      // have been purged for the last time.
 826      // This will build a cached version of the current theme for the user
 827      // to immediately start browsing the site.
 828      require_once($CFG->libdir.'/upgradelib.php');
 829      upgrade_themes();
 830  } else {
 831      echo get_string('cliskipdatabase', 'install')."\n";
 832  }
 833  
 834  echo get_string('cliinstallfinished', 'install')."\n";
 835  exit(0); // 0 means success