SiteConfigureForm.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. namespace Drupal\Core\Installer\Form;
  3. use Drupal\Core\Extension\ModuleInstallerInterface;
  4. use Drupal\Core\Form\ConfigFormBase;
  5. use Drupal\Core\Form\FormStateInterface;
  6. use Drupal\Core\Locale\CountryManagerInterface;
  7. use Drupal\Core\Site\Settings;
  8. use Drupal\Core\State\StateInterface;
  9. use Drupal\user\UserStorageInterface;
  10. use Symfony\Component\DependencyInjection\ContainerInterface;
  11. /**
  12. * Provides the site configuration form.
  13. *
  14. * @internal
  15. */
  16. class SiteConfigureForm extends ConfigFormBase {
  17. /**
  18. * The site path.
  19. *
  20. * @var string
  21. */
  22. protected $sitePath;
  23. /**
  24. * The user storage.
  25. *
  26. * @var \Drupal\user\UserStorageInterface
  27. */
  28. protected $userStorage;
  29. /**
  30. * The state service.
  31. *
  32. * @var \Drupal\Core\State\StateInterface
  33. */
  34. protected $state;
  35. /**
  36. * The module installer.
  37. *
  38. * @var \Drupal\Core\Extension\ModuleInstallerInterface
  39. */
  40. protected $moduleInstaller;
  41. /**
  42. * The country manager.
  43. *
  44. * @var \Drupal\Core\Locale\CountryManagerInterface
  45. */
  46. protected $countryManager;
  47. /**
  48. * The app root.
  49. *
  50. * @var string
  51. */
  52. protected $root;
  53. /**
  54. * Constructs a new SiteConfigureForm.
  55. *
  56. * @param string $root
  57. * The app root.
  58. * @param string $site_path
  59. * The site path.
  60. * @param \Drupal\user\UserStorageInterface $user_storage
  61. * The user storage.
  62. * @param \Drupal\Core\State\StateInterface $state
  63. * The state service.
  64. * @param \Drupal\Core\Extension\ModuleInstallerInterface $module_installer
  65. * The module installer.
  66. * @param \Drupal\Core\Locale\CountryManagerInterface $country_manager
  67. * The country manager.
  68. */
  69. public function __construct($root, $site_path, UserStorageInterface $user_storage, StateInterface $state, ModuleInstallerInterface $module_installer, CountryManagerInterface $country_manager) {
  70. $this->root = $root;
  71. $this->sitePath = $site_path;
  72. $this->userStorage = $user_storage;
  73. $this->state = $state;
  74. $this->moduleInstaller = $module_installer;
  75. $this->countryManager = $country_manager;
  76. }
  77. /**
  78. * {@inheritdoc}
  79. */
  80. public static function create(ContainerInterface $container) {
  81. return new static(
  82. $container->get('app.root'),
  83. $container->get('site.path'),
  84. $container->get('entity.manager')->getStorage('user'),
  85. $container->get('state'),
  86. $container->get('module_installer'),
  87. $container->get('country_manager')
  88. );
  89. }
  90. /**
  91. * {@inheritdoc}
  92. */
  93. public function getFormId() {
  94. return 'install_configure_form';
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. protected function getEditableConfigNames() {
  100. return [
  101. 'system.date',
  102. 'system.site',
  103. 'update.settings',
  104. ];
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function buildForm(array $form, FormStateInterface $form_state) {
  110. global $install_state;
  111. $form['#title'] = $this->t('Configure site');
  112. // Warn about settings.php permissions risk
  113. $settings_dir = $this->sitePath;
  114. $settings_file = $settings_dir . '/settings.php';
  115. // Check that $_POST is empty so we only show this message when the form is
  116. // first displayed, not on the next page after it is submitted. (We do not
  117. // want to repeat it multiple times because it is a general warning that is
  118. // not related to the rest of the installation process; it would also be
  119. // especially out of place on the last page of the installer, where it would
  120. // distract from the message that the Drupal installation has completed
  121. // successfully.)
  122. $post_params = $this->getRequest()->request->all();
  123. if (empty($post_params) && (Settings::get('skip_permissions_hardening') || !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'))) {
  124. $this->messenger()->addWarning(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>.', ['%dir' => $settings_dir, '%file' => $settings_file, ':handbook_url' => 'https://www.drupal.org/server-permissions']));
  125. }
  126. $form['#attached']['library'][] = 'system/drupal.system';
  127. // Add JavaScript time zone detection.
  128. $form['#attached']['library'][] = 'core/drupal.timezone';
  129. // We add these strings as settings because JavaScript translation does not
  130. // work during installation.
  131. $form['#attached']['drupalSettings']['copyFieldValue']['edit-site-mail'] = ['edit-account-mail'];
  132. $form['site_information'] = [
  133. '#type' => 'fieldgroup',
  134. '#title' => $this->t('Site information'),
  135. '#access' => empty($install_state['config_install_path']),
  136. ];
  137. $form['site_information']['site_name'] = [
  138. '#type' => 'textfield',
  139. '#title' => $this->t('Site name'),
  140. '#required' => TRUE,
  141. '#weight' => -20,
  142. '#access' => empty($install_state['config_install_path']),
  143. ];
  144. $form['site_information']['site_mail'] = [
  145. '#type' => 'email',
  146. '#title' => $this->t('Site email address'),
  147. '#default_value' => ini_get('sendmail_from'),
  148. '#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."),
  149. '#required' => TRUE,
  150. '#weight' => -15,
  151. '#access' => empty($install_state['config_install_path']),
  152. ];
  153. $form['admin_account'] = [
  154. '#type' => 'fieldgroup',
  155. '#title' => $this->t('Site maintenance account'),
  156. ];
  157. $form['admin_account']['account']['name'] = [
  158. '#type' => 'textfield',
  159. '#title' => $this->t('Username'),
  160. '#maxlength' => USERNAME_MAX_LENGTH,
  161. '#description' => $this->t("Several special characters are allowed, including space, period (.), hyphen (-), apostrophe ('), underscore (_), and the @ sign."),
  162. '#required' => TRUE,
  163. '#attributes' => ['class' => ['username']],
  164. ];
  165. $form['admin_account']['account']['pass'] = [
  166. '#type' => 'password_confirm',
  167. '#required' => TRUE,
  168. '#size' => 25,
  169. ];
  170. $form['admin_account']['account']['#tree'] = TRUE;
  171. $form['admin_account']['account']['mail'] = [
  172. '#type' => 'email',
  173. '#title' => $this->t('Email address'),
  174. '#required' => TRUE,
  175. ];
  176. $form['regional_settings'] = [
  177. '#type' => 'fieldgroup',
  178. '#title' => $this->t('Regional settings'),
  179. '#access' => empty($install_state['config_install_path']),
  180. ];
  181. $countries = $this->countryManager->getList();
  182. $form['regional_settings']['site_default_country'] = [
  183. '#type' => 'select',
  184. '#title' => $this->t('Default country'),
  185. '#empty_value' => '',
  186. '#default_value' => $this->config('system.date')->get('country.default'),
  187. '#options' => $countries,
  188. '#description' => $this->t('Select the default country for the site.'),
  189. '#weight' => 0,
  190. '#access' => empty($install_state['config_install_path']),
  191. ];
  192. $form['regional_settings']['date_default_timezone'] = [
  193. '#type' => 'select',
  194. '#title' => $this->t('Default time zone'),
  195. // Use system timezone if set, but avoid throwing a warning in PHP >=5.4
  196. '#default_value' => @date_default_timezone_get(),
  197. '#options' => system_time_zones(NULL, TRUE),
  198. '#description' => $this->t('By default, dates in this site will be displayed in the chosen time zone.'),
  199. '#weight' => 5,
  200. '#attributes' => ['class' => ['timezone-detect']],
  201. '#access' => empty($install_state['config_install_path']),
  202. ];
  203. $form['update_notifications'] = [
  204. '#type' => 'fieldgroup',
  205. '#title' => $this->t('Update notifications'),
  206. '#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>.', [':drupal' => 'https://www.drupal.org']),
  207. '#access' => empty($install_state['config_install_path']),
  208. ];
  209. $form['update_notifications']['enable_update_status_module'] = [
  210. '#type' => 'checkbox',
  211. '#title' => $this->t('Check for updates automatically'),
  212. '#default_value' => 1,
  213. '#access' => empty($install_state['config_install_path']),
  214. ];
  215. $form['update_notifications']['enable_update_status_emails'] = [
  216. '#type' => 'checkbox',
  217. '#title' => $this->t('Receive email notifications'),
  218. '#default_value' => 1,
  219. '#states' => [
  220. 'visible' => [
  221. 'input[name="enable_update_status_module"]' => ['checked' => TRUE],
  222. ],
  223. ],
  224. '#access' => empty($install_state['config_install_path']),
  225. ];
  226. $form['actions'] = ['#type' => 'actions'];
  227. $form['actions']['submit'] = [
  228. '#type' => 'submit',
  229. '#value' => $this->t('Save and continue'),
  230. '#weight' => 15,
  231. '#button_type' => 'primary',
  232. ];
  233. return $form;
  234. }
  235. /**
  236. * {@inheritdoc}
  237. */
  238. public function validateForm(array &$form, FormStateInterface $form_state) {
  239. if ($error = user_validate_name($form_state->getValue(['account', 'name']))) {
  240. $form_state->setErrorByName('account][name', $error);
  241. }
  242. }
  243. /**
  244. * {@inheritdoc}
  245. */
  246. public function submitForm(array &$form, FormStateInterface $form_state) {
  247. global $install_state;
  248. if (empty($install_state['config_install_path'])) {
  249. $this->config('system.site')
  250. ->set('name', (string) $form_state->getValue('site_name'))
  251. ->set('mail', (string) $form_state->getValue('site_mail'))
  252. ->save(TRUE);
  253. $this->config('system.date')
  254. ->set('timezone.default', (string) $form_state->getValue('date_default_timezone'))
  255. ->set('country.default', (string) $form_state->getValue('site_default_country'))
  256. ->save(TRUE);
  257. }
  258. $account_values = $form_state->getValue('account');
  259. // Enable update.module if this option was selected.
  260. $update_status_module = $form_state->getValue('enable_update_status_module');
  261. if (empty($install_state['config_install_path']) && $update_status_module) {
  262. $this->moduleInstaller->install(['file', 'update'], FALSE);
  263. // Add the site maintenance account's email address to the list of
  264. // addresses to be notified when updates are available, if selected.
  265. $email_update_status_emails = $form_state->getValue('enable_update_status_emails');
  266. if ($email_update_status_emails) {
  267. // Reset the configuration factory so it is updated with the new module.
  268. $this->resetConfigFactory();
  269. $this->config('update.settings')->set('notification.emails', [$account_values['mail']])->save(TRUE);
  270. }
  271. }
  272. // We precreated user 1 with placeholder values. Let's save the real values.
  273. $account = $this->userStorage->load(1);
  274. $account->init = $account->mail = $account_values['mail'];
  275. $account->roles = $account->getRoles();
  276. $account->activate();
  277. $account->timezone = $form_state->getValue('date_default_timezone');
  278. $account->pass = $account_values['pass'];
  279. $account->name = $account_values['name'];
  280. $account->save();
  281. // Record when this install ran.
  282. $this->state->set('install_time', $_SERVER['REQUEST_TIME']);
  283. }
  284. }