diff --git a/src/EventSubscriber/MigrationImportSync.php b/src/EventSubscriber/MigrationImportSync.php index ec84407..0223b48 100644 --- a/src/EventSubscriber/MigrationImportSync.php +++ b/src/EventSubscriber/MigrationImportSync.php @@ -3,6 +3,7 @@ namespace Drupal\migrate_tools\EventSubscriber; use Drupal\migrate\Event\MigrateEvents; +use Drupal\migrate\Event\MigrateRollbackEvent; use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate_plus\Event\MigrateEvents as MigratePlusEvents; use Drupal\migrate\Event\MigrateImportEvent; @@ -37,7 +38,7 @@ class MigrationImportSync implements EventSubscriberInterface { */ public static function getSubscribedEvents() { $events = []; - $events[MigrateEvents::POST_IMPORT][] = ['sync']; + $events[MigrateEvents::PRE_IMPORT][] = ['sync']; return $events; } @@ -45,7 +46,7 @@ class MigrationImportSync implements EventSubscriberInterface { * Event callback to sync source and destination. * * @param \Drupal\migrate\Event\MigrateImportEvent $event - * The migration post import event. + * The migration import event. */ public function sync(MigrateImportEvent $event) { $migration = $event->getMigration(); @@ -65,14 +66,15 @@ class MigrationImportSync implements EventSubscriberInterface { $map_source_id = $id_map->currentSource(); if (!in_array($map_source_id, $source_id_values, TRUE)) { $destination_ids = $id_map->currentDestination(); - $this->dispatchEvent(MigrateEvents::PRE_ROW_DELETE, $migration, $destination_ids); - $this->dispatchEvent(MigratePlusEvents::MISSING_SOURCE_ITEM, $migration, $destination_ids); + $this->dispatchRowDeleteEvent(MigrateEvents::PRE_ROW_DELETE, $migration, $destination_ids); + $this->dispatchRowDeleteEvent(MigratePlusEvents::MISSING_SOURCE_ITEM, $migration, $destination_ids); $destination->rollback($destination_ids); - $this->dispatchEvent(MigrateEvents::POST_ROW_DELETE, $migration, $destination_ids); - $id_map->delete($source_id_values); + $this->dispatchRowDeleteEvent(MigrateEvents::POST_ROW_DELETE, $migration, $destination_ids); + $id_map->delete($map_source_id); } $id_map->next(); } + $this->dispatcher->dispatch(MigrateEvents::POST_ROLLBACK, new MigrateRollbackEvent($migration)); } } @@ -86,7 +88,7 @@ class MigrationImportSync implements EventSubscriberInterface { * @param array $destination_ids * The destination identifier values of the record. */ - protected function dispatchEvent($event_name, MigrationInterface $migration, array $destination_ids) { + protected function dispatchRowDeleteEvent($event_name, MigrationInterface $migration, array $destination_ids) { // Symfony changing dispatcher so implementation could change. $this->dispatcher->dispatch($event_name, new MigrateRowDeleteEvent($migration, $destination_ids)); } diff --git a/src/MigrateExecutable.php b/src/MigrateExecutable.php index 0988d48..18f9312 100644 --- a/src/MigrateExecutable.php +++ b/src/MigrateExecutable.php @@ -114,7 +114,7 @@ class MigrateExecutable extends MigrateExecutableBase { $this->listeners[MigrateEvents::POST_ROW_DELETE] = [$this, 'onPostRowDelete']; $this->listeners[MigratePlusEvents::PREPARE_ROW] = [$this, 'onPrepareRow']; foreach ($this->listeners as $event => $listener) { - \Drupal::service('event_dispatcher')->addListener($event, $listener); + $this->getEventDispatcher()->addListener($event, $listener); } } @@ -245,7 +245,7 @@ class MigrateExecutable extends MigrateExecutableBase { */ protected function removeListeners() { foreach ($this->listeners as $event => $listener) { - \Drupal::service('event_dispatcher')->removeListener($event, $listener); + $this->getEventDispatcher()->removeListener($event, $listener); } } @@ -290,7 +290,11 @@ class MigrateExecutable extends MigrateExecutableBase { $migrate_last_imported_store = \Drupal::keyValue('migrate_last_imported'); $migrate_last_imported_store->set($event->getMigration()->id(), FALSE); $this->rollbackMessage(); - $this->removeListeners(); + // If this is a sync import, then don't remove listeners or post import will + // not be executed. Leave it to post import to remove listeners. + if (empty($event->getMigration()->syncSource)) { + $this->removeListeners(); + } } /** diff --git a/tests/src/Functional/DrushCommandsTest.php b/tests/src/Functional/DrushCommandsTest.php index c8bbbd1..01faf94 100644 --- a/tests/src/Functional/DrushCommandsTest.php +++ b/tests/src/Functional/DrushCommandsTest.php @@ -175,16 +175,25 @@ class DrushCommandsTest extends BrowserTestBase { $this->assertEquals(3, \Drupal::entityTypeManager()->getStorage('taxonomy_term')->getQuery()->count()->execute()); $source = $this->container->get('config.factory')->getEditable('migrate_plus.migration.fruit_terms')->get('source'); unset($source['data_rows'][1]); + $source['data_rows'][] = ['name' => 'Grape']; $this->container->get('config.factory')->getEditable('migrate_plus.migration.fruit_terms')->set('source', $source)->save(); // Flush cache so the recently changed migration can be refreshed. drupal_flush_all_caches(); $this->drush('mim', ['fruit_terms'], ['sync' => NULL]); $expected = [ - '1/2 [==============>-------------] 50% [notice] Processed 0 items (0 created, 0 updated, 0 failed, 0 ignored) - done with \'fruit_terms\'', + '1/3 [=========>------------------] 33% [notice] Rolled back 1 item - done with \'fruit_terms\'', + '', + ' 2/3 [==================>---------] 66%', + ' 3/3 [============================] 100%', + ' 4/4 [============================] 100% [notice] Processed 3 items (1 created, 2 updated, 0 failed, 0 ignored) - done with \'fruit_terms\'', ]; $this->assertEquals($expected, $this->getErrorOutputAsList()); - $this->assertEquals(2, \Drupal::entityTypeManager()->getStorage('taxonomy_term')->getQuery()->count()->execute()); + $this->assertEquals(3, \Drupal::entityTypeManager()->getStorage('taxonomy_term')->getQuery()->count()->execute()); $this->assertEmpty(\Drupal::entityTypeManager()->getStorage('taxonomy_term')->load(2)); + + /** @var \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map */ + $id_map = $this->container->get('plugin.manager.migration')->createInstance('fruit_terms')->getIdMap(); + $this->assertCount(3, $id_map); } }