You are here

class SyncConfigureForm in Configuration installer 8

Installation step to configure sync directory or upload a tarball.

Hierarchy

Expanded class hierarchy of SyncConfigureForm

File

src/Form/SyncConfigureForm.php, line 23

Namespace

Drupal\config_installer\Form
View source
class SyncConfigureForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'config_installer_sync_configure_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#title'] = $this
      ->t('Configure configuration import location');
    $form['sync_directory'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Synchronisation directory'),
      '#default_value' => config_get_config_directory(CONFIG_SYNC_DIRECTORY),
      '#maxlength' => 255,
      '#description' => $this
        ->t('Path to the config directory you wish to import, can be relative to document root or an absolute path.'),
      '#required' => TRUE,
      // This value can only be changed if settngs.php is writable.
      '#disabled' => !is_writable(\Drupal::service('site.path') . '/settings.php'),
    ];
    $form['import_tarball'] = [
      '#type' => 'file',
      '#title' => $this
        ->t('Select your configuration export file'),
      '#description' => $this
        ->t('If the sync directory is empty you can upload a configuration export file.'),
    ];
    $form['actions'] = [
      '#type' => 'actions',
    ];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Save and continue'),
      '#weight' => 15,
      '#button_type' => 'primary',
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    global $config_directories;
    global $install_state;
    $file_upload = $this
      ->getRequest()->files
      ->get('files', NULL, TRUE);
    $has_upload = FALSE;
    if (!empty($file_upload['import_tarball']) && $file_upload['import_tarball']
      ->isValid()) {

      // The sync directory must be empty if we are doing an upload.
      $form_state
        ->setValue('import_tarball', $file_upload['import_tarball']
        ->getRealPath());
      $has_upload = TRUE;
    }
    $sync_directory = $form_state
      ->getValue('sync_directory');

    // If we've customised the sync directory ensure its good to go.
    if ($sync_directory !== config_get_config_directory(CONFIG_SYNC_DIRECTORY)) {

      // We have to create the directory if it does not exist. If it exists we
      // need to ensure it is writeable is we are processing an upload.
      $create_directory = !is_dir($sync_directory) || $has_upload;
      if ($create_directory && !file_prepare_directory($sync_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
        $form_state
          ->setErrorByName('sync_directory', t('The directory %directory could not be created or could not be made writable. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see the <a href="@handbook_url">online handbook</a>.', [
          '%directory' => $sync_directory,
          '@handbook_url' => 'http://drupal.org/server-permissions',
        ]));
      }
    }

    // If no tarball ensure we have files.
    if (!$has_upload && !$form_state
      ->hasAnyErrors()) {
      $sync = new FileStorage($sync_directory);
      if (count($sync
        ->listAll()) === 0) {
        $form_state
          ->setErrorByName('sync_directory', $this
          ->t('No file upload provided and the sync directory is empty'));
      }
    }

    // Early exit if we have errors.
    if ($form_state
      ->hasAnyErrors()) {
      return;
    }

    // Update the sync directory setting if required.
    if ($sync_directory !== config_get_config_directory(CONFIG_SYNC_DIRECTORY)) {
      $settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [
        'value' => $sync_directory,
        'required' => TRUE,
      ];
      drupal_rewrite_settings($settings);
      $config_directories[CONFIG_SYNC_DIRECTORY] = $sync_directory;
    }

    // Upload tarball if provided so we can validate the files.
    if ($tarball_path = $form_state
      ->getValue('import_tarball')) {

      // Ensure that we have an empty directory if we're going.
      $sync = new FileStorage($sync_directory);
      $sync
        ->deleteAll();
      try {
        $archiver = new ArchiveTar($tarball_path, 'gz');
        $files = [];
        $list = $archiver
          ->listContent();
        if (is_array($list)) {

          /** @var array $list */
          foreach ($list as $file) {
            $files[] = $file['filename'];
          }
          $archiver
            ->extractList($files, config_get_config_directory(CONFIG_SYNC_DIRECTORY));
        }
      } catch (\Exception $e) {
        $form_state
          ->setErrorByName('import_tarball', $this
          ->t('Could not extract the contents of the tar file. The error message is <em>@message</em>', [
          '@message' => $e
            ->getMessage(),
        ]));
      }
      drupal_unlink($tarball_path);
      if (empty($files)) {
        $form_state
          ->setErrorByName('import_tarball', $this
          ->t('The tar file contoins no files.'));
      }
    }

    // Early exit if we have errors.
    if ($form_state
      ->hasAnyErrors()) {
      return;
    }

    // Create a source storage that reads from sync.
    $listing = new ExtensionDiscovery(\Drupal::root());
    $listing
      ->setProfileDirectories([]);
    $sync = new SourceStorage(\Drupal::service('config.storage.sync'), $listing
      ->scan('profile'));

    // Match up the site uuids, the install_base_system install task will have
    // installed the system module and created a new UUID.
    $system_site = $sync
      ->read('system.site');
    \Drupal::configFactory()
      ->getEditable('system.site')
      ->set('uuid', $system_site['uuid'])
      ->save();
    if (version_compare(\Drupal::VERSION, '8.3', '>=')) {

      // In Drupal 8.3.x the install profile has moved to configuration.
      // @see https://www.drupal.org/node/2156401
      \Drupal::configFactory()
        ->getEditable('core.extension')
        ->set('profile', _config_installer_get_original_install_profile())
        ->save();
    }

    // Create the storage comparer and the config importer.
    $config_manager = \Drupal::service('config.manager');
    $storage_comparer = new StorageComparer($sync, \Drupal::service('config.storage'), $config_manager);
    $storage_comparer
      ->createChangelist();
    $config_importer = new ConfigImporter($storage_comparer, \Drupal::service('event_dispatcher'), $config_manager, \Drupal::service('lock.persistent'), \Drupal::service('config.typed'), \Drupal::service('module_handler'), \Drupal::service('module_installer'), \Drupal::service('theme_handler'), \Drupal::service('string_translation'));

    // Change $install_state profile to find profile modules during validation.
    $install_state['parameters']['profile'] = _config_installer_get_original_install_profile();
    try {
      $config_importer
        ->validate();
    } catch (ConfigImporterException $e) {
      $error_message = [
        '#type' => 'inline_template',
        '#template' => '{% trans %}The configuration cannot be imported because it failed validation for the following reasons:{% endtrans%}{{ errors }}',
        '#context' => [
          'errors' => [
            '#theme' => 'item_list',
            '#items' => $config_importer
              ->getErrors(),
          ],
        ],
      ];
      $field_name = $has_upload ? 'import_tarball' : 'sync_directory';
      $form_state
        ->setErrorByName($field_name, \Drupal::service('renderer')
        ->renderPlain($error_message));
    }

    // Revert $install_state profie to continue with the regular process.
    $install_state['parameters']['profile'] = 'config_installer';
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    global $install_state;

    // Change the langcode to the site default langcode provided by the
    // configuration.
    $config_storage = new FileStorage(config_get_config_directory(CONFIG_SYNC_DIRECTORY));
    $install_state['parameters']['langcode'] = $config_storage
      ->read('system.site')['langcode'];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormBase::$configFactory protected property The config factory. 1
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
FormBase::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create 87
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
SyncConfigureForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
SyncConfigureForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
SyncConfigureForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
SyncConfigureForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.