| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 require_once './includes/install.inc'; 4 5 define('MAINTENANCE_MODE', 'install'); 6 7 /** 8 * The Drupal installation happens in a series of steps. We begin by verifying 9 * that the current environment meets our minimum requirements. We then go 10 * on to verify that settings.php is properly configured. From there we 11 * connect to the configured database and verify that it meets our minimum 12 * requirements. Finally we can allow the user to select an installation 13 * profile and complete the installation process. 14 * 15 * @param $phase 16 * The installation phase we should proceed to. 17 */ 18 function install_main() { 19 require_once './includes/bootstrap.inc'; 20 drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); 21 22 // This must go after drupal_bootstrap(), which unsets globals! 23 global $profile, $install_locale, $conf; 24 25 require_once './modules/system/system.install'; 26 require_once './includes/file.inc'; 27 28 // Ensure correct page headers are sent (e.g. caching) 29 drupal_page_header(); 30 31 // Set up $language, so t() caller functions will still work. 32 drupal_init_language(); 33 34 // Load module basics (needed for hook invokes). 35 include_once './includes/module.inc'; 36 $module_list['system']['filename'] = 'modules/system/system.module'; 37 $module_list['filter']['filename'] = 'modules/filter/filter.module'; 38 module_list(TRUE, FALSE, FALSE, $module_list); 39 drupal_load('module', 'system'); 40 drupal_load('module', 'filter'); 41 42 // Install profile chosen, set the global immediately. 43 // This needs to be done before the theme cache gets 44 // initialized in drupal_maintenance_theme(). 45 if (!empty($_GET['profile'])) { 46 $profile = preg_replace('/[^a-zA-Z_0-9]/', '', $_GET['profile']); 47 } 48 49 // Set up theme system for the maintenance page. 50 drupal_maintenance_theme(); 51 52 // Check existing settings.php. 53 $verify = install_verify_settings(); 54 55 if ($verify) { 56 // Since we have a database connection, we use the normal cache system. 57 // This is important, as the installer calls into the Drupal system for 58 // the clean URL checks, so we should maintain the cache properly. 59 require_once './includes/cache.inc'; 60 $conf['cache_inc'] = './includes/cache.inc'; 61 62 // Establish a connection to the database. 63 require_once './includes/database.inc'; 64 db_set_active(); 65 66 // Check if Drupal is installed. 67 $task = install_verify_drupal(); 68 if ($task == 'done') { 69 install_already_done_error(); 70 } 71 } 72 else { 73 // Since no persistent storage is available yet, and functions that check 74 // for cached data will fail, we temporarily replace the normal cache 75 // system with a stubbed-out version that short-circuits the actual 76 // caching process and avoids any errors. 77 require_once './includes/cache-install.inc'; 78 $conf['cache_inc'] = './includes/cache-install.inc'; 79 80 $task = NULL; 81 } 82 83 // No profile was passed in GET, ask the user. 84 if (empty($_GET['profile'])) { 85 if ($profile = install_select_profile()) { 86 install_goto("install.php?profile=$profile"); 87 } 88 else { 89 install_no_profile_error(); 90 } 91 } 92 93 // Load the profile. 94 require_once "./profiles/$profile/$profile.profile"; 95 96 // Locale selection 97 if (!empty($_GET['locale'])) { 98 $install_locale = preg_replace('/[^a-zA-Z_0-9\-]/', '', $_GET['locale']); 99 } 100 elseif (($install_locale = install_select_locale($profile)) !== FALSE) { 101 install_goto("install.php?profile=$profile&locale=$install_locale"); 102 } 103 104 // Tasks come after the database is set up 105 if (!$task) { 106 global $db_url; 107 108 if (!$verify && !empty($db_url)) { 109 // Do not install over a configured settings.php. 110 install_already_done_error(); 111 } 112 113 // Check the installation requirements for Drupal and this profile. 114 install_check_requirements($profile, $verify); 115 116 // Verify existence of all required modules. 117 $modules = drupal_verify_profile($profile, $install_locale); 118 119 // If any error messages are set now, it means a requirement problem. 120 $messages = drupal_set_message(); 121 if (!empty($messages['error'])) { 122 install_task_list('requirements'); 123 drupal_set_title(st('Requirements problem')); 124 print theme('install_page', ''); 125 exit; 126 } 127 128 // Change the settings.php information if verification failed earlier. 129 // Note: will trigger a redirect if database credentials change. 130 if (!$verify) { 131 install_change_settings($profile, $install_locale); 132 } 133 // The default lock implementation uses a database table, 134 // so we cannot use it for install, but we still need 135 // the API functions available. 136 require_once './includes/lock-install.inc'; 137 $conf['lock_inc'] = './includes/lock-install.inc'; 138 lock_init(); 139 140 // Install system.module. 141 drupal_install_system(); 142 // Save the list of other modules to install for the 'profile-install' 143 // task. variable_set() can be used now that system.module is installed 144 // and drupal is bootstrapped. 145 variable_set('install_profile_modules', array_diff($modules, array('system'))); 146 } 147 148 // The database is set up, turn to further tasks. 149 install_tasks($profile, $task); 150 } 151 152 /** 153 * Verify if Drupal is installed. 154 */ 155 function install_verify_drupal() { 156 // Read the variable manually using the @ so we don't trigger an error if it fails. 157 $result = @db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task'); 158 if ($result) { 159 return unserialize(db_result($result)); 160 } 161 } 162 163 /** 164 * Verify existing settings.php 165 */ 166 function install_verify_settings() { 167 global $db_prefix, $db_type, $db_url; 168 169 // Verify existing settings (if any). 170 if (!empty($db_url)) { 171 // We need this because we want to run form_get_errors. 172 include_once './includes/form.inc'; 173 174 $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url); 175 $db_user = urldecode($url['user']); 176 $db_pass = isset($url['pass']) ? urldecode($url['pass']) : NULL; 177 $db_host = urldecode($url['host']); 178 $db_port = isset($url['port']) ? urldecode($url['port']) : ''; 179 $db_path = ltrim(urldecode($url['path']), '/'); 180 $settings_file = './'. conf_path(FALSE, TRUE) .'/settings.php'; 181 182 $form_state = array(); 183 _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, $form_state); 184 if (!form_get_errors()) { 185 return TRUE; 186 } 187 } 188 return FALSE; 189 } 190 191 /** 192 * Configure and rewrite settings.php. 193 */ 194 function install_change_settings($profile = 'default', $install_locale = '') { 195 global $db_url, $db_type, $db_prefix; 196 197 $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url); 198 $db_user = isset($url['user']) ? urldecode($url['user']) : ''; 199 $db_pass = isset($url['pass']) ? urldecode($url['pass']) : ''; 200 $db_host = isset($url['host']) ? urldecode($url['host']) : ''; 201 $db_port = isset($url['port']) ? urldecode($url['port']) : ''; 202 $db_path = ltrim(urldecode($url['path']), '/'); 203 $conf_path = './'. conf_path(FALSE, TRUE); 204 $settings_file = $conf_path .'/settings.php'; 205 206 // We always need this because we want to run form_get_errors. 207 include_once './includes/form.inc'; 208 install_task_list('database'); 209 210 $output = drupal_get_form('install_settings_form', $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path); 211 drupal_set_title(st('Database configuration')); 212 print theme('install_page', $output); 213 exit; 214 } 215 216 217 /** 218 * Form API array definition for install_settings. 219 */ 220 function install_settings_form(&$form_state, $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path) { 221 if (empty($db_host)) { 222 $db_host = 'localhost'; 223 } 224 $db_types = drupal_detect_database_types(); 225 226 // If both 'mysql' and 'mysqli' are available, we disable 'mysql': 227 if (isset($db_types['mysqli'])) { 228 unset($db_types['mysql']); 229 } 230 231 if (count($db_types) == 0) { 232 $form['no_db_types'] = array( 233 '#value' => st('Your web server does not appear to support any common database types. Check with your hosting provider to see if they offer any databases that <a href="@drupal-databases">Drupal supports</a>.', array('@drupal-databases' => 'http://drupal.org/node/270#database')), 234 ); 235 } 236 else { 237 $form['basic_options'] = array( 238 '#type' => 'fieldset', 239 '#title' => st('Basic options'), 240 '#description' => '<p>'. st('To set up your @drupal database, enter the following information.', array('@drupal' => drupal_install_profile_name())) .'</p>', 241 ); 242 243 if (count($db_types) > 1) { 244 $form['basic_options']['db_type'] = array( 245 '#type' => 'radios', 246 '#title' => st('Database type'), 247 '#required' => TRUE, 248 '#options' => $db_types, 249 '#default_value' => ($db_type ? $db_type : current($db_types)), 250 '#description' => st('The type of database your @drupal data will be stored in.', array('@drupal' => drupal_install_profile_name())), 251 ); 252 $db_path_description = st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_name())); 253 } 254 else { 255 if (count($db_types) == 1) { 256 $db_types = array_values($db_types); 257 $form['basic_options']['db_type'] = array( 258 '#type' => 'hidden', 259 '#value' => $db_types[0], 260 ); 261 $db_path_description = st('The name of the %db_type database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%db_type' => $db_types[0], '@drupal' => drupal_install_profile_name())); 262 } 263 } 264 265 // Database name 266 $form['basic_options']['db_path'] = array( 267 '#type' => 'textfield', 268 '#title' => st('Database name'), 269 '#default_value' => $db_path, 270 '#size' => 45, 271 '#required' => TRUE, 272 '#description' => $db_path_description 273 ); 274 275 // Database username 276 $form['basic_options']['db_user'] = array( 277 '#type' => 'textfield', 278 '#title' => st('Database username'), 279 '#default_value' => $db_user, 280 '#size' => 45, 281 '#required' => TRUE, 282 ); 283 284 // Database username 285 $form['basic_options']['db_pass'] = array( 286 '#type' => 'password', 287 '#title' => st('Database password'), 288 '#default_value' => $db_pass, 289 '#size' => 45, 290 ); 291 292 $form['advanced_options'] = array( 293 '#type' => 'fieldset', 294 '#title' => st('Advanced options'), 295 '#collapsible' => TRUE, 296 '#collapsed' => TRUE, 297 '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider.") 298 ); 299 300 // Database host 301 $form['advanced_options']['db_host'] = array( 302 '#type' => 'textfield', 303 '#title' => st('Database host'), 304 '#default_value' => $db_host, 305 '#size' => 45, 306 // Hostnames can be 255 characters long. 307 '#maxlength' => 255, 308 '#required' => TRUE, 309 '#description' => st('If your database is located on a different server, change this.'), 310 ); 311 312 // Database port 313 $form['advanced_options']['db_port'] = array( 314 '#type' => 'textfield', 315 '#title' => st('Database port'), 316 '#default_value' => $db_port, 317 '#size' => 45, 318 // The maximum port number is 65536, 5 digits. 319 '#maxlength' => 5, 320 '#description' => st('If your database server is listening to a non-standard port, enter its number.'), 321 ); 322 323 // Table prefix 324 $prefix = ($profile == 'default') ? 'drupal_' : $profile .'_'; 325 $form['advanced_options']['db_prefix'] = array( 326 '#type' => 'textfield', 327 '#title' => st('Table prefix'), 328 '#default_value' => $db_prefix, 329 '#size' => 45, 330 '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_name(), '%prefix' => $prefix)), 331 ); 332 333 $form['save'] = array( 334 '#type' => 'submit', 335 '#value' => st('Save and continue'), 336 ); 337 338 $form['errors'] = array(); 339 $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file); 340 $form['_db_url'] = array('#type' => 'value'); 341 $form['#action'] = "install.php?profile=$profile". ($install_locale ? "&locale=$install_locale" : ''); 342 $form['#redirect'] = FALSE; 343 } 344 return $form; 345 } 346 347 /** 348 * Form API validate for install_settings form. 349 */ 350 function install_settings_form_validate($form, &$form_state) { 351 global $db_url; 352 _install_settings_form_validate($form_state['values']['db_prefix'], $form_state['values']['db_type'], $form_state['values']['db_user'], $form_state['values']['db_pass'], $form_state['values']['db_host'], $form_state['values']['db_port'], $form_state['values']['db_path'], $form_state['values']['settings_file'], $form_state, $form); 353 } 354 355 /** 356 * Helper function for install_settings_validate. 357 */ 358 function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, &$form_state, $form = NULL) { 359 global $db_url; 360 361 // Verify the table prefix 362 if (!empty($db_prefix) && is_string($db_prefix) && !preg_match('/^[A-Za-z0-9_.]+$/', $db_prefix)) { 363 form_set_error('db_prefix', st('The database table prefix you have entered, %db_prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%db_prefix' => $db_prefix)), 'error'); 364 } 365 366 if (!empty($db_port) && !is_numeric($db_port)) { 367 form_set_error('db_port', st('Database port must be a number.')); 368 } 369 370 // Check database type 371 if (!isset($form)) { 372 $_db_url = is_array($db_url) ? $db_url['default'] : $db_url; 373 $db_type = substr($_db_url, 0, strpos($_db_url, '://')); 374 } 375 $databases = drupal_detect_database_types(); 376 if (!in_array($db_type, $databases)) { 377 form_set_error('db_type', st("In your %settings_file file you have configured @drupal to use a %db_type server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_name(), '%db_type' => $db_type))); 378 } 379 else { 380 // Verify 381 $db_url = $db_type .'://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path); 382 if (isset($form)) { 383 form_set_value($form['_db_url'], $db_url, $form_state); 384 } 385 $success = array(); 386 387 $function = 'drupal_test_'. $db_type; 388 if (!$function($db_url, $success)) { 389 if (isset($success['CONNECT'])) { 390 form_set_error('db_type', st('In order for Drupal to work, and to continue with the installation process, you must resolve all permission issues reported above. We were able to verify that we have permission for the following commands: %commands. For more help with configuring your database server, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.', array('%commands' => implode($success, ', ')))); 391 } 392 else { 393 form_set_error('db_type', ''); 394 } 395 } 396 } 397 } 398 399 /** 400 * Form API submit for install_settings form. 401 */ 402 function install_settings_form_submit($form, &$form_state) { 403 global $profile, $install_locale; 404 405 // Update global settings array and save 406 $settings['db_url'] = array( 407 'value' => $form_state['values']['_db_url'], 408 'required' => TRUE, 409 ); 410 $settings['db_prefix'] = array( 411 'value' => $form_state['values']['db_prefix'], 412 'required' => TRUE, 413 ); 414 drupal_rewrite_settings($settings); 415 416 // Continue to install profile step 417 install_goto("install.php?profile=$profile". ($install_locale ? "&locale=$install_locale" : '')); 418 } 419 420 /** 421 * Find all .profile files. 422 */ 423 function install_find_profiles() { 424 return file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS'), 0, TRUE, 'name', 0); 425 } 426 427 /** 428 * Allow admin to select which profile to install. 429 * 430 * @return 431 * The selected profile. 432 */ 433 function install_select_profile() { 434 include_once './includes/form.inc'; 435 436 $profiles = install_find_profiles(); 437 // Don't need to choose profile if only one available. 438 if (sizeof($profiles) == 1) { 439 $profile = array_pop($profiles); 440 require_once $profile->filename; 441 return $profile->name; 442 } 443 elseif (sizeof($profiles) > 1) { 444 foreach ($profiles as $profile) { 445 if (!empty($_POST['profile']) && ($_POST['profile'] == $profile->name)) { 446 return $profile->name; 447 } 448 } 449 450 install_task_list('profile-select'); 451 452 drupal_set_title(st('Select an installation profile')); 453 print theme('install_page', drupal_get_form('install_select_profile_form', $profiles)); 454 exit; 455 } 456 } 457 458 /** 459 * Form API array definition for the profile selection form. 460 * 461 * @param $form_state 462 * Array of metadata about state of form processing. 463 * @param $profile_files 464 * Array of .profile files, as returned from file_scan_directory(). 465 */ 466 function install_select_profile_form(&$form_state, $profile_files) { 467 $profiles = array(); 468 $names = array(); 469 470 foreach ($profile_files as $profile) { 471 include_once($profile->filename); 472 473 // Load profile details and store them for later retrieval. 474 $function = $profile->name .'_profile_details'; 475 if (function_exists($function)) { 476 $details = $function(); 477 } 478 $profiles[$profile->name] = $details; 479 480 // Determine the name of the profile; default to file name if defined name 481 // is unspecified. 482 $name = isset($details['name']) ? $details['name'] : $profile->name; 483 $names[$profile->name] = $name; 484 } 485 486 // Display radio buttons alphabetically by human-readable name. 487 natcasesort($names); 488 foreach ($names as $profile => $name) { 489 $form['profile'][$name] = array( 490 '#type' => 'radio', 491 '#value' => 'default', 492 '#return_value' => $profile, 493 '#title' => $name, 494 '#description' => isset($profiles[$profile]['description']) ? $profiles[$profile]['description'] : '', 495 '#parents' => array('profile'), 496 ); 497 } 498 $form['submit'] = array( 499 '#type' => 'submit', 500 '#value' => st('Save and continue'), 501 ); 502 return $form; 503 } 504 505 /** 506 * Find all .po files for the current profile. 507 */ 508 function install_find_locales($profilename) { 509 $locales = file_scan_directory('./profiles/'. $profilename .'/translations', '\.po$', array('.', '..', 'CVS'), 0, FALSE); 510 array_unshift($locales, (object) array('name' => 'en')); 511 return $locales; 512 } 513 514 /** 515 * Allow admin to select which locale to use for the current profile. 516 * 517 * @return 518 * The selected language. 519 */ 520 function install_select_locale($profilename) { 521 include_once './includes/file.inc'; 522 include_once './includes/form.inc'; 523 524 // Find all available locales. 525 $locales = install_find_locales($profilename); 526 527 // If only the built-in (English) language is available, 528 // and we are using the default profile, inform the user 529 // that the installer can be localized. Otherwise we assume 530 // the user know what he is doing. 531 if (count($locales) == 1) { 532 if ($profilename == 'default') { 533 install_task_list('locale-select'); 534 drupal_set_title(st('Choose language')); 535 if (!empty($_GET['localize'])) { 536 $output = '<p>'. st('With the addition of an appropriate translation package, this installer is capable of proceeding in another language of your choice. To install and use Drupal in a language other than English:') .'</p>'; 537 $output .= '<ul><li>'. st('Determine if <a href="@translations" target="_blank">a translation of this Drupal version</a> is available in your language of choice. A translation is provided via a translation package; each translation package enables the display of a specific version of Drupal in a specific language. Not all languages are available for every version of Drupal.', array('@translations' => 'http://localize.drupal.org')) .'</li>'; 538 $output .= '<li>'. st('If an alternative translation package of your choice is available, download and extract its contents to your Drupal root directory.') .'</li>'; 539 $output .= '<li>'. st('Return to choose language using the second link below and select your desired language from the displayed list. Reloading the page allows the list to automatically adjust to the presence of new translation packages.') .'</li>'; 540 $output .= '</ul><p>'. st('Alternatively, to install and use Drupal in English, or to defer the selection of an alternative language until after installation, select the first link below.') .'</p>'; 541 $output .= '<p>'. st('How should the installation continue?') .'</p>'; 542 $output .= '<ul><li><a href="install.php?profile='. $profilename .'&locale=en">'. st('Continue installation in English') .'</a></li><li><a href="install.php?profile='. $profilename .'">'. st('Return to choose a language') .'</a></li></ul>'; 543 } 544 else { 545 $output = '<ul><li><a href="install.php?profile='. $profilename .'&locale=en">'. st('Install Drupal in English') .'</a></li><li><a href="install.php?profile='. $profilename .'&localize=true">'. st('Learn how to install Drupal in other languages') .'</a></li></ul>'; 546 } 547 print theme('install_page', $output); 548 exit; 549 } 550 // One language, but not the default profile, assume 551 // the user knows what he is doing. 552 return FALSE; 553 } 554 else { 555 // Allow profile to pre-select the language, skipping the selection. 556 $function = $profilename .'_profile_details'; 557 if (function_exists($function)) { 558 $details = $function(); 559 if (isset($details['language'])) { 560 foreach ($locales as $locale) { 561 if ($details['language'] == $locale->name) { 562 return $locale->name; 563 } 564 } 565 } 566 } 567 568 if (!empty($_POST['locale'])) { 569 foreach ($locales as $locale) { 570 if ($_POST['locale'] == $locale->name) { 571 return $locale->name; 572 } 573 } 574 } 575 576 install_task_list('locale-select'); 577 578 drupal_set_title(st('Choose language')); 579 print theme('install_page', drupal_get_form('install_select_locale_form', $locales)); 580 exit; 581 } 582 } 583 584 /** 585 * Form API array definition for language selection. 586 */ 587 function install_select_locale_form(&$form_state, $locales) { 588 include_once './includes/locale.inc'; 589 $languages = _locale_get_predefined_list(); 590 foreach ($locales as $locale) { 591 // Try to use verbose locale name 592 $name = $locale->name; 593 if (isset($languages[$name])) { 594 $name = $languages[$name][0] . (isset($languages[$name][1]) ? ' '. st('(@language)', array('@language' => $languages[$name][1])) : ''); 595 } 596 $form['locale'][$locale->name] = array( 597 '#type' => 'radio', 598 '#return_value' => $locale->name, 599 '#default_value' => ($locale->name == 'en' ? TRUE : FALSE), 600 '#title' => $name . ($locale->name == 'en' ? ' '. st('(built-in)') : ''), 601 '#parents' => array('locale') 602 ); 603 } 604 $form['submit'] = array( 605 '#type' => 'submit', 606 '#value' => st('Select language'), 607 ); 608 return $form; 609 } 610 611 /** 612 * Show an error page when there are no profiles available. 613 */ 614 function install_no_profile_error() { 615 install_task_list('profile-select'); 616 drupal_set_title(st('No profiles available')); 617 print theme('install_page', '<p>'. st('We were unable to find any installer profiles. Installer profiles tell us what modules to enable and what schema to install in the database. A profile is necessary to continue with the installation process.') .'</p>'); 618 exit; 619 } 620 621 622 /** 623 * Show an error page when Drupal has already been installed. 624 */ 625 function install_already_done_error() { 626 global $base_url; 627 628 drupal_set_title(st('Drupal already installed')); 629 print theme('install_page', st('<ul><li>To start over, you must empty your existing database.</li><li>To install to a different database, edit the appropriate <em>settings.php</em> file in the <em>sites</em> folder.</li><li>To upgrade an existing installation, proceed to the <a href="@base-url/update.php">update script</a>.</li><li>View your <a href="@base-url">existing site</a>.</li></ul>', array('@base-url' => $base_url))); 630 exit; 631 } 632 633 /** 634 * Tasks performed after the database is initialized. 635 */ 636 function install_tasks($profile, $task) { 637 global $base_url, $install_locale; 638 639 // Bootstrap newly installed Drupal, while preserving existing messages. 640 $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : ''; 641 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); 642 $_SESSION['messages'] = $messages; 643 644 // URL used to direct page requests. 645 $url = $base_url .'/install.php?locale='. $install_locale .'&profile='. $profile; 646 647 // Build a page for final tasks. 648 if (empty($task)) { 649 variable_set('install_task', 'profile-install'); 650 $task = 'profile-install'; 651 } 652 653 // We are using a list of if constructs here to allow for 654 // passing from one task to the other in the same request. 655 656 // Install profile modules. 657 if ($task == 'profile-install') { 658 $modules = variable_get('install_profile_modules', array()); 659 $files = module_rebuild_cache(); 660 variable_del('install_profile_modules'); 661 $operations = array(); 662 foreach ($modules as $module) { 663 $operations[] = array('_install_module_batch', array($module, $files[$module]->info['name'])); 664 } 665 $batch = array( 666 'operations' => $operations, 667 'finished' => '_install_profile_batch_finished', 668 'title' => st('Installing @drupal', array('@drupal' => drupal_install_profile_name())), 669 'error_message' => st('The installation has encountered an error.'), 670 ); 671 // Start a batch, switch to 'profile-install-batch' task. We need to 672 // set the variable here, because batch_process() redirects. 673 variable_set('install_task', 'profile-install-batch'); 674 batch_set($batch); 675 batch_process($url, $url); 676 } 677 // We are running a batch install of the profile's modules. 678 // This might run in multiple HTTP requests, constantly redirecting 679 // to the same address, until the batch finished callback is invoked 680 // and the task advances to 'locale-initial-import'. 681 if ($task == 'profile-install-batch') { 682 include_once 'includes/batch.inc'; 683 $output = _batch_page(); 684 } 685 686 // Import interface translations for the enabled modules. 687 if ($task == 'locale-initial-import') { 688 if (!empty($install_locale) && ($install_locale != 'en')) { 689 include_once 'includes/locale.inc'; 690 // Enable installation language as default site language. 691 locale_add_language($install_locale, NULL, NULL, NULL, NULL, NULL, 1, TRUE); 692 // Collect files to import for this language. 693 $batch = locale_batch_by_language($install_locale, '_install_locale_initial_batch_finished'); 694 if (!empty($batch)) { 695 // Remember components we cover in this batch set. 696 variable_set('install_locale_batch_components', $batch['#components']); 697 // Start a batch, switch to 'locale-batch' task. We need to 698 // set the variable here, because batch_process() redirects. 699 variable_set('install_task', 'locale-initial-batch'); 700 batch_set($batch); 701 batch_process($url, $url); 702 } 703 } 704 // Found nothing to import or not foreign language, go to next task. 705 $task = 'configure'; 706 } 707 if ($task == 'locale-initial-batch') { 708 include_once 'includes/batch.inc'; 709 include_once 'includes/locale.inc'; 710 $output = _batch_page(); 711 } 712 713 if ($task == 'configure') { 714 if (variable_get('site_name', FALSE) || variable_get('site_mail', FALSE)) { 715 // Site already configured: This should never happen, means re-running 716 // the installer, possibly by an attacker after the 'install_task' variable 717 // got accidentally blown somewhere. Stop it now. 718 install_already_done_error(); 719 } 720 $form = drupal_get_form('install_configure_form', $url); 721 722 if (!variable_get('site_name', FALSE) && !variable_get('site_mail', FALSE)) { 723 // Not submitted yet: Prepare to display the form. 724 $output = $form; 725 drupal_set_title(st('Configure site')); 726 727 // Warn about settings.php permissions risk 728 $settings_dir = './'. conf_path(); 729 $settings_file = $settings_dir .'/settings.php'; 730 if (!drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || !drupal_verify_install_file($settings_dir, FILE_NOT_WRITABLE, 'dir')) { 731 drupal_set_message(st('All necessary changes to %dir and %file have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, please consult the <a href="@handbook_url">on-line handbook</a>.', array('%dir' => $settings_dir, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/getting-started')), 'error'); 732 } 733 else { 734 drupal_set_message(st('All necessary changes to %dir and %file have been made. They have been set to read-only for security.', array('%dir' => $settings_dir, '%file' => $settings_file))); 735 } 736 737 // Add JavaScript validation. 738 _user_password_dynamic_validation(); 739 drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module'); 740 // We add these strings as settings because JavaScript translation does not 741 // work on install time. 742 drupal_add_js(array('copyFieldValue' => array('edit-site-mail' => array('edit-account-mail')), 'cleanURL' => array('success' => st('Your server has been successfully tested to support this feature.'), 'failure' => st('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => st('Testing clean URLs...'))), 'setting'); 743 drupal_add_js(' 744 // Global Killswitch 745 if (Drupal.jsEnabled) { 746 $(document).ready(function() { 747 Drupal.cleanURLsInstallCheck(); 748 Drupal.setDefaultTimezone(); 749 }); 750 }', 'inline'); 751 // Build menu to allow clean URL check. 752 menu_rebuild(); 753 } 754 755 else { 756 $task = 'profile'; 757 } 758 } 759 760 // If found an unknown task or the 'profile' task, which is 761 // reserved for profiles, hand over the control to the profile, 762 // so it can run any number of custom tasks it defines. 763 if (!in_array($task, install_reserved_tasks())) { 764 $function = $profile .'_profile_tasks'; 765 if (function_exists($function)) { 766 // The profile needs to run more code, maybe even more tasks. 767 // $task is sent through as a reference and may be changed! 768 $output = $function($task, $url); 769 } 770 771 // If the profile doesn't move on to a new task we assume 772 // that it is done. 773 if ($task == 'profile') { 774 $task = 'profile-finished'; 775 } 776 } 777 778 // Profile custom tasks are done, so let the installer regain 779 // control and proceed with importing the remaining translations. 780 if ($task == 'profile-finished') { 781 if (!empty($install_locale) && ($install_locale != 'en')) { 782 include_once 'includes/locale.inc'; 783 // Collect files to import for this language. Skip components 784 // already covered in the initial batch set. 785 $batch = locale_batch_by_language($install_locale, '_install_locale_remaining_batch_finished', variable_get('install_locale_batch_components', array())); 786 // Remove temporary variable. 787 variable_del('install_locale_batch_components'); 788 if (!empty($batch)) { 789 // Start a batch, switch to 'locale-remaining-batch' task. We need to 790 // set the variable here, because batch_process() redirects. 791 variable_set('install_task', 'locale-remaining-batch'); 792 batch_set($batch); 793 batch_process($url, $url); 794 } 795 } 796 // Found nothing to import or not foreign language, go to next task. 797 $task = 'finished'; 798 } 799 if ($task == 'locale-remaining-batch') { 800 include_once 'includes/batch.inc'; 801 include_once 'includes/locale.inc'; 802 $output = _batch_page(); 803 } 804 805 // Display a 'finished' page to user. 806 if ($task == 'finished') { 807 drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_name()))); 808 $messages = drupal_set_message(); 809 $output = '<p>'. st('Congratulations, @drupal has been successfully installed.', array('@drupal' => drupal_install_profile_name())) .'</p>'; 810 $output .= '<p>'. (isset($messages['error']) ? st('Please review the messages above before continuing on to <a href="@url">your new site</a>.', array('@url' => url(''))) : st('You may now visit <a href="@url">your new site</a>.', array('@url' => url('')))) .'</p>'; 811 $task = 'done'; 812 } 813 814 // The end of the install process. Remember profile used. 815 if ($task == 'done') { 816 // Rebuild menu to get content type links registered by the profile, 817 // and possibly any other menu items created through the tasks. 818 menu_rebuild(); 819 820 // Register actions declared by any modules. 821 actions_synchronize(); 822 823 // Randomize query-strings on css/js files, to hide the fact that 824 // this is a new install, not upgraded yet. 825 _drupal_flush_css_js(); 826 827 variable_set('install_profile', $profile); 828 } 829 830 // Set task for user, and remember the task in the database. 831 install_task_list($task); 832 variable_set('install_task', $task); 833 834 // Output page, if some output was required. Otherwise it is possible 835 // that we are printing a JSON page and theme output should not be there. 836 if (isset($output)) { 837 print theme('maintenance_page', $output); 838 } 839 } 840 841 /** 842 * Batch callback for batch installation of modules. 843 */ 844 function _install_module_batch($module, $module_name, &$context) { 845 _drupal_install_module($module); 846 // We enable the installed module right away, so that the module will be 847 // loaded by drupal_bootstrap in subsequent batch requests, and other 848 // modules possibly depending on it can safely perform their installation 849 // steps. 850 module_enable(array($module)); 851 $context['results'][] = $module; 852 $context['message'] = st('Installed %module module.', array('%module' => $module_name)); 853 } 854 855 /** 856 * Finished callback for the modules install batch. 857 * 858 * Advance installer task to language import. 859 */ 860 function _install_profile_batch_finished($success, $results) { 861 variable_set('install_task', 'locale-initial-import'); 862 } 863 864 /** 865 * Finished callback for the first locale import batch. 866 * 867 * Advance installer task to the configure screen. 868 */ 869 function _install_locale_initial_batch_finished($success, $results) { 870 variable_set('install_task', 'configure'); 871 } 872 873 /** 874 * Finished callback for the second locale import batch. 875 * 876 * Advance installer task to the finished screen. 877 */ 878 function _install_locale_remaining_batch_finished($success, $results) { 879 variable_set('install_task', 'finished'); 880 } 881 882 /** 883 * The list of reserved tasks to run in the installer. 884 */ 885 function install_reserved_tasks() { 886 return array('configure', 'profile-install', 'profile-install-batch', 'locale-initial-import', 'locale-initial-batch', 'profile-finished', 'locale-remaining-batch', 'finished', 'done'); 887 } 888 889 /** 890 * Check installation requirements and report any errors. 891 */ 892 function install_check_requirements($profile, $verify) { 893 894 // If Drupal is not set up already, we need to create a settings file. 895 if (!$verify) { 896 $writable = FALSE; 897 $conf_path = './'. conf_path(FALSE, TRUE); 898 $settings_file = $conf_path .'/settings.php'; 899 $file = $conf_path; 900 $exists = FALSE; 901 // Verify that the directory exists. 902 if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) { 903 // Check to make sure a settings.php already exists. 904 $file = $settings_file; 905 if (drupal_verify_install_file($settings_file, FILE_EXIST)) { 906 $exists = TRUE; 907 // If it does, make sure it is writable. 908 $writable = drupal_verify_install_file($settings_file, FILE_READABLE|FILE_WRITABLE); 909 } 910 } 911 if (!$exists) { 912 drupal_set_message(st('The @drupal installer requires that you create a settings file as part of the installation process. 913 <ol> 914 <li>Copy the %default_file file to %file.</li> 915 <li>Change file permissions so that it is writable by the web server. If you are unsure how to grant file permissions, please consult the <a href="@handbook_url">on-line handbook</a>.</li> 916 </ol> 917 More details about installing Drupal are available in INSTALL.txt.', array('@drupal' => drupal_install_profile_name(), '%file' => $file, '%default_file' => $conf_path .'/default.settings.php', '@handbook_url' => 'http://drupal.org/server-permissions')), 'error'); 918 } 919 elseif (!$writable) { 920 drupal_set_message(st('The @drupal installer requires write permissions to %file during the installation process. If you are unsure how to grant file permissions, please consult the <a href="@handbook_url">on-line handbook</a>.', array('@drupal' => drupal_install_profile_name(), '%file' => $file, '@handbook_url' => 'http://drupal.org/server-permissions')), 'error'); 921 } 922 } 923 924 // Check the other requirements. 925 $requirements = drupal_check_profile($profile); 926 $severity = drupal_requirements_severity($requirements); 927 928 // If there are issues, report them. 929 if ($severity == REQUIREMENT_ERROR) { 930 931 foreach ($requirements as $requirement) { 932 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { 933 $message = $requirement['description']; 934 if (isset($requirement['value']) && $requirement['value']) { 935 $message .= ' ('. st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')'; 936 } 937 drupal_set_message($message, 'error'); 938 } 939 } 940 } 941 if ($severity == REQUIREMENT_WARNING) { 942 943 foreach ($requirements as $requirement) { 944 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_WARNING) { 945 $message = $requirement['description']; 946 if (isset($requirement['value']) && $requirement['value']) { 947 $message .= ' ('. st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')'; 948 } 949 drupal_set_message($message, 'warning'); 950 } 951 } 952 } 953 } 954 955 /** 956 * Add the installation task list to the current page. 957 */ 958 function install_task_list($active = NULL) { 959 // Default list of tasks. 960 $tasks = array( 961 'profile-select' => st('Choose profile'), 962 'locale-select' => st('Choose language'), 963 'requirements' => st('Verify requirements'), 964 'database' => st('Set up database'), 965 'profile-install-batch' => st('Install profile'), 966 'locale-initial-batch' => st('Set up translations'), 967 'configure' => st('Configure site'), 968 ); 969 970 $profiles = install_find_profiles(); 971 $profile = isset($_GET['profile']) && isset($profiles[$_GET['profile']]) ? $_GET['profile'] : '.'; 972 $locales = install_find_locales($profile); 973 974 // If we have only one profile, remove 'Choose profile' 975 // and rename 'Install profile'. 976 if (count($profiles) == 1) { 977 unset($tasks['profile-select']); 978 $tasks['profile-install-batch'] = st('Install site'); 979 } 980 981 // Add tasks defined by the profile. 982 if ($profile) { 983 $function = $profile .'_profile_task_list'; 984 if (function_exists($function)) { 985 $result = $function(); 986 if (is_array($result)) { 987 $tasks += $result; 988 } 989 } 990 } 991 992 if (count($locales) < 2 || empty($_GET['locale']) || $_GET['locale'] == 'en') { 993 // If not required, remove translation import from the task list. 994 unset($tasks['locale-initial-batch']); 995 } 996 else { 997 // If required, add remaining translations import task. 998 $tasks += array('locale-remaining-batch' => st('Finish translations')); 999 } 1000 1001 // Add finished step as the last task. 1002 $tasks += array( 1003 'finished' => st('Finished') 1004 ); 1005 1006 // Let the theming function know that 'finished' and 'done' 1007 // include everything, so every step is completed. 1008 if (in_array($active, array('finished', 'done'))) { 1009 $active = NULL; 1010 } 1011 drupal_set_content('left', theme_task_list($tasks, $active)); 1012 } 1013 1014 /** 1015 * Form API array definition for site configuration. 1016 */ 1017 function install_configure_form(&$form_state, $url) { 1018 1019 $form['intro'] = array( 1020 '#value' => st('To configure your website, please provide the following information.'), 1021 '#weight' => -10, 1022 ); 1023 $form['site_information'] = array( 1024 '#type' => 'fieldset', 1025 '#title' => st('Site information'), 1026 '#collapsible' => FALSE, 1027 ); 1028 $form['site_information']['site_name'] = array( 1029 '#type' => 'textfield', 1030 '#title' => st('Site name'), 1031 '#required' => TRUE, 1032 '#weight' => -20, 1033 ); 1034 $form['site_information']['site_mail'] = array( 1035 '#type' => 'textfield', 1036 '#title' => st('Site e-mail address'), 1037 '#default_value' => ini_get('sendmail_from'), 1038 '#description' => st("The <em>From</em> address in automated e-mails sent during registration and new password requests, and other notifications. (Use an address ending in your site's domain to help prevent this e-mail being flagged as spam.)"), 1039 '#required' => TRUE, 1040 '#weight' => -15, 1041 ); 1042 $form['admin_account'] = array( 1043 '#type' => 'fieldset', 1044 '#title' => st('Administrator account'), 1045 '#collapsible' => FALSE, 1046 ); 1047 $form['admin_account']['account']['#tree'] = TRUE; 1048 $form['admin_account']['markup'] = array( 1049 '#value' => '<p class="description">'. st('The administrator account has complete access to the site; it will automatically be granted all permissions and can perform any administrative activity. This will be the only account that can perform certain activities, so keep its credentials safe.') .'</p>', 1050 '#weight' => -10, 1051 ); 1052 1053 $form['admin_account']['account']['name'] = array('#type' => 'textfield', 1054 '#title' => st('Username'), 1055 '#maxlength' => USERNAME_MAX_LENGTH, 1056 '#description' => st('Spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'), 1057 '#required' => TRUE, 1058 '#weight' => -10, 1059 ); 1060 1061 $form['admin_account']['account']['mail'] = array('#type' => 'textfield', 1062 '#title' => st('E-mail address'), 1063 '#maxlength' => EMAIL_MAX_LENGTH, 1064 '#description' => st('All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'), 1065 '#required' => TRUE, 1066 '#weight' => -5, 1067 ); 1068 $form['admin_account']['account']['pass'] = array( 1069 '#type' => 'password_confirm', 1070 '#required' => TRUE, 1071 '#size' => 25, 1072 '#weight' => 0, 1073 ); 1074 1075 $form['server_settings'] = array( 1076 '#type' => 'fieldset', 1077 '#title' => st('Server settings'), 1078 '#collapsible' => FALSE, 1079 ); 1080 $form['server_settings']['date_default_timezone'] = array( 1081 '#type' => 'select', 1082 '#title' => st('Default time zone'), 1083 '#default_value' => 0, 1084 '#options' => _system_zonelist(), 1085 '#description' => st('By default, dates in this site will be displayed in the chosen time zone.'), 1086 '#weight' => 5, 1087 ); 1088 1089 $form['server_settings']['clean_url'] = array( 1090 '#type' => 'radios', 1091 '#title' => st('Clean URLs'), 1092 '#default_value' => 0, 1093 '#options' => array(0 => st('Disabled'), 1 => st('Enabled')), 1094 '#description' => st('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'), 1095 '#disabled' => TRUE, 1096 '#prefix' => '<div id="clean-url" class="install">', 1097 '#suffix' => '</div>', 1098 '#weight' => 10, 1099 ); 1100 1101 $form['server_settings']['update_status_module'] = array( 1102 '#type' => 'checkboxes', 1103 '#title' => st('Update notifications'), 1104 '#options' => array(1 => st('Check for updates automatically')), 1105 '#default_value' => array(1), 1106 '#description' => st('With this option enabled, Drupal will notify you when new releases are available. This will significantly enhance your site\'s security and is <strong>highly recommended</strong>. This requires your site to periodically send anonymous information on its installed components to <a href="@drupal">drupal.org</a>. For more information please see the <a href="@update">update notification information</a>.', array('@drupal' => 'http://drupal.org', '@update' => 'http://drupal.org/handbook/modules/update')), 1107 '#weight' => 15, 1108 ); 1109 1110 $form['submit'] = array( 1111 '#type' => 'submit', 1112 '#value' => st('Save and continue'), 1113 '#weight' => 15, 1114 ); 1115 $form['#action'] = $url; 1116 $form['#redirect'] = FALSE; 1117 1118 // Allow the profile to alter this form. $form_state isn't available 1119 // here, but to conform to the hook_form_alter() signature, we pass 1120 // an empty array. 1121 $hook_form_alter = $_GET['profile'] .'_form_alter'; 1122 if (function_exists($hook_form_alter)) { 1123 $hook_form_alter($form, array(), 'install_configure'); 1124 } 1125 return $form; 1126 } 1127 1128 /** 1129 * Form API validate for the site configuration form. 1130 */ 1131 function install_configure_form_validate($form, &$form_state) { 1132 if ($error = user_validate_name($form_state['values']['account']['name'])) { 1133 form_error($form['admin_account']['account']['name'], $error); 1134 } 1135 if ($error = user_validate_mail($form_state['values']['account']['mail'])) { 1136 form_error($form['admin_account']['account']['mail'], $error); 1137 } 1138 if ($error = user_validate_mail($form_state['values']['site_mail'])) { 1139 form_error($form['site_information']['site_mail'], $error); 1140 } 1141 } 1142 1143 /** 1144 * Form API submit for the site configuration form. 1145 */ 1146 function install_configure_form_submit($form, &$form_state) { 1147 global $user; 1148 1149 variable_set('site_name', $form_state['values']['site_name']); 1150 variable_set('site_mail', $form_state['values']['site_mail']); 1151 variable_set('date_default_timezone', $form_state['values']['date_default_timezone']); 1152 1153 // Enable update.module if this option was selected. 1154 if ($form_state['values']['update_status_module'][1]) { 1155 drupal_install_modules(array('update')); 1156 } 1157 1158 // Turn this off temporarily so that we can pass a password through. 1159 variable_set('user_email_verification', FALSE); 1160 $form_state['old_values'] = $form_state['values']; 1161 $form_state['values'] = $form_state['values']['account']; 1162 1163 // We precreated user 1 with placeholder values. Let's save the real values. 1164 $account = user_load(1); 1165 $merge_data = array('init' => $form_state['values']['mail'], 'roles' => array(), 'status' => 1); 1166 user_save($account, array_merge($form_state['values'], $merge_data)); 1167 // Log in the first user. 1168 user_authenticate($form_state['values']); 1169 $form_state['values'] = $form_state['old_values']; 1170 unset($form_state['old_values']); 1171 variable_set('user_email_verification', TRUE); 1172 1173 if (isset($form_state['values']['clean_url'])) { 1174 variable_set('clean_url', $form_state['values']['clean_url']); 1175 } 1176 // The user is now logged in, but has no session ID yet, which 1177 // would be required later in the request, so remember it. 1178 $user->sid = session_id(); 1179 1180 // Record when this install ran. 1181 variable_set('install_time', time()); 1182 } 1183 1184 // Start the installer. 1185 install_main();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |