diff --git a/core/modules/config/config.info.yml b/core/modules/config/config.info.yml index 88821ce..3381f65 100644 --- a/core/modules/config/config.info.yml +++ b/core/modules/config/config.info.yml @@ -4,4 +4,4 @@ description: 'Allows administrators to manage configuration changes.' package: Core version: VERSION core: 8.x -configure: config.sync +configure: config.import_full diff --git a/core/modules/config/config.links.menu.yml b/core/modules/config/config.links.menu.yml index 87a9b92..c055d2a 100644 --- a/core/modules/config/config.links.menu.yml +++ b/core/modules/config/config.links.menu.yml @@ -1,5 +1,5 @@ -config.sync: +config.import_full: title: 'Configuration management' - description: 'Import, export, or synchronize your site configuration.' - route_name: config.sync + description: 'Import or export your site configuration.' + route_name: config.import_full parent: system.admin_config_development diff --git a/core/modules/config/config.links.task.yml b/core/modules/config/config.links.task.yml index 5a894f0..968c563 100644 --- a/core/modules/config/config.links.task.yml +++ b/core/modules/config/config.links.task.yml @@ -1,34 +1,29 @@ -config.sync: - route_name: config.sync - base_route: config.sync - title: 'Synchronize' - -config.full: +config.import: route_name: config.import_full - title: 'Full Import/Export' - base_route: config.sync + title: 'Import' + base_route: config.import -config.single: - route_name: config.import_single - title: 'Single Import/Export' - base_route: config.sync +config.export: + route_name: config.export_full + title: 'Export' + base_route: config.import config.export_full: route_name: config.export_full - title: Export - parent_id: config.full + title: Full + parent_id: config.export config.import_full: route_name: config.import_full - title: Import - parent_id: config.full + title: Full + parent_id: config.import config.export_single: route_name: config.export_single - title: Export - parent_id: config.single + title: Single + parent_id: config.export config.import_single: route_name: config.import_single - title: Import - parent_id: config.single + title: Single + parent_id: config.import diff --git a/core/modules/config/config.module b/core/modules/config/config.module index f58dff9..5f86162 100644 --- a/core/modules/config/config.module +++ b/core/modules/config/config.module @@ -31,9 +31,9 @@ function config_help($route_name, RouteMatchInterface $route_match) { $output .= ''; return $output; - case 'config.sync': + case 'config.import_full': $output = ''; - $output .= '

' . t('Import configuration that is placed in your staging directory. All changes, deletions, renames, and additions are listed below.') . '

'; + $output .= '

' . t('Pellentesque sit amet sem et purus pretium consectetuer.') . '

'; return $output; case 'config.export_full': diff --git a/core/modules/config/config.permissions.yml b/core/modules/config/config.permissions.yml index ee24216..5407f60 100644 --- a/core/modules/config/config.permissions.yml +++ b/core/modules/config/config.permissions.yml @@ -1,6 +1,3 @@ -synchronize configuration: - title: 'Synchronize configuration' - restrict access: true export configuration: title: 'Export configuration' restrict access: true diff --git a/core/modules/config/config.routing.yml b/core/modules/config/config.routing.yml index 8eebac3..d8a45ad 100644 --- a/core/modules/config/config.routing.yml +++ b/core/modules/config/config.routing.yml @@ -1,18 +1,10 @@ -config.sync: - path: '/admin/config/development/configuration' - defaults: - _form: '\Drupal\config\Form\ConfigSync' - _title: 'Synchronize' - requirements: - _permission: 'synchronize configuration' - config.diff: path: '/admin/config/development/configuration/sync/diff/{source_name}/{target_name}' defaults: _controller: '\Drupal\config\Controller\ConfigController::diff' target_name: NULL requirements: - _permission: 'synchronize configuration' + _permission: 'import configuration' config.diff_collection: path: '/admin/config/development/configuration/sync/diff_collection/{collection}/{source_name}/{target_name}' @@ -20,7 +12,7 @@ config.diff_collection: _controller: '\Drupal\config\Controller\ConfigController::diff' target_name: NULL requirements: - _permission: 'synchronize configuration' + _permission: 'import configuration' config.export_download: path: '/admin/config/development/configuration/full/export-download' @@ -62,3 +54,11 @@ config.export_single: config_name: NULL requirements: _permission: 'export configuration' + +config.import_full_import_confirm: + path: '/admin/config/development/configuration/full/import/confirm' + defaults: + _form: 'Drupal\config\Form\ConfigImportConfirmForm' + _title: 'Confirm configuration import' + requirements: + _permission: 'import configuration' diff --git a/core/modules/config/src/Controller/ConfigController.php b/core/modules/config/src/Controller/ConfigController.php index b6ee57a..a76fc92 100644 --- a/core/modules/config/src/Controller/ConfigController.php +++ b/core/modules/config/src/Controller/ConfigController.php @@ -156,8 +156,8 @@ public function diff($source_name, $target_name = NULL, $collection = NULL) { 'dialog-cancel', ), ), - '#title' => "Back to 'Synchronize configuration' page.", - '#url' => Url::fromRoute('config.sync'), + '#title' => "Back to 'Import configuration' page.", + '#url' => Url::fromRoute('config.import_full'), ); return $build; diff --git a/core/modules/config/src/Form/ConfigImportConfirmForm.php b/core/modules/config/src/Form/ConfigImportConfirmForm.php new file mode 100644 index 0000000..c72866d --- /dev/null +++ b/core/modules/config/src/Form/ConfigImportConfirmForm.php @@ -0,0 +1,265 @@ +eventDispatcher = $event_dispatcher; + $this->configManager = $config_manager; + $this->lock = $lock; + $this->typedConfigManager = $typed_config_manager; + $this->moduleHandler = $module_handler; + $this->moduleInstaller = $module_installer; + $this->themeHandler = $theme_handler; + $this->keyValueExpirable = $key_value_expirable; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('event_dispatcher'), + $container->get('config.manager'), + $container->get('lock.persistent'), + $container->get('config.typed'), + $container->get('module_handler'), + $container->get('module_installer'), + $container->get('theme_handler'), + $container->get('keyvalue.expirable')->get('config_import') + ); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $account = $this->currentUser()->id(); + $this->storageComparer = $this->keyValueExpirable->get($account); + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $config_importer = new ConfigImporter( + $this->storageComparer, + $this->eventDispatcher, + $this->configManager, + $this->lock, + $this->typedConfigManager, + $this->moduleHandler, + $this->moduleInstaller, + $this->themeHandler, + $this->getStringTranslation() + ); + if ($config_importer->alreadyImporting()) { + drupal_set_message($this->t('Another request may be synchronizing configuration already.')); + } + else { + try { + $sync_steps = $config_importer->initialize(); + $batch = array( + 'operations' => array(), + 'finished' => array(get_class($this), 'finishBatch'), + 'title' => t('Synchronizing configuration'), + 'init_message' => t('Starting configuration synchronization.'), + 'progress_message' => t('Completed @current step of @total.'), + 'error_message' => t('Configuration synchronization has encountered an error.'), + 'file' => drupal_get_path('module', 'config') . '/config.admin.inc', + ); + foreach ($sync_steps as $sync_step) { + $batch['operations'][] = array( + array(get_class($this), 'processBatch'), + array($config_importer, $sync_step), + ); + } + + batch_set($batch); + $form_state->setRedirect('config.import_full'); + } + catch (ConfigImporterException $e) { + // There are validation errors. + drupal_set_message($this->t('The configuration cannot be imported because it failed validation for the following reasons:'), 'error'); + foreach ($config_importer->getErrors() as $message) { + drupal_set_message($message, 'error'); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return t('Confirm configuration import'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Import'); + } + + /** + * {@inheritdoc} + */ + public function getCancelUrl() { + return new Url('config.import_full'); + } + + /** + * Processes the config import batch and persists the importer. + * + * @param \Drupal\Core\Config\ConfigImporter $config_importer + * The batch config importer object to persist. + * @param string $sync_step + * The synchronization step to do. + * @param array $context + * The batch context. + */ + public static function processBatch(ConfigImporter $config_importer, $sync_step, &$context) { + if (!isset($context['sandbox']['config_importer'])) { + $context['sandbox']['config_importer'] = $config_importer; + } + + $config_importer = $context['sandbox']['config_importer']; + $config_importer->doSyncStep($sync_step, $context); + if ($errors = $config_importer->getErrors()) { + if (!isset($context['results']['errors'])) { + $context['results']['errors'] = array(); + } + $context['results']['errors'] += $errors; + } + } + + /** + * Finish batch. + * + * This function is a static function to avoid serializing the ConfigSync + * object unnecessarily. + */ + public static function finishBatch($success, $results, $operations) { + if ($success) { + if (!empty($results['errors'])) { + foreach ($results['errors'] as $error) { + drupal_set_message($error, 'error'); + \Drupal::logger('config_sync')->error($error); + } + drupal_set_message(\Drupal::translation()->translate('The configuration was imported with errors.'), 'warning'); + } + else { + drupal_set_message(\Drupal::translation()->translate('The configuration was imported successfully.')); + } + } + else { + // An error occurred. + // $operations contains the operations that remained unprocessed. + $error_operation = reset($operations); + $message = \Drupal::translation()->translate('An error occurred while processing %error_operation with arguments: @arguments', array( + '%error_operation' => $error_operation[0], + '@arguments' => print_r($error_operation[1], TRUE), + )); + drupal_set_message($message, 'error'); + } + } +} diff --git a/core/modules/config/src/Form/ConfigImportForm.php b/core/modules/config/src/Form/ConfigImportForm.php index 7b29e3f..0fc8b24 100644 --- a/core/modules/config/src/Form/ConfigImportForm.php +++ b/core/modules/config/src/Form/ConfigImportForm.php @@ -9,8 +9,13 @@ use Drupal\Core\Archiver\ArchiveTar; use Drupal\Core\Config\StorageInterface; +use Drupal\Core\Config\ConfigManagerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Config\StorageComparer; +use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; +use Drupal\Core\Render\RendererInterface; +use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -26,13 +31,54 @@ class ConfigImportForm extends FormBase { protected $configStorage; /** + * The staging configuration object. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $stagingStorage; + + /** + * The active configuration object. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $activeStorage; + + /** + * The snapshot configuration object. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $snapshotStorage; + + /** + * The configuration manager. + * + * @var \Drupal\Core\Config\ConfigManagerInterface; + */ + protected $configManager; + + /** + * The renderer. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** * Constructs a new ConfigImportForm. * * @param \Drupal\Core\Config\StorageInterface $config_storage * The configuration storage. */ - public function __construct(StorageInterface $config_storage) { + public function __construct(StorageInterface $staging_storage, StorageInterface $active_storage, StorageInterface $snapshot_storage, StorageInterface $config_storage, ConfigManagerInterface $config_manager, KeyValueStoreExpirableInterface $key_value_expirable, RendererInterface $renderer) { + $this->stagingStorage = $staging_storage; + $this->activeStorage = $active_storage; + $this->snapshotStorage = $snapshot_storage; $this->configStorage = $config_storage; + $this->configManager = $config_manager; + $this->keyValueExpirable = $key_value_expirable; + $this->renderer = $renderer; } /** @@ -40,7 +86,13 @@ public function __construct(StorageInterface $config_storage) { */ public static function create(ContainerInterface $container) { return new static( - $container->get('config.storage.staging') + $container->get('config.storage.staging'), + $container->get('config.storage'), + $container->get('config.storage.snapshot'), + $container->get('config.storage.staging'), + $container->get('config.manager'), + $container->get('keyvalue.expirable')->get('config_import'), + $container->get('renderer') ); } @@ -65,6 +117,142 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#type' => 'submit', '#value' => $this->t('Upload'), ); + + $source_list = $this->stagingStorage->listAll(); + $storage_comparer = new StorageComparer($this->stagingStorage, $this->activeStorage, $this->configManager); + if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) { + $form['no_changes'] = array( + '#type' => 'table', + '#header' => array('Name', 'Operations'), + '#rows' => array(), + '#empty' => $this->t('There are no configuration changes to import.'), + ); + $form['actions']['#access'] = FALSE; + return $form; + } + elseif (!$storage_comparer->validateSiteUuid()) { + drupal_set_message($this->t('The staged configuration cannot be imported, because it originates from a different site than this site. You can only synchronize configuration between cloned instances of this site.'), 'error'); + $form['actions']['#access'] = FALSE; + return $form; + } + + if ($this->snapshotStorage->exists('core.extension')) { + $snapshot_comparer = new StorageComparer($this->activeStorage, $this->snapshotStorage, $this->configManager); + if (!$form_state->getUserInput() && $snapshot_comparer->createChangelist()->hasChanges()) { + $change_list = array(); + foreach ($snapshot_comparer->getAllCollectionNames() as $collection) { + foreach ($snapshot_comparer->getChangelist(NULL, $collection) as $config_names) { + if (empty($config_names)) { + continue; + } + foreach ($config_names as $config_name) { + $change_list[] = $config_name; + } + } + } + sort($change_list); + $change_list_render = array( + '#theme' => 'item_list', + '#items' => $change_list, + ); + $change_list_html = $this->renderer->renderPlain($change_list_render); + drupal_set_message($this->t('The following items in your active configuration have changes since the last import that may be lost on the next import. !changes', array('!changes' => $change_list_html)), 'warning'); + } + } + + // Store the comparer for use in the submit. + $form_state->set('storage_comparer', $storage_comparer); + + // Add the AJAX library to the form for dialog support. + $form['#attached']['library'][] = 'core/drupal.ajax'; + + foreach ($storage_comparer->getAllCollectionNames() as $collection) { + if ($collection != StorageInterface::DEFAULT_COLLECTION) { + $form[$collection]['collection_heading'] = array( + '#type' => 'html_tag', + '#tag' => 'h2', + '#value' => $this->t('!collection configuration collection', array('!collection' => $collection)), + ); + } + foreach ($storage_comparer->getChangelist(NULL, $collection) as $config_change_type => $config_names) { + if (empty($config_names)) { + continue; + } + + // @todo A table caption would be more appropriate, but does not have + // the visual importance of a heading. + $form[$collection][$config_change_type]['heading'] = array( + '#type' => 'html_tag', + '#tag' => 'h3', + ); + switch ($config_change_type) { + case 'create': + $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count new', '@count new'); + break; + + case 'update': + $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count changed', '@count changed'); + break; + + case 'delete': + $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count removed', '@count removed'); + break; + + case 'rename': + $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count renamed', '@count renamed'); + break; + } + $form[$collection][$config_change_type]['list'] = array( + '#type' => 'table', + '#header' => array('Name', 'Operations'), + ); + + foreach ($config_names as $config_name) { + if ($config_change_type == 'rename') { + $names = $storage_comparer->extractRenameNames($config_name); + $route_options = array('source_name' => $names['old_name'], 'target_name' => $names['new_name']); + $config_name = $this->t('!source_name to !target_name', array('!source_name' => $names['old_name'], '!target_name' => $names['new_name'])); + } + else { + $route_options = array('source_name' => $config_name); + } + if ($collection != StorageInterface::DEFAULT_COLLECTION) { + $route_name = 'config.diff_collection'; + $route_options['collection'] = $collection; + } + else { + $route_name = 'config.diff'; + } + $links['view_diff'] = array( + 'title' => $this->t('View differences'), + 'url' => Url::fromRoute($route_name, $route_options), + 'attributes' => array( + 'class' => array('use-ajax'), + 'data-dialog-type' => 'modal', + 'data-dialog-options' => json_encode(array( + 'width' => 700, + )), + ), + ); + $form[$collection][$config_change_type]['list']['#rows'][] = array( + 'name' => $config_name, + 'operations' => array( + 'data' => array( + '#type' => 'operations', + '#links' => $links, + ), + ), + ); + } + } + } + + $form['import'] = array( + '#type' => 'submit', + '#value' => $this->t('Import all'), + ); + + return $form; } @@ -72,12 +260,14 @@ public function buildForm(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { - $file_upload = $this->getRequest()->files->get('files[import_tarball]', NULL, TRUE); - if ($file_upload && $file_upload->isValid()) { - $form_state->setValue('import_tarball', $file_upload->getRealPath()); - } - else { - $form_state->setErrorByName('import_tarball', $this->t('The file could not be uploaded.')); + if ($form_state->getValue('op') == t('Upload')) { + $file_upload = $this->getRequest()->files->get('files[import_tarball]', NULL, TRUE); + if ($file_upload && $file_upload->isValid()) { + $form_state->setValue('import_tarball', $file_upload->getRealPath()); + } + else { + $form_state->setErrorByName('import_tarball', $this->t('The file could not be uploaded.')); + } } } @@ -85,24 +275,32 @@ public function validateForm(array &$form, FormStateInterface $form_state) { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - if ($path = $form_state->getValue('import_tarball')) { - $this->configStorage->deleteAll(); - try { - $archiver = new ArchiveTar($path, 'gz'); - $files = array(); - foreach ($archiver->listContent() as $file) { - $files[] = $file['filename']; + if ($form_state->getValue('op') == t('Upload')) { + if ($path = $form_state->getValue('import_tarball')) { + $this->configStorage->deleteAll(); + try { + $archiver = new ArchiveTar($path, 'gz'); + $files = array(); + foreach ($archiver->listContent() as $file) { + $files[] = $file['filename']; + } + $archiver->extractList($files, config_get_config_directory(CONFIG_STAGING_DIRECTORY)); + drupal_set_message($this->t('Your configuration files were successfully uploaded and are ready for import.')); + $form_state->setRedirect('config.import_full'); + } catch (\Exception $e) { + drupal_set_message($this->t('Could not extract the contents of the tar file. The error message is @message', array('@message' => $e->getMessage())), 'error'); } - $archiver->extractList($files, config_get_config_directory(CONFIG_STAGING_DIRECTORY)); - drupal_set_message($this->t('Your configuration files were successfully uploaded and are ready for import.')); - $form_state->setRedirect('config.sync'); + drupal_unlink($path); } - catch (\Exception $e) { - drupal_set_message($this->t('Could not extract the contents of the tar file. The error message is @message', array('@message' => $e->getMessage())), 'error'); - } - drupal_unlink($path); } - } + else { + $account = $this->currentUser()->id(); + $this->keyValueExpirable->setWithExpire($account, $form_state->get('storage_comparer'), 60); + // Redirect to the confirmation form. + $form_state->setRedirect('config.import_full_import_confirm'); + return; + } + } } diff --git a/core/modules/config/src/Form/ConfigSync.php b/core/modules/config/src/Form/ConfigSync.php deleted file mode 100644 index 7f240e3..0000000 --- a/core/modules/config/src/Form/ConfigSync.php +++ /dev/null @@ -1,418 +0,0 @@ -stagingStorage = $staging_storage; - $this->activeStorage = $active_storage; - $this->snapshotStorage = $snapshot_storage; - $this->lock = $lock; - $this->eventDispatcher = $event_dispatcher; - $this->configManager = $config_manager; - $this->typedConfigManager = $typed_config; - $this->moduleHandler = $module_handler; - $this->moduleInstaller = $module_installer; - $this->themeHandler = $theme_handler; - $this->renderer = $renderer; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('config.storage.staging'), - $container->get('config.storage'), - $container->get('config.storage.snapshot'), - $container->get('lock.persistent'), - $container->get('event_dispatcher'), - $container->get('config.manager'), - $container->get('config.typed'), - $container->get('module_handler'), - $container->get('module_installer'), - $container->get('theme_handler'), - $container->get('renderer') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'config_admin_import_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state) { - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => $this->t('Import all'), - ); - $source_list = $this->stagingStorage->listAll(); - $storage_comparer = new StorageComparer($this->stagingStorage, $this->activeStorage, $this->configManager); - if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) { - $form['no_changes'] = array( - '#type' => 'table', - '#header' => array('Name', 'Operations'), - '#rows' => array(), - '#empty' => $this->t('There are no configuration changes to import.'), - ); - $form['actions']['#access'] = FALSE; - return $form; - } - elseif (!$storage_comparer->validateSiteUuid()) { - drupal_set_message($this->t('The staged configuration cannot be imported, because it originates from a different site than this site. You can only synchronize configuration between cloned instances of this site.'), 'error'); - $form['actions']['#access'] = FALSE; - return $form; - } - // A list of changes will be displayed, so check if the user should be - // warned of potential losses to configuration. - if ($this->snapshotStorage->exists('core.extension')) { - $snapshot_comparer = new StorageComparer($this->activeStorage, $this->snapshotStorage, $this->configManager); - if (!$form_state->getUserInput() && $snapshot_comparer->createChangelist()->hasChanges()) { - $change_list = array(); - foreach ($snapshot_comparer->getAllCollectionNames() as $collection) { - foreach ($snapshot_comparer->getChangelist(NULL, $collection) as $config_names) { - if (empty($config_names)) { - continue; - } - foreach ($config_names as $config_name) { - $change_list[] = $config_name; - } - } - } - sort($change_list); - $change_list_render = array( - '#theme' => 'item_list', - '#items' => $change_list, - ); - $change_list_html = $this->renderer->renderPlain($change_list_render); - drupal_set_message($this->t('The following items in your active configuration have changes since the last import that may be lost on the next import. !changes', array('!changes' => $change_list_html)), 'warning'); - } - } - - // Store the comparer for use in the submit. - $form_state->set('storage_comparer', $storage_comparer); - - // Add the AJAX library to the form for dialog support. - $form['#attached']['library'][] = 'core/drupal.ajax'; - - foreach ($storage_comparer->getAllCollectionNames() as $collection) { - if ($collection != StorageInterface::DEFAULT_COLLECTION) { - $form[$collection]['collection_heading'] = array( - '#type' => 'html_tag', - '#tag' => 'h2', - '#value' => $this->t('!collection configuration collection', array('!collection' => $collection)), - ); - } - foreach ($storage_comparer->getChangelist(NULL, $collection) as $config_change_type => $config_names) { - if (empty($config_names)) { - continue; - } - - // @todo A table caption would be more appropriate, but does not have the - // visual importance of a heading. - $form[$collection][$config_change_type]['heading'] = array( - '#type' => 'html_tag', - '#tag' => 'h3', - ); - switch ($config_change_type) { - case 'create': - $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count new', '@count new'); - break; - - case 'update': - $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count changed', '@count changed'); - break; - - case 'delete': - $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count removed', '@count removed'); - break; - - case 'rename': - $form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count renamed', '@count renamed'); - break; - } - $form[$collection][$config_change_type]['list'] = array( - '#type' => 'table', - '#header' => array('Name', 'Operations'), - ); - - foreach ($config_names as $config_name) { - if ($config_change_type == 'rename') { - $names = $storage_comparer->extractRenameNames($config_name); - $route_options = array('source_name' => $names['old_name'], 'target_name' => $names['new_name']); - $config_name = $this->t('!source_name to !target_name', array('!source_name' => $names['old_name'], '!target_name' => $names['new_name'])); - } - else { - $route_options = array('source_name' => $config_name); - } - if ($collection != StorageInterface::DEFAULT_COLLECTION) { - $route_name = 'config.diff_collection'; - $route_options['collection'] = $collection; - } - else { - $route_name = 'config.diff'; - } - $links['view_diff'] = array( - 'title' => $this->t('View differences'), - 'url' => Url::fromRoute($route_name, $route_options), - 'attributes' => array( - 'class' => array('use-ajax'), - 'data-dialog-type' => 'modal', - 'data-dialog-options' => json_encode(array( - 'width' => 700 - )), - ), - ); - $form[$collection][$config_change_type]['list']['#rows'][] = array( - 'name' => $config_name, - 'operations' => array( - 'data' => array( - '#type' => 'operations', - '#links' => $links, - ), - ), - ); - } - } - } - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $config_importer = new ConfigImporter( - $form_state->get('storage_comparer'), - $this->eventDispatcher, - $this->configManager, - $this->lock, - $this->typedConfigManager, - $this->moduleHandler, - $this->moduleInstaller, - $this->themeHandler, - $this->getStringTranslation() - ); - if ($config_importer->alreadyImporting()) { - drupal_set_message($this->t('Another request may be synchronizing configuration already.')); - } - else{ - try { - $sync_steps = $config_importer->initialize(); - $batch = array( - 'operations' => array(), - 'finished' => array(get_class($this), 'finishBatch'), - 'title' => t('Synchronizing configuration'), - 'init_message' => t('Starting configuration synchronization.'), - 'progress_message' => t('Completed @current step of @total.'), - 'error_message' => t('Configuration synchronization has encountered an error.'), - 'file' => drupal_get_path('module', 'config') . '/config.admin.inc', - ); - foreach ($sync_steps as $sync_step) { - $batch['operations'][] = array(array(get_class($this), 'processBatch'), array($config_importer, $sync_step)); - } - - batch_set($batch); - } - catch (ConfigImporterException $e) { - // There are validation errors. - drupal_set_message($this->t('The configuration cannot be imported because it failed validation for the following reasons:'), 'error'); - foreach ($config_importer->getErrors() as $message) { - drupal_set_message($message, 'error'); - } - } - } - } - - /** - * Processes the config import batch and persists the importer. - * - * @param \Drupal\Core\Config\ConfigImporter $config_importer - * The batch config importer object to persist. - * @param string $sync_step - * The synchronization step to do. - * @param array $context - * The batch context. - */ - public static function processBatch(ConfigImporter $config_importer, $sync_step, &$context) { - if (!isset($context['sandbox']['config_importer'])) { - $context['sandbox']['config_importer'] = $config_importer; - } - - $config_importer = $context['sandbox']['config_importer']; - $config_importer->doSyncStep($sync_step, $context); - if ($errors = $config_importer->getErrors()) { - if (!isset($context['results']['errors'])) { - $context['results']['errors'] = array(); - } - $context['results']['errors'] += $errors; - } - } - - /** - * Finish batch. - * - * This function is a static function to avoid serializing the ConfigSync - * object unnecessarily. - */ - public static function finishBatch($success, $results, $operations) { - if ($success) { - if (!empty($results['errors'])) { - foreach ($results['errors'] as $error) { - drupal_set_message($error, 'error'); - \Drupal::logger('config_sync')->error($error); - } - drupal_set_message(\Drupal::translation()->translate('The configuration was imported with errors.'), 'warning'); - } - else { - drupal_set_message(\Drupal::translation()->translate('The configuration was imported successfully.')); - } - } - else { - // An error occurred. - // $operations contains the operations that remained unprocessed. - $error_operation = reset($operations); - $message = \Drupal::translation()->translate('An error occurred while processing %error_operation with arguments: @arguments', array('%error_operation' => $error_operation[0], '@arguments' => print_r($error_operation[1], TRUE))); - drupal_set_message($message, 'error'); - } - } - - -} diff --git a/core/modules/config/src/Tests/ConfigExportImportUITest.php b/core/modules/config/src/Tests/ConfigExportImportUITest.php index 6a63df7..0878ede 100644 --- a/core/modules/config/src/Tests/ConfigExportImportUITest.php +++ b/core/modules/config/src/Tests/ConfigExportImportUITest.php @@ -91,7 +91,7 @@ protected function setUp() { */ public function testExportImport() { // After installation there is no snapshot and nothing to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertNoText(t('Warning message')); $this->assertText(t('There are no configuration changes to import.')); @@ -173,6 +173,11 @@ public function testExportImport() { $this->assertText($this->contentType->label()); $this->drupalPostForm(NULL, array(), 'Import all'); + + // We now have to confirm the import. + $this->assertText(t('This action cannot be undone.')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), 'Import'); + // After importing the snapshot has been updated an there are no warnings. $this->assertNoText(t('Warning message')); $this->assertText(t('There are no configuration changes to import.')); @@ -185,13 +190,13 @@ public function testExportImport() { $this->config('system.site') ->set('slogan', $this->originalSlogan) ->save(); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertText(t('Warning message')); $this->assertText('The following items in your active configuration have changes since the last import that may be lost on the next import. system.site'); // Remove everything from staging. The warning about differences between the // active and snapshot should no longer exist. \Drupal::service('config.storage.staging')->deleteAll(); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertNoText(t('Warning message')); $this->assertNoText('The following items in your active configuration have changes since the last import that may be lost on the next import. system.site'); $this->assertText(t('There are no configuration changes to import.')); @@ -203,7 +208,7 @@ public function testExportImport() { $data['slogan'] = 'in the face'; $this->copyConfig($this->container->get('config.storage'), $staging); $staging->write('system.site', $data); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertText(t('Warning message')); $this->assertText('The following items in your active configuration have changes since the last import that may be lost on the next import. system.site'); } @@ -271,7 +276,7 @@ public function testExportImportCollections() { $this->drupalPostForm('admin/config/development/configuration/full/import', array('files[import_tarball]' => $filename), 'Upload'); // Verify that there are configuration differences to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertNoText(t('There are no configuration changes to import.')); $this->assertText(t('!collection configuration collection', array('!collection' => 'collection.test1'))); $this->assertText(t('!collection configuration collection', array('!collection' => 'collection.test2'))); @@ -289,6 +294,11 @@ public function testExportImportCollections() { $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test2/config_test.another_delete'); $this->drupalPostForm(NULL, array(), 'Import all'); + + // We now have to confirm the import. + $this->assertText(t('This action cannot be undone.')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), 'Import'); + $this->assertText(t('There are no configuration changes to import.')); // Test data in collections. diff --git a/core/modules/config/src/Tests/ConfigImportAllTest.php b/core/modules/config/src/Tests/ConfigImportAllTest.php index 6e1aaea..dd0575b 100644 --- a/core/modules/config/src/Tests/ConfigImportAllTest.php +++ b/core/modules/config/src/Tests/ConfigImportAllTest.php @@ -23,7 +23,7 @@ class ConfigImportAllTest extends ModuleTestBase { use SchemaCheckTestTrait; /** - * A user with the 'synchronize configuration' permission. + * A user with the 'Import configuration' permission. * * @var \Drupal\user\UserInterface */ @@ -41,7 +41,7 @@ class ConfigImportAllTest extends ModuleTestBase { protected function setUp() { parent::setUp(); - $this->webUser = $this->drupalCreateUser(array('synchronize configuration')); + $this->webUser = $this->drupalCreateUser(array('import configuration')); $this->drupalLogin($this->webUser); } @@ -129,7 +129,8 @@ public function testInstallUninstall() { } // Import the configuration thereby re-installing all the modules. - $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), 'Import'); // Modules have been installed that have services. $this->rebuildContainer(); diff --git a/core/modules/config/src/Tests/ConfigImportInstallProfileTest.php b/core/modules/config/src/Tests/ConfigImportInstallProfileTest.php index 64b2d5d..d294239 100644 --- a/core/modules/config/src/Tests/ConfigImportInstallProfileTest.php +++ b/core/modules/config/src/Tests/ConfigImportInstallProfileTest.php @@ -31,7 +31,7 @@ class ConfigImportInstallProfileTest extends WebTestBase { public static $modules = array('config'); /** - * A user with the 'synchronize configuration' permission. + * A user with the 'import configuration' permission. * * @var \Drupal\user\UserInterface */ @@ -40,7 +40,7 @@ class ConfigImportInstallProfileTest extends WebTestBase { protected function setUp() { parent::setUp(); - $this->webUser = $this->drupalCreateUser(array('synchronize configuration')); + $this->webUser = $this->drupalCreateUser(array('import configuration')); $this->drupalLogin($this->webUser); $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging')); } @@ -59,7 +59,8 @@ public function testInstallProfileValidation() { unset($core['module']['testing_config_import']); $staging->write('core.extension', $core); - $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText('The configuration cannot be imported because it failed validation for the following reasons:'); $this->assertText('Unable to uninstall the Testing config import profile since it is the install profile.'); @@ -73,7 +74,8 @@ public function testInstallProfileValidation() { $theme = $staging->read('system.theme'); $theme['default'] = 'classy'; $staging->write('system.theme', $theme); - $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText('The configuration was imported successfully.'); $this->rebuildContainer(); $this->assertFalse(\Drupal::moduleHandler()->moduleExists('syslog'), 'The syslog module has been uninstalled.'); diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/src/Tests/ConfigImportUITest.php index dd00edf..219edfa 100644 --- a/core/modules/config/src/Tests/ConfigImportUITest.php +++ b/core/modules/config/src/Tests/ConfigImportUITest.php @@ -26,7 +26,7 @@ class ConfigImportUITest extends WebTestBase { public static $modules = array('config', 'config_test', 'config_import_test', 'text', 'options'); /** - * A user with the 'synchronize configuration' permission. + * A user with the 'Import configuration' permission. * * @var \Drupal\user\UserInterface */ @@ -35,7 +35,7 @@ class ConfigImportUITest extends WebTestBase { protected function setUp() { parent::setUp(); - $this->webUser = $this->drupalCreateUser(array('synchronize configuration')); + $this->webUser = $this->drupalCreateUser(array('import configuration')); $this->drupalLogin($this->webUser); $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging')); } @@ -49,7 +49,7 @@ function testImport() { /** @var \Drupal\Core\Config\StorageInterface $staging */ $staging = $this->container->get('config.storage.staging'); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertText('There are no configuration changes to import.'); $this->assertNoFieldById('edit-submit', t('Import all')); @@ -113,23 +113,24 @@ function testImport() { \Drupal::state()->set('ConfigImportUITest.core.extension.modules_uninstalled', array()); // Verify that both appear as ready to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertRaw('' . $name); $this->assertRaw('' . $dynamic_name); $this->assertRaw('core.extension'); $this->assertRaw('system.theme'); $this->assertRaw('action.settings'); - $this->assertFieldById('edit-submit', t('Import all')); + $this->assertFieldById('edit-import', t('Import all')); // Import and verify that both do not appear anymore. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), 'Import'); $this->assertNoRaw('' . $name); $this->assertNoRaw('' . $dynamic_name); $this->assertNoRaw('core.extension'); $this->assertNoRaw('system.theme'); $this->assertNoRaw('action.settings'); - $this->assertNoFieldById('edit-submit', t('Import all')); + $this->assertNoFieldById('edit-import', t('Import all')); // Verify that there are no further changes to import. $this->assertText(t('There are no configuration changes to import.')); @@ -188,13 +189,14 @@ function testImport() { \Drupal::state()->set('ConfigImportUITest.core.extension.modules_uninstalled', array()); // Verify that both appear as ready to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertRaw('core.extension'); $this->assertRaw('system.theme'); $this->assertRaw('action.settings'); // Import and verify that both do not appear anymore. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), 'Import'); $this->assertNoRaw('core.extension'); $this->assertNoRaw('system.theme'); $this->assertNoRaw('action.settings'); @@ -231,7 +233,7 @@ function testImportLock() { $this->prepareSiteNameUpdate($new_site_name); // Verify that there are configuration differences to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertNoText(t('There are no configuration changes to import.')); // Acquire a fake-lock on the import mechanism. @@ -240,6 +242,7 @@ function testImportLock() { // Attempt to import configuration and verify that an error message appears. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText(t('Another request may be synchronizing configuration already.')); // Release the lock, just to keep testing sane. @@ -261,7 +264,7 @@ function testImportSiteUuidValidation() { $staging->write('system.site', $config_data); // Verify that there are configuration differences to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertText(t('The staged configuration cannot be imported, because it originates from a different site than this site. You can only synchronize configuration between cloned instances of this site.')); $this->assertNoFieldById('edit-submit', t('Import all')); } @@ -321,9 +324,10 @@ public function testImportValidation() { $new_site_name = 'Config import test ' . $this->randomString(); $this->prepareSiteNameUpdate($new_site_name); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertNoText(t('There are no configuration changes to import.')); $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm(NULL, array(), t('Import')); // Verify that the validation messages appear. $this->assertText('The configuration cannot be imported because it failed validation for the following reasons:'); @@ -341,11 +345,12 @@ public function testConfigUninstallConfigException() { unset($core_extension['module']['config']); $staging->write('core.extension', $core_extension); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertText('core.extension'); // Import and verify that both do not appear anymore. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText('Can not uninstall the Configuration module as part of a configuration synchronization through the user interface.'); } @@ -398,11 +403,12 @@ function testImportErrorLog() { ); $staging->write($name_secondary, $values_secondary); // Verify that there are configuration differences to import. - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertNoText(t('There are no configuration changes to import.')); // Attempt to import configuration and verify that an error message appears. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText(SafeMarkup::format('Deleted and replaced configuration entity "@name"', array('@name' => $name_secondary))); $this->assertText(t('The configuration was imported with errors.')); $this->assertNoText(t('The configuration was imported successfully.')); @@ -420,7 +426,7 @@ public function testEntityBundleDelete() { $node_type = $this->drupalCreateContentType(); $node = $this->drupalCreateNode(array('type' => $node_type->id())); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); // The node type, body field and entity displays will be scheduled for // removal. $this->assertText(format_string('node.type.@type', array('@type' => $node_type->id()))); @@ -433,17 +439,13 @@ public function testEntityBundleDelete() { // and the node type, body field and entity displays are still scheduled for // removal. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $validation_message = t('Entities exist of type %entity_type and %bundle_label %bundle. These entities need to be deleted before importing.', array('%entity_type' => $node->getEntityType()->getLabel(), '%bundle_label' => $node->getEntityType()->getBundleLabel(), '%bundle' => $node_type->label())); $this->assertRaw($validation_message); - $this->assertText(format_string('node.type.@type', array('@type' => $node_type->id()))); - $this->assertText(format_string('field.field.node.@type.body', array('@type' => $node_type->id()))); - $this->assertText(format_string('core.entity_view_display.node.@type.teaser', array('@type' => $node_type->id()))); - $this->assertText(format_string('core.entity_view_display.node.@type.default', array('@type' => $node_type->id()))); - $this->assertText(format_string('core.entity_form_display.node.@type.default', array('@type' => $node_type->id()))); // Delete the node and try to import again. $node->delete(); - $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm(NULL, array(), t('Import')); $this->assertNoRaw($validation_message); $this->assertText(t('There are no configuration changes to import.')); $this->assertNoText(format_string('node.type.@type', array('@type' => $node_type->id()))); @@ -480,7 +482,8 @@ public function testExtensionValidation() { $core['theme']['does_not_exist'] = 0; $staging->write('core.extension', $core); - $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText('The configuration cannot be imported because it failed validation for the following reasons:'); $this->assertText('Unable to uninstall the Text module since the Node module is installed.'); $this->assertText('Unable to uninstall the Classy theme since the Bartik theme is installed.'); diff --git a/core/modules/config/tests/src/Unit/Menu/ConfigLocalTasksTest.php b/core/modules/config/tests/src/Unit/Menu/ConfigLocalTasksTest.php index 1da4148..670191b 100644 --- a/core/modules/config/tests/src/Unit/Menu/ConfigLocalTasksTest.php +++ b/core/modules/config/tests/src/Unit/Menu/ConfigLocalTasksTest.php @@ -35,11 +35,10 @@ public function testConfigAdminLocalTasks($route, $expected) { */ public function getConfigAdminRoutes() { return array( - array('config.sync', array(array('config.sync', 'config.full', 'config.single'))), - array('config.export_full', array(array('config.sync', 'config.full', 'config.single'), array('config.export_full', 'config.import_full'))), - array('config.import_full', array(array('config.sync', 'config.full', 'config.single'), array('config.export_full', 'config.import_full'))), - array('config.export_single', array(array('config.sync', 'config.full', 'config.single'), array('config.export_single', 'config.import_single'))), - array('config.import_single', array(array('config.sync', 'config.full', 'config.single'), array('config.export_single', 'config.import_single'))), + array('config.import_full', array(array('config.import', 'config.export'), array('config.import_full', 'config.import_single'))), + array('config.import_single', array(array('config.import', 'config.export'), array('config.import_full', 'config.import_single'))), + array('config.export_full', array(array('config.import', 'config.export'), array('config.export_full', 'config.export_single'))), + array('config.export_single', array(array('config.import', 'config.export'), array('config.export_full', 'config.export_single'))), ); } diff --git a/core/modules/field/field.module b/core/modules/field/field.module index d09049e..b39170c 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -281,7 +281,7 @@ function field_config_import_steps_alter(&$sync_steps, ConfigImporter $config_im * * @see \Drupal\field\ConfigImporterFieldPurger */ -function field_form_config_admin_import_form_alter(&$form, FormStateInterface $form_state) { +function field_form_config_import_form_alter(&$form, FormStateInterface $form_state) { // Only display the message when there is a storage comparer available and the // form is not submitted. $user_input = $form_state->getUserInput(); diff --git a/core/modules/field/src/Tests/FieldImportDeleteUninstallUiTest.php b/core/modules/field/src/Tests/FieldImportDeleteUninstallUiTest.php index de793dd..f400fd4 100644 --- a/core/modules/field/src/Tests/FieldImportDeleteUninstallUiTest.php +++ b/core/modules/field/src/Tests/FieldImportDeleteUninstallUiTest.php @@ -28,7 +28,7 @@ class FieldImportDeleteUninstallUiTest extends FieldTestBase { protected function setUp() { parent::setUp(); - $this->drupalLogin($this->drupalCreateUser(array('synchronize configuration'))); + $this->drupalLogin($this->drupalCreateUser(array('import configuration'))); } /** @@ -90,7 +90,7 @@ public function testImportDeleteUninstall() { // Stage the field deletion $staging->delete('field.storage.entity_test.field_tel'); $staging->delete('field.field.entity_test.entity_test.field_tel'); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); // Test that the message for one field being purged during a configuration // synchronization is correct. $this->assertText('This synchronization will delete data from the field entity_test.field_tel.'); @@ -100,12 +100,13 @@ public function testImportDeleteUninstall() { unset($core_extension['module']['datetime']); $staging->write('core.extension', $core_extension); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertText('This synchronization will delete data from the fields: entity_test.field_tel, entity_test.field_date.'); // This will purge all the data, delete the field and uninstall the // Telephone and Text modules. $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm(NULL, array(), t('Import')); $this->assertNoText('Field data will be deleted by this synchronization.'); $this->rebuildContainer(); $this->assertFalse(\Drupal::moduleHandler()->moduleExists('telephone')); diff --git a/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php b/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php index af29bce..f8e1d2b 100644 --- a/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php +++ b/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php @@ -39,7 +39,7 @@ class NodeTypeRenameConfigImportTest extends WebTestBase { */ protected function setUp() { parent::setUp(); - $this->webUser = $this->drupalCreateUser(array('synchronize configuration')); + $this->webUser = $this->drupalCreateUser(array('import configuration')); $this->drupalLogin($this->webUser); } @@ -101,7 +101,7 @@ public function testConfigurationRename() { $renames = $this->configImporter()->getUnprocessedConfiguration('rename'); $this->assertIdentical($expected, $renames); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); foreach ($expected as $rename) { $names = $this->configImporter()->getStorageComparer()->extractRenameNames($rename); $this->assertText(SafeMarkup::format('!source_name to !target_name', array('!source_name' => $names['old_name'], '!target_name' => $names['new_name']))); @@ -130,7 +130,8 @@ public function testConfigurationRename() { } // Run the import. - $this->drupalPostForm('admin/config/development/configuration', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import', array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $this->assertText(t('There are no configuration changes to import.')); $this->assertFalse(NodeType::load($active_type), 'The content no longer exists with the old name.'); diff --git a/core/modules/options/src/Tests/OptionsFloatFieldImportTest.php b/core/modules/options/src/Tests/OptionsFloatFieldImportTest.php index 5be5840..9d859b2 100644 --- a/core/modules/options/src/Tests/OptionsFloatFieldImportTest.php +++ b/core/modules/options/src/Tests/OptionsFloatFieldImportTest.php @@ -29,7 +29,7 @@ protected function setUp() { parent::setUp(); // Create test user. - $admin_user = $this->drupalCreateUser(array('synchronize configuration', 'access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'bypass node access', 'administer node fields', 'administer node display')); + $admin_user = $this->drupalCreateUser(array('import configuration', 'access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'bypass node access', 'administer node fields', 'administer node display')); $this->drupalLogin($admin_user); } @@ -59,8 +59,9 @@ public function testImport() { // Import configuration with dots in the allowed values key names. This // tests \Drupal\Core\Config\Entity\ConfigEntityStorage::importUpdate(). - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $field_storage = FieldStorageConfig::loadByName('node', $field_name); $this->assertIdentical($field_storage->getSetting('allowed_values'), $array = array('0' => 'Zero', '0.5' => 'Point five')); @@ -68,8 +69,9 @@ public function testImport() { // \Drupal\Core\Config\Entity\ConfigEntityStorage::importCreate(). FieldConfig::loadByName('node', $type, $field_name)->delete(); - $this->drupalGet('admin/config/development/configuration'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->drupalPostForm(NULL, array(), t('Import all')); + $this->drupalPostForm('admin/config/development/configuration/full/import/confirm', array(), t('Import')); $field_storage = FieldStorageConfig::loadByName('node', $field_name); $this->assertIdentical($field_storage->getSetting('allowed_values'), $array = array('0' => 'Zero', '0.5' => 'Point five')); } diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml index ecb1c43..f2bbae0 100644 --- a/sites/default/default.services.yml +++ b/sites/default/default.services.yml @@ -51,7 +51,7 @@ parameters: # changes (see auto_reload below). # # For more information about debugging Twig templates, see - # https://www.drupal.org/node/1906392. + # http://drupal.org/node/1906392. # # Not recommended in production environments # @default false diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 330cc56..18b0f03 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -22,7 +22,7 @@ * 'sites/default' will be used. * * For example, for a fictitious site installed at - * https://www.drupal.org:8080/mysite/test/, the 'settings.php' file is searched + * http://www.drupal.org:8080/mysite/test/, the 'settings.php' file is searched * for in the following directories: * * - sites/8080.www.drupal.org.mysite.test @@ -44,7 +44,7 @@ * * Note that if you are installing on a non-standard port number, prefix the * hostname with that number. For example, - * https://www.drupal.org:8080/mysite/test/ could be loaded from + * http://www.drupal.org:8080/mysite/test/ could be loaded from * sites/8080.www.drupal.org.mysite.test/. * * @see example.sites.php @@ -440,7 +440,7 @@ * the code directly via SSH or FTP themselves. This setting completely * disables all functionality related to these authorized file operations. * - * @see https://www.drupal.org/node/244924 + * @see http://drupal.org/node/244924 * * Remove the leading hash signs to disable. */ @@ -473,8 +473,8 @@ * Note: Caches need to be cleared when this value is changed to make the * private:// stream wrapper available to the system. * - * See https://www.drupal.org/documentation/modules/file for more information - * about securing private files. + * See http://drupal.org/documentation/modules/file for more information about + * securing private files. */ # $settings['file_private_path'] = '';