Issue #2825603 by quietone, mikeryan: Fix rollback of configuration translations

8.3.x
Alex Pott 2017-01-17 15:21:47 +00:00
parent 5dd7448232
commit 7b76b1698e
7 changed files with 210 additions and 11 deletions

View File

@ -12,3 +12,4 @@ process:
destination: destination:
plugin: config plugin: config
config_name: system.maintenance config_name: system.maintenance
translations: true

View File

@ -36,3 +36,4 @@ process:
destination: destination:
plugin: config plugin: config
config_name: system.site config_name: system.site
translations: true

View File

@ -66,3 +66,4 @@ process:
destination: destination:
plugin: config plugin: config
config_name: user.mail config_name: user.mail
translations: true

View File

@ -27,3 +27,4 @@ process:
destination: destination:
plugin: config plugin: config
config_name: user.settings config_name: user.settings
translations: true

View File

@ -54,13 +54,16 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
* The migration entity. * The migration entity.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory. * The configuration factory.
* @param \Drupal\Core\Language\ConfigurableLanguageManagerInterface $language_manager * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager. * The language manager.
*/ */
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ConfigFactoryInterface $config_factory, LanguageManagerInterface $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); parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
$this->config = $config_factory->getEditable($configuration['config_name']); $this->config = $config_factory->getEditable($configuration['config_name']);
$this->language_manager = $language_manager; $this->language_manager = $language_manager;
if ($this->isTranslationDestination()) {
$this->supportsRollback = TRUE;
}
} }
/** /**
@ -81,7 +84,7 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
* {@inheritdoc} * {@inheritdoc}
*/ */
public function import(Row $row, array $old_destination_id_values = array()) { 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()); $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(); $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() { public function getIds() {
$ids['config_name']['type'] = 'string'; $ids['config_name']['type'] = 'string';
if ($this->isTranslationDestination()) {
$ids['langcode']['type'] = 'string';
}
return $ids; return $ids;
} }
@ -118,4 +128,25 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
return $this->dependencies; 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();
}
}
} }

View File

@ -0,0 +1,170 @@
<?php
namespace Drupal\Tests\migrate\Kernel;
use Drupal\migrate\MigrateExecutable;
/**
* Tests rolling back of configuration objects.
*
* @group migrate
*/
class MigrateConfigRollbackTest extends MigrateTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'language', 'config_translation'];
/**
* Tests rolling back configuration.
*/
public function testConfigRollback() {
// Use system.site configuration to demonstrate importing and rolling back
// configuration.
$variable = [
[
'id' => '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'));
}
}

View File

@ -44,9 +44,6 @@ class ConfigTest extends UnitTestCase {
$row = $this->getMockBuilder('Drupal\migrate\Row') $row = $this->getMockBuilder('Drupal\migrate\Row')
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$row->expects($this->once())
->method('hasDestinationProperty')
->will($this->returnValue(FALSE));
$row->expects($this->any()) $row->expects($this->any())
->method('getRawDestination') ->method('getRawDestination')
->will($this->returnValue($source)); ->will($this->returnValue($source));
@ -94,9 +91,6 @@ class ConfigTest extends UnitTestCase {
$row = $this->getMockBuilder('Drupal\migrate\Row') $row = $this->getMockBuilder('Drupal\migrate\Row')
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$row->expects($this->once())
->method('hasDestinationProperty')
->will($this->returnValue($source));
$row->expects($this->any()) $row->expects($this->any())
->method('getRawDestination') ->method('getRawDestination')
->will($this->returnValue($source)); ->will($this->returnValue($source));
@ -110,9 +104,9 @@ class ConfigTest extends UnitTestCase {
->method('getLanguageConfigOverride') ->method('getLanguageConfigOverride')
->with('mi', 'd8_config') ->with('mi', 'd8_config')
->will($this->returnValue($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); $destination_id = $destination->import($row);
$this->assertEquals($destination_id, ['d8_config']); $this->assertEquals($destination_id, ['d8_config', 'mi']);
} }
} }