Commit 9d7f684a authored by Gábor Hojtsy's avatar Gábor Hojtsy

Issue #3001749 by quietone, Jo Fitzgerald, heddn, masipila, Gábor Hojtsy:...

Issue #3001749 by quietone, Jo Fitzgerald, heddn, masipila, Gábor Hojtsy: Migrate D7 i18n custom blocks
parent 44b86a44
......@@ -2,9 +2,7 @@
namespace Drupal\block_content\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
use Drupal\content_translation\Plugin\migrate\source\d6\I18nQueryTrait;
use Drupal\block_content\Plugin\migrate\source\d7\BlockCustomTranslation as D7BlockCustomTranslation;
/**
* Gets Drupal 6 i18n custom block translations from database.
......@@ -14,78 +12,12 @@
* source_module = "i18nblocks"
* )
*/
class BoxTranslation extends DrupalSqlBase {
use I18nQueryTrait;
/**
* {@inheritdoc}
*/
public function query() {
// Build a query based on i18n_strings table where each row has the
// translation for only one property, either title or description. The
// method prepareRow() is then used to obtain the translation for the
// other property.
$query = $this->select('boxes', 'b')
->fields('b', ['bid', 'format', 'body'])
->fields('i18n', ['property'])
->fields('lt', ['lid', 'translation', 'language'])
->orderBy('b.bid')
->isNotNull('lt.lid');
// Use 'title' for the info field to match the property name in the
// i18n_strings table.
$query->addField('b', 'info', 'title');
// Add in the property, which is either title or body. Cast the bid to text
// so PostgreSQL can make the join.
$query->leftJoin('i18n_strings', 'i18n', 'i18n.objectid = CAST(b.bid as CHAR(255))');
$query->condition('i18n.type', 'block');
// Add in the translation for the property.
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
parent::prepareRow($row);
// Save the translation for this property.
$property_in_row = $row->getSourceProperty('property');
// Get the translation for the property not already in the row and save it
// in the row.
$property_not_in_row = ($property_in_row === 'title') ? 'body' : 'title';
return $this->getPropertyNotInRowTranslation($row, $property_not_in_row, 'bid', $this->idMap);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'bid' => $this->t('The block numeric identifier.'),
'format' => $this->t('Input format of the custom block/box content.'),
'lid' => $this->t('i18n_string table id'),
'language' => $this->t('Language for this field.'),
'property' => $this->t('Block property'),
'translation' => $this->t('The translation of the value of "property".'),
'title' => $this->t('Block title.'),
'title_translated' => $this->t('Block title translation.'),
'body' => $this->t('Block body.'),
'body_translated' => $this->t('Block body translation.'),
];
}
class BoxTranslation extends D7BlockCustomTranslation {
/**
* {@inheritdoc}
* Drupal 6 table names.
*/
public function getIds() {
$ids['bid']['type'] = 'integer';
$ids['bid']['alias'] = 'b';
$ids['language']['type'] = 'string';
return $ids;
}
const CUSTOM_BLOCK_TABLE = 'boxes';
const I18N_STRING_TABLE = 'i18n_strings';
}
<?php
namespace Drupal\block_content\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
use Drupal\content_translation\Plugin\migrate\source\I18nQueryTrait;
/**
* Gets Drupal 7 custom block translation from database.
*
* @MigrateSource(
* id = "d7_block_custom_translation",
* source_module = "block"
* )
*/
class BlockCustomTranslation extends DrupalSqlBase {
use I18nQueryTrait;
/**
* Drupal 7 table names.
*/
const CUSTOM_BLOCK_TABLE = 'block_custom';
const I18N_STRING_TABLE = 'i18n_string';
/**
* {@inheritdoc}
*/
public function query() {
// Build a query based on blockCustomTable table where each row has the
// translation for only one property, either title or description. The
// method prepareRow() is then used to obtain the translation for the
// other property.
$query = $this->select(static::CUSTOM_BLOCK_TABLE, 'b')
->fields('b', ['bid', 'format', 'body'])
->fields('i18n', ['property'])
->fields('lt', ['lid', 'translation', 'language'])
->orderBy('b.bid')
->isNotNull('lt.lid');
// Use 'title' for the info field to match the property name in
// i18nStringTable.
$query->addField('b', 'info', 'title');
// Add in the property, which is either title or body. Cast the bid to text
// so PostgreSQL can make the join.
$query->leftJoin(static::I18N_STRING_TABLE, 'i18n', 'i18n.objectid = CAST(b.bid as CHAR(255))');
$query->condition('i18n.type', 'block');
// Add in the translation for the property.
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
parent::prepareRow($row);
// Set the i18n string table for use in I18nQueryTrait.
$this->i18nStringTable = static::I18N_STRING_TABLE;
// Save the translation for this property.
$property_in_row = $row->getSourceProperty('property');
// Get the translation for the property not already in the row and save it
// in the row.
$property_not_in_row = ($property_in_row === 'title') ? 'body' : 'title';
return $this->getPropertyNotInRowTranslation($row, $property_not_in_row, 'bid', $this->idMap);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'bid' => $this->t('The block numeric identifier.'),
'format' => $this->t('Input format of the custom block/box content.'),
'lid' => $this->t('i18n_string table id'),
'language' => $this->t('Language for this field.'),
'property' => $this->t('Block property'),
'translation' => $this->t('The translation of the value of "property".'),
'title' => $this->t('Block title.'),
'title_translated' => $this->t('Block title translation.'),
'body' => $this->t('Block body.'),
'body_translated' => $this->t('Block body translation.'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['bid']['type'] = 'integer';
$ids['bid']['alias'] = 'b';
$ids['language']['type'] = 'string';
return $ids;
}
}
<?php
namespace Drupal\Tests\block_content\Kernel\Migrate\d7;
use Drupal\block_content\Entity\BlockContent;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests migration of i18n custom block strings.
*
* @group migrate_drupal_7
*/
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'block_content',
'content_translation',
'filter',
'language',
'text',
// Required for translation migrations.
'migrate_drupal_multilingual',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['block_content']);
$this->installEntitySchema('block_content');
$this->executeMigrations([
'language',
'd7_filter_format',
'block_content_type',
'block_content_body_field',
'd7_custom_block',
'd7_custom_block_translation',
]);
}
/**
* Tests the Drupal 7 i18n custom block strings to Drupal 8 migration.
*/
public function testCustomBlockContentTranslation() {
/** @var \Drupal\block_content\Entity\BlockContent $block */
$block = BlockContent::load(1)->getTranslation('fr');
$this->assertSame('fr - Mildly amusing limerick of the day', $block->label());
$this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
$this->assertSame('fr', $block->language()->getId());
$translation = "fr - A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
$this->assertSame($translation, $block->body->value);
$this->assertSame('filtered_html', $block->body->format);
$block = $block->getTranslation('is');
$this->assertSame('is - Mildly amusing limerick of the day', $block->label());
$this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
$this->assertSame('is', $block->language()->getId());
$text = "A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
$this->assertSame($text, $block->body->value);
$this->assertSame('filtered_html', $block->body->format);
}
}
<?php
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests i18n custom block translations source plugin.
*
* @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustomTranslation
*
* @group content_translation
*/
class BlockCustomTranslationTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['block_content', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['database']['block_custom'] = [
[
'bid' => 1,
'body' => 'box 1 body',
'info' => 'box 1 title',
'format' => '2',
],
[
'bid' => 2,
'body' => 'box 2 body',
'info' => 'box 2 title',
'format' => '2',
],
];
$tests[0]['database']['i18n_string'] = [
[
'lid' => 1,
'objectid' => 1,
'type' => 'block',
'property' => 'title',
'objectindex' => 1,
'format' => 0,
],
[
'lid' => 2,
'objectid' => 1,
'type' => 'block',
'property' => 'body',
'objectindex' => 1,
'format' => 0,
],
[
'lid' => 3,
'objectid' => 2,
'type' => 'block',
'property' => 'body',
'objectindex' => 2,
'format' => 2,
],
];
$tests[0]['database']['locales_target'] = [
[
'lid' => 1,
'language' => 'fr',
'translation' => 'fr - title translation',
'plid' => 0,
'plural' => 0,
'i18n_status' => 0,
],
[
'lid' => 2,
'language' => 'fr',
'translation' => 'fr - body translation',
'plid' => 0,
'plural' => 0,
'i18n_status' => 0,
],
[
'lid' => 3,
'language' => 'zu',
'translation' => 'zu - body translation',
'plid' => 0,
'plural' => 0,
'i18n_status' => 0,
],
];
$tests[0]['database']['system'] = [
[
'type' => 'module',
'name' => 'system',
'schema_version' => '7001',
'status' => '1',
],
];
$tests[0]['expected_results'] = [
[
'lid' => '1',
'property' => 'title',
'language' => 'fr',
'translation' => 'fr - title translation',
'bid' => '1',
'format' => '2',
'title_translated' => 'fr - title translation',
'body_translated' => 'fr - body translation',
'title' => 'box 1 title',
'body' => 'box 1 body',
],
[
'lid' => '2',
'property' => 'body',
'language' => 'fr',
'translation' => 'fr - body translation',
'bid' => '1',
'format' => '2',
'title_translated' => 'fr - title translation',
'body_translated' => 'fr - body translation',
'title' => 'box 1 title',
'body' => 'box 1 body',
],
[
'lid' => '3',
'property' => 'body',
'language' => 'zu',
'translation' => 'zu - body translation',
'bid' => '2',
'format' => '2',
'title_translated' => NULL,
'body_translated' => 'zu - body translation',
'title' => 'box 2 title',
'body' => 'box 2 body',
],
];
return $tests;
}
}
id: d7_custom_block_translation
label: Custom block translations
migration_tags:
- Drupal 7
- Content
- Multilingual
source:
plugin: d7_block_custom_translation
process:
id:
plugin: migration_lookup
migration: d7_custom_block
source:
- bid
langcode: language
info:
-
plugin: callback
source:
- title_translated
- title
callable: array_filter
-
plugin: callback
callable: current
'body/value':
-
plugin: callback
source:
- body_translated
- body
callable: array_filter
-
plugin: callback
callable: current
'body/format':
plugin: migration_lookup
migration: d7_filter_format
source: format
destination:
plugin: entity:block_content
no_stub: true
translations: true
destination_module: content_translation
migration_dependencies:
required:
- d7_filter_format
- block_content_body_field
- d7_custom_block
- language
<?php
namespace Drupal\content_translation\Plugin\migrate\source\d6;
namespace Drupal\content_translation\Plugin\migrate\source;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
use Drupal\migrate\MigrateException;
......@@ -12,11 +12,18 @@
trait I18nQueryTrait {
/**
* Get the translation for the property not already in the row.
* The i18n string table name.
*
* @var string
*/
protected $i18nStringTable;
/**
* Gets the translation for the property not already in the row.
*
* For some i18n migrations there are two translation values, such as a
* translated title and a translated description, that need to be retrieved.
* Since these values are stored in separate rows of the i18n_strings
* Since these values are stored in separate rows of the i18nStringTable
* table we get them individually, one in the source plugin query() and the
* other in prepareRow(). The names of the properties varies, for example,
* in BoxTranslation they are 'body' and 'title' whereas in
......@@ -26,7 +33,7 @@ trait I18nQueryTrait {
* @param \Drupal\migrate\Row $row
* The current migration row which must include both a 'language' property
* and an 'objectid' property. The 'objectid' is the value for the
* 'objectid' field in the i18n_strings table.
* 'objectid' field in the i18n_string table.
* @param string $property_not_in_row
* The name of the property to get the translation for.
* @param string $object_id_name
......@@ -60,7 +67,7 @@ protected function getPropertyNotInRowTranslation(Row $row, $property_not_in_row
// Get the translation, if one exists, for the property not already in the
// row.
$query = $this->select('i18n_strings', 'i18n')
$query = $this->select($this->i18nStringTable, 'i18n')
->fields('i18n', ['lid'])
->condition('i18n.property', $property_not_in_row)
->condition('i18n.objectid', $object_id);
......
......@@ -2,7 +2,7 @@
namespace Drupal\menu_link_content\Plugin\migrate\source\d6;
use Drupal\content_translation\Plugin\migrate\source\d6\I18nQueryTrait;
use Drupal\content_translation\Plugin\migrate\source\I18nQueryTrait;
use Drupal\migrate\Row;
use Drupal\menu_link_content\Plugin\migrate\source\MenuLink;
......@@ -18,6 +18,11 @@ class MenuLinkTranslation extends MenuLink {
use I18nQueryTrait;
/**
* Drupal 6 table names.
*/
const I18N_STRING_TABLE = 'i18n_strings';
/**
* {@inheritdoc}
*/
......@@ -35,7 +40,7 @@ public function query() {
// Add in the property, which is either title or description. Cast the mlid
// to text so PostgreSQL can make the join.
$query->leftJoin('i18n_strings', 'i18n', 'CAST(ml.mlid as CHAR(255)) = i18n.objectid');
$query->leftJoin(static::I18N_STRING_TABLE, 'i18n', 'CAST(ml.mlid as CHAR(255)) = i18n.objectid');
$query->isNotNull('i18n.lid');
$query->addField('i18n', 'lid');
$query->addField('i18n', 'property');
......@@ -56,6 +61,8 @@ public function prepareRow(Row $row) {
// Save the translation for this property.
$property_in_row = $row->getSourceProperty('property');
// Set the i18n string table for use in I18nQueryTrait.
$this->i18nStringTable = static::I18N_STRING_TABLE;
// Get the translation for the property not already in the row and save it
// in the row.
$property_not_in_row = ($property_in_row == 'title') ? 'description' : 'title';
......
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