diff --git a/core/modules/migrate/config/schema/migrate.destination.schema.yml b/core/modules/migrate/config/schema/migrate.destination.schema.yml index b295741..9c657f9 100644 --- a/core/modules/migrate/config/schema/migrate.destination.schema.yml +++ b/core/modules/migrate/config/schema/migrate.destination.schema.yml @@ -16,3 +16,12 @@ migrate.destination.config: config_name: type: string label: 'Configuration name' + +migrate.destination.entity_revision:*: + type: migrate_destination + label: 'Entity revision' + mapping: + translated: + type: boolean + label: 'Whether revisions are translated' + default: false diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php index 76164e6..8195831 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php @@ -30,24 +30,6 @@ protected static function getEntityTypeId($plugin_id) { } /** - * Get the previous revision of an entity. - */ - protected function getPreviousRevision($entity_id, $revision_id) { - $query = $this->storage->getQuery(); - $query->condition($this->getKey('id'), $entity_id); - $query->condition($this->getKey('revision'), $revision_id, '<'); - $query->sort('vid', 'DESC'); - $query->range(0, 1); - $query->allRevisions(); - $ids = $query->execute(); - - if (empty($ids)) { - return NULL; - } - return $this->storage->loadRevision(key($ids)); - } - - /** * Gets the entity. * * @param \Drupal\migrate\Row $row @@ -64,31 +46,22 @@ protected function getEntity(Row $row, array $old_destination_id_values) { $row->getDestinationProperty($this->getKey('revision')); if (!empty($revision_id) && ($entity = $this->storage->loadRevision($revision_id))) { $entity->setNewRevision(FALSE); - $existing = TRUE; } else { $entity_id = $row->getDestinationProperty($this->getKey('id')); - $entity = $this->getPreviousRevision($entity_id, $revision_id); - } + $entity = $this->storage->load($entity_id); - if ($entity) { - $this->updateEntity($entity, $row); - } - else { - if ($row->isStub()) { - $this->processStubRow($row); + // If we fail to load the original entity something is wrong and we need + // to return immediately. + if (!$entity) { + return FALSE; } - $entity = $this->storage->create($row->getDestination()); - } - if (!isset($existing)) { $entity->enforceIsNew(FALSE); $entity->setNewRevision(TRUE); - // Reset the revision ID, since setNewRevision clears it. - $entity->set($this->getKey('revision'), $revision_id); - $entity->isDefaultRevision(FALSE); } - + $this->updateEntity($entity, $row); + $entity->isDefaultRevision(FALSE); return $entity; } @@ -97,7 +70,13 @@ protected function getEntity(Row $row, array $old_destination_id_values) { */ protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) { $entity->save(); - return array($entity->getRevisionId()); + $ids = array($entity->getRevisionId()); + + if (isset($this->configuration['translated']) && $this->configuration['translated']) { + $ids[] = $entity->language()->getId(); + } + + return $ids; } /** @@ -106,9 +85,21 @@ protected function save(ContentEntityInterface $entity, array $old_destination_i public function getIds() { if ($key = $this->getKey('revision')) { $ids[$key]['type'] = 'integer'; - return $ids; } - throw new MigrateException('This entity type does not support revisions.'); + else { + throw new MigrateException('This entity type does not support revisions.'); + } + + if (isset($this->configuration['translated']) && $this->configuration['translated']) { + if ($key = $this->getKey('langcode')) { + $ids[$key]['type'] = 'string'; + } + else { + throw new MigrateException('This entity type does not support translation.'); + } + } + + return $ids; } } diff --git a/core/modules/migrate/src/Tests/MigrateFilterExecutable.php b/core/modules/migrate/src/Tests/MigrateFilterExecutable.php new file mode 100644 index 0000000..422904e --- /dev/null +++ b/core/modules/migrate/src/Tests/MigrateFilterExecutable.php @@ -0,0 +1,46 @@ +filter = $filter; + } + + public function processRow(Row $row, array $process = NULL, $value = NULL) { + if (!call_user_func($this->filter, $this->migration, $row)) { + throw new MigrateSkipRowException("Row filtered", FALSE); + } + parent::processRow($row, $process, $value); + } + +} diff --git a/core/modules/migrate/src/Tests/MigrateTestBase.php b/core/modules/migrate/src/Tests/MigrateTestBase.php index e9012e3..23ea4e5 100644 --- a/core/modules/migrate/src/Tests/MigrateTestBase.php +++ b/core/modules/migrate/src/Tests/MigrateTestBase.php @@ -147,8 +147,10 @@ protected function prepareMigrations(array $id_mappings) { * * @param string|\Drupal\migrate\Entity\MigrationInterface $migration * The migration to execute, or its ID. + * @param callback $filter + * Predicate for source rows to migrate. */ - protected function executeMigration($migration) { + protected function executeMigration($migration, $filter = NULL) { if (is_string($migration)) { $this->migration = Migration::load($migration); } @@ -158,7 +160,15 @@ protected function executeMigration($migration) { if ($this instanceof MigrateDumpAlterInterface) { static::migrateDumpAlter($this); } - (new MigrateExecutable($this->migration, $this))->import(); + + $executable = NULL; + if ($filter) { + $executable = new MigrateFilterExecutable($this->migration, $this, NULL, $filter); + } + else { + $executable = new MigrateExecutable($this->migration, $this); + } + $executable->import(); } /** @@ -166,10 +176,14 @@ protected function executeMigration($migration) { * * @param string[] $ids * Array of migration IDs, in any order. + * @param callback $filter + * Predicate for source rows to migrate. */ - protected function executeMigrations(array $ids) { + protected function executeMigrations(array $ids, $filter = NULL) { $migrations = Migration::loadMultiple($ids); - array_walk($migrations, [$this, 'executeMigration']); + array_walk($migrations, function($id) use ($filter) { + $this->executeMigration($id, $filter); + }); } /** diff --git a/core/modules/node/migration_templates/d6_node_revision.yml b/core/modules/node/migration_templates/d6_node_revision.yml index e7f3b54..eaba3e9 100644 --- a/core/modules/node/migration_templates/d6_node_revision.yml +++ b/core/modules/node/migration_templates/d6_node_revision.yml @@ -39,3 +39,4 @@ process: destination: plugin: entity_revision:node + translated: true diff --git a/core/modules/node/src/Plugin/migrate/source/d6/Node.php b/core/modules/node/src/Plugin/migrate/source/d6/Node.php index e3ca482..53300f4 100644 --- a/core/modules/node/src/Plugin/migrate/source/d6/Node.php +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php @@ -7,8 +7,6 @@ namespace Drupal\node\Plugin\migrate\source\d6; -use Drupal\Core\Database\Query\Condition; -use Drupal\Core\Database\Query\SelectInterface; use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; @@ -20,11 +18,10 @@ * ) */ class Node extends DrupalSqlBase { - /** - * The join options between the node and the node_revisions table. + * An expression for the translation set of a node. */ - const JOIN = 'n.vid = nr.vid'; + const NODE_TRANSLATION_SET = 'CASE n.tnid WHEN 0 THEN n.nid ELSE n.tnid END'; /** * The default filter format. @@ -44,12 +41,11 @@ class Node extends DrupalSqlBase { * {@inheritdoc} */ public function query() { + $query = $this->translationQuery(); + // Select node in its last revision. - $query = $this->select('node_revisions', 'nr') - ->fields('n', array( - 'nid', + $query->fields('n', array( 'type', - 'language', 'status', 'created', 'changed', @@ -57,7 +53,6 @@ public function query() { 'promote', 'moderate', 'sticky', - 'tnid', 'translate', )) ->fields('nr', array( @@ -70,14 +65,11 @@ public function query() { )); $query->addField('n', 'uid', 'node_uid'); $query->addField('nr', 'uid', 'revision_uid'); - $query->innerJoin('node', 'n', static::JOIN); if (isset($this->configuration['node_type'])) { - $query->condition('type', $this->configuration['node_type']); + $query->condition('n.type', $this->configuration['node_type']); } - $this->addTranslationConditions($query); - return $query; } @@ -110,7 +102,6 @@ public function fields() { 'sticky' => $this->t('Sticky at top of lists'), 'revision' => $this->t('Create new revision'), 'language' => $this->t('Language (fr, en, ...)'), - 'tnid' => $this->t('The translation set id for this node'), 'timestamp' => $this->t('The timestamp the latest revision of this node was created.'), ); return $fields; @@ -242,7 +233,7 @@ protected function getCckData(array $field, Row $node) { // the time being. ->isNotNull($field['field_name'] . '_' . $columns[0]) ->condition('nid', $node->getSourceProperty('nid')) - ->condition('vid', $node->getSourceProperty('vid')) + ->condition('vid', $node->getSourceProperty('field_vid')) ->execute() ->fetchAllAssoc('delta'); } @@ -261,20 +252,43 @@ public function getIds() { } /** - * Add conditions related to translations. + * Build a query to get the maximum vid of each translation set. * - * @param $query + * @return \Drupal\Core\Database\Query\SelectInterface + * The generated query. */ - protected function addTranslationConditions(SelectInterface $query) { - // Use the maximum vid for each translation set. + protected function maxVidQuery() { $subquery = $this->select('node', 'n'); - $subquery->addExpression("CASE n.tnid WHEN 0 THEN n.nid ELSE n.tnid END", - 'translation_set'); + $subquery->addExpression(self::NODE_TRANSLATION_SET, 'translation_set'); $subquery->groupBy('translation_set'); $subquery->addExpression('MAX(vid)', 'vid'); + return $subquery; + } - $query->innerJoin($subquery, 'max_vid', 'n.nid = max_vid.translation_set'); + /** + * Build a query that yields the rows we want to migrate. + * + * It should have a node table 'n', and a node_revision table 'nr'. + * + * @return \Drupal\Core\Database\Query\SelectInterface + * The generated query. + */ + protected function translationQuery() { + $query = $this->select('node', 'n'); + $query->fields('n', ['nid', 'language']); + + // Only yield the default node for each translation set. + $query->where('n.tnid = 0 OR n.nid = n.tnid'); + + // Claim our vid is the maximum vid of our translation set. + $query->join($this->maxVidQuery(), 'max_vid', 'n.nid = max_vid.translation_set'); $query->fields('max_vid', ['vid']); + + // Use the real vid for finding fields. + $query->join('node_revisions', 'nr', 'n.vid = nr.vid'); + $query->addField('nr', 'vid', 'field_vid'); + + return $query; } } diff --git a/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php b/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php index faf8e35..2ce683a 100644 --- a/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php +++ b/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php @@ -7,9 +7,6 @@ namespace Drupal\node\Plugin\migrate\source\d6; -use Drupal\Core\Database\Query\SelectInterface; -use Drupal\migrate\Row; - /** * Drupal 6 node revision source from database. * @@ -20,19 +17,9 @@ class NodeRevision extends Node { /** - * The join options between the node and the node_revisions_table. + * The join options between a node table and its translations. */ - const JOIN = 'n.nid = nr.nid'; - - /** - * {@inheritdoc} - */ - public function prepareRow(Row $row) { - if ($tnid = $row->getSourceProperty('tnid')) { - $row->setSourceProperty('nid', $tnid); - } - return parent::prepareRow($row); - } + const NODE_TRANSLATION_JOIN = '(n.tnid <> 0 AND n.tnid = nt.tnid) OR n.nid = nt.nid'; /** * {@inheritdoc} @@ -50,18 +37,87 @@ public function fields() { */ public function getIds() { $ids['vid']['type'] = 'integer'; - $ids['vid']['alias'] = 'nr'; + $ids['vid']['alias'] = 'tvids'; + $ids['language']['type'] = 'string'; + $ids['language']['alias'] = 'tvids'; return $ids; } /** + * Build a query to turn each revision into multiple translation rows. + * + * For each D6 revision, generate a row for each translation that existed + * at that time. + * + * Eg: If we have: + * | tnid | nid | vid | language | + * | 1 | 1 | 1 | en | + * | 1 | 2 | 2 | fr | + * | 1 | 3 | 3 | de | + * | 1 | 1 | 4 | en | + * + * + * Then we generate the following rows: + * | vid | language | tvid | + * | 1 | en | 1 | + * | 2 | en | 1 | + * | 2 | fr | 2 | + * | 3 | en | 1 | + * | 3 | fr | 2 | + * | 3 | de | 3 | + * | 4 | en | 4 | + * | 4 | fr | 2 | + * | 4 | de | 3 | + * + * @return \Drupal\Core\Database\Query\SelectInterface + * The generated query. + */ + protected function translationRevisionsQuery() { + // Find the nodes that are translations of this node. + $query = $this->select('node_revisions', 'nr'); + $query->join('node', 'n', 'n.nid = nr.nid'); + $query->join('node', 'nt', self::NODE_TRANSLATION_JOIN); + + // Find all translation revisions with lower vids than the current one. + $query->join('node_revisions', 'nrt', + 'nrt.nid = nt.nid AND nr.vid >= nrt.vid'); + + // For each vid/language pair, we only want the top translation vid. + $query->groupBy('nr.vid'); + $query->groupBy('nt.language'); + $query->addField('nr', 'vid'); + $query->addField('nt', 'language'); + $query->addExpression('MAX(nrt.vid)', 'tvid'); + + return $query; + } + + /** * {@inheritdoc} */ - protected function addTranslationConditions(SelectInterface $query) { - // Get revisions in order, so when we import a revision we can use previous - // ones. - $query->fields('nr', ['vid']); - $query->orderBy('vid', 'ASC'); + protected function translationQuery() { + // Multiply each revision according to translationRevisionsQuery. + $query = $this->select('node_revisions', 'nr'); + $query->join($this->translationRevisionsQuery(), 'tvids', + 'nr.vid = tvids.tvid'); + + // Get fields according to this row of node_revisions. + $query->addField('nr', 'vid', 'field_vid'); + // Claim to be from a translation, see 'vid' in the table from + // translationRevisionsQuery. + $query->fields('tvids', ['vid', 'language']); + + // Get the default node for this translation set. + $query->join('node', 'nt', 'nt.nid = nr.nid'); + $query->join('node', 'n', self::NODE_TRANSLATION_JOIN); + $query->where('n.tnid = 0 OR n.tnid = n.nid'); + $query->addField('n', 'nid'); + + // Add orders, for reproducible results. + $query->orderBy('vid'); + $query->orderBy('language'); + + return $query; } } diff --git a/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php b/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php index 0f46d08..bb817b6 100644 --- a/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php +++ b/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php @@ -8,6 +8,8 @@ namespace Drupal\node\Tests\Migrate\d6; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\migrate\Entity\MigrationInterface; +use Drupal\migrate\Row; use Drupal\node\NodeInterface; /** @@ -26,13 +28,13 @@ protected function setUp() { // the necessary languages. ConfigurableLanguage::createFromLangcode('en')->save(); ConfigurableLanguage::createFromLangcode('fr')->save(); - $this->executeMigrations(['d6_node:*', 'd6_node_revision:*']); } /** * Test node revisions migration from Drupal 6 to 8. */ public function testNodeRevision() { + $this->executeMigrations(['d6_node:*', 'd6_node_revision:*']); $storage = \Drupal::entityManager()->getStorage('node'); $node = $storage->loadRevision(2); @@ -87,4 +89,36 @@ public function testNodeRevision() { $this->assertIdentical(['en', 'fr'], $languages); } + /** + * Test partial node revision migrations from Drupal 6 to 8. + */ + public function testSomeNodeRevision() { + $storage = \Drupal::entityManager()->getStorage('node'); + + // Make sure we don't already have a revision. + $this->assertNull($storage->loadRevision(13), 'No revision before migrations'); + + $this->executeMigrations(['d6_node:*', 'd6_node_revision:*'], function(MigrationInterface $migration, Row $row) { + // Only include nodes with nid 9. + if ($row->getSourceProperty('nid') != 9) { + return FALSE; + } + // Only include revision 13. + if (strstr($migration->id(), 'node_revision') !== FALSE) { + if ($row->getSourceProperty('vid') != 13) { + return FALSE; + } + } + return TRUE; + }); + + /** @var \Drupal\node\NodeInterface $node */ + $node = $storage->loadRevision(13); + // Both languages should be present in this revision. + $this->assertTrue($node->hasTranslation('en'), 'English translation exists'); + $this->assertIdentical('The Real McCoy', $node->getTranslation('en')->getTitle()); + $this->assertTrue($node->hasTranslation('fr'), 'French translation exists'); + $this->assertIdentical('Le Vrai McCoy', $node->getTranslation('fr')->getTitle()); + } + } diff --git a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php index 069db5d..0f9bc4c 100644 --- a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php +++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php @@ -62,6 +62,42 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'uid' => 1, 'title' => 'title for revision 2 (node 2)', ], + // A translation set. + [ + 'nid' => 3, + 'type' => 'article', + 'language' => 'en', + 'status' => 1, + 'created' => 1279309100, + 'changed' => 1279309300, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'tnid' => 3, + 'translate' => 0, + 'vid' => 2, + 'uid' => 1, + 'title' => 'title for revision 7 (node 3)', + ], + [ + 'nid' => 4, + 'type' => 'article', + 'language' => 'fr', + 'status' => 1, + 'created' => 1279309200, + 'changed' => 1279309200, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'tnid' => 3, + 'translate' => 0, + 'vid' => 2, + 'uid' => 1, + 'title' => 'title for revision 6 (node 4)', + ], + ], 'node_revisions' => [ [ @@ -108,6 +144,40 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'format' => 1, 'timestamp' => 1279308993, ], + // Translations. + [ + 'nid' => 3, + 'vid' => 5, + 'uid' => 1, + 'title' => 'title for revision 5 (node 3)', + 'body' => 'body for revision 5 (node 3)', + 'teaser' => 'teaser for revision 5 (node 3)', + 'log' => 'log for revision 5 (node 3)', + 'format' => 1, + 'timestamp' => 1279309100, + ], + [ + 'nid' => 3, + 'vid' => 7, + 'uid' => 1, + 'title' => 'title for revision 7 (node 3)', + 'body' => 'body for revision 7 (node 3)', + 'teaser' => 'teaser for revision 7 (node 3)', + 'log' => 'log for revision 7 (node 3)', + 'format' => 1, + 'timestamp' => 1279309300, + ], + [ + 'nid' => 4, + 'vid' => 6, + 'uid' => 1, + 'title' => 'title for revision 6 (node 4)', + 'body' => 'body for revision 6 (node 4)', + 'teaser' => 'teaser for revision 6 (node 4)', + 'log' => 'log for revision 6 (node 4)', + 'format' => 1, + 'timestamp' => 1279309200, + ], ], ]; @@ -126,7 +196,6 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, // Node revision fields. 'vid' => 1, @@ -137,6 +206,7 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'teaser' => 'teaser for revision 1 (node 1)', 'log' => 'log for revision 1 (node 1)', 'format' => 1, + 'field_vid' => 1, ], [ 'nid' => 2, @@ -149,7 +219,6 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, 'vid' => 2, 'node_uid' => 1, @@ -160,6 +229,7 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'log' => 'log for revision 2 (node 2)', 'format' => 1, 'timestamp' => 1279308993, + 'field_vid' => 2, ], [ // Node fields. @@ -173,7 +243,6 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, // Node revision fields. 'vid' => 3, @@ -184,6 +253,7 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'teaser' => 'teaser for revision 3 (node 1)', 'log' => 'log for revision 3 (node 1)', 'format' => 1, + 'field_vid' => 3, ], [ 'nid' => 1, @@ -196,7 +266,6 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, 'vid' => 4, 'node_uid' => 1, @@ -207,6 +276,123 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase { 'log' => 'log for revision 4 (node 1)', 'format' => 1, 'timestamp' => 1279051598, + 'field_vid' => 4, + ], + // Translations add extra revisions. + [ + 'nid' => 3, + 'type' => 'article', + 'language' => 'en', + 'status' => 1, + 'created' => 1279309100, + 'changed' => 1279309300, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'vid' => 5, + 'node_uid' => 1, + 'revision_uid' => 1, + 'title' => 'title for revision 5 (node 3)', + 'body' => 'body for revision 5 (node 3)', + 'teaser' => 'teaser for revision 5 (node 3)', + 'log' => 'log for revision 5 (node 3)', + 'format' => 1, + 'timestamp' => 1279309100, + 'field_vid' => 5, + ], + [ + 'nid' => 3, + 'type' => 'article', + 'language' => 'en', + 'status' => 1, + 'created' => 1279309100, + 'changed' => 1279309300, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'vid' => 6, + 'node_uid' => 1, + 'revision_uid' => 1, + 'title' => 'title for revision 5 (node 3)', + 'body' => 'body for revision 5 (node 3)', + 'teaser' => 'teaser for revision 5 (node 3)', + 'log' => 'log for revision 5 (node 3)', + 'format' => 1, + 'timestamp' => 1279309100, + 'field_vid' => 5, + ], + [ + 'nid' => 3, + 'type' => 'article', + 'language' => 'fr', + 'status' => 1, + 'created' => 1279309100, + 'changed' => 1279309300, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'vid' => 6, + 'node_uid' => 1, + 'revision_uid' => 1, + 'title' => 'title for revision 6 (node 4)', + 'body' => 'body for revision 6 (node 4)', + 'teaser' => 'teaser for revision 6 (node 4)', + 'log' => 'log for revision 6 (node 4)', + 'format' => 1, + 'timestamp' => 1279309200, + 'field_vid' => 6, + ], + [ + 'nid' => 3, + 'type' => 'article', + 'language' => 'en', + 'status' => 1, + 'created' => 1279309100, + 'changed' => 1279309300, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'vid' => 7, + 'node_uid' => 1, + 'revision_uid' => 1, + 'title' => 'title for revision 7 (node 3)', + 'body' => 'body for revision 7 (node 3)', + 'teaser' => 'teaser for revision 7 (node 3)', + 'log' => 'log for revision 7 (node 3)', + 'format' => 1, + 'timestamp' => 1279309300, + 'field_vid' => 7, + ], + [ + 'nid' => 3, + 'type' => 'article', + 'language' => 'fr', + 'status' => 1, + 'created' => 1279309100, + 'changed' => 1279309300, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'vid' => 7, + 'node_uid' => 1, + 'revision_uid' => 1, + 'title' => 'title for revision 6 (node 4)', + 'body' => 'body for revision 6 (node 4)', + 'teaser' => 'teaser for revision 6 (node 4)', + 'log' => 'log for revision 6 (node 4)', + 'format' => 1, + 'timestamp' => 1279309200, + 'field_vid' => 6, ], ]; diff --git a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php index 13131a1..c38af09 100644 --- a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php +++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php @@ -41,7 +41,6 @@ class NodeTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, // Node revision fields. 'body' => 'body for node 1', @@ -65,7 +64,6 @@ class NodeTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, // Node revision fields. 'body' => 'body for node 2', @@ -88,7 +86,6 @@ class NodeTest extends MigrateSqlSourceTestCase { 'promote' => 1, 'moderate' => 0, 'sticky' => 0, - 'tnid' => 0, 'translate' => 0, // Node revision fields. 'body' => 'body for node 5', @@ -100,6 +97,28 @@ class NodeTest extends MigrateSqlSourceTestCase { array('value' => '3.14159'), ), ), + array( + 'nid' => 6, + 'vid' => 7, + 'type' => 'story', + 'language' => 'en', + 'title' => 'node title 6', + 'uid' => 1, + 'status' => 1, + 'created' => 1279290909, + 'changed' => 1279308994, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + // Node revision fields. + 'body' => 'body for node 6', + 'teaser' => 'body for node 6', + 'log' => '', + 'timestamp' => 1279308994, + 'format' => 1, + ), ); /** @@ -150,22 +169,114 @@ protected function setUp() { 'status' => TRUE, ), ); - foreach ($this->expectedResults as $k => $row) { + $this->databaseContents['node'] = [ + [ + 'nid' => 1, + 'vid' => 1, + 'type' => 'page', + 'language' => 'en', + 'title' => 'node title 1', + 'uid' => 1, + 'status' => 1, + 'created' => 1279051598, + 'changed' => 1279051598, + 'comment' => 2, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'tnid' => 0, + ], + [ + 'nid' => 2, + 'vid' => 2, + 'type' => 'page', + 'language' => 'en', + 'title' => 'node title 2', + 'uid' => 1, + 'status' => 1, + 'created' => 1279290908, + 'changed' => 1279308993, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'tnid' => 0, + ], + [ + 'nid' => 5, + 'vid' => 5, + 'type' => 'story', + 'language' => 'en', + 'title' => 'node title 5', + 'uid' => 1, + 'status' => 1, + 'created' => 1279290908, + 'changed' => 1279308993, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'tnid' => 0, + ], + [ + 'nid' => 6, + 'vid' => 6, + 'type' => 'story', + 'language' => 'en', + 'title' => 'node title 6', + 'uid' => 1, + 'status' => 1, + 'created' => 1279290909, + 'changed' => 1279308994, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'tnid' => 6, + ], + [ + 'nid' => 7, + 'vid' => 7, + 'type' => 'story', + 'language' => 'fr', + 'title' => 'node title 7', + 'uid' => 1, + 'status' => 1, + 'created' => 1279290910, + 'changed' => 1279308995, + 'comment' => 0, + 'promote' => 1, + 'moderate' => 0, + 'sticky' => 0, + 'translate' => 0, + 'tnid' => 6, + ], + ]; + + foreach ($this->databaseContents['node'] as $k => $row) { + // Find the equivalent row from expected results. + $result_row = NULL; + foreach ($this->expectedResults as $result) { + if (in_array($result['nid'], [$row['nid'], $row['tnid']])) { + $result_row = $result; + break; + } + } + + // Populate node_revisions. foreach (array('nid', 'vid', 'title', 'uid', 'body', 'teaser', 'format', 'timestamp', 'log') as $field) { - $this->databaseContents['node_revisions'][$k][$field] = $row[$field]; - switch ($field) { - case 'nid': case 'vid': - break; - case 'uid': - $this->databaseContents['node_revisions'][$k]['uid']++; - break; - default: - unset($row[$field]); - break; + $value = isset($row[$field]) ? $row[$field] : $result_row[$field]; + $this->databaseContents['node_revisions'][$k][$field] = $value; + if ($field == 'uid') { + $this->databaseContents['node_revisions'][$k]['uid']++; } } - $this->databaseContents['node'][$k] = $row; } + array_walk($this->expectedResults, function (&$row) { $row['node_uid'] = $row['uid']; $row['revision_uid'] = $row['uid'] + 1;