/** * Checking permissions on files and folders. */ function check_permission() { $conf_dir = drupal_verify_install_file(conf_path(), FILE_NOT_WRITABLE, 'dir'); if (!$conf_dir) { $data = '<li>' . t('The directory %file is not protected from modifications and poses a security risk. You must change the directory\'s permissions to be non-writable. ', array('%file' => conf_path())) . '</li>'; fwrite($GLOBALS['createdFile'], $data); } $conf_file = drupal_verify_install_file(conf_path() . '/settings.php', FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE); if (!$conf_file) { $data = '<li>' . t('The file %file is not protected from modifications and poses a security risk. You must change the file\'s permissions to be non-writable.', array('%file' => conf_path() . '/settings.php')) . '</li>'; fwrite($GLOBALS['createdFile'], $data); } }
/** * Tests the default behavior to restrict directory permissions is enforced. * * Checks both the the current sites directory and settings.php. */ public function testSitesDirectoryHardening() { $site_path = $this->kernel->getSitePath(); $settings_file = $this->settingsFile($site_path); // First, we check based on what the initial install has set. $this->assertTrue(drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir'), new FormattableMarkup('Verified permissions for @file.', array('@file' => $site_path))); // We intentionally don't check for settings.local.php as that file is // not created by Drupal. $this->assertTrue(drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE), new FormattableMarkup('Verified permissions for @file.', array('@file' => $settings_file))); $this->makeWritable($site_path); $this->checkSystemRequirements(); $this->assertTrue(drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir'), new FormattableMarkup('Verified permissions for @file after manual permissions change.', array('@file' => $site_path))); $this->assertTrue(drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE), new FormattableMarkup('Verified permissions for @file after manual permissions change.', array('@file' => $settings_file))); }
/** * Check installation requirements and report any errors. */ function install_check_requirements($profile, $verify) { // If Drupal is not set up already, we need to create a settings file. if (!$verify) { $writable = FALSE; $conf_path = './' . conf_path(FALSE, TRUE); $settings_file = $conf_path . '/settings.php'; $file = $conf_path; $exists = FALSE; // Verify that the directory exists. if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) { // Check to make sure a settings.php already exists. $file = $settings_file; if (drupal_verify_install_file($settings_file, FILE_EXIST)) { $exists = TRUE; // If it does, make sure it is writable. $writable = drupal_verify_install_file($settings_file, FILE_READABLE | FILE_WRITABLE); } } if (!$exists) { drupal_set_message(st('The @drupal installer requires that you create a settings file as part of the installation process. <ol> <li>Copy the %default_file file to %file.</li> <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> </ol> 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'); } elseif (!$writable) { 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'); } } // Check the other requirements. $requirements = drupal_check_profile($profile); $severity = drupal_requirements_severity($requirements); // If there are issues, report them. if ($severity == REQUIREMENT_ERROR) { foreach ($requirements as $requirement) { if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { $message = $requirement['description']; if (isset($requirement['value']) && $requirement['value']) { $message .= ' (' . st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) . ')'; } drupal_set_message($message, 'error'); } } } if ($severity == REQUIREMENT_WARNING) { foreach ($requirements as $requirement) { if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_WARNING) { $message = $requirement['description']; if (isset($requirement['value']) && $requirement['value']) { $message .= ' (' . st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) . ')'; } drupal_set_message($message, 'warning'); } } } }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $form['#title'] = $this->t('Configure site'); // Warn about settings.php permissions risk $settings_dir = $this->sitePath; $settings_file = $settings_dir . '/settings.php'; // Check that $_POST is empty so we only show this message when the form is // first displayed, not on the next page after it is submitted. (We do not // want to repeat it multiple times because it is a general warning that is // not related to the rest of the installation process; it would also be // especially out of place on the last page of the installer, where it would // distract from the message that the Drupal installation has completed // successfully.) $post_params = $this->getRequest()->request->all(); if (empty($post_params) && (!drupal_verify_install_file($this->root . '/' . $settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE) || !drupal_verify_install_file($this->root . '/' . $settings_dir, FILE_NOT_WRITABLE, 'dir'))) { drupal_set_message(t('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, consult the <a href=":handbook_url">online handbook</a>.', array('%dir' => $settings_dir, '%file' => $settings_file, ':handbook_url' => 'https://www.drupal.org/server-permissions')), 'warning'); } $form['#attached']['library'][] = 'system/drupal.system'; // Add JavaScript time zone detection. $form['#attached']['library'][] = 'core/drupal.timezone'; // We add these strings as settings because JavaScript translation does not // work during installation. $form['#attached']['drupalSettings']['copyFieldValue']['edit-site-mail'] = ['edit-account-mail']; $form['site_information'] = array('#type' => 'fieldgroup', '#title' => $this->t('Site information')); $form['site_information']['site_name'] = array('#type' => 'textfield', '#title' => $this->t('Site name'), '#required' => TRUE, '#weight' => -20); $form['site_information']['site_mail'] = array('#type' => 'email', '#title' => $this->t('Site email address'), '#default_value' => ini_get('sendmail_from'), '#description' => $this->t("Automated emails, such as registration information, will be sent from this address. Use an address ending in your site's domain to help prevent these emails from being flagged as spam."), '#required' => TRUE, '#weight' => -15); $form['admin_account'] = array('#type' => 'fieldgroup', '#title' => $this->t('Site maintenance account')); $form['admin_account']['account']['name'] = array('#type' => 'textfield', '#title' => $this->t('Username'), '#maxlength' => USERNAME_MAX_LENGTH, '#description' => $this->t("Several special characters are allowed, including space, period (.), hyphen (-), apostrophe ('), underscore (_), and the @ sign."), '#required' => TRUE, '#attributes' => array('class' => array('username'))); $form['admin_account']['account']['pass'] = array('#type' => 'password_confirm', '#required' => TRUE, '#size' => 25); $form['admin_account']['account']['#tree'] = TRUE; $form['admin_account']['account']['mail'] = array('#type' => 'email', '#title' => $this->t('Email address'), '#required' => TRUE); $form['regional_settings'] = array('#type' => 'fieldgroup', '#title' => $this->t('Regional settings')); $countries = $this->countryManager->getList(); $form['regional_settings']['site_default_country'] = array('#type' => 'select', '#title' => $this->t('Default country'), '#empty_value' => '', '#default_value' => $this->config('system.date')->get('country.default'), '#options' => $countries, '#description' => $this->t('Select the default country for the site.'), '#weight' => 0); $form['regional_settings']['date_default_timezone'] = array('#type' => 'select', '#title' => $this->t('Default time zone'), '#default_value' => @date_default_timezone_get(), '#options' => system_time_zones(), '#description' => $this->t('By default, dates in this site will be displayed in the chosen time zone.'), '#weight' => 5, '#attributes' => array('class' => array('timezone-detect'))); $form['update_notifications'] = array('#type' => 'fieldgroup', '#title' => $this->t('Update notifications')); $form['update_notifications']['update_status_module'] = array('#type' => 'checkboxes', '#title' => $this->t('Update notifications'), '#options' => array(1 => $this->t('Check for updates automatically'), 2 => $this->t('Receive email notifications')), '#default_value' => array(1, 2), '#description' => $this->t('The system will notify you when updates and important security releases are available for installed components. Anonymous information about your site is sent to <a href=":drupal">Drupal.org</a>.', array(':drupal' => 'https://www.drupal.org')), '#weight' => 15); $form['update_notifications']['update_status_module'][2] = array('#states' => array('visible' => array('input[name="update_status_module[1]"]' => array('checked' => TRUE)))); $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save and continue'), '#weight' => 15, '#button_type' => 'primary'); return $form; }
/** * Users who still have a Drupal 6 database (and are in the process of * updating to Drupal 7) need extra help before a full bootstrap can be * achieved. This function does the necessary preliminary work that allows * the bootstrap to be successful. * * No access check has been performed when this function is called, so no * changes to the database should be made here. */ function update_prepare_d7_bootstrap() { // Allow the bootstrap to proceed even if a Drupal 6 settings.php file is // still being used. include_once DRUPAL_ROOT . '/includes/install.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); global $databases, $db_url, $update_rewrite_settings; if (empty($databases) && !empty($db_url)) { $databases = update_parse_db_url($db_url); // Record the fact that the settings.php file will need to be rewritten. $update_rewrite_settings = TRUE; $settings_file = conf_path() . '/settings.php'; $writable = drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_WRITABLE); $requirements = array('settings file' => array('title' => 'Settings file', 'value' => $writable ? 'The settings file is writable.' : 'The settings file is not writable.', 'severity' => $writable ? REQUIREMENT_OK : REQUIREMENT_ERROR, 'description' => $writable ? '' : 'Drupal requires write permissions to <em>' . $settings_file . '</em> during the update process. If you are unsure how to grant file permissions, please consult the <a href="http://drupal.org/server-permissions">online handbook</a>.')); update_extra_requirements($requirements); } // Allow the database system to work even if the registry has not been // created yet. drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); drupal_install_init_database(); spl_autoload_unregister('drupal_autoload_class'); spl_autoload_unregister('drupal_autoload_interface'); // The new {blocked_ips} table is used in Drupal 7 to store a list of // banned IP addresses. If this table doesn't exist then we are still // running on a Drupal 6 database, so suppress the unavoidable errors // that occur. try { drupal_bootstrap(DRUPAL_BOOTSTRAP_ACCESS); } catch (Exception $e) { if (db_table_exists('blocked_ips')) { throw $e; } } }
/** * Configure and rewrite settings.php. */ function install_change_settings($profile = 'default', $install_locale = '') { global $db_url, $db_type, $db_prefix; $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url); $db_user = urldecode($url['user']); $db_pass = urldecode($url['pass']); $db_host = urldecode($url['host']); $db_port = isset($url['port']) ? urldecode($url['port']) : ''; $db_path = ltrim(urldecode($url['path']), '/'); $settings_file = './' . conf_path() . '/settings.php'; // We always need this because we want to run form_get_errors. include_once './includes/form.inc'; drupal_maintenance_theme(); // Don't fill in placeholders if ($db_url == 'mysql://*****:*****@localhost/databasename') { $db_user = $db_pass = $db_path = ''; } elseif (!empty($db_url)) { // Do not install over a configured settings.php. install_already_done_error(); } // The existing database settings are not working, so we need write access // to settings.php to change them. if (!drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_WRITABLE)) { drupal_set_message(st('The @drupal installer requires write permissions to %file during the installation process.', array('@drupal' => drupal_install_profile_name(), '%file' => $settings_file)), 'error'); drupal_set_title(st('Drupal database setup')); print theme('install_page', ''); exit; } $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); drupal_set_title(st('Database configuration')); print theme('install_page', $output); exit; }
/** * Check installation requirements and report any errors. */ function install_check_requirements($profile, $verify) { // Check the profile requirements. $requirements = drupal_check_profile($profile); // If Drupal is not set up already, we need to create a settings file. if (!$verify) { $writable = FALSE; $conf_path = './' . conf_path(FALSE, TRUE); $settings_file = $conf_path . '/settings.php'; $file = $conf_path; $exists = FALSE; // Verify that the directory exists. if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) { // Check to make sure a settings.php already exists. $file = $settings_file; if (drupal_verify_install_file($settings_file, FILE_EXIST)) { $exists = TRUE; // If it does, make sure it is writable. $writable = drupal_verify_install_file($settings_file, FILE_READABLE | FILE_WRITABLE); $exists = TRUE; } } if (!$exists) { $requirements['settings file exists'] = array('title' => st('Settings file'), 'value' => st('The settings file does not exist.'), 'severity' => REQUIREMENT_ERROR, 'description' => st('The @drupal installer requires that you create a settings file as part of the installation process. Copy the %default_file file to %file. More details about installing Drupal are available in <a href="@install_txt">INSTALL.txt</a>.', array('@drupal' => drupal_install_profile_name(), '%file' => $file, '%default_file' => $conf_path . '/default.settings.php', '@install_txt' => base_path() . 'INSTALL.txt'))); } else { $requirements['settings file exists'] = array('title' => st('Settings file'), 'value' => st('The %file file exists.', array('%file' => $file))); if (!$writable) { $requirements['settings file writable'] = array('title' => st('Settings file'), 'value' => st('The settings file is not writable.'), 'severity' => REQUIREMENT_ERROR, 'description' => 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">online handbook</a>.', array('@drupal' => drupal_install_profile_name(), '%file' => $file, '@handbook_url' => 'http://drupal.org/server-permissions'))); } else { $requirements['settings file'] = array('title' => st('Settings file'), 'value' => st('Settings file is writable.')); } } } return $requirements; }
/** * Tasks performed after the database is initialized. */ function install_tasks($profile, $task) { global $base_url, $install_locale; // Bootstrap newly installed Drupal, while preserving existing messages. $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : ''; drupal_install_init_database(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); drupal_set_session('messages', $messages); // URL used to direct page requests. $url = $base_url . '/install.php?locale=' . $install_locale . '&profile=' . $profile; // Build a page for final tasks. if (empty($task)) { variable_set('install_task', 'profile-install'); $task = 'profile-install'; } // We are using a list of if constructs here to allow for // passing from one task to the other in the same request. // Install profile modules. if ($task == 'profile-install') { $modules = variable_get('install_profile_modules', array()); $files = module_rebuild_cache(); variable_del('install_profile_modules'); $operations = array(); foreach ($modules as $module) { $operations[] = array('_install_module_batch', array($module, $files[$module]->info['name'])); } $batch = array('operations' => $operations, 'finished' => '_install_profile_batch_finished', 'title' => st('Installing @drupal', array('@drupal' => drupal_install_profile_name())), 'error_message' => st('The installation has encountered an error.')); // Start a batch, switch to 'profile-install-batch' task. We need to // set the variable here, because batch_process() redirects. variable_set('install_task', 'profile-install-batch'); batch_set($batch); batch_process($url, $url); } // We are running a batch install of the profile's modules. // This might run in multiple HTTP requests, constantly redirecting // to the same address, until the batch finished callback is invoked // and the task advances to 'locale-initial-import'. if ($task == 'profile-install-batch') { include_once DRUPAL_ROOT . '/includes/batch.inc'; $output = _batch_page(); } // Import interface translations for the enabled modules. if ($task == 'locale-initial-import') { if (!empty($install_locale) && $install_locale != 'en') { include_once DRUPAL_ROOT . '/includes/locale.inc'; // Enable installation language as default site language. locale_add_language($install_locale, NULL, NULL, NULL, '', NULL, 1, TRUE); // Collect files to import for this language. $batch = locale_batch_by_language($install_locale, '_install_locale_initial_batch_finished'); if (!empty($batch)) { // Remember components we cover in this batch set. variable_set('install_locale_batch_components', $batch['#components']); // Start a batch, switch to 'locale-batch' task. We need to // set the variable here, because batch_process() redirects. variable_set('install_task', 'locale-initial-batch'); batch_set($batch); batch_process($url, $url); } } // Found nothing to import or not foreign language, go to next task. $task = 'configure'; } if ($task == 'locale-initial-batch') { include_once DRUPAL_ROOT . '/includes/batch.inc'; include_once DRUPAL_ROOT . '/includes/locale.inc'; $output = _batch_page(); } if ($task == 'configure') { if (variable_get('site_name', FALSE) || variable_get('site_mail', FALSE)) { // Site already configured: This should never happen, means re-running // the installer, possibly by an attacker after the 'install_task' variable // got accidentally blown somewhere. Stop it now. install_already_done_error(); } $form = drupal_get_form('install_configure_form', $url); if (!variable_get('site_name', FALSE) && !variable_get('site_mail', FALSE)) { // Not submitted yet: Prepare to display the form. $output = $form; drupal_set_title(st('Configure site')); // Warn about settings.php permissions risk $settings_dir = './' . conf_path(); $settings_file = $settings_dir . '/settings.php'; if (!drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE) || !drupal_verify_install_file($settings_dir, FILE_NOT_WRITABLE, 'dir')) { 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">online handbook</a>.', array('%dir' => $settings_dir, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/server-permissions')), 'error'); } else { 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))); } // Add JavaScript validation. _user_password_dynamic_validation(); drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); // Add JavaScript time zone detection. drupal_add_js('misc/timezone.js'); // We add these strings as settings because JavaScript translation does not // work on install time. drupal_add_js(array('copyFieldValue' => array('edit-site-mail' => array('edit-account-mail'))), 'setting'); drupal_add_js('jQuery(function () { Drupal.cleanURLsInstallCheck(); });', 'inline'); // Build menu to allow clean URL check. menu_rebuild(); // Cache a fully-built schema. This is necessary for any // invocation of index.php because: (1) setting cache table // entries requires schema information, (2) that occurs during // bootstrap before any module are loaded, so (3) if there is no // cached schema, drupal_get_schema() will try to generate one // but with no loaded modules will return nothing. // // This logically could be done during task 'done' but the clean // URL check requires it now. drupal_get_schema(NULL, TRUE); } else { $task = 'profile'; } } // If found an unknown task or the 'profile' task, which is // reserved for profiles, hand over the control to the profile, // so it can run any number of custom tasks it defines. if (!in_array($task, install_reserved_tasks())) { $function = $profile . '_profile_tasks'; if (function_exists($function)) { // The profile needs to run more code, maybe even more tasks. // $task is sent through as a reference and may be changed! $output = $function($task, $url); } // If the profile doesn't move on to a new task we assume // that it is done. if ($task == 'profile') { $task = 'profile-finished'; } } // Profile custom tasks are done, so let the installer regain // control and proceed with importing the remaining translations. if ($task == 'profile-finished') { if (!empty($install_locale) && $install_locale != 'en') { include_once DRUPAL_ROOT . '/includes/locale.inc'; // Collect files to import for this language. Skip components // already covered in the initial batch set. $batch = locale_batch_by_language($install_locale, '_install_locale_remaining_batch_finished', variable_get('install_locale_batch_components', array())); // Remove temporary variable. variable_del('install_locale_batch_components'); if (!empty($batch)) { // Start a batch, switch to 'locale-remaining-batch' task. We need to // set the variable here, because batch_process() redirects. variable_set('install_task', 'locale-remaining-batch'); batch_set($batch); batch_process($url, $url); } } // Found nothing to import or not foreign language, go to next task. $task = 'finished'; } if ($task == 'locale-remaining-batch') { include_once DRUPAL_ROOT . '/includes/batch.inc'; include_once DRUPAL_ROOT . '/includes/locale.inc'; $output = _batch_page(); } // Display a 'finished' page to user. if ($task == 'finished') { drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_name()))); $messages = drupal_set_message(); $output = '<p>' . st('Congratulations, @drupal has been successfully installed.', array('@drupal' => drupal_install_profile_name())) . '</p>'; $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>'; $task = 'done'; } // The end of the install process. Remember profile used. if ($task == 'done') { // Rebuild menu and registry to get content type links registered by the // profile, and possibly any other menu items created through the tasks. menu_rebuild(); // Register actions declared by any modules. actions_synchronize(); // Randomize query-strings on css/js files, to hide the fact that // this is a new install, not upgraded yet. _drupal_flush_css_js(); variable_set('install_profile', $profile); // Cache a fully-built schema. drupal_get_schema(NULL, TRUE); } // Set task for user, and remember the task in the database. install_task_list($task); variable_set('install_task', $task); // Run cron to populate update status tables (if available) so that users // will be warned if they've installed an out of date Drupal version. // Will also trigger indexing of profile-supplied content or feeds. drupal_cron_run(); // Output page, if some output was required. Otherwise it is possible // that we are printing a JSON page and theme output should not be there. if (isset($output)) { print theme('maintenance_page', $output); } }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $form['#title'] = $this->t('Configure site'); // Warn about settings.php permissions risk $settings_file = $this->sitePath . '/settings.php'; // Check that $_POST is empty so we only show this message when the form is // first displayed, not on the next page after it is submitted. (We do not // want to repeat it multiple times because it is a general warning that is // not related to the rest of the installation process; it would also be // especially out of place on the last page of the installer, where it would // distract from the message that the Drupal installation has completed // successfully.) $post_params = $this->getRequest()->request->all(); if (empty($post_params)) { $original_profile_name = _config_installer_get_original_install_profile(); if ($original_profile_name) { $settings['settings']['install_profile'] = (object) array('value' => $original_profile_name, 'required' => TRUE); drupal_rewrite_settings($settings); } if (!drupal_verify_install_file($this->root . '/' . $settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE) || !drupal_verify_install_file($this->root . '/' . $this->sitePath, FILE_NOT_WRITABLE, 'dir')) { drupal_set_message(t('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, consult the <a href="@handbook_url">online handbook</a>.', array('%dir' => $this->sitePath, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/server-permissions')), 'warning'); } } $form['#attached']['library'][] = 'system/drupal.system'; $form['admin_account'] = array('#type' => 'fieldgroup', '#title' => $this->t('Site maintenance account')); $form['admin_account']['account']['name'] = array('#type' => 'textfield', '#title' => $this->t('Username'), '#maxlength' => USERNAME_MAX_LENGTH, '#description' => $this->t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'), '#required' => TRUE, '#attributes' => array('class' => array('username'))); $form['admin_account']['account']['pass'] = array('#type' => 'password_confirm', '#required' => TRUE, '#size' => 25); $form['admin_account']['account']['#tree'] = TRUE; $form['admin_account']['account']['mail'] = array('#type' => 'email', '#title' => $this->t('Email address'), '#required' => TRUE); // Use default drush options if available whilst running a site install. if (function_exists('drush_get_option') && function_exists('drush_generate_password')) { $form['admin_account']['account']['name']['#default_value'] = drush_get_option('account-name', 'admin'); $form['admin_account']['account']['pass']['#type'] = 'textfield'; $form['admin_account']['account']['pass']['#default_value'] = drush_get_option('account-pass', drush_generate_password()); $form['admin_account']['account']['mail']['#default_value'] = drush_get_option('account-mail', '*****@*****.**'); } $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save and continue'), '#weight' => 15, '#button_type' => 'primary'); return $form; }