diff -u b/core/modules/config/config.routing.yml b/core/modules/config/config.routing.yml --- b/core/modules/config/config.routing.yml +++ b/core/modules/config/config.routing.yml @@ -2,12 +2,12 @@ path: '/admin/config/development/configuration' defaults: _form: '\Drupal\config\Form\ConfigSync' - _title: 'Synchronize' + _title: 'Synchronize Configuration' requirements: _permission: 'synchronize configuration' config.diff: - path: '/admin/config/development/configuration/sync/diff/{source_name}/{target_name}' + path: '/admin/config/development/configuration/sync/diff/{source}/{target}/{source_name}/{target_name}' defaults: _content: '\Drupal\config\Controller\ConfigController::diff' target_name: NULL @@ -58,6 +58,19 @@ -config.snapshot_diff: - path: '/admin/config/development/configuration/sync/snapshot-diff/{storage}' +config.snapshot_active: + path: '/admin/config/development/configuration/compare/active' defaults: - _content: '\Drupal\config\Controller\ConfigController::snapshotDiff' + _title: 'Changes between snapshot and active configuration' + _form: '\Drupal\config\Form\ConfigSync' + source: "snapshot" + target: "active" requirements: - _permission: 'import configuration' + _permission: 'synchronize configuration' + +config.snapshot_staging: + path: '/admin/config/development/configuration/compare/staging' + defaults: + _title: 'Changes between snapshot and staging configuration' + _form: '\Drupal\config\Form\ConfigSync' + source: "snapshot" + target: "staging" + requirements: + _permission: 'synchronize configuration' diff -u b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php --- b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php +++ b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php @@ -14,7 +14,6 @@ use Drupal\system\FileDownloadController; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; -use Drupal\Core\Config\StorageComparer; use Drupal\Core\Controller\ControllerBase; /** @@ -23,21 +22,21 @@ class ConfigController extends ControllerBase { /** - * The target storage. + * The active storage. * * @var \Drupal\Core\Config\StorageInterface */ - protected $targetStorage; + protected $activeStorage; /** - * The source storage. + * The staging storage. * * @var \Drupal\Core\Config\StorageInterface */ - protected $sourceStorage; + protected $stagingStorage; /** - * The snapshot. + * The snapshot storage. * * @var \Drupal\Core\Config\StorageInterface */ @@ -73,16 +72,18 @@ /** * Constructs a ConfigController object. * - * @param \Drupal\Core\Config\StorageInterface $target_storage - * The target storage. - * @param \Drupal\Core\Config\StorageInterface $source_storage - * The source storage + * @param \Drupal\Core\Config\StorageInterface $active_storage + * The active storage. + * @param \Drupal\Core\Config\StorageInterface $staging_storage + * The staging storage + * @param \Drupal\Core\Config\StorageInterface $snapshot_storage + * The snapshot storage * @param \Drupal\system\FileDownloadController $file_download_controller * The file download controller. */ - public function __construct(StorageInterface $target_storage, StorageInterface $source_storage, StorageInterface $snapshot_storage, ConfigManagerInterface $config_manager, FileDownloadController $file_download_controller) { - $this->targetStorage = $target_storage; - $this->sourceStorage = $source_storage; + public function __construct(StorageInterface $active_storage, StorageInterface $staging_storage, StorageInterface $snapshot_storage, ConfigManagerInterface $config_manager, FileDownloadController $file_download_controller) { + $this->activeStorage = $active_storage; + $this->stagingStorage = $staging_storage; $this->snapshotStorage = $snapshot_storage; $this->configManager = $config_manager; $this->fileDownloadController = $file_download_controller; @@ -106,15 +107,27 @@ /** * Shows diff of specificed configuration file. * - * @param string $config_file - * The name of the configuration file. + * @param string $source + * The source storage container name. + * + * @param string $target + * The target storage container name. + * + * @param string $source_name + * The source configuration item name to compare. + * + * @param string $target_name + * The target configuration item name to compare. * * @return string * Table showing a two-way diff between the active and staged configuration. */ - public function diff($source_name, $target_name = NULL) { + public function diff($source = 'staging', $target = 'active', $source_name, $target_name = NULL) { - $diff = $this->configManager->diff($this->targetStorage, $this->sourceStorage, $source_name, $target_name); + $source_storage = $source . 'Storage'; + $target_storage = $target . 'Storage'; + + $diff = $this->configManager->diff($this->$target_storage, $this->$source_storage, $source_name, $target_name); $formatter = new \DrupalDiffFormatter(); $formatter->show_header = FALSE; @@ -127,8 +140,8 @@ $build['diff'] = array( '#type' => 'table', '#header' => array( - array('data' => $this->t('Old'), 'colspan' => '2'), - array('data' => $this->t('New'), 'colspan' => '2'), + array('data' => $target, 'colspan' => '2'), + array('data' => $source, 'colspan' => '2'), ), '#rows' => $formatter->format($diff), ); @@ -148,59 +161,2 @@ } - - /** - * Show diff of snapshot and active/staging storage. - * - * @return string - * Table showing a two-way diff between the snapshot and - * active/staged configuration. - */ - public function snapshotDiff($storage = 'active') { - $build = array(); - - // Add the CSS for the inline diff. - $build['#attached']['css'][] = drupal_get_path('module', 'system') . '/css/system.diff.css'; - - if ($storage == 'active') { - $build['#title'] = $this->t('View changes between snapshot and active configuration.'); - $used_storage = $this->targetStorage; - $compare_button = $this->l($this->t('Compare snapshot with staging storage'), 'config.snapshot_diff', array('storage' => 'staging'), array('attributes' => array('class' => array('button')))); - } - else { - $build['#title'] = $this->t('View changes between snapshot and staging configuration.'); - $used_storage = $this->sourceStorage; - $compare_button = $this->l($this->t('Compare snapshot with active storage'), 'config.snapshot_diff', array('storage' => 'active'), array('attributes' => array('class' => array('button')))); - } - - $build['compare']['#markup'] = $compare_button; - - $storage_snapshot_comparer = new StorageComparer($used_storage, $this->snapshotStorage); - - // Collect changes. - $storage_snapshot_comparer->createChangelist(); - $changelist = $storage_snapshot_comparer->getChangelist(); - - // Verify that we have an initial snapshot that matches the active/staging - // configuration. - if ($storage_snapshot_comparer->createChangelist()->hasChanges()) { - // Show changes for each configuration object. - foreach ($changelist as $op) { - foreach ($op as $name) { - $diff = $this->configManager->diff($this->snapshotStorage, $used_storage, $name); - $formatter = new \DrupalDiffFormatter(); - $formatter->show_header = FALSE; - $build[$name] = array( - '#prefix' => '

' . $name . '

', - '#type' => 'table', - '#header' => array( - array('data' => $this->t('Snapshot'), 'colspan' => '2'), - array('data' => ($storage == 'active') ? $this->t('Active storage') : $this->t('Staging storage'), 'colspan' => '2'), - ), - '#rows' => $formatter->format($diff), - ); - } - } - } - - return $build; - } } diff -u b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php --- b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php +++ b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php @@ -36,18 +36,25 @@ protected $lock; /** - * The source configuration object. + * The staging configuration object. * * @var \Drupal\Core\Config\StorageInterface */ - protected $sourceStorage; + protected $stagingStorage; /** - * The target configuration object. + * The active configuration object. * * @var \Drupal\Core\Config\StorageInterface */ - protected $targetStorage; + protected $activeStorage; + + /** + * The snapshot configuration object. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $snapshotStorage; /** * Event dispatcher. @@ -92,21 +99,14 @@ protected $themeHandler; /** - * The snapshot configuration object. - * - * @var \Drupal\Core\Config\StorageInterface - */ - protected $snapshotStorage; - - /** * Constructs the object. * - * @param \Drupal\Core\Config\StorageInterface $sourceStorage - * The source storage object. - * @param \Drupal\Core\Config\StorageInterface $targetStorage - * The target storage manager. + * @param \Drupal\Core\Config\StorageInterface $stagingStorage + * The staging storage object. + * @param \Drupal\Core\Config\StorageInterface $activeStorage + * The active storage manager. * @param \Drupal\Core\Config\StorageInterface $snapshotStorage - * The snapshot storage object. + * The snapshot storage manager. * @param \Drupal\Core\Lock\LockBackendInterface $lock * The lock object. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher @@ -122,9 +122,9 @@ * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler * The theme handler */ - public function __construct(StorageInterface $sourceStorage, StorageInterface $targetStorage, StorageInterface $snapshotStorage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, UrlGeneratorInterface $url_generator, TypedConfigManager $typed_config, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) { - $this->sourceStorage = $sourceStorage; - $this->targetStorage = $targetStorage; + public function __construct(StorageInterface $stagingStorage, StorageInterface $activeStorage, StorageInterface $snapshotStorage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, UrlGeneratorInterface $url_generator, TypedConfigManager $typed_config, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) { + $this->stagingStorage = $stagingStorage; + $this->activeStorage = $activeStorage; $this->snapshotStorage = $snapshotStorage; $this->lock = $lock; $this->eventDispatcher = $event_dispatcher; @@ -163,25 +163,29 @@ /** * {@inheritdoc} */ - public function buildForm(array $form, array &$form_state) { - $active_snapshot_comparer = new StorageComparer($this->targetStorage, $this->snapshotStorage); + public function buildForm(array $form, array &$form_state, $source = 'staging', $target = 'active') { + + $active_snapshot_comparer = new StorageComparer($this->activeStorage, $this->snapshotStorage); // Verify that we have an initial snapshot that matches the active // configuration. if (empty($form_state['input']) && $active_snapshot_comparer->createChangelist()->hasChanges()) { drupal_set_message($this->t('Changes have been made to your active configuration, which might be lost on the next import attempt. You can find and review the differences between snapshot and active/staging storage here: Compare snapshot and active/staging storage.', array( - '@link' => $this->url('config.snapshot_diff', array('storage' => 'active')))), 'warning'); + '@link' => $this->url('config.snapshot_active'))), 'warning'); } + $source_storage = $source . 'Storage'; + $target_storage = $target . 'Storage'; + $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', '#value' => $this->t('Import all'), ); - $source_list = $this->sourceStorage->listAll(); - $storage_comparer = new StorageComparer($this->sourceStorage, $this->targetStorage); + $source_list = $this->$source_storage->listAll(); + $storage_comparer = new StorageComparer($this->$source_storage, $this->$target_storage); if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) { $form['no_changes'] = array( '#type' => 'table', @@ -241,11 +245,11 @@ foreach ($config_names as $config_name) { if ($config_change_type == 'rename') { $names = $storage_comparer->extractRenameNames($config_name); - $href = $this->urlGenerator->getPathFromRoute('config.diff', array('source_name' => $names['old_name'], 'target_name' => $names['new_name'])); + $href = $this->urlGenerator->getPathFromRoute('config.diff', array('source' => $source, 'target' => $target, '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 { - $href = $this->urlGenerator->getPathFromRoute('config.diff', array('source_name' => $config_name)); + $href = $this->urlGenerator->getPathFromRoute('config.diff', array('source' => $source, 'target' => $target, 'source_name' => $config_name)); } $links['view_diff'] = array( 'title' => $this->t('View differences'), @@ -254,7 +258,7 @@ 'class' => array('use-ajax'), 'data-accepts' => 'application/vnd.drupal-modal', 'data-dialog-options' => json_encode(array( - 'width' => 700 + 'width' => 700, )), ), ); @@ -290,16 +294,16 @@ if ($config_importer->alreadyImporting()) { drupal_set_message($this->t('Another request may be synchronizing configuration already.')); } - else{ + 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.'), + 'title' => $this->t('Synchronizing configuration'), + 'init_message' => $this->t('Starting configuration synchronization.'), + 'progress_message' => $this->t('Completed @current step of @total.'), + 'error_message' => $this->t('Configuration synchronization has encountered an error.'), 'file' => drupal_get_path('module', 'config') . '/config.admin.inc', ); foreach ($sync_steps as $sync_step) { reverted: --- b/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php +++ a/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php @@ -130,24 +130,4 @@ $this->drupalGet('node/add'); $this->assertFieldByName("{$this->field->name}[0][value]", '', 'Widget is displayed'); } - - /** - * Tests that a warning appears when unsynchronized changes exist. - */ - public function testImportWarning() { - $new_slogan = $this->randomName(16); - \Drupal::config('system.site') - ->set('slogan', $new_slogan) - ->save(); - - $this->drupalGet('admin/config/development/configuration'); - $this->assertText('Changes have been made to your active configuration, which might be lost on the next import attempt. You can find and review the differences between snapshot and active/staging storage here'); - $this->clickLink('Compare snapshot and active/staging storage'); - $this->assertText('View changes between snapshot and active configuration'); - $this->assertText('system.site'); - $this->assertText('Active storage'); - $this->assertText($new_slogan, "New slogan $new_slogan found when viewing changes."); - $this->clickLink('Compare snapshot with staging storage'); - $this->assertText('View changes between snapshot and staging configuration'); - } } only in patch2: unchanged: --- a/core/modules/config/config.local_tasks.yml +++ b/core/modules/config/config.local_tasks.yml @@ -32,3 +32,21 @@ config.import_single: route_name: config.import_single title: Import parent_id: config.single + +config.staging_active: + route_name: config.sync + title: Compare staging with active + parent_id: config.sync + weight: -1 + +config.snapshot_active: + route_name: config.snapshot_active + title: Compare snapshot with active + parent_id: config.sync + weight: 0 + +config.snapshot_staging: + route_name: config.snapshot_staging + title: Compare snapshot with staging + parent_id: config.sync + weight: 1