/**
  * Tests migration interruptions.
  */
 public function testPrepareRowSkip()
 {
     // Run a simple little migration with two data rows which should be skipped
     // in different ways.
     $definition = ['migration_tags' => ['prepare_row test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => [['id' => '1', 'data' => 'skip_and_record'], ['id' => '2', 'data' => 'skip_and_dont_record']], 'ids' => ['id' => ['type' => 'string']]], 'process' => ['value' => 'data'], 'destination' => ['plugin' => 'config', 'config_name' => 'migrate_test.settings'], 'load' => ['plugin' => 'null']];
     $migration = new Migration([], uniqid(), $definition);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     $result = $executable->import();
     $this->assertEqual($result, MigrationInterface::RESULT_COMPLETED);
     $id_map_plugin = $migration->getIdMap();
     // The first row is recorded in the map as ignored.
     $map_row = $id_map_plugin->getRowBySource(['id' => 1]);
     $this->assertEqual(MigrateIdMapInterface::STATUS_IGNORED, $map_row['source_row_status']);
     // The second row is not recorded in the map.
     $map_row = $id_map_plugin->getRowBySource(['id' => 2]);
     $this->assertFalse($map_row);
 }
 /**
  * Tests rolling back configuration and content entities.
  */
 public function testRollback()
 {
     // We use vocabularies to demonstrate importing and rolling back
     // configuration entities.
     $vocabulary_data_rows = [['id' => '1', 'name' => 'categories', 'weight' => '2'], ['id' => '2', 'name' => 'tags', 'weight' => '1']];
     $ids = ['id' => ['type' => 'integer']];
     $definition = ['id' => 'vocabularies', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $vocabulary_data_rows, 'ids' => $ids], 'process' => ['vid' => 'id', 'name' => 'name', 'weight' => 'weight'], 'destination' => ['plugin' => 'entity:taxonomy_vocabulary']];
     $vocabulary_migration = new Migration([], uniqid(), $definition);
     $vocabulary_id_map = $vocabulary_migration->getIdMap();
     $this->assertTrue($vocabulary_migration->getDestinationPlugin()->supportsRollback());
     // Import and validate vocabulary config entities were created.
     $vocabulary_executable = new MigrateExecutable($vocabulary_migration, $this);
     $vocabulary_executable->import();
     foreach ($vocabulary_data_rows as $row) {
         /** @var Vocabulary $vocabulary */
         $vocabulary = Vocabulary::load($row['id']);
         $this->assertTrue($vocabulary);
         $map_row = $vocabulary_id_map->getRowBySource(['id' => $row['id']]);
         $this->assertNotNull($map_row['destid1']);
     }
     // We use taxonomy terms to demonstrate importing and rolling back content
     // entities.
     $term_data_rows = [['id' => '1', 'vocab' => '1', 'name' => 'music'], ['id' => '2', 'vocab' => '2', 'name' => 'Bach'], ['id' => '3', 'vocab' => '2', 'name' => 'Beethoven']];
     $ids = ['id' => ['type' => 'integer']];
     $definition = ['id' => 'terms', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_data_rows, 'ids' => $ids], 'process' => ['tid' => 'id', 'vid' => 'vocab', 'name' => 'name'], 'destination' => ['plugin' => 'entity:taxonomy_term'], 'migration_dependencies' => ['required' => ['vocabularies']]];
     $term_migration = new Migration([], uniqid(), $definition);
     $term_id_map = $term_migration->getIdMap();
     $this->assertTrue($term_migration->getDestinationPlugin()->supportsRollback());
     // Pre-create a term, to make sure it isn't deleted on rollback.
     $preserved_term_ids[] = 1;
     $new_term = Term::create(['tid' => 1, 'vid' => 1, 'name' => 'music']);
     $new_term->save();
     // Import and validate term entities were created.
     $term_executable = new MigrateExecutable($term_migration, $this);
     $term_executable->import();
     // Also explicitly mark one row to be preserved on rollback.
     $preserved_term_ids[] = 2;
     $map_row = $term_id_map->getRowBySource(['id' => 2]);
     $dummy_row = new Row(['id' => 2], $ids);
     $term_id_map->saveIdMapping($dummy_row, [$map_row['destid1']], $map_row['source_row_status'], MigrateIdMapInterface::ROLLBACK_PRESERVE);
     foreach ($term_data_rows as $row) {
         /** @var Term $term */
         $term = Term::load($row['id']);
         $this->assertTrue($term);
         $map_row = $term_id_map->getRowBySource(['id' => $row['id']]);
         $this->assertNotNull($map_row['destid1']);
     }
     // Rollback and verify the entities are gone.
     $term_executable->rollback();
     foreach ($term_data_rows as $row) {
         $term = Term::load($row['id']);
         if (in_array($row['id'], $preserved_term_ids)) {
             $this->assertNotNull($term);
         } else {
             $this->assertNull($term);
         }
         $map_row = $term_id_map->getRowBySource(['id' => $row['id']]);
         $this->assertFalse($map_row);
     }
     $vocabulary_executable->rollback();
     foreach ($vocabulary_data_rows as $row) {
         $term = Vocabulary::load($row['id']);
         $this->assertNull($term);
         $map_row = $vocabulary_id_map->getRowBySource(['id' => $row['id']]);
         $this->assertFalse($map_row);
     }
     // Test that simple configuration is not rollbackable.
     $term_setting_rows = [['id' => 1, 'override_selector' => '0', 'terms_per_page_admin' => '10']];
     $ids = ['id' => ['type' => 'integer']];
     $definition = ['id' => 'taxonomy_settings', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_setting_rows, 'ids' => $ids], 'process' => ['override_selector' => 'override_selector', 'terms_per_page_admin' => 'terms_per_page_admin'], 'destination' => ['plugin' => 'config', 'config_name' => 'taxonomy.settings'], 'migration_dependencies' => ['required' => ['vocabularies']]];
     $settings_migration = new Migration([], uniqid(), $definition);
     $this->assertFalse($settings_migration->getDestinationPlugin()->supportsRollback());
 }
 /**
  * Tests migration events.
  */
 public function testMigrateEvents()
 {
     // Run a simple little migration, which should trigger one of each event
     // other than map_delete.
     $definition = ['migration_tags' => ['Event test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => [['data' => 'dummy value']], 'ids' => ['data' => ['type' => 'string']]], 'process' => ['value' => 'data'], 'destination' => ['plugin' => 'dummy']];
     $migration = new Migration([], uniqid(), $definition);
     $executable = new MigrateExecutable($migration, new MigrateMessage());
     // As the import runs, events will be dispatched, recording the received
     // information in state.
     $executable->import();
     // Validate from the recorded state that the events were received.
     $event = $this->state->get('migrate_events_test.pre_import_event', []);
     $this->assertIdentical($event['event_name'], MigrateEvents::PRE_IMPORT);
     $this->assertIdentical($event['migration']->id(), $migration->id());
     $event = $this->state->get('migrate_events_test.post_import_event', []);
     $this->assertIdentical($event['event_name'], MigrateEvents::POST_IMPORT);
     $this->assertIdentical($event['migration']->id(), $migration->id());
     $event = $this->state->get('migrate_events_test.map_save_event', []);
     $this->assertIdentical($event['event_name'], MigrateEvents::MAP_SAVE);
     // Validating the last row processed.
     $this->assertIdentical($event['fields']['sourceid1'], 'dummy value');
     $this->assertIdentical($event['fields']['destid1'], 'dummy value');
     $this->assertIdentical($event['fields']['source_row_status'], 0);
     $event = $this->state->get('migrate_events_test.map_delete_event', []);
     $this->assertIdentical($event, []);
     $event = $this->state->get('migrate_events_test.pre_row_save_event', []);
     $this->assertIdentical($event['event_name'], MigrateEvents::PRE_ROW_SAVE);
     $this->assertIdentical($event['migration']->id(), $migration->id());
     // Validating the last row processed.
     $this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value');
     $event = $this->state->get('migrate_events_test.post_row_save_event', []);
     $this->assertIdentical($event['event_name'], MigrateEvents::POST_ROW_SAVE);
     $this->assertIdentical($event['migration']->id(), $migration->id());
     // Validating the last row processed.
     $this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value');
     $this->assertIdentical($event['destination_id_values']['value'], 'dummy value');
     // Generate a map delete event.
     $migration->getIdMap()->delete(['data' => 'dummy value']);
     $event = $this->state->get('migrate_events_test.map_delete_event', []);
     $this->assertIdentical($event['event_name'], MigrateEvents::MAP_DELETE);
     $this->assertIdentical($event['source_id'], ['data' => 'dummy value']);
 }