View source
<?php
namespace Drupal\Tests\migrate\Unit;
use Drupal\Core\Database\Driver\sqlite\Connection;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
use Drupal\migrate\Row;
class MigrateSqlIdMapTest extends MigrateTestCase {
protected $migrationConfiguration = [
'id' => 'sql_idmap_test',
];
protected $sourceIds = [
'source_id_property' => [
'type' => 'string',
],
];
protected $destinationIds = [
'destination_id_property' => [
'type' => 'string',
],
];
protected $database;
public function setUp() {
$this->database = $this
->getDatabase([]);
}
protected function saveMap(array $map) {
$table = 'migrate_map_sql_idmap_test';
$schema = $this->database
->schema();
if ($schema
->tableExists($table)) {
foreach (array_keys($map) as $field) {
if (!$schema
->fieldExists($table, $field)) {
$schema
->addField($table, $field, [
'type' => 'text',
]);
}
}
}
else {
$schema
->createTable($table, $this
->createSchemaFromRow($map));
}
$this->database
->insert($table)
->fields($map)
->execute();
}
protected function getIdMap() {
$migration = $this
->getMigration();
$plugin = $this
->getMock('Drupal\\migrate\\Plugin\\MigrateSourceInterface');
$plugin
->method('getIds')
->willReturn($this->sourceIds);
$migration
->method('getSourcePlugin')
->willReturn($plugin);
$plugin = $this
->getMock('Drupal\\migrate\\Plugin\\MigrateDestinationInterface');
$plugin
->method('getIds')
->willReturn($this->destinationIds);
$migration
->method('getDestinationPlugin')
->willReturn($plugin);
$event_dispatcher = $this
->getMock('Symfony\\Component\\EventDispatcher\\EventDispatcherInterface');
$id_map = new TestSqlIdMap($this->database, [], 'sql', [], $migration, $event_dispatcher);
$migration
->method('getIdMap')
->willReturn($id_map);
return $id_map;
}
protected function idMapDefaults() {
$defaults = array(
'source_row_status' => MigrateIdMapInterface::STATUS_IMPORTED,
'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
'hash' => '',
);
if ($this->database
->driver() == 'sqlite') {
$defaults['source_row_status'] = (string) $defaults['source_row_status'];
$defaults['rollback_action'] = (string) $defaults['rollback_action'];
}
return $defaults;
}
public function testSaveIdMapping() {
$source = array(
'source_id_property' => 'source_value',
);
$row = new Row($source, [
'source_id_property' => [],
]);
$id_map = $this
->getIdMap();
$id_map
->saveIdMapping($row, [
'destination_id_property' => 2,
]);
$expected_result = [
[
'sourceid1' => 'source_value',
'destid1' => 2,
] + $this
->idMapDefaults(),
];
$this
->queryResultTest($this
->getIdMapContents(), $expected_result);
$source = [
'source_id_property' => 'source_value_1',
];
$row = new Row($source, [
'source_id_property' => [],
]);
$id_map
->saveIdMapping($row, [
'destination_id_property' => 3,
]);
$expected_result[] = [
'sourceid1' => 'source_value_1',
'destid1' => 3,
] + $this
->idMapDefaults();
$this
->queryResultTest($this
->getIdMapContents(), $expected_result);
$id_map
->saveIdMapping($row, [
'destination_id_property' => 4,
]);
$expected_result[1]['destid1'] = 4;
$this
->queryResultTest($this
->getIdMapContents(), $expected_result);
}
public function testSetMessage() {
$message = $this
->getMock('Drupal\\migrate\\MigrateMessageInterface');
$id_map = $this
->getIdMap();
$id_map
->setMessage($message);
$this
->assertAttributeEquals($message, 'message', $id_map);
}
public function testClearMessages() {
$message = 'Hello world.';
$expected_results = [
0,
1,
2,
3,
];
$id_map = $this
->getIdMap();
foreach ($expected_results as $key => $expected_result) {
$id_map
->saveMessage([
'source_id_property' => $key,
], $message);
}
$this
->assertEquals($id_map
->messageCount(), 4);
$id_map
->clearMessages();
$count = $id_map
->messageCount();
$this
->assertEquals($count, 0);
}
public function testGetRowsNeedingUpdate() {
$id_map = $this
->getIdMap();
$row_statuses = [
MigrateIdMapInterface::STATUS_IMPORTED,
MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
MigrateIdMapInterface::STATUS_IGNORED,
MigrateIdMapInterface::STATUS_FAILED,
];
foreach ($row_statuses as $status) {
$source = [
'source_id_property' => 'source_value_' . $status,
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_' . $status,
];
$id_map
->saveIdMapping($row, $destination, $status);
$expected_results[] = [
'sourceid1' => 'source_value_' . $status,
'destid1' => 'destination_value_' . $status,
'source_row_status' => $status,
'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
'hash' => '',
];
if ($status == MigrateIdMapInterface::STATUS_IMPORTED) {
$rows_needing_update = $id_map
->getRowsNeedingUpdate(1);
$this
->assertCount(0, $rows_needing_update);
}
}
$this
->queryResultTest($this
->getIdMapContents(), $expected_results);
$row_needing_update = $id_map
->getRowsNeedingUpdate(1);
$this
->assertCount(1, $row_needing_update);
$source_id = $expected_results[MigrateIdMapInterface::STATUS_NEEDS_UPDATE]['sourceid1'];
$test_row = $id_map
->getRowBySource([
'source_id_property' => $source_id,
]);
$this
->assertSame($test_row, (array) $row_needing_update[0]);
$source = [
'source_id_property' => 'source_value_multiple',
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_multiple',
];
$id_map
->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
$rows_needing_update = $id_map
->getRowsNeedingUpdate(2);
$this
->assertCount(2, $rows_needing_update);
}
public function testMessageCount() {
$message = 'Hello world.';
$expected_results = [
0,
1,
2,
3,
];
$id_map = $this
->getIdMap();
foreach ($expected_results as $key => $expected_result) {
$count = $id_map
->messageCount();
$this
->assertEquals($expected_result, $count);
$id_map
->saveMessage([
'source_id_property' => $key,
], $message);
}
}
public function testMessageSave() {
$message = 'Hello world.';
$expected_results = [
1 => [
'message' => $message,
'level' => MigrationInterface::MESSAGE_ERROR,
],
2 => [
'message' => $message,
'level' => MigrationInterface::MESSAGE_WARNING,
],
3 => [
'message' => $message,
'level' => MigrationInterface::MESSAGE_NOTICE,
],
4 => [
'message' => $message,
'level' => MigrationInterface::MESSAGE_INFORMATIONAL,
],
];
$id_map = $this
->getIdMap();
foreach ($expected_results as $key => $expected_result) {
$id_map
->saveMessage([
'source_id_property' => $key,
], $message, $expected_result['level']);
}
foreach ($id_map
->getMessageIterator() as $message_row) {
$key = $message_row->sourceid1;
$this
->assertEquals($expected_results[$key]['message'], $message_row->message);
$this
->assertEquals($expected_results[$key]['level'], $message_row->level);
}
$message_default = 'Hello world default.';
$id_map
->saveMessage([
'source_id_property' => 5,
], $message_default);
$messages = $id_map
->getMessageIterator([
'source_id_property' => 5,
]);
$count = 0;
foreach ($messages as $key => $message_row) {
$count = 1;
$this
->assertEquals($message_default, $message_row->message);
$this
->assertEquals(MigrationInterface::MESSAGE_ERROR, $message_row->level);
}
$this
->assertEquals($count, 1);
$messages = $id_map
->getMessageIterator([], MigrationInterface::MESSAGE_WARNING);
$count = 0;
foreach ($messages as $key => $message_row) {
$count = 1;
$this
->assertEquals(MigrationInterface::MESSAGE_WARNING, $message_row->level);
}
$this
->assertEquals($count, 1);
}
public function testGetRowBySource() {
$this
->getDatabase([]);
$row = [
'sourceid1' => 'source_id_value_1',
'sourceid2' => 'source_id_value_2',
'destid1' => 'destination_id_value_1',
] + $this
->idMapDefaults();
$this
->saveMap($row);
$row = [
'sourceid1' => 'source_id_value_3',
'sourceid2' => 'source_id_value_4',
'destid1' => 'destination_id_value_2',
] + $this
->idMapDefaults();
$this
->saveMap($row);
$source_id_values = [
'source_id_property' => $row['sourceid1'],
'sourceid2' => $row['sourceid2'],
];
$id_map = $this
->getIdMap();
$result_row = $id_map
->getRowBySource($source_id_values);
$this
->assertSame($row, $result_row);
$source_id_values = [
'source_id_property' => 'missing_value_1',
'sourceid2' => 'missing_value_2',
];
$result_row = $id_map
->getRowBySource($source_id_values);
$this
->assertFalse($result_row);
}
public function lookupDestinationIdMappingDataProvider() {
return [
[
1,
1,
],
[
2,
2,
],
[
1,
2,
],
[
2,
1,
],
];
}
public function testLookupDestinationIdMapping($num_source_fields, $num_destination_fields) {
$this->sourceIds = [];
$this->destinationIds = [];
$source_id_values = [];
$nonexistent_id_values = [];
$row = $this
->idMapDefaults();
for ($i = 1; $i <= $num_source_fields; $i++) {
$row["sourceid{$i}"] = "source_id_value_{$i}";
$source_id_values[] = "source_id_value_{$i}";
$nonexistent_id_values[] = "nonexistent_source_id_value_{$i}";
$this->sourceIds["source_id_property_{$i}"] = [];
}
$expected_result = [];
for ($i = 1; $i <= $num_destination_fields; $i++) {
$row["destid{$i}"] = "destination_id_value_{$i}";
$expected_result[] = "destination_id_value_{$i}";
$this->destinationIds["destination_id_property_{$i}"] = [];
}
$this
->saveMap($row);
$id_map = $this
->getIdMap();
$destination_id = $id_map
->lookupDestinationId($source_id_values);
$this
->assertSame($expected_result, $destination_id);
$destination_id = $id_map
->lookupDestinationId($nonexistent_id_values);
$this
->assertSame(0, count($destination_id));
}
public function testGetRowByDestination() {
$row = [
'sourceid1' => 'source_id_value_1',
'sourceid2' => 'source_id_value_2',
'destid1' => 'destination_id_value_1',
] + $this
->idMapDefaults();
$this
->saveMap($row);
$row = [
'sourceid1' => 'source_id_value_3',
'sourceid2' => 'source_id_value_4',
'destid1' => 'destination_id_value_2',
] + $this
->idMapDefaults();
$this
->saveMap($row);
$dest_id_values = [
'destination_id_property' => $row['destid1'],
];
$id_map = $this
->getIdMap();
$result_row = $id_map
->getRowByDestination($dest_id_values);
$this
->assertSame($row, $result_row);
$dest_id_values = [
'destination_id_property' => 'invalid_destination_id_property',
];
$id_map = $this
->getIdMap();
$result_row = $id_map
->getRowByDestination($dest_id_values);
$this
->assertFalse($result_row);
}
public function lookupSourceIDMappingDataProvider() {
return [
[
1,
1,
],
[
2,
2,
],
[
1,
2,
],
[
2,
1,
],
];
}
public function testLookupSourceIDMapping($num_source_fields, $num_destination_fields) {
$this->sourceIds = [];
$this->destinationIds = [];
$row = $this
->idMapDefaults();
$expected_result = [];
for ($i = 1; $i <= $num_source_fields; $i++) {
$row["sourceid{$i}"] = "source_id_value_{$i}";
$expected_result["source_id_property_{$i}"] = "source_id_value_{$i}";
$this->sourceIds["source_id_property_{$i}"] = [];
}
$destination_id_values = [];
$nonexistent_id_values = [];
for ($i = 1; $i <= $num_destination_fields; $i++) {
$row["destid{$i}"] = "destination_id_value_{$i}";
$destination_id_values["destination_id_property_{$i}"] = "destination_id_value_{$i}";
$nonexistent_id_values["destination_id_property_{$i}"] = "nonexistent_destination_id_value_{$i}";
$this->destinationIds["destination_id_property_{$i}"] = [];
}
$this
->saveMap($row);
$id_map = $this
->getIdMap();
$source_id = $id_map
->lookupSourceID($destination_id_values);
$this
->assertSame($expected_result, $source_id);
$source_id = $id_map
->lookupSourceID($nonexistent_id_values);
$this
->assertSame(0, count($source_id));
}
public function testImportedCount() {
$id_map = $this
->getIdMap();
$source = [
'source_id_property' => 'source_value_failed',
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_failed',
];
$id_map
->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_FAILED);
$this
->assertSame(0, (int) $id_map
->importedCount());
$source = [
'source_id_property' => 'source_value_imported',
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_imported',
];
$id_map
->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_IMPORTED);
$this
->assertSame(1, (int) $id_map
->importedCount());
$source = [
'source_id_property' => 'source_value_update',
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_update',
];
$id_map
->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
$this
->assertSame(2, (int) $id_map
->importedCount());
}
public function testProcessedCount() {
$id_map = $this
->getIdMap();
$this
->assertSame(0, (int) $id_map
->processedCount());
$row_statuses = [
MigrateIdMapInterface::STATUS_IMPORTED,
MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
MigrateIdMapInterface::STATUS_IGNORED,
MigrateIdMapInterface::STATUS_FAILED,
];
foreach ($row_statuses as $status) {
$source = [
'source_id_property' => 'source_value_' . $status,
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_' . $status,
];
$id_map
->saveIdMapping($row, $destination, $status);
if ($status == MigrateIdMapInterface::STATUS_IMPORTED) {
$this
->assertSame(1, (int) $id_map
->processedCount());
}
}
$this
->assertSame(count($row_statuses), (int) $id_map
->processedCount());
}
public function updateCountDataProvider() {
return [
[
0,
],
[
1,
],
[
3,
],
];
}
public function testUpdateCount($num_update_rows) {
for ($i = 0; $i < 5; $i++) {
$row = $this
->idMapDefaults();
$row['sourceid1'] = "source_id_value_{$i}";
$row['destid1'] = "destination_id_value_{$i}";
$row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
$this
->saveMap($row);
}
for (; $i < 5 + $num_update_rows; $i++) {
$row = $this
->idMapDefaults();
$row['sourceid1'] = "source_id_value_{$i}";
$row['destid1'] = "destination_id_value_{$i}";
$row['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
$this
->saveMap($row);
}
$id_map = $this
->getIdMap();
$this
->assertSame($num_update_rows, (int) $id_map
->updateCount());
}
public function errorCountDataProvider() {
return [
[
0,
],
[
1,
],
[
3,
],
];
}
public function testErrorCount($num_error_rows) {
for ($i = 0; $i < 5; $i++) {
$row = $this
->idMapDefaults();
$row['sourceid1'] = "source_id_value_{$i}";
$row['destid1'] = "destination_id_value_{$i}";
$row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
$this
->saveMap($row);
}
for (; $i < 5 + $num_error_rows; $i++) {
$row = $this
->idMapDefaults();
$row['sourceid1'] = "source_id_value_{$i}";
$row['destid1'] = "destination_id_value_{$i}";
$row['source_row_status'] = MigrateIdMapInterface::STATUS_FAILED;
$this
->saveMap($row);
}
$this
->assertSame($num_error_rows, (int) $this
->getIdMap()
->errorCount());
}
public function testSetUpdate() {
$id_map = $this
->getIdMap();
$row_statuses = [
MigrateIdMapInterface::STATUS_IMPORTED,
MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
MigrateIdMapInterface::STATUS_IGNORED,
MigrateIdMapInterface::STATUS_FAILED,
];
foreach ($row_statuses as $status) {
$source = [
'source_id_property' => 'source_value_' . $status,
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_' . $status,
];
$id_map
->saveIdMapping($row, $destination, $status);
$expected_results[] = [
'sourceid1' => 'source_value_' . $status,
'destid1' => 'destination_value_' . $status,
'source_row_status' => $status,
'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
'hash' => '',
];
}
$this
->queryResultTest($this
->getIdMapContents(), $expected_results);
foreach ($row_statuses as $status) {
$id_map
->setUpdate([
'source_id_property' => 'source_value_' . $status,
]);
}
foreach ($expected_results as $key => $value) {
$expected_results[$key]['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
}
$this
->queryResultTest($this
->getIdMapContents(), $expected_results);
try {
$id_map
->setUpdate([]);
$this
->assertFalse(FALSE, 'MigrateException not thrown, when source identifiers were provided to update.');
} catch (MigrateException $e) {
$this
->assertTrue(TRUE, "MigrateException thrown, when source identifiers were not provided to update.");
}
}
public function testPrepareUpdate() {
$id_map = $this
->getIdMap();
$row_statuses = [
MigrateIdMapInterface::STATUS_IMPORTED,
MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
MigrateIdMapInterface::STATUS_IGNORED,
MigrateIdMapInterface::STATUS_FAILED,
];
foreach ($row_statuses as $status) {
$source = [
'source_id_property' => 'source_value_' . $status,
];
$row = new Row($source, [
'source_id_property' => [],
]);
$destination = [
'destination_id_property' => 'destination_value_' . $status,
];
$id_map
->saveIdMapping($row, $destination, $status);
$expected_results[] = [
'sourceid1' => 'source_value_' . $status,
'destid1' => 'destination_value_' . $status,
'source_row_status' => $status,
'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
'hash' => '',
];
}
$this
->queryResultTest($this
->getIdMapContents(), $expected_results);
$id_map
->prepareUpdate();
foreach ($expected_results as $key => $value) {
$expected_results[$key]['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
}
$this
->queryResultTest($this
->getIdMapContents(), $expected_results);
}
public function testDestroy() {
$id_map = $this
->getIdMap();
$id_map
->getDatabase();
$map_table_name = $id_map
->mapTableName();
$message_table_name = $id_map
->messageTableName();
$row = new Row([
'source_id_property' => 'source_value',
], [
'source_id_property' => [],
]);
$id_map
->saveIdMapping($row, [
'destination_id_property' => 2,
]);
$id_map
->saveMessage([
'source_id_property' => 'source_value',
], 'A message');
$this
->assertTrue($this->database
->schema()
->tableExists($map_table_name), "{$map_table_name} exists");
$this
->assertTrue($this->database
->schema()
->tableExists($message_table_name), "{$message_table_name} exists");
$id_map
->destroy();
$this
->assertFalse($this->database
->schema()
->tableExists($map_table_name), "{$map_table_name} does not exist");
$this
->assertFalse($this->database
->schema()
->tableExists($message_table_name), "{$message_table_name} does not exist");
}
public function testGetQualifiedMapTablePrefix() {
$connection_options = [
'database' => ':memory:',
'prefix' => 'prefix',
];
$pdo = Connection::open($connection_options);
$this->database = new Connection($pdo, $connection_options);
$qualified_map_table = $this
->getIdMap()
->getQualifiedMapTableName();
$this
->assertEquals('prefix.migrate_map_sql_idmap_test', $qualified_map_table);
}
public function testIterators() {
for ($i = 0; $i < 3; $i++) {
$row = $this
->idMapDefaults();
$row['sourceid1'] = "source_id_value_{$i}";
$row['destid1'] = "destination_id_value_{$i}";
$row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
$expected_results[serialize([
'sourceid1' => $row['sourceid1'],
])] = [
'destid1' => $row['destid1'],
];
$this
->saveMap($row);
}
$this
->assertSame(iterator_to_array($this
->getIdMap()), $expected_results);
}
private function getIdMapContents() {
$result = $this->database
->select('migrate_map_sql_idmap_test', 't')
->fields('t')
->execute();
$contents = [];
foreach ($result as $row) {
$contents[] = (array) $row;
}
return $contents;
}
}