diff --git a/core/modules/aggregator/migration_templates/d6_aggregator_feed.yml b/core/modules/aggregator/migration_templates/d6_aggregator_feed.yml index cad1553..105d09b 100644 --- a/core/modules/aggregator/migration_templates/d6_aggregator_feed.yml +++ b/core/modules/aggregator/migration_templates/d6_aggregator_feed.yml @@ -2,6 +2,7 @@ id: d6_aggregator_feed label: Aggregator feeds migration_tags: - Drupal 6 +audit_ids: true source: plugin: aggregator_feed process: diff --git a/core/modules/aggregator/migration_templates/d6_aggregator_item.yml b/core/modules/aggregator/migration_templates/d6_aggregator_item.yml index e14dbd6..022a780 100644 --- a/core/modules/aggregator/migration_templates/d6_aggregator_item.yml +++ b/core/modules/aggregator/migration_templates/d6_aggregator_item.yml @@ -2,6 +2,7 @@ id: d6_aggregator_item label: Aggregator items migration_tags: - Drupal 6 +audit_ids: true source: plugin: aggregator_item process: diff --git a/core/modules/aggregator/migration_templates/d7_aggregator_feed.yml b/core/modules/aggregator/migration_templates/d7_aggregator_feed.yml index 5dbeb25..9a038b7 100644 --- a/core/modules/aggregator/migration_templates/d7_aggregator_feed.yml +++ b/core/modules/aggregator/migration_templates/d7_aggregator_feed.yml @@ -2,6 +2,7 @@ id: d7_aggregator_feed label: Aggregator feeds migration_tags: - Drupal 7 +audit_ids: true source: plugin: aggregator_feed process: diff --git a/core/modules/aggregator/migration_templates/d7_aggregator_item.yml b/core/modules/aggregator/migration_templates/d7_aggregator_item.yml index 054ba43..ac76a8c 100644 --- a/core/modules/aggregator/migration_templates/d7_aggregator_item.yml +++ b/core/modules/aggregator/migration_templates/d7_aggregator_item.yml @@ -2,6 +2,7 @@ id: d7_aggregator_item label: Aggregator items migration_tags: - Drupal 7 +audit_ids: true source: plugin: aggregator_item process: diff --git a/core/modules/ban/migration_templates/d7_blocked_ips.yml b/core/modules/ban/migration_templates/d7_blocked_ips.yml index 0122dc6..9197cf2 100644 --- a/core/modules/ban/migration_templates/d7_blocked_ips.yml +++ b/core/modules/ban/migration_templates/d7_blocked_ips.yml @@ -2,6 +2,7 @@ id: d7_blocked_ips label: Blocked IPs migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_blocked_ips process: diff --git a/core/modules/block_content/migration_templates/d6_custom_block.yml b/core/modules/block_content/migration_templates/d6_custom_block.yml index 55fbcb5..d2826c7 100644 --- a/core/modules/block_content/migration_templates/d6_custom_block.yml +++ b/core/modules/block_content/migration_templates/d6_custom_block.yml @@ -2,6 +2,7 @@ id: d6_custom_block label: Custom blocks migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_box process: diff --git a/core/modules/block_content/migration_templates/d7_custom_block.yml b/core/modules/block_content/migration_templates/d7_custom_block.yml index ca06cf0..1089ca3 100644 --- a/core/modules/block_content/migration_templates/d7_custom_block.yml +++ b/core/modules/block_content/migration_templates/d7_custom_block.yml @@ -2,6 +2,7 @@ id: d7_custom_block label: Custom blocks migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_block_custom process: diff --git a/core/modules/book/migration_templates/d6_book.yml b/core/modules/book/migration_templates/d6_book.yml index 94d7a8f..f075c39 100644 --- a/core/modules/book/migration_templates/d6_book.yml +++ b/core/modules/book/migration_templates/d6_book.yml @@ -2,6 +2,7 @@ id: d6_book label: Books migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_book process: diff --git a/core/modules/comment/migration_templates/d6_comment.yml b/core/modules/comment/migration_templates/d6_comment.yml index 06820d4..4add74b 100644 --- a/core/modules/comment/migration_templates/d6_comment.yml +++ b/core/modules/comment/migration_templates/d6_comment.yml @@ -2,6 +2,7 @@ id: d6_comment label: Comments migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_comment constants: diff --git a/core/modules/comment/migration_templates/d7_comment.yml b/core/modules/comment/migration_templates/d7_comment.yml index 94a2884..c020ab2 100644 --- a/core/modules/comment/migration_templates/d7_comment.yml +++ b/core/modules/comment/migration_templates/d7_comment.yml @@ -2,6 +2,7 @@ id: d7_comment label: Comments migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_comment constants: diff --git a/core/modules/file/migration_templates/d6_file.yml b/core/modules/file/migration_templates/d6_file.yml index 8371d45..8589978 100644 --- a/core/modules/file/migration_templates/d6_file.yml +++ b/core/modules/file/migration_templates/d6_file.yml @@ -4,6 +4,7 @@ id: d6_file label: Files migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_file constants: diff --git a/core/modules/file/migration_templates/d6_upload.yml b/core/modules/file/migration_templates/d6_upload.yml index a497099..0942e10 100644 --- a/core/modules/file/migration_templates/d6_upload.yml +++ b/core/modules/file/migration_templates/d6_upload.yml @@ -2,6 +2,7 @@ id: d6_upload label: File uploads migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_upload process: diff --git a/core/modules/file/migration_templates/d7_file.yml b/core/modules/file/migration_templates/d7_file.yml index 3fee046..8bc2147 100644 --- a/core/modules/file/migration_templates/d7_file.yml +++ b/core/modules/file/migration_templates/d7_file.yml @@ -4,6 +4,7 @@ id: d7_file label: Files migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_file scheme: public diff --git a/core/modules/file/migration_templates/d7_file_private.yml b/core/modules/file/migration_templates/d7_file_private.yml index 9c6b8e2..d2e7c89 100644 --- a/core/modules/file/migration_templates/d7_file_private.yml +++ b/core/modules/file/migration_templates/d7_file_private.yml @@ -2,6 +2,7 @@ id: d7_file_private label: Files migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_file scheme: private diff --git a/core/modules/menu_link_content/migration_templates/d6_menu_links.yml b/core/modules/menu_link_content/migration_templates/d6_menu_links.yml index 2c8ad4a..2a79d35 100644 --- a/core/modules/menu_link_content/migration_templates/d6_menu_links.yml +++ b/core/modules/menu_link_content/migration_templates/d6_menu_links.yml @@ -2,6 +2,7 @@ id: d6_menu_links label: Menu links migration_tags: - Drupal 6 +audit_ids: true source: plugin: menu_link process: diff --git a/core/modules/menu_link_content/migration_templates/d7_menu_links.yml b/core/modules/menu_link_content/migration_templates/d7_menu_links.yml index 200a792..854a056 100644 --- a/core/modules/menu_link_content/migration_templates/d7_menu_links.yml +++ b/core/modules/menu_link_content/migration_templates/d7_menu_links.yml @@ -2,6 +2,7 @@ id: d7_menu_links label: Menu links migration_tags: - Drupal 7 +audit_ids: true source: plugin: menu_link constants: diff --git a/core/modules/migrate/migrate.services.yml b/core/modules/migrate/migrate.services.yml index 1a4f64d..1b95191 100644 --- a/core/modules/migrate/migrate.services.yml +++ b/core/modules/migrate/migrate.services.yml @@ -30,3 +30,5 @@ services: plugin.manager.migration: class: Drupal\migrate\Plugin\MigrationPluginManager arguments: ['@module_handler', '@cache.discovery_migration', '@language_manager'] + migrate.id_auditor: + class: Drupal\migrate\MigrateIdAuditor diff --git a/core/modules/migrate/src/MigrateIdAuditor.php b/core/modules/migrate/src/MigrateIdAuditor.php new file mode 100644 index 0000000..19f92cb --- /dev/null +++ b/core/modules/migrate/src/MigrateIdAuditor.php @@ -0,0 +1,35 @@ +getDestinationPlugin(); + if ($destination instanceof MigrateIdAuditInterface) { + if ($destination->unsafeIdsExist($migration->getIdMap())) { + $ret[$destination->entityTypeId()] = TRUE; + } + } + } + return array_keys($ret); + } + +} diff --git a/core/modules/migrate/src/Plugin/MigrateIdAuditInterface.php b/core/modules/migrate/src/Plugin/MigrateIdAuditInterface.php new file mode 100644 index 0000000..f582210 --- /dev/null +++ b/core/modules/migrate/src/Plugin/MigrateIdAuditInterface.php @@ -0,0 +1,39 @@ +getSettings(); } + /** + * Get the highest ID that exists for this destination. + * + * This is not the highest ID that has been migrated, but the highest ID + * that exists in the destination, eg: highest node ID on the site. + * + * @return int + * The highest ID value found. If no IDs at all are found, or if the + * concept of a highest ID is not meaningful, zero should be returned. + */ + protected function highestDestinationId() { + $query = $this->storage->getQuery() + ->sort($this->getHighestIdField(), 'DESC') + ->range(0, 1); + $found = $query->execute(); + return (int) reset($found); + } + + /** + * {@inheritdoc} + */ + public function getHighestIdField() { + return $this->getKey('id'); + } + + /** + * {@inheritdoc} + */ + public function unsafeIdsExist(MigrateIdMapInterface $id_map) { + // If IDs are are audited, see if there are any conflicts. + if (!empty($this->migration->getPluginDefinition()['audit_ids'])) { + if (!($id_map instanceof MigrateMaxIdInterface)) { + // We don't know how to audit IDs without a cooperating ID map. + return FALSE; + } + $highestMigrated = $id_map->getMaxId($this->getHighestIdField()); + if ($this->highestDestinationId() > $highestMigrated) { + // There's a new ID that we might conflict with! + return TRUE; + } + } + } + + /** + * {@inheritdoc} + */ + public function entityTypeId() { + return $this->storage->getEntityTypeId(); + } + } diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php index b0db476..b646059 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php @@ -78,4 +78,11 @@ public function getIds() { throw new MigrateException('This entity type does not support revisions.'); } + /** + * {@inheritdoc} + */ + public function getHighestIdField() { + return $this->getKey('revision'); + } + } diff --git a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php index 27b7569..2b6e30c 100644 --- a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php +++ b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php @@ -6,6 +6,7 @@ use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\PluginBase; +use Drupal\migrate\Plugin\MigrateMaxIdInterface; use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Event\MigrateIdMapMessageEvent; use Drupal\migrate\MigrateException; @@ -26,7 +27,7 @@ * * @PluginID("sql") */ -class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryPluginInterface { +class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryPluginInterface, MigrateMaxIdInterface { /** * Column name of hashed source id values. @@ -923,4 +924,22 @@ public function valid() { return $this->currentRow !== FALSE; } + /** + * {@inheritdoc} + */ + public function getMaxId($field) { + if (!$this->getDatabase()->schema()->tableExists($this->mapTableName())) { + return 0; + } + + $sqlField = $this->destinationIdFields()[$field]; + + $query = $this->getDatabase()->select($this->mapTableName(), 'map') + ->fields('map', [$sqlField]) + ->orderBy($sqlField, 'DESC') + ->range(0, 1); + $found = $query->execute()->fetchField(); + return (int) $found; + } + } diff --git a/core/modules/migrate/tests/modules/migrate_high_water_test/migration_templates/migrate.migration.high_water_test.yml b/core/modules/migrate/tests/modules/migrate_high_water_test/migration_templates/migrate.migration.high_water_test.yml index 6a86577..73f32a8 100644 --- a/core/modules/migrate/tests/modules/migrate_high_water_test/migration_templates/migrate.migration.high_water_test.yml +++ b/core/modules/migrate/tests/modules/migrate_high_water_test/migration_templates/migrate.migration.high_water_test.yml @@ -1,5 +1,6 @@ id: high_water_test label: High water test. +audit_ids: true source: plugin: high_water_test high_water_property: diff --git a/core/modules/migrate_drupal/tests/modules/migrate_overwrite_test/migration_templates/users.yml b/core/modules/migrate_drupal/tests/modules/migrate_overwrite_test/migration_templates/users.yml index e23d90d..0bddcf4 100644 --- a/core/modules/migrate_drupal/tests/modules/migrate_overwrite_test/migration_templates/users.yml +++ b/core/modules/migrate_drupal/tests/modules/migrate_overwrite_test/migration_templates/users.yml @@ -3,6 +3,7 @@ label: User migration migration_tags: - Drupal 6 - Drupal 7 +audit_ids: true source: plugin: d6_user process: diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php index c87247e..53a2a46 100644 --- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php @@ -3,11 +3,13 @@ namespace Drupal\migrate_drupal_ui\Form; use Drupal\Core\Datetime\DateFormatterInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\RendererInterface; use Drupal\Core\State\StateInterface; use Drupal\Core\Url; +use Drupal\migrate\MigrateIdAuditor; use Drupal\migrate\Plugin\MigrationPluginManagerInterface; use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch; use Drupal\migrate_drupal\MigrationConfigurationTrait; @@ -713,6 +715,20 @@ class MigrateUpgradeForm extends ConfirmFormBase { protected $pluginManager; /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * The ID conflict auditor. + * + * @var \Drupal\migrate\MigrateIdAuditor $idAuditor + */ + protected $idAuditor; + + /** * Constructs the MigrateUpgradeForm. * * @param \Drupal\Core\State\StateInterface $state @@ -723,12 +739,18 @@ class MigrateUpgradeForm extends ConfirmFormBase { * The renderer service. * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $plugin_manager * The migration plugin manager. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + * @param \Drupal\migrate\MigrateIdAuditor $id_auditor + * The ID conflict auditor. */ - public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager) { + public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager, EntityTypeManagerInterface $entity_type_manager, MigrateIdAuditor $id_auditor) { $this->state = $state; $this->dateFormatter = $date_formatter; $this->renderer = $renderer; $this->pluginManager = $plugin_manager; + $this->entityTypeManager = $entity_type_manager; + $this->idAuditor = $id_auditor; } /** @@ -739,7 +761,9 @@ public static function create(ContainerInterface $container) { $container->get('state'), $container->get('date.formatter'), $container->get('renderer'), - $container->get('plugin.manager.migration') + $container->get('plugin.manager.migration'), + $container->get('entity_type.manager'), + $container->get('migrate.id_auditor') ); } @@ -762,6 +786,9 @@ public function buildForm(array $form, FormStateInterface $form_state) { case 'credentials': return $this->buildCredentialForm($form, $form_state); + case 'confirm_id_conflicts': + return $this->buildIdConflictForm($form, $form_state); + case 'confirm': return $this->buildConfirmForm($form, $form_state); @@ -1082,6 +1109,64 @@ public function validateCredentialForm(array &$form, FormStateInterface $form_st */ public function submitCredentialForm(array &$form, FormStateInterface $form_state) { // Indicate the next step is confirmation. + $form_state->set('step', 'confirm_id_conflicts'); + $form_state->setRebuild(); + } + + /** + * Confirmation form for ID conflicts. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * + * @return array + * The form structure. + */ + public function buildIdConflictForm(array &$form, FormStateInterface $form_state) { + // Check if there are conflicts. If none, just skip this form! + $migration_ids = array_keys($form_state->get('migrations')); + $migrations = $this->pluginManager->createInstances($migration_ids); + $type_ids = $this->idAuditor->auditIds($migrations); + if (empty($type_ids)) { + $form_state->set('step', 'confirm'); + return $this->buildForm($form, $form_state); + } + + $form = parent::buildForm($form, $form_state); + $form['actions']['submit']['#submit'] = ['::submitConfirmIdConflictForm']; + $form['actions']['submit']['#value'] = $this->t('I acknowledge I may lose data, continue anyway.'); + + $form['warning'] = [ + '#type' => 'markup', + '#markup' => '

' . $this->t('Entities may be overwritten') . '

' . + '

' . $this->t('Upgrades work on brand new sites, or sites with previously upgraded data. However, it looks like you have content in your site that is unknown to the migrate system; perhaps manually added. These new entities may be overwritten if you run this upgrade. For more information, see the online handbook entry for handling migration conflicts..', [':id-conflicts-handbook' => 'https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#id_conflicts']) . '

', + ]; + + $items = []; + sort($type_ids); + foreach ($type_ids as $typeId) { + $items[] = $this->entityTypeManager->getDefinition($typeId)->getLabel(); + } + $form['type_list'] = [ + '#title' => $this->t('These entities are of the following types:'), + '#theme' => 'item_list', + '#items' => $items, + ]; + + return $form; + } + + /** + * Submission handler for the confirmation form. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + */ + public function submitConfirmIdConflictForm(array &$form, FormStateInterface $form_state) { $form_state->set('step', 'confirm'); $form_state->setRebuild(); } diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php index 9741a0b..b88fbb1 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php @@ -37,7 +37,6 @@ 'telephone', 'aggregator', 'book', - 'forum', 'statistics', ]; @@ -111,6 +110,29 @@ protected function tearDown() { * Executes all steps of migrations upgrade. */ public function testMigrateUpgrade() { + $driver = $this->sourceDatabase->getConnectionOptions()['driver']; + $edits = $this->getUiEditsArray(); + + // Ensure submitting the form with invalid database credentials gives us a + // nice warning. + $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade')); + $this->assertText('Resolve the issue below to continue the upgrade.'); + + $this->drupalPostForm(NULL, $edits, t('Review upgrade')); + $this->assertResponse(200); + $this->assertText('Are you sure?'); + $this->drupalPostForm(NULL, [], t('Perform upgrade')); + $this->assertText(t('Congratulations, you upgraded Drupal!')); + + $this->runPostMigrationTests(); + } + + /** + * Build a re-usable form $edits array for the UI. + * + * @return array $edits + */ + protected function getUiEditsArray() { $connection_options = $this->sourceDatabase->getConnectionOptions(); $this->drupalGet('/upgrade'); $this->assertText('Upgrade a site by importing it into a clean and empty new install of Drupal 8. You will lose any existing configuration once you import your site into it. See the online documentation for Drupal site upgrades for more detailed information.'); @@ -137,29 +159,23 @@ public function testMigrateUpgrade() { if (count($drivers) !== 1) { $edit['driver'] = $driver; } - $edits = $this->translatePostValues($edit); - - // Ensure submitting the form with invalid database credentials gives us a - // nice warning. - $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade')); - $this->assertText('Resolve the issue below to continue the upgrade.'); - - $this->drupalPostForm(NULL, $edits, t('Review upgrade')); - $this->assertResponse(200); - $this->assertText('Are you sure?'); - $this->drupalPostForm(NULL, [], t('Perform upgrade')); - $this->assertText(t('Congratulations, you upgraded Drupal!')); + return $this->translatePostValues($edit); + } + /** + * Runs all post migration tests. + */ + protected function runPostMigrationTests() { + $version = $this->getLegacyDrupalVersion($this->sourceDatabase); // Have to reset all the statics after migration to ensure entities are // loadable. $this->resetAll(); $expected_counts = $this->getEntityCounts(); - foreach (array_keys(\Drupal::entityTypeManager() - ->getDefinitions()) as $entity_type) { + foreach (array_keys(\Drupal::entityTypeManager()->getDefinitions()) as $entity_type) { $real_count = \Drupal::entityQuery($entity_type)->count()->execute(); $expected_count = isset($expected_counts[$entity_type]) ? $expected_counts[$entity_type] : 0; - $this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count."); + $this->assertSame($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count."); } $plugin_manager = \Drupal::service('plugin.manager.migration'); @@ -182,12 +198,10 @@ public function testMigrateUpgrade() { $this->fail($message); } else { - $this->pass($message); + $this->assertTrue(TRUE, $message); } } } - \Drupal::service('module_installer')->install(['forum']); - \Drupal::service('module_installer')->install(['book']); } /** diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php index 1c4b883..24a0d2c 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php @@ -17,6 +17,19 @@ class MigrateUpgrade6Test extends MigrateUpgradeTestBase { /** * {@inheritdoc} */ + public static $modules = [ + 'language', + 'content_translation', + 'migrate_drupal_ui', + 'telephone', + 'aggregator', + 'book', + 'statistics', + ]; + + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); $this->loadFixture(drupal_get_path('module', 'migrate_drupal') . '/tests/fixtures/drupal6.php'); @@ -40,7 +53,7 @@ protected function getEntityCounts() { 'block_content' => 2, 'block_content_type' => 1, 'comment' => 3, - 'comment_type' => 3, + 'comment_type' => 2, 'contact_form' => 5, 'configurable_language' => 5, 'editor' => 2, diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgradeConflicts6Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgradeConflicts6Test.php new file mode 100644 index 0000000..642bb9e --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgradeConflicts6Test.php @@ -0,0 +1,60 @@ +sourceDatabase->getConnectionOptions()['driver']; + $edits = $this->getUiEditsArray(); + + // Ensure submitting the form with invalid database credentials gives us a + // nice warning. + $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade')); + $this->assertText('Resolve the issue below to continue the upgrade.'); + + $this->drupalPostForm(NULL, $edits, t('Review upgrade')); + $this->assertResponse(200); + $this->assertText('Are you sure?'); + $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data, continue anyway.')); + $this->drupalPostForm(NULL, [], t('Perform upgrade')); + $this->assertText(t('Congratulations, you upgraded Drupal!')); + + $this->runPostMigrationTests(); + } + + /** + * {@inheritdoc} + */ + protected function getEntityCounts() { + $counts = parent::getEntityCounts(); + $counts['comment_type'] = 3; + return $counts; + } + +} diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php index 248213a..6cadfe5 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php @@ -45,7 +45,7 @@ protected function getEntityCounts() { 'block_content' => 1, 'block_content_type' => 1, 'comment' => 1, - 'comment_type' => 8, + 'comment_type' => 7, // Module 'language' comes with 'en', 'und', 'zxx'. Migration adds 'is'. 'configurable_language' => 4, 'contact_form' => 3, diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgradeConflicts7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgradeConflicts7Test.php new file mode 100644 index 0000000..5bba621 --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgradeConflicts7Test.php @@ -0,0 +1,62 @@ +sourceDatabase->getConnectionOptions()['driver']; + $edits = $this->getUiEditsArray(); + + // Ensure submitting the form with invalid database credentials gives us a + // nice warning. + $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade')); + $this->assertText('Resolve the issue below to continue the upgrade.'); + + $this->drupalPostForm(NULL, $edits, t('Review upgrade')); + $this->assertResponse(200); + $this->assertText('Are you sure?'); + $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data, continue anyway.')); + $this->drupalPostForm(NULL, [], t('Perform upgrade')); + $this->assertText(t('Congratulations, you upgraded Drupal!')); + + $this->runPostMigrationTests(); + } + + /** + * {@inheritdoc} + */ + protected function getEntityCounts() { + $counts = parent::getEntityCounts(); + // Forum has a comment. + $counts['comment_type'] = 8; + return $counts; + } + +} diff --git a/core/modules/node/migration_templates/d6_node.yml b/core/modules/node/migration_templates/d6_node.yml index 56d0459..1bcae10 100644 --- a/core/modules/node/migration_templates/d6_node.yml +++ b/core/modules/node/migration_templates/d6_node.yml @@ -3,6 +3,7 @@ label: Nodes migration_tags: - Drupal 6 deriver: Drupal\node\Plugin\migrate\D6NodeDeriver +audit_ids: true source: plugin: d6_node process: diff --git a/core/modules/node/migration_templates/d6_node_revision.yml b/core/modules/node/migration_templates/d6_node_revision.yml index f4ff301..ec44d58 100644 --- a/core/modules/node/migration_templates/d6_node_revision.yml +++ b/core/modules/node/migration_templates/d6_node_revision.yml @@ -3,6 +3,7 @@ label: Node revisions migration_tags: - Drupal 6 deriver: Drupal\node\Plugin\migrate\D6NodeDeriver +audit_ids: true source: plugin: d6_node_revision process: diff --git a/core/modules/node/migration_templates/d6_node_translation.yml b/core/modules/node/migration_templates/d6_node_translation.yml index 3eb06e8..0f6579e 100644 --- a/core/modules/node/migration_templates/d6_node_translation.yml +++ b/core/modules/node/migration_templates/d6_node_translation.yml @@ -3,6 +3,7 @@ label: Node translations migration_tags: - Drupal 6 deriver: Drupal\node\Plugin\migrate\D6NodeDeriver +audit_ids: true source: plugin: d6_node translations: true diff --git a/core/modules/node/migration_templates/d7_node.yml b/core/modules/node/migration_templates/d7_node.yml index 5de3055..824662f 100644 --- a/core/modules/node/migration_templates/d7_node.yml +++ b/core/modules/node/migration_templates/d7_node.yml @@ -3,6 +3,7 @@ label: Nodes migration_tags: - Drupal 7 deriver: Drupal\node\Plugin\migrate\D7NodeDeriver +audit_ids: true source: plugin: d7_node process: diff --git a/core/modules/node/migration_templates/d7_node_revision.yml b/core/modules/node/migration_templates/d7_node_revision.yml index c6081ef..420fe58 100644 --- a/core/modules/node/migration_templates/d7_node_revision.yml +++ b/core/modules/node/migration_templates/d7_node_revision.yml @@ -3,6 +3,7 @@ label: Node revisions migration_tags: - Drupal 7 deriver: Drupal\node\Plugin\migrate\D7NodeDeriver +audit_ids: true source: plugin: d7_node_revision process: diff --git a/core/modules/node/migration_templates/d7_node_translation.yml b/core/modules/node/migration_templates/d7_node_translation.yml index 11dfbb7..5a073d7 100644 --- a/core/modules/node/migration_templates/d7_node_translation.yml +++ b/core/modules/node/migration_templates/d7_node_translation.yml @@ -4,6 +4,7 @@ migration_tags: - Drupal 7 - translation deriver: Drupal\node\Plugin\migrate\D7NodeDeriver +audit_ids: true source: plugin: d7_node translations: true diff --git a/core/modules/path/migration_templates/d6_url_alias.yml b/core/modules/path/migration_templates/d6_url_alias.yml index fcf2036..f9c604c 100644 --- a/core/modules/path/migration_templates/d6_url_alias.yml +++ b/core/modules/path/migration_templates/d6_url_alias.yml @@ -2,6 +2,7 @@ id: d6_url_alias label: URL aliases migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_url_alias constants: diff --git a/core/modules/path/migration_templates/d7_url_alias.yml b/core/modules/path/migration_templates/d7_url_alias.yml index dffaf46..12a985c 100644 --- a/core/modules/path/migration_templates/d7_url_alias.yml +++ b/core/modules/path/migration_templates/d7_url_alias.yml @@ -2,6 +2,7 @@ id: d7_url_alias label: URL aliases migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_url_alias constants: diff --git a/core/modules/shortcut/migration_templates/d7_shortcut.yml b/core/modules/shortcut/migration_templates/d7_shortcut.yml index dac9354..a597780 100644 --- a/core/modules/shortcut/migration_templates/d7_shortcut.yml +++ b/core/modules/shortcut/migration_templates/d7_shortcut.yml @@ -2,6 +2,7 @@ id: d7_shortcut label: Shortcut links migration_tags: - Drupal 7 +audit_ids: false source: plugin: d7_shortcut constants: diff --git a/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml b/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml index d0eb219..9726732 100644 --- a/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml +++ b/core/modules/shortcut/migration_templates/d7_shortcut_set_users.yml @@ -2,6 +2,7 @@ id: d7_shortcut_set_users label: Shortcut set user mapping migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_shortcut_set_users process: diff --git a/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml b/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml index e3c3e3d..7ed88a7 100644 --- a/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml +++ b/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml @@ -2,6 +2,7 @@ id: d6_taxonomy_term label: Taxonomy terms migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_taxonomy_term process: diff --git a/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml b/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml index 11af8cd..473ab23 100644 --- a/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml +++ b/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml @@ -2,6 +2,7 @@ id: d6_taxonomy_term_translation label: Taxonomy terms migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_taxonomy_term translations: true diff --git a/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml b/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml index dbb1793..2d143d0 100644 --- a/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml +++ b/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml @@ -2,6 +2,7 @@ id: d6_taxonomy_vocabulary_translation label: Taxonomy vocabularies migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_taxonomy_vocabulary_translation process: diff --git a/core/modules/taxonomy/migration_templates/d6_term_node.yml b/core/modules/taxonomy/migration_templates/d6_term_node.yml index 846334d..bda7d58 100644 --- a/core/modules/taxonomy/migration_templates/d6_term_node.yml +++ b/core/modules/taxonomy/migration_templates/d6_term_node.yml @@ -3,6 +3,7 @@ label: Term/node relationships migration_tags: - Drupal 6 deriver: Drupal\taxonomy\Plugin\migrate\D6TermNodeDeriver +audit_ids: true source: plugin: d6_term_node process: diff --git a/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml b/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml index 91c8362..24da88f 100644 --- a/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml +++ b/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml @@ -3,6 +3,7 @@ label: Term/node relationship revisions migration_tags: - Drupal 6 deriver: Drupal\taxonomy\Plugin\migrate\D6TermNodeDeriver +audit_ids: true source: plugin: d6_term_node_revision process: diff --git a/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml b/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml index 99004df..e518ead 100644 --- a/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml +++ b/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml @@ -3,6 +3,7 @@ label: Taxonomy terms migration_tags: - Drupal 7 deriver: Drupal\taxonomy\Plugin\migrate\D7TaxonomyTermDeriver +audit_ids: true source: plugin: d7_taxonomy_term process: diff --git a/core/modules/tracker/migration_templates/d7_tracker_node.yml b/core/modules/tracker/migration_templates/d7_tracker_node.yml index 02645d7..2bf3b07 100644 --- a/core/modules/tracker/migration_templates/d7_tracker_node.yml +++ b/core/modules/tracker/migration_templates/d7_tracker_node.yml @@ -2,6 +2,7 @@ id: d7_tracker_node label: Tracker node migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_tracker_node process: diff --git a/core/modules/tracker/migration_templates/d7_tracker_user.yml b/core/modules/tracker/migration_templates/d7_tracker_user.yml index ae3c51d..776e1c7 100644 --- a/core/modules/tracker/migration_templates/d7_tracker_user.yml +++ b/core/modules/tracker/migration_templates/d7_tracker_user.yml @@ -2,6 +2,7 @@ id: d7_tracker_user label: Tracker user migration_tags: - Drupal 7 +audit_ids: true source: plugin: d7_tracker_user process: diff --git a/core/modules/user/migration_templates/d6_profile_values.yml b/core/modules/user/migration_templates/d6_profile_values.yml index 5530ca5..8b0d4b0 100644 --- a/core/modules/user/migration_templates/d6_profile_values.yml +++ b/core/modules/user/migration_templates/d6_profile_values.yml @@ -3,6 +3,7 @@ label: Profile values class: Drupal\user\Plugin\migrate\ProfileValues migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_profile_field_values process: diff --git a/core/modules/user/migration_templates/d6_user.yml b/core/modules/user/migration_templates/d6_user.yml index d58607b..034ce22 100644 --- a/core/modules/user/migration_templates/d6_user.yml +++ b/core/modules/user/migration_templates/d6_user.yml @@ -2,6 +2,7 @@ id: d6_user label: User accounts migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_user process: diff --git a/core/modules/user/migration_templates/d6_user_contact_settings.yml b/core/modules/user/migration_templates/d6_user_contact_settings.yml index 0d9a228..3fc3c3f 100644 --- a/core/modules/user/migration_templates/d6_user_contact_settings.yml +++ b/core/modules/user/migration_templates/d6_user_contact_settings.yml @@ -2,6 +2,7 @@ id: d6_user_contact_settings label: User contact settings migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_user constants: diff --git a/core/modules/user/migration_templates/d6_user_picture_file.yml b/core/modules/user/migration_templates/d6_user_picture_file.yml index 3518d7a..93a6e5e 100644 --- a/core/modules/user/migration_templates/d6_user_picture_file.yml +++ b/core/modules/user/migration_templates/d6_user_picture_file.yml @@ -2,6 +2,7 @@ id: d6_user_picture_file label: User pictures migration_tags: - Drupal 6 +audit_ids: true source: plugin: d6_user_picture_file constants: diff --git a/core/modules/user/migration_templates/d7_user.yml b/core/modules/user/migration_templates/d7_user.yml index ae52384..9babed3 100644 --- a/core/modules/user/migration_templates/d7_user.yml +++ b/core/modules/user/migration_templates/d7_user.yml @@ -3,6 +3,7 @@ label: User accounts migration_tags: - Drupal 7 class: Drupal\user\Plugin\migrate\User +audit_ids: true source: plugin: d7_user process: diff --git a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php index 7c2c81a..f0206e5 100644 --- a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php +++ b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php @@ -127,4 +127,18 @@ protected function processStubRow(Row $row) { } } + /** + * {@inheritdoc} + */ + protected function highestDestinationId() { + $found = parent::highestDestinationId(); + + // Every Drupal site must have at least a single non-anonymous user, and + // it's normal for upgrade migrations to overwrite this user. + if ($found == 1) { + return 0; + } + return $found; + } + }