Version 1
[yaffs-website] / web / core / lib / Drupal / Core / Installer / Form / SiteSettingsForm.php
diff --git a/web/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/web/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
new file mode 100644 (file)
index 0000000..5442d15
--- /dev/null
@@ -0,0 +1,247 @@
+<?php
+
+namespace Drupal\Core\Installer\Form;
+
+use Drupal\Component\Utility\Crypt;
+use Drupal\Core\Database\Database;
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RendererInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a form to configure and rewrite settings.php.
+ */
+class SiteSettingsForm extends FormBase {
+
+  /**
+   * The site path.
+   *
+   * @var string
+   */
+  protected $sitePath;
+
+  /**
+   * The renderer.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * Constructs a new SiteSettingsForm.
+   *
+   * @param string $site_path
+   *   The site path.
+   */
+  public function __construct($site_path, RendererInterface $renderer) {
+    $this->sitePath = $site_path;
+    $this->renderer = $renderer;
+  }
+
+  /**
+    * {@inheritdoc}
+    */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('site.path'),
+      $container->get('renderer')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'install_settings_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $settings_file = './' . $this->sitePath . '/settings.php';
+
+    $form['#title'] = $this->t('Database configuration');
+
+    $drivers = drupal_get_database_types();
+    $drivers_keys = array_keys($drivers);
+
+    // Unless there is input for this form (for a non-interactive installation,
+    // input originates from the $settings array passed into install_drupal()),
+    // check whether database connection settings have been prepared in
+    // settings.php already.
+    // Note: The installer even executes this form if there is a valid database
+    // connection already, since the submit handler of this form is responsible
+    // for writing all $settings to settings.php (not limited to $databases).
+    $input = &$form_state->getUserInput();
+    if (!isset($input['driver']) && $database = Database::getConnectionInfo()) {
+      $input['driver'] = $database['default']['driver'];
+      $input[$database['default']['driver']] = $database['default'];
+    }
+
+    if (isset($input['driver'])) {
+      $default_driver = $input['driver'];
+      // In case of database connection info from settings.php, as well as for a
+      // programmed form submission (non-interactive installer), the table prefix
+      // information is usually normalized into an array already, but the form
+      // element only allows to configure one default prefix for all tables.
+      $prefix = &$input[$default_driver]['prefix'];
+      if (isset($prefix) && is_array($prefix)) {
+        $prefix = $prefix['default'];
+      }
+      $default_options = $input[$default_driver];
+    }
+    // If there is no database information yet, suggest the first available driver
+    // as default value, so that its settings form is made visible via #states
+    // when JavaScript is enabled (see below).
+    else {
+      $default_driver = current($drivers_keys);
+      $default_options = [];
+    }
+
+    $form['driver'] = [
+      '#type' => 'radios',
+      '#title' => $this->t('Database type'),
+      '#required' => TRUE,
+      '#default_value' => $default_driver,
+    ];
+    if (count($drivers) == 1) {
+      $form['driver']['#disabled'] = TRUE;
+    }
+
+    // Add driver specific configuration options.
+    foreach ($drivers as $key => $driver) {
+      $form['driver']['#options'][$key] = $driver->name();
+
+      $form['settings'][$key] = $driver->getFormOptions($default_options);
+      $form['settings'][$key]['#prefix'] = '<h2 class="js-hide">' . $this->t('@driver_name settings', ['@driver_name' => $driver->name()]) . '</h2>';
+      $form['settings'][$key]['#type'] = 'container';
+      $form['settings'][$key]['#tree'] = TRUE;
+      $form['settings'][$key]['advanced_options']['#parents'] = [$key];
+      $form['settings'][$key]['#states'] = [
+        'visible' => [
+          ':input[name=driver]' => ['value' => $key],
+        ]
+      ];
+    }
+
+    $form['actions'] = ['#type' => 'actions'];
+    $form['actions']['save'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Save and continue'),
+      '#button_type' => 'primary',
+      '#limit_validation_errors' => [
+        ['driver'],
+        [$default_driver],
+      ],
+      '#submit' => ['::submitForm'],
+    ];
+
+    $form['errors'] = [];
+    $form['settings_file'] = ['#type' => 'value', '#value' => $settings_file];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    $driver = $form_state->getValue('driver');
+    $database = $form_state->getValue($driver);
+    $drivers = drupal_get_database_types();
+    $reflection = new \ReflectionClass($drivers[$driver]);
+    $install_namespace = $reflection->getNamespaceName();
+    // Cut the trailing \Install from namespace.
+    $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\'));
+    $database['driver'] = $driver;
+
+    $form_state->set('database', $database);
+    foreach ($this->getDatabaseErrors($database, $form_state->getValue('settings_file')) as $name => $message) {
+      $form_state->setErrorByName($name, $message);
+    }
+  }
+
+  /**
+   * Get any database errors and links them to a form element.
+   *
+   * @param array $database
+   *   An array of database settings.
+   * @param string $settings_file
+   *   The settings file that contains the database settings.
+   *
+   * @return array
+   *   An array of form errors keyed by the element name and parents.
+   */
+  protected function getDatabaseErrors(array $database, $settings_file) {
+    $errors = install_database_errors($database, $settings_file);
+    $form_errors = array_filter($errors, function($value) {
+      // Errors keyed by something other than an integer already are linked to
+      // form elements.
+      return is_int($value);
+    });
+
+    // Find the generic errors.
+    $errors = array_diff_key($errors, $form_errors);
+
+    if (count($errors)) {
+      $error_message = [
+        '#type' => 'inline_template',
+        '#template' => '{% trans %}Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="https://www.drupal.org/getting-started/install">installation handbook</a>, or contact your hosting provider.{% endtrans%}{{ errors }}',
+        '#context' => [
+          'errors' => [
+            '#theme' => 'item_list',
+            '#items' => $errors,
+          ],
+        ],
+      ];
+
+      // These are generic errors, so we do not have any specific key of the
+      // database connection array to attach them to; therefore, we just put
+      // them in the error array with standard numeric keys.
+      $form_errors[$database['driver'] . '][0'] = $this->renderer->renderPlain($error_message);
+    }
+
+    return $form_errors;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    global $install_state;
+
+    // Update global settings array and save.
+    $settings = [];
+    $database = $form_state->get('database');
+    $settings['databases']['default']['default'] = (object) [
+      'value'    => $database,
+      'required' => TRUE,
+    ];
+    $settings['settings']['hash_salt'] = (object) [
+      'value'    => Crypt::randomBytesBase64(55),
+      'required' => TRUE,
+    ];
+    // Remember the profile which was used.
+    $settings['settings']['install_profile'] = (object) [
+      'value' => $install_state['parameters']['profile'],
+      'required' => TRUE,
+    ];
+
+    drupal_rewrite_settings($settings);
+
+    // Add the config directories to settings.php.
+    drupal_install_config_directories();
+
+    // Indicate that the settings file has been verified, and check the database
+    // for the last completed task, now that we have a valid connection. This
+    // last step is important since we want to trigger an error if the new
+    // database already has Drupal installed.
+    $install_state['settings_verified'] = TRUE;
+    $install_state['config_verified'] = TRUE;
+    $install_state['database_verified'] = TRUE;
+    $install_state['completed_task'] = install_verify_completed_task();
+  }
+
+}