Commit fbe82f78 authored by catch's avatar catch

Issue #2669984 by maxocub, masipila: Migrate Drupal 7 user entity translations data to Drupal 8

parent bf7029a6
id: d7_user_entity_translation
label: User accounts entity translations
migration_tags:
- Drupal 7
- translation
- Content
- Multilingual
class: Drupal\user\Plugin\migrate\User
source:
plugin: d7_user_entity_translation
process:
uid: entity_id
langcode: language
content_translation_source: source
content_translation_uid: uid
content_translation_status: status
content_translation_outdated: translate
content_translation_created: created
destination:
plugin: entity:user
translations: true
destination_module: content_translation
migration_dependencies:
required:
- language
- d7_entity_translation_settings
- d7_user
......@@ -3171,6 +3171,30 @@
'created' => '1527594929',
'changed' => '1527594929',
))
->values(array(
'entity_type' => 'user',
'entity_id' => '2',
'revision_id' => '2',
'language' => 'fr',
'source' => 'en',
'uid' => '1',
'status' => '0',
'translate' => '0',
'created' => '1531663916',
'changed' => '1531663916',
))
->values(array(
'entity_type' => 'user',
'entity_id' => '2',
'revision_id' => '2',
'language' => 'is',
'source' => 'en',
'uid' => '2',
'status' => '1',
'translate' => '1',
'created' => '1531663925',
'changed' => '1531663925',
))
->execute();
$connection->schema()->createTable('entity_translation_revision', array(
......@@ -6142,6 +6166,26 @@
'delta' => '0',
'field_integer_value' => '99',
))
->values(array(
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => '0',
'entity_id' => '2',
'revision_id' => '2',
'language' => 'fr',
'delta' => '0',
'field_integer_value' => '9',
))
->values(array(
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => '0',
'entity_id' => '2',
'revision_id' => '2',
'language' => 'is',
'delta' => '0',
'field_integer_value' => '1',
))
->values(array(
'entity_type' => 'taxonomy_term',
'bundle' => 'test_vocabulary',
......@@ -21,7 +21,7 @@ process:
timezone: timezone
langcode:
plugin: user_langcode
source: language
source: entity_language
fallback_to_site_default: false
preferred_langcode:
plugin: user_langcode
......
......@@ -62,18 +62,32 @@ public function fields() {
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$uid = $row->getSourceProperty('uid');
$roles = $this->select('users_roles', 'ur')
->fields('ur', ['rid'])
->condition('ur.uid', $row->getSourceProperty('uid'))
->condition('ur.uid', $uid)
->execute()
->fetchCol();
$row->setSourceProperty('roles', $roles);
$row->setSourceProperty('data', unserialize($row->getSourceProperty('data')));
// If this entity was translated using Entity Translation, we need to get
// its source language to get the field values in the right language.
// The translations will be migrated by the d7_user_entity_translation
// migration.
$entity_translatable = $this->isEntityTranslatable('user');
$source_language = $this->getEntityTranslationSourceLanguage('user', $uid);
$language = $entity_translatable && $source_language ? $source_language : $row->getSourceProperty('language');
$row->setSourceProperty('entity_language', $language);
// Get Field API field values.
foreach (array_keys($this->getFields('user')) as $field) {
$row->setSourceProperty($field, $this->getFieldValues('user', $field, $row->getSourceProperty('uid')));
foreach ($this->getFields('user') as $field_name => $field) {
// Ensure we're using the right language if the entity and the field are
// translatable.
$field_language = $entity_translatable && $field['translatable'] ? $language : NULL;
$row->setSourceProperty($field_name, $this->getFieldValues('user', $field_name, $uid, NULL, $field_language));
}
// Get profile field values. This code is lifted directly from the D6
......
<?php
namespace Drupal\user\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Provides Drupal 7 user entity translations source plugin.
*
* @MigrateSource(
* id = "d7_user_entity_translation",
* source_module = "entity_translation"
* )
*/
class UserEntityTranslation extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('entity_translation', 'et')
->fields('et')
->condition('et.entity_type', 'user')
->condition('et.source', '', '<>');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$uid = $row->getSourceProperty('entity_id');
$language = $row->getSourceProperty('language');
// Get Field API field values.
foreach ($this->getFields('user') as $field_name => $field) {
// Ensure we're using the right language if the entity is translatable.
$field_language = $field['translatable'] ? $language : NULL;
$row->setSourceProperty($field_name, $this->getFieldValues('user', $field_name, $uid, NULL, $field_language));
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'entity_type' => $this->t('The entity type this translation relates to'),
'entity_id' => $this->t('The entity id this translation relates to'),
'revision_id' => $this->t('The entity revision id this translation relates to'),
'language' => $this->t('The target language for this translation.'),
'source' => $this->t('The source language from which this translation was created.'),
'uid' => $this->t('The author of this translation.'),
'status' => $this->t('Boolean indicating whether the translation is published (visible to non-administrators).'),
'translate' => $this->t('A boolean indicating whether this translation needs to be updated.'),
'created' => $this->t('The Unix timestamp when the translation was created.'),
'changed' => $this->t('The Unix timestamp when the translation was most recently saved.'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
return [
'entity_id' => [
'type' => 'integer',
],
'language' => [
'type' => 'string',
],
];
}
}
......@@ -24,11 +24,14 @@ class MigrateUserTest extends MigrateDrupal7TestBase {
*/
public static $modules = [
'comment',
'content_translation',
'datetime',
'file',
'image',
'language',
'link',
// Required for translation migrations.
'migrate_drupal_multilingual',
'node',
'system',
'taxonomy',
......@@ -44,6 +47,9 @@ protected function setUp() {
// Prepare to migrate user pictures as well.
$this->installEntitySchema('file');
$this->installEntitySchema('comment');
$this->installEntitySchema('node');
$this->installEntitySchema('taxonomy_term');
$this->createNodeCommentCombination('page');
$this->createNodeCommentCombination('article');
$this->createNodeCommentCombination('blog');
......@@ -59,6 +65,8 @@ protected function setUp() {
'd7_field',
'd7_field_instance',
'd7_user',
'd7_entity_translation_settings',
'd7_user_entity_translation',
]);
}
......@@ -81,8 +89,10 @@ protected function setUp() {
* The last login time.
* @param bool $blocked
* Whether or not the account is blocked.
* @param string $langcode
* The user account's language code.
* @param string $entity_langcode
* The user entity language code.
* @param string $prefered_langcode
* The user prefered language code.
* @param string $timezone
* The user account's timezone name.
* @param string $init
......@@ -96,7 +106,7 @@ protected function setUp() {
* @param bool $has_picture
* (optional) Whether the user is expected to have a picture attached.
*/
protected function assertEntity($id, $label, $mail, $password, $created, $access, $login, $blocked, $langcode, $timezone, $init, $roles, $field_integer, $field_file_target_id = FALSE, $has_picture = FALSE) {
protected function assertEntity($id, $label, $mail, $password, $created, $access, $login, $blocked, $entity_langcode, $prefered_langcode, $timezone, $init, $roles, $field_integer, $field_file_target_id = FALSE, $has_picture = FALSE) {
/** @var \Drupal\user\UserInterface $user */
$user = User::load($id);
$this->assertTrue($user instanceof UserInterface);
......@@ -115,20 +125,20 @@ protected function assertEntity($id, $label, $mail, $password, $created, $access
// test if the value was imported correctly.
$language_manager = $this->container->get('language_manager');
$default_langcode = $language_manager->getDefaultLanguage()->getId();
if ($langcode == '') {
if ($prefered_langcode == '') {
$this->assertSame('en', $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
elseif ($language_manager->getLanguage($langcode) === NULL) {
elseif ($language_manager->getLanguage($prefered_langcode) === NULL) {
$this->assertSame($default_langcode, $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
else {
$this->assertSame($langcode, $user->langcode->value);
$this->assertSame($langcode, $user->preferred_langcode->value);
$this->assertSame($langcode, $user->preferred_admin_langcode->value);
$this->assertSame($entity_langcode, $user->langcode->value);
$this->assertSame($prefered_langcode, $user->preferred_langcode->value);
$this->assertSame($prefered_langcode, $user->preferred_admin_langcode->value);
}
$this->assertSame($timezone, $user->getTimeZone());
......@@ -170,10 +180,21 @@ public function testUser() {
$roles[] = reset($role);
}
$entity_translation = Database::getConnection('default', 'migrate')
->select('entity_translation', 'et')
->fields('et', ['language'])
->condition('et.entity_type', 'user')
->condition('et.entity_id', $source->uid)
->condition('et.source', '')
->execute()
->fetchField();
$entity_language = $entity_translation ?: $source->language;
$field_integer = Database::getConnection('default', 'migrate')
->select('field_data_field_integer', 'fi')
->fields('fi', ['field_integer_value'])
->condition('fi.entity_id', $source->uid)
->condition('fi.language', $entity_language)
->execute()
->fetchCol();
$field_integer = !empty($field_integer) ? $field_integer : NULL;
......@@ -194,6 +215,7 @@ public function testUser() {
$source->access,
$source->login,
$source->status,
$entity_language,
$source->language,
$source->timezone,
$source->init,
......@@ -218,4 +240,45 @@ public function testUser() {
}
}
/**
* Tests the Drupal 7 user entity translations to Drupal 8 migration.
*/
public function testUserEntityTranslations() {
$manager = $this->container->get('content_translation.manager');
// Get the user and its translations.
$user = User::load(2);
$user_fr = $user->getTranslation('fr');
$user_is = $user->getTranslation('is');
// Test that fields translated with Entity Translation are migrated.
$this->assertSame('99', $user->field_integer->value);
$this->assertSame('9', $user_fr->field_integer->value);
$this->assertSame('1', $user_is->field_integer->value);
// Test that the French translation metadata is correctly migrated.
$metadata_fr = $manager->getTranslationMetadata($user_fr);
$this->assertSame('en', $metadata_fr->getSource());
$this->assertSame('1', $metadata_fr->getAuthor()->uid->value);
$this->assertSame('1531663916', $metadata_fr->getCreatedTime());
$this->assertFalse($metadata_fr->isOutdated());
$this->assertFalse($metadata_fr->isPublished());
// Test that the Icelandic translation metadata is correctly migrated.
$metadata_is = $manager->getTranslationMetadata($user_is);
$this->assertSame('en', $metadata_is->getSource());
$this->assertSame('2', $metadata_is->getAuthor()->uid->value);
$this->assertSame('1531663925', $metadata_is->getCreatedTime());
$this->assertTrue($metadata_is->isOutdated());
$this->assertTrue($metadata_is->isPublished());
// Test that untranslatable properties are the same as the source language.
$this->assertSame($user->label(), $user_fr->label());
$this->assertSame($user->label(), $user_is->label());
$this->assertSame($user->getEmail(), $user_fr->getEmail());
$this->assertSame($user->getEmail(), $user_is->getEmail());
$this->assertSame($user->getPassword(), $user_fr->getPassword());
$this->assertSame($user->getPassword(), $user_is->getPassword());
}
}
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests D7 user entity translation source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d7\UserEntityTranslation
*
* @group user
*/
class UserEntityTranslationTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['entity_translation'] = [
[
'entity_type' => 'user',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'en',
'source' => '',
'uid' => 1,
'status' => 1,
'translate' => 0,
'created' => 1531343498,
'changed' => 1531343498,
],
[
'entity_type' => 'user',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'fr',
'source' => 'en',
'uid' => 2,
'status' => 1,
'translate' => 1,
'created' => 1531343508,
'changed' => 1531343508,
],
[
'entity_type' => 'user',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'es',
'source' => 'en',
'uid' => 1,
'status' => 0,
'translate' => 0,
'created' => 1531343456,
'changed' => 1531343456,
],
];
$tests[0]['source_data']['field_config'] = [
[
'id' => 1,
'field_name' => 'field_test',
'type' => 'text',
'module' => 'text',
'active' => 1,
'storage_type' => 'field_sql_storage',
'storage_module' => 'field_sql_storage',
'storage_active' => 1,
'locked' => 1,
'data' => 'a:0:{}',
'cardinality' => 1,
'translatable' => 1,
'deleted' => 0,
],
];
$tests[0]['source_data']['field_config_instance'] = [
[
'id' => 1,
'field_id' => 1,
'field_name' => 'field_test',
'entity_type' => 'user',
'bundle' => 'user',
'data' => 'a:0:{}',
'deleted' => 0,
],
];
$tests[0]['source_data']['field_data_field_test'] = [
[
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => 0,
'entity_id' => 1,
'revision_id' => 1,
'language' => 'en',
'delta' => 0,
'field_test_value' => 'English field',
'field_test_format' => NULL,
],
[
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => 0,
'entity_id' => 1,
'revision_id' => 1,
'language' => 'fr',
'delta' => 0,
'field_test_value' => 'French field',
'field_test_format' => NULL,
],
[
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => 0,
'entity_id' => 1,
'revision_id' => 1,
'language' => 'es',
'delta' => 0,
'field_test_value' => 'Spanish field',
'field_test_format' => NULL,
],
];
$tests[0]['source_data']['users'] = [
[
'uid' => 1,
'name' => 'admin',
'pass' => 'password123',
'mail' => 'admin@example.com',
'theme' => '',
'signature' => '',
'signature_format' => 'filtered_html',
'created' => 1531343456,
'access' => 1531343456,
'login' => 1531343456,
'status' => 1,
'timezone' => 'America/New_York',
'language' => 'fr',
'picture' => 0,
'init' => 'admin@example.com',
'data' => 'a:0:{}',
],
];
$tests[0]['source_data']['users_roles'] = [
[
'uid' => 1,
'rid' => 3,
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'entity_type' => 'user',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'fr',
'source' => 'en',
'uid' => 2,
'status' => 1,
'translate' => 1,
'created' => 1531343508,
'changed' => 1531343508,
'field_test' => [
[
'value' => 'French field',
'format' => NULL,
],
],
],
[
'entity_type' => 'user',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'es',
'source' => 'en',
'uid' => 1,
'status' => 0,
'translate' => 0,
'created' => 1531343456,
'changed' => 1531343456,
'field_test' => [
[
'value' => 'Spanish field',
'format' => NULL,
],
],
],
];
return $tests;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment