Issue #2579343 by Lendude, drclaw, heddn, mikeryan: Migrate rollback does not rollback failed items

8.3.x
Alex Pott 2016-08-10 21:42:48 +01:00
parent 493eac19cb
commit 51a76efb66
5 changed files with 65 additions and 1 deletions

View File

@ -329,6 +329,12 @@ class MigrateExecutable implements MigrateExecutableInterface {
// We're now done with this row, so remove it from the map. // We're now done with this row, so remove it from the map.
$id_map->deleteDestination($destination_key); $id_map->deleteDestination($destination_key);
} }
else {
// If there is no destination key the import probably failed and we can
// remove the row without further action.
$source_key = $id_map->currentSource();
$id_map->delete($source_key);
}
// Check for memory exhaustion. // Check for memory exhaustion.
if (($return = $this->checkStatus()) != MigrationInterface::RESULT_COMPLETED) { if (($return = $this->checkStatus()) != MigrationInterface::RESULT_COMPLETED) {

View File

@ -243,6 +243,14 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
*/ */
public function currentDestination(); public function currentDestination();
/**
* Looks up the source identifier(s) currently being iterated.
*
* @return array
* The source identifier values of the record, or NULL on failure.
*/
public function currentSource();
/** /**
* Removes any persistent storage used by this map. * Removes any persistent storage used by this map.
* *

View File

@ -845,8 +845,26 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
if ($this->valid()) { if ($this->valid()) {
$result = array(); $result = array();
foreach ($this->destinationIdFields() as $destination_field_name => $idmap_field_name) { foreach ($this->destinationIdFields() as $destination_field_name => $idmap_field_name) {
if (!is_null($this->currentRow[$idmap_field_name])) {
$result[$destination_field_name] = $this->currentRow[$idmap_field_name]; $result[$destination_field_name] = $this->currentRow[$idmap_field_name];
} }
}
return $result;
}
else {
return NULL;
}
}
/**
* @inheritdoc
*/
public function currentSource() {
if ($this->valid()) {
$result = array();
foreach ($this->sourceIdFields() as $field_name => $source_id) {
$result[$field_name] = $this->currentKey[$source_id];
}
return $result; return $result;
} }
else { else {

View File

@ -128,6 +128,9 @@ class MigrateRollbackTest extends MigrateTestBase {
$this->assertNotNull($map_row['destid1']); $this->assertNotNull($map_row['destid1']);
} }
// Add a failed row to test if this can be rolled back without errors.
$this->mockFailure($term_migration, ['id' => '4', 'vocab' => '2', 'name' => 'FAIL']);
// Rollback and verify the entities are gone. // Rollback and verify the entities are gone.
$term_executable->rollback(); $term_executable->rollback();
foreach ($term_data_rows as $row) { foreach ($term_data_rows as $row) {

View File

@ -640,6 +640,35 @@ class MigrateSqlIdMapTest extends MigrateTestCase {
$this->assertSame(0, count($source_id)); $this->assertSame(0, count($source_id));
} }
/**
* Tests currentDestination() and currentSource().
*/
public function testCurrentDestinationAndSource() {
// Simple map with one source and one destination ID.
$id_map = $this->setupRows(['nid'], ['nid'], [
[1, 101],
[2, 102],
[3, 103],
// Mock a failed row by setting the destination ID to NULL.
[4, NULL],
]);
// The rows are ordered by destination ID so the failed row should be first.
$id_map->rewind();
$this->assertEquals([], $id_map->currentDestination());
$this->assertEquals(['nid' => 4], $id_map->currentSource());
$id_map->next();
$this->assertEquals(['nid' => 101], $id_map->currentDestination());
$this->assertEquals(['nid' => 1], $id_map->currentSource());
$id_map->next();
$this->assertEquals(['nid' => 102], $id_map->currentDestination());
$this->assertEquals(['nid' => 2], $id_map->currentSource());
$id_map->next();
$this->assertEquals(['nid' => 103], $id_map->currentDestination());
$this->assertEquals(['nid' => 3], $id_map->currentSource());
$id_map->next();
}
/** /**
* Tests the imported count method. * Tests the imported count method.
* *