Commit 9eb5b8be authored by webchick's avatar webchick

Issue #2577155 by mikeryan, benjy: Some source plugins produce duplicate rows

parent 158d4345
......@@ -33,6 +33,7 @@ class CommentType extends DrupalSqlBase {
*/
public function query() {
return $this->select('field_config_instance', 'fci')
->distinct()
->fields('fci', array('bundle'))
->condition('entity_type', 'comment');
}
......
......@@ -9,6 +9,7 @@
use Drupal\comment\CommentTypeInterface;
use Drupal\comment\Entity\CommentType;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
......@@ -58,6 +59,11 @@ public function testMigration() {
$this->assertEntity('comment_node_book', 'Book page comment');
$this->assertEntity('comment_node_forum', 'Forum topic comment');
$this->assertEntity('comment_node_test_content_type', 'Test content type comment');
// Validate that the source count and processed count match up.
/** @var \Drupal\migrate\Entity\MigrationInterface $migration */
$migration = Migration::load('d7_comment_type');
$this->assertIdentical($migration->getSourcePlugin()->count(), $migration->getIdMap()->processedCount());
}
}
......@@ -130,7 +130,6 @@ process:
source:
- '@type'
- global_settings
- widget_settings
destination:
plugin: md_entity:field_storage_config
......@@ -26,8 +26,8 @@ class FieldSettings extends ProcessPluginBase {
* Get the field default/mapped settings.
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($field_type, $global_settings, $widget_settings) = $value;
return $this->getSettings($field_type, $global_settings, $widget_settings);
list($field_type, $global_settings) = $value;
return $this->getSettings($field_type, $global_settings);
}
/**
......@@ -37,13 +37,11 @@ public function transform($value, MigrateExecutableInterface $migrate_executable
* The field type.
* @param array $global_settings
* The field settings.
* @param array $widget_settings
* The widget settings needed for some settings.
*
* @return array
* A valid array of settings.
*/
public function getSettings($field_type, $global_settings, $widget_settings) {
public function getSettings($field_type, $global_settings) {
$max_length = isset($global_settings['max_length']) ? $global_settings['max_length'] : '';
$max_length = empty($max_length) ? 255 : $max_length;
if (isset($global_settings['allowed_values'])) {
......
......@@ -37,12 +37,9 @@ public function query() {
'active',
'locked',
))
->fields('cnfi', array(
'widget_type',
'widget_settings',
));
$query->join('content_node_field_instance', 'cnfi', 'cnfi.field_name = cnf.field_name');
$query->orderBy('field_name');
->distinct();
// Only import fields which are actually being used.
$query->innerJoin('content_node_field_instance', 'cnfi', 'cnfi.field_name = cnf.field_name');
return $query;
}
......@@ -54,6 +51,7 @@ public function fields() {
return array(
'field_name' => $this->t('Field name'),
'type' => $this->t('Type (text, integer, ....)'),
'widget_type' => $this->t('An instance-specific widget type'),
'global_settings' => $this->t('Global settings. Shared with every field instance.'),
'required' => $this->t('Required'),
'multiple' => $this->t('Multiple'),
......@@ -69,12 +67,33 @@ public function fields() {
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// The instance widget_type helps determine what D8 field type we'll use.
// Identify the distinct widget_types being used in D6.
$widget_types = $this->select('content_node_field_instance', 'cnfi')
->fields('cnfi', ['widget_type'])
->condition('field_name', $row->getSourceProperty('field_name'))
->distinct()
->orderBy('widget_type')
->execute()
->fetchCol();
assert(count($widget_types) > 0);
// Arbitrarily use the first widget_type - if there are multiples, let the
// migrator know.
$row->setSourceProperty('widget_type', $widget_types[0]);
if (count($widget_types) > 1) {
$this->migration->getIdMap()->saveMessage(
['field_name' => $row->getSourceProperty('field_name')],
$this->t('Widget types @types are used in Drupal 6 field instances: widget type @selected_type applied to the Drupal 8 base field', [
'@types' => implode(', ', $widget_types),
'@selected_type' => $widget_types[0],
])
);
}
// Unserialize data.
$global_settings = unserialize($row->getSourceProperty('global_settings'));
$widget_settings = unserialize($row->getSourceProperty('widget_settings'));
$db_columns = unserialize($row->getSourceProperty('db_columns'));
$row->setSourceProperty('global_settings', $global_settings);
$row->setSourceProperty('widget_settings', $widget_settings);
$row->setSourceProperty('db_columns', $db_columns);
return parent::prepareRow($row);
}
......
......@@ -24,6 +24,7 @@ class Field extends DrupalSqlBase {
*/
public function query() {
$query = $this->select('field_config', 'fc')
->distinct()
->fields('fc')
->fields('fci', array('entity_type'))
->condition('fc.active', 1)
......
......@@ -8,6 +8,7 @@
namespace Drupal\field\Tests\Migrate\d6;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
/**
......@@ -94,6 +95,19 @@ public function testFields() {
// Text field with a single checkbox.
$field_storage = FieldStorageConfig::load('node.field_test_text_single_checkbox');
$this->assertIdentical("boolean", $field_storage->getType(), t('Field type is @fieldtype. It should be boolean.', array('@fieldtype' => $field_storage->getType())));
// Validate that the source count and processed count match up.
/** @var \Drupal\migrate\Entity\MigrationInterface $migration */
$migration = Migration::load('d6_field');
$this->assertIdentical($migration->getSourcePlugin()->count(), $migration->getIdMap()->processedCount());
// Check that we've reported on a conflict in widget_types.
$messages = [];
foreach ($migration->getIdMap()->getMessageIterator() as $message_row) {
$messages[] = $message_row->message;
}
$this->assertIdentical(count($messages), 1);
$this->assertIdentical($messages[0], 'Widget types optionwidgets_onoff, text_textfield are used in Drupal 6 field instances: widget type optionwidgets_onoff applied to the Drupal 8 base field');
}
}
......@@ -9,6 +9,7 @@
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
/**
......@@ -113,6 +114,11 @@ public function testFields() {
$this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
$field = FieldStorageConfig::load('node.taxonomy_forums');
$this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
// Validate that the source count and processed count match up.
/** @var \Drupal\migrate\Entity\MigrationInterface $migration */
$migration = Migration::load('d7_field');
$this->assertIdentical($migration->getSourcePlugin()->count(), $migration->getIdMap()->processedCount());
}
}
......@@ -69,7 +69,6 @@ protected function setUp() {
$this->databaseContents['content_node_field'][0]['global_settings'] = serialize($this->databaseContents['content_node_field'][0]['global_settings']);
$this->databaseContents['content_node_field'][0]['db_columns'] = serialize($this->databaseContents['content_node_field'][0]['db_columns']);
$this->databaseContents['content_node_field_instance'][0]['widget_settings'] = serialize(array());
$this->databaseContents['content_node_field_instance'][0]['widget_type'] = 'text_textarea';
$this->databaseContents['content_node_field_instance'][0]['field_name'] = 'field_body';
parent::setUp();
......
<?php
/**
* @file
* Contains \Drupal\migrate_drupal\Tests\Table\d6\ContentFieldTestTextSingleCheckbox.
*
* THIS IS A GENERATED FILE. DO NOT EDIT.
*
* @see core/scripts/migrate-db.sh
* @see https://www.drupal.org/sandbox/benjy/2405029
*/
namespace Drupal\migrate_drupal\Tests\Table\d6;
use Drupal\migrate_drupal\Tests\Dump\DrupalDumpBase;
/**
* Generated file to represent the content_field_test_text_single_checkbox table.
*/
class ContentFieldTestTextSingleCheckbox extends DrupalDumpBase {
public function load() {
$this->createTable("content_field_test_text_single_checkbox", array(
'primary key' => array(
'vid',
),
'fields' => array(
'vid' => array(
'type' => 'int',
'not null' => TRUE,
'length' => '10',
'default' => '0',
'unsigned' => TRUE,
),
'nid' => array(
'type' => 'int',
'not null' => TRUE,
'length' => '10',
'default' => '0',
'unsigned' => TRUE,
),
'field_test_text_single_checkbox_value' => array(
'type' => 'text',
'not null' => FALSE,
'length' => 100,
),
),
'mysql_character_set' => 'utf8',
));
$this->database->insert("content_field_test_text_single_checkbox")->fields(array(
'vid',
'nid',
'field_test_text_single_checkbox_value',
))
->values(array(
'vid' => '1',
'nid' => '1',
'field_test_text_single_checkbox_value' => '0',
))->values(array(
'vid' => '2',
'nid' => '1',
'field_test_text_single_checkbox_value' => NULL,
))->values(array(
'vid' => '3',
'nid' => '2',
'field_test_text_single_checkbox_value' => NULL,
))->values(array(
'vid' => '5',
'nid' => '2',
'field_test_text_single_checkbox_value' => NULL,
))->execute();
}
}
#ad2cfdaf51bfe9c961e00f14580d3102
......@@ -80,7 +80,7 @@ public function load() {
'locked' => array(
'type' => 'int',
'not null' => TRUE,
'length' => '11',
'length' => '4',
'default' => '0',
),
),
......@@ -291,7 +291,7 @@ public function load() {
'global_settings' => "a:4:{s:15:\"text_processing\";s:1:\"0\";s:10:\"max_length\";s:0:\"\";s:14:\"allowed_values\";s:18:\"0|Hello\r\n1|Goodbye\";s:18:\"allowed_values_php\";s:0:\"\";}",
'required' => '0',
'multiple' => '0',
'db_storage' => '1',
'db_storage' => '0',
'module' => 'text',
'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
'active' => '1',
......@@ -322,4 +322,4 @@ public function load() {
}
}
#e1fbb3a444896287af59cd6395555fbf
#aacab7ae9503014a764572f877dd3f6f
......@@ -115,11 +115,6 @@ public function load() {
'precision' => '10',
'scale' => '0',
),
'field_test_text_single_checkbox_value' => array(
'type' => 'text',
'not null' => FALSE,
'length' => 100,
),
'field_test_integer_selectlist_value' => array(
'type' => 'int',
'not null' => FALSE,
......@@ -192,7 +187,6 @@ public function load() {
'field_test_filefield_list',
'field_test_filefield_data',
'field_test_four_value',
'field_test_text_single_checkbox_value',
'field_test_integer_selectlist_value',
'field_test_float_single_checkbox_value',
'field_test_decimal_radio_buttons_value',
......@@ -221,7 +215,6 @@ public function load() {
'field_test_filefield_list' => '1',
'field_test_filefield_data' => 'a:1:{s:11:"description";s:4:"desc";}',
'field_test_four_value' => NULL,
'field_test_text_single_checkbox_value' => '0',
'field_test_integer_selectlist_value' => '3412',
'field_test_float_single_checkbox_value' => '3',
'field_test_decimal_radio_buttons_value' => NULL,
......@@ -249,7 +242,6 @@ public function load() {
'field_test_filefield_list' => NULL,
'field_test_filefield_data' => NULL,
'field_test_four_value' => NULL,
'field_test_text_single_checkbox_value' => NULL,
'field_test_integer_selectlist_value' => NULL,
'field_test_float_single_checkbox_value' => NULL,
'field_test_decimal_radio_buttons_value' => NULL,
......@@ -277,7 +269,6 @@ public function load() {
'field_test_filefield_list' => NULL,
'field_test_filefield_data' => NULL,
'field_test_four_value' => NULL,
'field_test_text_single_checkbox_value' => NULL,
'field_test_integer_selectlist_value' => NULL,
'field_test_float_single_checkbox_value' => NULL,
'field_test_decimal_radio_buttons_value' => NULL,
......@@ -305,7 +296,6 @@ public function load() {
'field_test_filefield_list' => NULL,
'field_test_filefield_data' => NULL,
'field_test_four_value' => NULL,
'field_test_text_single_checkbox_value' => NULL,
'field_test_integer_selectlist_value' => NULL,
'field_test_float_single_checkbox_value' => NULL,
'field_test_decimal_radio_buttons_value' => NULL,
......@@ -319,4 +309,4 @@ public function load() {
}
}
#e355803b63e8cbefe404f59e30bbf793
#91ccaaf5513eb0c3922e6a0d1022b0c4
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