diff --git a/core/modules/config_translation/migration_templates/d6_i18n_system_maintenance.yml b/core/modules/config_translation/migration_templates/d6_i18n_system_maintenance.yml index c2270192892a..1c99961cc8d2 100644 --- a/core/modules/config_translation/migration_templates/d6_i18n_system_maintenance.yml +++ b/core/modules/config_translation/migration_templates/d6_i18n_system_maintenance.yml @@ -12,3 +12,4 @@ process: destination: plugin: config config_name: system.maintenance + translations: true diff --git a/core/modules/config_translation/migration_templates/d6_i18n_system_site.yml b/core/modules/config_translation/migration_templates/d6_i18n_system_site.yml index 9c9337c42faa..3c80821337c0 100644 --- a/core/modules/config_translation/migration_templates/d6_i18n_system_site.yml +++ b/core/modules/config_translation/migration_templates/d6_i18n_system_site.yml @@ -36,3 +36,4 @@ process: destination: plugin: config config_name: system.site + translations: true diff --git a/core/modules/config_translation/migration_templates/d6_i18n_user_mail.yml b/core/modules/config_translation/migration_templates/d6_i18n_user_mail.yml index b3c916f786ff..d1e5db501b82 100644 --- a/core/modules/config_translation/migration_templates/d6_i18n_user_mail.yml +++ b/core/modules/config_translation/migration_templates/d6_i18n_user_mail.yml @@ -66,3 +66,4 @@ process: destination: plugin: config config_name: user.mail + translations: true diff --git a/core/modules/config_translation/migration_templates/d6_i18n_user_settings.yml b/core/modules/config_translation/migration_templates/d6_i18n_user_settings.yml index 979a74a4efb4..36b0fa6c8822 100644 --- a/core/modules/config_translation/migration_templates/d6_i18n_user_settings.yml +++ b/core/modules/config_translation/migration_templates/d6_i18n_user_settings.yml @@ -27,3 +27,4 @@ process: destination: plugin: config config_name: user.settings + translations: true diff --git a/core/modules/migrate/src/Plugin/migrate/destination/Config.php b/core/modules/migrate/src/Plugin/migrate/destination/Config.php index 32d5e1bff0a4..422037be5e2f 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/Config.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/Config.php @@ -54,13 +54,16 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface, * The migration entity. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The configuration factory. - * @param \Drupal\Core\Language\ConfigurableLanguageManagerInterface $language_manager + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ConfigFactoryInterface $config_factory, LanguageManagerInterface $language_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition, $migration); $this->config = $config_factory->getEditable($configuration['config_name']); $this->language_manager = $language_manager; + if ($this->isTranslationDestination()) { + $this->supportsRollback = TRUE; + } } /** @@ -81,7 +84,7 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface, * {@inheritdoc} */ public function import(Row $row, array $old_destination_id_values = array()) { - if ($row->hasDestinationProperty('langcode')) { + if ($this->isTranslationDestination()) { $this->config = $this->language_manager->getLanguageConfigOverride($row->getDestinationProperty('langcode'), $this->config->getName()); } @@ -91,7 +94,11 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface, } } $this->config->save(); - return [$this->config->getName()]; + $ids[] = $this->config->getName(); + if ($this->isTranslationDestination()) { + $ids[] = $row->getDestinationProperty('langcode'); + } + return $ids; } /** @@ -106,6 +113,9 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface, */ public function getIds() { $ids['config_name']['type'] = 'string'; + if ($this->isTranslationDestination()) { + $ids['langcode']['type'] = 'string'; + } return $ids; } @@ -118,4 +128,25 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface, return $this->dependencies; } + /** + * Get whether this destination is for translations. + * + * @return bool + * Whether this destination is for translations. + */ + protected function isTranslationDestination() { + return !empty($this->configuration['translations']); + } + + /** + * {@inheritdoc} + */ + public function rollback(array $destination_identifier) { + if ($this->isTranslationDestination()) { + $language = $destination_identifier['langcode']; + $config = $this->language_manager->getLanguageConfigOverride($language, $this->config->getName()); + $config->delete(); + } + } + } diff --git a/core/modules/migrate/tests/src/Kernel/MigrateConfigRollbackTest.php b/core/modules/migrate/tests/src/Kernel/MigrateConfigRollbackTest.php new file mode 100644 index 000000000000..14e50b951450 --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/MigrateConfigRollbackTest.php @@ -0,0 +1,170 @@ + 'site_name', + 'site_name' => 'Some site', + 'site_slogan' => 'Awesome slogan', + ], + ]; + $ids = [ + 'id' => + [ + 'type' => 'string' + ], + ]; + $definition = [ + 'id' => 'config', + 'migration_tags' => ['Import and rollback test'], + 'source' => [ + 'plugin' => 'embedded_data', + 'data_rows' => $variable, + 'ids' => $ids, + ], + 'process' => [ + 'name' => 'site_name', + 'slogan' => 'site_slogan', + ], + 'destination' => [ + 'plugin' => 'config', + 'config_name' => 'system.site', + ], + ]; + + /** @var \Drupal\migrate\Plugin\Migration $config_migration */ + $config_migration = \Drupal::service('plugin.manager.migration') + ->createStubMigration($definition); + $config_id_map = $config_migration->getIdMap(); + + // Rollback is not enabled for configuration translations. + $this->assertFalse($config_migration->getDestinationPlugin()->supportsRollback()); + + // Import and validate config entities were created. + $config_executable = new MigrateExecutable($config_migration, $this); + $config_executable->import(); + $config = $this->config('system.site'); + $this->assertSame('Some site', $config->get('name')); + $this->assertSame('Awesome slogan', $config->get('slogan')); + $map_row = $config_id_map->getRowBySource(['id' => $variable[0]['id']]); + $this->assertNotNull($map_row['destid1']); + + // Rollback and verify the configuration changes are still there. + $config_executable->rollback(); + $config = $this->config('system.site'); + $this->assertSame('Some site', $config->get('name')); + $this->assertSame('Awesome slogan', $config->get('slogan')); + // Confirm the map row is deleted. + $map_row = $config_id_map->getRowBySource(['id' => $variable[0]['id']]); + $this->assertNull($map_row['destid1']); + + // We use system configuration to demonstrate importing and rolling back + // configuration translations. + $i18n_variable = [ + [ + 'id' => 'site_name', + 'language' => 'fr', + 'site_name' => 'fr - Some site', + 'site_slogan' => 'fr - Awesome slogan', + ], + [ + 'id' => 'site_name', + 'language' => 'is', + 'site_name' => 'is - Some site', + 'site_slogan' => 'is - Awesome slogan', + ], + ]; + $ids = [ + 'id' => + [ + 'type' => 'string' + ], + 'language' => + [ + 'type' => 'string' + ] + ]; + $definition = [ + 'id' => 'i18n_config', + 'migration_tags' => ['Import and rollback test'], + 'source' => [ + 'plugin' => 'embedded_data', + 'data_rows' => $i18n_variable, + 'ids' => $ids, + ], + 'process' => [ + 'langcode' => 'language', + 'name' => 'site_name', + 'slogan' => 'site_slogan', + ], + 'destination' => [ + 'plugin' => 'config', + 'config_name' => 'system.site', + 'translations' => 'true', + ], + ]; + + $config_migration = \Drupal::service('plugin.manager.migration') + ->createStubMigration($definition); + $config_id_map = $config_migration->getIdMap(); + + // Rollback is enabled for configuration translations. + $this->assertTrue($config_migration->getDestinationPlugin()->supportsRollback()); + + // Import and validate config entities were created. + $config_executable = new MigrateExecutable($config_migration, $this); + $config_executable->import(); + + $language_manager = \Drupal::service('language_manager'); + foreach ($i18n_variable as $row) { + $langcode = $row['language']; + /** @var \Drupal\language\Config\LanguageConfigOverride $config_translation */ + $config_translation = $language_manager->getLanguageConfigOverride($langcode, 'system.site'); + $this->assertSame($row['site_name'], $config_translation->get('name')); + $this->assertSame($row['site_slogan'], $config_translation->get('slogan')); + $map_row = $config_id_map->getRowBySource(['id' => $row['id'], 'language' => $row['language']]); + $this->assertNotNull($map_row['destid1']); + } + + // Rollback and verify the translation have been removed. + $config_executable->rollback(); + foreach ($i18n_variable as $row) { + $langcode = $row['language']; + $config_translation = $language_manager->getLanguageConfigOverride($langcode, 'system.site'); + $this->assertNull($config_translation->get('name')); + $this->assertNull($config_translation->get('slogan')); + // Confirm the map row is deleted. + $map_row = $config_id_map->getRowBySource(['id' => $row['id'], 'language' => $langcode]); + $this->assertFalse($map_row); + } + + // Test that the configuration is still present. + $config = $this->config('system.site'); + $this->assertSame('Some site', $config->get('name')); + $this->assertSame('Awesome slogan', $config->get('slogan')); + } + +} diff --git a/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php b/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php index 59b93d54e545..25eeebb1802f 100644 --- a/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php +++ b/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php @@ -44,9 +44,6 @@ class ConfigTest extends UnitTestCase { $row = $this->getMockBuilder('Drupal\migrate\Row') ->disableOriginalConstructor() ->getMock(); - $row->expects($this->once()) - ->method('hasDestinationProperty') - ->will($this->returnValue(FALSE)); $row->expects($this->any()) ->method('getRawDestination') ->will($this->returnValue($source)); @@ -94,9 +91,6 @@ class ConfigTest extends UnitTestCase { $row = $this->getMockBuilder('Drupal\migrate\Row') ->disableOriginalConstructor() ->getMock(); - $row->expects($this->once()) - ->method('hasDestinationProperty') - ->will($this->returnValue($source)); $row->expects($this->any()) ->method('getRawDestination') ->will($this->returnValue($source)); @@ -110,9 +104,9 @@ class ConfigTest extends UnitTestCase { ->method('getLanguageConfigOverride') ->with('mi', 'd8_config') ->will($this->returnValue($config)); - $destination = new Config(array('config_name' => 'd8_config'), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config_factory, $language_manager); + $destination = new Config(array('config_name' => 'd8_config', 'translations' => 'true'), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config_factory, $language_manager); $destination_id = $destination->import($row); - $this->assertEquals($destination_id, ['d8_config']); + $this->assertEquals($destination_id, ['d8_config', 'mi']); } }