Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\migrate\Unit;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Database\Driver\sqlite\Connection;
|
Chris@0
|
6 use Drupal\migrate\Plugin\MigrationInterface;
|
Chris@0
|
7 use Drupal\migrate\MigrateException;
|
Chris@0
|
8 use Drupal\migrate\Plugin\MigrateIdMapInterface;
|
Chris@0
|
9 use Drupal\migrate\Row;
|
Chris@0
|
10
|
Chris@0
|
11 /**
|
Chris@0
|
12 * Tests the SQL ID map plugin.
|
Chris@0
|
13 *
|
Chris@0
|
14 * @group migrate
|
Chris@0
|
15 */
|
Chris@0
|
16 class MigrateSqlIdMapTest extends MigrateTestCase {
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * The migration configuration, initialized to set the ID and destination IDs.
|
Chris@0
|
20 *
|
Chris@0
|
21 * @var array
|
Chris@0
|
22 */
|
Chris@0
|
23 protected $migrationConfiguration = [
|
Chris@0
|
24 'id' => 'sql_idmap_test',
|
Chris@0
|
25 ];
|
Chris@0
|
26
|
Chris@0
|
27 /**
|
Chris@0
|
28 * The source IDs.
|
Chris@0
|
29 *
|
Chris@0
|
30 * @var array
|
Chris@0
|
31 */
|
Chris@0
|
32 protected $sourceIds = [
|
Chris@0
|
33 'source_id_property' => [
|
Chris@0
|
34 'type' => 'string',
|
Chris@0
|
35 ],
|
Chris@0
|
36 ];
|
Chris@0
|
37
|
Chris@0
|
38 /**
|
Chris@0
|
39 * The destination IDs.
|
Chris@0
|
40 *
|
Chris@0
|
41 * @var array
|
Chris@0
|
42 */
|
Chris@0
|
43 protected $destinationIds = [
|
Chris@0
|
44 'destination_id_property' => [
|
Chris@0
|
45 'type' => 'string',
|
Chris@0
|
46 ],
|
Chris@0
|
47 ];
|
Chris@0
|
48
|
Chris@0
|
49 /**
|
Chris@0
|
50 * The database connection.
|
Chris@0
|
51 *
|
Chris@0
|
52 * @var \Drupal\Core\Database\Connection
|
Chris@0
|
53 */
|
Chris@0
|
54 protected $database;
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * {@inheritdoc}
|
Chris@0
|
58 */
|
Chris@0
|
59 protected function setUp() {
|
Chris@0
|
60 $this->database = $this->getDatabase([]);
|
Chris@0
|
61 }
|
Chris@0
|
62
|
Chris@0
|
63 /**
|
Chris@0
|
64 * Saves a single ID mapping row in the database.
|
Chris@0
|
65 *
|
Chris@0
|
66 * @param array $map
|
Chris@0
|
67 * The row to save.
|
Chris@0
|
68 */
|
Chris@0
|
69 protected function saveMap(array $map) {
|
Chris@0
|
70 $table = 'migrate_map_sql_idmap_test';
|
Chris@0
|
71
|
Chris@0
|
72 $schema = $this->database->schema();
|
Chris@0
|
73 // If the table already exists, add any columns which are in the map array,
|
Chris@0
|
74 // but don't yet exist in the table. Yay, flexibility!
|
Chris@0
|
75 if ($schema->tableExists($table)) {
|
Chris@0
|
76 foreach (array_keys($map) as $field) {
|
Chris@0
|
77 if (!$schema->fieldExists($table, $field)) {
|
Chris@0
|
78 $schema->addField($table, $field, ['type' => 'text']);
|
Chris@0
|
79 }
|
Chris@0
|
80 }
|
Chris@0
|
81 }
|
Chris@0
|
82 else {
|
Chris@0
|
83 $schema->createTable($table, $this->createSchemaFromRow($map));
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@0
|
86 $this->database->insert($table)->fields($map)->execute();
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 /**
|
Chris@0
|
90 * Creates a test SQL ID map plugin.
|
Chris@0
|
91 *
|
Chris@0
|
92 * @return \Drupal\Tests\migrate\Unit\TestSqlIdMap
|
Chris@0
|
93 * A SQL ID map plugin test instance.
|
Chris@0
|
94 */
|
Chris@0
|
95 protected function getIdMap() {
|
Chris@0
|
96 $migration = $this->getMigration();
|
Chris@0
|
97
|
Chris@0
|
98 $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
|
Chris@0
|
99 $plugin
|
Chris@0
|
100 ->method('getIds')
|
Chris@0
|
101 ->willReturn($this->sourceIds);
|
Chris@0
|
102 $migration
|
Chris@0
|
103 ->method('getSourcePlugin')
|
Chris@0
|
104 ->willReturn($plugin);
|
Chris@0
|
105
|
Chris@0
|
106 $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
|
Chris@0
|
107 $plugin
|
Chris@0
|
108 ->method('getIds')
|
Chris@0
|
109 ->willReturn($this->destinationIds);
|
Chris@0
|
110 $migration
|
Chris@0
|
111 ->method('getDestinationPlugin')
|
Chris@0
|
112 ->willReturn($plugin);
|
Chris@0
|
113 $event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
Chris@0
|
114
|
Chris@0
|
115 $id_map = new TestSqlIdMap($this->database, [], 'sql', [], $migration, $event_dispatcher);
|
Chris@0
|
116 $migration
|
Chris@0
|
117 ->method('getIdMap')
|
Chris@0
|
118 ->willReturn($id_map);
|
Chris@0
|
119
|
Chris@0
|
120 return $id_map;
|
Chris@0
|
121 }
|
Chris@0
|
122
|
Chris@0
|
123 /**
|
Chris@0
|
124 * Sets defaults for SQL ID map plugin tests.
|
Chris@0
|
125 *
|
Chris@0
|
126 * @return array
|
Chris@0
|
127 * An associative array with the following keys:
|
Chris@0
|
128 * - source_row_status
|
Chris@0
|
129 * - rollback_action
|
Chris@0
|
130 * - hash
|
Chris@0
|
131 */
|
Chris@0
|
132 protected function idMapDefaults() {
|
Chris@0
|
133 $defaults = [
|
Chris@0
|
134 'source_row_status' => MigrateIdMapInterface::STATUS_IMPORTED,
|
Chris@0
|
135 'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
|
Chris@0
|
136 'hash' => '',
|
Chris@0
|
137 ];
|
Chris@0
|
138 // By default, the PDO SQLite driver strongly prefers to return strings
|
Chris@0
|
139 // from SELECT queries. Even for columns that don't store strings. Even
|
Chris@0
|
140 // if the connection's STRINGIFY_FETCHES attribute is FALSE. This can cause
|
Chris@0
|
141 // assertSame() calls to fail, since 0 !== '0'. Casting these values to
|
Chris@0
|
142 // strings isn't the most elegant workaround, but it allows the assertions
|
Chris@0
|
143 // to pass properly.
|
Chris@0
|
144 if ($this->database->driver() == 'sqlite') {
|
Chris@0
|
145 $defaults['source_row_status'] = (string) $defaults['source_row_status'];
|
Chris@0
|
146 $defaults['rollback_action'] = (string) $defaults['rollback_action'];
|
Chris@0
|
147 }
|
Chris@0
|
148 return $defaults;
|
Chris@0
|
149 }
|
Chris@0
|
150
|
Chris@0
|
151 /**
|
Chris@0
|
152 * Tests the ID mapping method.
|
Chris@0
|
153 *
|
Chris@0
|
154 * Create two ID mappings and update the second to verify that:
|
Chris@0
|
155 * - saving new to empty tables work.
|
Chris@0
|
156 * - saving new to nonempty tables work.
|
Chris@0
|
157 * - updating work.
|
Chris@0
|
158 */
|
Chris@0
|
159 public function testSaveIdMapping() {
|
Chris@0
|
160 $source = [
|
Chris@0
|
161 'source_id_property' => 'source_value',
|
Chris@0
|
162 ];
|
Chris@0
|
163 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
164 $id_map = $this->getIdMap();
|
Chris@0
|
165 $id_map->saveIdMapping($row, ['destination_id_property' => 2]);
|
Chris@0
|
166 $expected_result = [
|
Chris@0
|
167 [
|
Chris@0
|
168 'sourceid1' => 'source_value',
|
Chris@16
|
169 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source),
|
Chris@0
|
170 'destid1' => 2,
|
Chris@0
|
171 ] + $this->idMapDefaults(),
|
Chris@0
|
172 ];
|
Chris@0
|
173 $this->queryResultTest($this->getIdMapContents(), $expected_result);
|
Chris@0
|
174 $source = [
|
Chris@0
|
175 'source_id_property' => 'source_value_1',
|
Chris@0
|
176 ];
|
Chris@0
|
177 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
178 $id_map->saveIdMapping($row, ['destination_id_property' => 3]);
|
Chris@0
|
179 $expected_result[] = [
|
Chris@0
|
180 'sourceid1' => 'source_value_1',
|
Chris@16
|
181 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source),
|
Chris@0
|
182 'destid1' => 3,
|
Chris@0
|
183 ] + $this->idMapDefaults();
|
Chris@0
|
184 $this->queryResultTest($this->getIdMapContents(), $expected_result);
|
Chris@0
|
185 $id_map->saveIdMapping($row, ['destination_id_property' => 4]);
|
Chris@0
|
186 $expected_result[1]['destid1'] = 4;
|
Chris@0
|
187 $this->queryResultTest($this->getIdMapContents(), $expected_result);
|
Chris@0
|
188 }
|
Chris@0
|
189
|
Chris@0
|
190 /**
|
Chris@0
|
191 * Tests the SQL ID map set message method.
|
Chris@0
|
192 */
|
Chris@0
|
193 public function testSetMessage() {
|
Chris@0
|
194 $message = $this->getMock('Drupal\migrate\MigrateMessageInterface');
|
Chris@0
|
195 $id_map = $this->getIdMap();
|
Chris@0
|
196 $id_map->setMessage($message);
|
Chris@0
|
197 $this->assertAttributeEquals($message, 'message', $id_map);
|
Chris@0
|
198 }
|
Chris@0
|
199
|
Chris@0
|
200 /**
|
Chris@0
|
201 * Tests the clear messages method.
|
Chris@0
|
202 */
|
Chris@0
|
203 public function testClearMessages() {
|
Chris@0
|
204 $message = 'Hello world.';
|
Chris@0
|
205 $expected_results = [0, 1, 2, 3];
|
Chris@0
|
206 $id_map = $this->getIdMap();
|
Chris@0
|
207
|
Chris@0
|
208 // Insert 4 message for later delete.
|
Chris@0
|
209 foreach ($expected_results as $key => $expected_result) {
|
Chris@0
|
210 $id_map->saveMessage(['source_id_property' => $key], $message);
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 // Truncate and check that 4 messages were deleted.
|
Chris@14
|
214 $this->assertSame($id_map->messageCount(), 4);
|
Chris@0
|
215 $id_map->clearMessages();
|
Chris@0
|
216 $count = $id_map->messageCount();
|
Chris@14
|
217 $this->assertSame($count, 0);
|
Chris@0
|
218 }
|
Chris@0
|
219
|
Chris@0
|
220 /**
|
Chris@0
|
221 * Tests the getRowsNeedingUpdate method for rows that need an update.
|
Chris@0
|
222 */
|
Chris@0
|
223 public function testGetRowsNeedingUpdate() {
|
Chris@0
|
224 $id_map = $this->getIdMap();
|
Chris@0
|
225 $row_statuses = [
|
Chris@0
|
226 MigrateIdMapInterface::STATUS_IMPORTED,
|
Chris@0
|
227 MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
|
Chris@0
|
228 MigrateIdMapInterface::STATUS_IGNORED,
|
Chris@0
|
229 MigrateIdMapInterface::STATUS_FAILED,
|
Chris@0
|
230 ];
|
Chris@0
|
231 // Create a mapping row for each STATUS constant.
|
Chris@0
|
232 foreach ($row_statuses as $status) {
|
Chris@0
|
233 $source = ['source_id_property' => 'source_value_' . $status];
|
Chris@0
|
234 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
235 $destination = ['destination_id_property' => 'destination_value_' . $status];
|
Chris@0
|
236 $id_map->saveIdMapping($row, $destination, $status);
|
Chris@0
|
237 $expected_results[] = [
|
Chris@0
|
238 'sourceid1' => 'source_value_' . $status,
|
Chris@16
|
239 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source),
|
Chris@0
|
240 'destid1' => 'destination_value_' . $status,
|
Chris@0
|
241 'source_row_status' => $status,
|
Chris@0
|
242 'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
|
Chris@0
|
243 'hash' => '',
|
Chris@0
|
244 ];
|
Chris@0
|
245 // Assert zero rows need an update.
|
Chris@0
|
246 if ($status == MigrateIdMapInterface::STATUS_IMPORTED) {
|
Chris@0
|
247 $rows_needing_update = $id_map->getRowsNeedingUpdate(1);
|
Chris@0
|
248 $this->assertCount(0, $rows_needing_update);
|
Chris@0
|
249 }
|
Chris@0
|
250 }
|
Chris@0
|
251 // Assert that test values exist.
|
Chris@0
|
252 $this->queryResultTest($this->getIdMapContents(), $expected_results);
|
Chris@0
|
253
|
Chris@0
|
254 // Assert a single row needs an update.
|
Chris@0
|
255 $row_needing_update = $id_map->getRowsNeedingUpdate(1);
|
Chris@0
|
256 $this->assertCount(1, $row_needing_update);
|
Chris@0
|
257
|
Chris@0
|
258 // Assert the row matches its original source.
|
Chris@0
|
259 $source_id = $expected_results[MigrateIdMapInterface::STATUS_NEEDS_UPDATE]['sourceid1'];
|
Chris@0
|
260 $test_row = $id_map->getRowBySource(['source_id_property' => $source_id]);
|
Chris@0
|
261 // $row_needing_update is an array of objects returned from the database,
|
Chris@0
|
262 // but $test_row is an array, so the cast is necessary.
|
Chris@0
|
263 $this->assertSame($test_row, (array) $row_needing_update[0]);
|
Chris@0
|
264
|
Chris@0
|
265 // Add additional row that needs an update.
|
Chris@0
|
266 $source = ['source_id_property' => 'source_value_multiple'];
|
Chris@0
|
267 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
268 $destination = ['destination_id_property' => 'destination_value_multiple'];
|
Chris@0
|
269 $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
|
Chris@0
|
270
|
Chris@0
|
271 // Assert multiple rows need an update.
|
Chris@0
|
272 $rows_needing_update = $id_map->getRowsNeedingUpdate(2);
|
Chris@0
|
273 $this->assertCount(2, $rows_needing_update);
|
Chris@0
|
274 }
|
Chris@0
|
275
|
Chris@0
|
276 /**
|
Chris@0
|
277 * Tests the SQL ID map message count method by counting and saving messages.
|
Chris@0
|
278 */
|
Chris@0
|
279 public function testMessageCount() {
|
Chris@0
|
280 $message = 'Hello world.';
|
Chris@0
|
281 $expected_results = [0, 1, 2, 3];
|
Chris@0
|
282 $id_map = $this->getIdMap();
|
Chris@0
|
283
|
Chris@0
|
284 // Test count message multiple times starting from 0.
|
Chris@0
|
285 foreach ($expected_results as $key => $expected_result) {
|
Chris@0
|
286 $count = $id_map->messageCount();
|
Chris@14
|
287 $this->assertSame($expected_result, $count);
|
Chris@0
|
288 $id_map->saveMessage(['source_id_property' => $key], $message);
|
Chris@0
|
289 }
|
Chris@0
|
290 }
|
Chris@0
|
291
|
Chris@0
|
292 /**
|
Chris@0
|
293 * Tests the SQL ID map save message method.
|
Chris@0
|
294 */
|
Chris@0
|
295 public function testMessageSave() {
|
Chris@0
|
296 $message = 'Hello world.';
|
Chris@0
|
297 $original_values = [
|
Chris@0
|
298 1 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_ERROR],
|
Chris@0
|
299 2 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_WARNING],
|
Chris@0
|
300 3 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_NOTICE],
|
Chris@0
|
301 4 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_INFORMATIONAL],
|
Chris@0
|
302 ];
|
Chris@0
|
303 $expected_results = [
|
Chris@0
|
304 '7ad742edb7e866caa78ced1e4455d2e9cbd8adb2074e7c323d21b4e67732e755' => ['message' => $message, 'level' => MigrationInterface::MESSAGE_ERROR],
|
Chris@0
|
305 '2d3ec2b0c547e819346e6ae03f881fd9f5c978ff3cbe29dfb807d40735e53703' => ['message' => $message, 'level' => MigrationInterface::MESSAGE_WARNING],
|
Chris@0
|
306 '12a042f72cad9a2a8c7715df0c7695d762975f0687d87f5d480725dae1432a6f' => ['message' => $message, 'level' => MigrationInterface::MESSAGE_NOTICE],
|
Chris@0
|
307 'd9d1fd27a2447ace48f47a2e9ff649673f67b446d9381a7963c949fc083f8791' => ['message' => $message, 'level' => MigrationInterface::MESSAGE_INFORMATIONAL],
|
Chris@0
|
308 ];
|
Chris@0
|
309 $id_map = $this->getIdMap();
|
Chris@0
|
310
|
Chris@0
|
311 foreach ($original_values as $key => $original_value) {
|
Chris@0
|
312 $id_map->saveMessage(['source_id_property' => $key], $message, $original_value['level']);
|
Chris@0
|
313 }
|
Chris@0
|
314
|
Chris@0
|
315 foreach ($id_map->getMessageIterator() as $message_row) {
|
Chris@0
|
316 $key = $message_row->source_ids_hash;
|
Chris@0
|
317 $this->assertEquals($expected_results[$key]['message'], $message_row->message);
|
Chris@0
|
318 $this->assertEquals($expected_results[$key]['level'], $message_row->level);
|
Chris@0
|
319 }
|
Chris@0
|
320
|
Chris@0
|
321 // Insert with default level.
|
Chris@0
|
322 $message_default = 'Hello world default.';
|
Chris@0
|
323 $id_map->saveMessage(['source_id_property' => 5], $message_default);
|
Chris@0
|
324 $messages = $id_map->getMessageIterator(['source_id_property' => 5]);
|
Chris@0
|
325 $count = 0;
|
Chris@0
|
326 foreach ($messages as $key => $message_row) {
|
Chris@0
|
327 $count = 1;
|
Chris@0
|
328 $this->assertEquals($message_default, $message_row->message);
|
Chris@0
|
329 $this->assertEquals(MigrationInterface::MESSAGE_ERROR, $message_row->level);
|
Chris@0
|
330 }
|
Chris@0
|
331 $this->assertEquals($count, 1);
|
Chris@0
|
332
|
Chris@0
|
333 // Retrieve messages with a specific level.
|
Chris@0
|
334 $messages = $id_map->getMessageIterator([], MigrationInterface::MESSAGE_WARNING);
|
Chris@0
|
335 $count = 0;
|
Chris@0
|
336 foreach ($messages as $key => $message_row) {
|
Chris@0
|
337 $count = 1;
|
Chris@0
|
338 $this->assertEquals(MigrationInterface::MESSAGE_WARNING, $message_row->level);
|
Chris@0
|
339 }
|
Chris@0
|
340 $this->assertEquals($count, 1);
|
Chris@0
|
341 }
|
Chris@0
|
342
|
Chris@0
|
343 /**
|
Chris@0
|
344 * Tests the getRowBySource method.
|
Chris@0
|
345 */
|
Chris@0
|
346 public function testGetRowBySource() {
|
Chris@0
|
347 $this->getDatabase([]);
|
Chris@0
|
348 $row = [
|
Chris@0
|
349 'sourceid1' => 'source_id_value_1',
|
Chris@0
|
350 'sourceid2' => 'source_id_value_2',
|
Chris@16
|
351 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_1']),
|
Chris@0
|
352 'destid1' => 'destination_id_value_1',
|
Chris@0
|
353 ] + $this->idMapDefaults();
|
Chris@0
|
354 $this->saveMap($row);
|
Chris@0
|
355 $row = [
|
Chris@0
|
356 'sourceid1' => 'source_id_value_3',
|
Chris@0
|
357 'sourceid2' => 'source_id_value_4',
|
Chris@16
|
358 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_3', 'sourceid2' => 'source_id_value_4']),
|
Chris@0
|
359 'destid1' => 'destination_id_value_2',
|
Chris@0
|
360 ] + $this->idMapDefaults();
|
Chris@0
|
361 $this->saveMap($row);
|
Chris@0
|
362 $source_id_values = ['source_id_property' => $row['sourceid1'], 'sourceid2' => $row['sourceid2']];
|
Chris@0
|
363 $id_map = $this->getIdMap();
|
Chris@0
|
364 $result_row = $id_map->getRowBySource($source_id_values);
|
Chris@0
|
365 $this->assertSame($row, $result_row);
|
Chris@0
|
366 $source_id_values = ['source_id_property' => 'missing_value_1', 'sourceid2' => 'missing_value_2'];
|
Chris@0
|
367 $result_row = $id_map->getRowBySource($source_id_values);
|
Chris@0
|
368 $this->assertFalse($result_row);
|
Chris@0
|
369 }
|
Chris@0
|
370
|
Chris@0
|
371 /**
|
Chris@0
|
372 * Data provider for testLookupDestinationIdMapping().
|
Chris@0
|
373 *
|
Chris@0
|
374 * Scenarios to test (for both hits and misses) are:
|
Chris@0
|
375 * - Single-value source ID to single-value destination ID.
|
Chris@0
|
376 * - Multi-value source ID to multi-value destination ID.
|
Chris@0
|
377 * - Single-value source ID to multi-value destination ID.
|
Chris@0
|
378 * - Multi-value source ID to single-value destination ID.
|
Chris@0
|
379 *
|
Chris@0
|
380 * @return array
|
Chris@0
|
381 * An array of data values.
|
Chris@0
|
382 */
|
Chris@0
|
383 public function lookupDestinationIdMappingDataProvider() {
|
Chris@0
|
384 return [
|
Chris@0
|
385 [1, 1],
|
Chris@0
|
386 [2, 2],
|
Chris@0
|
387 [1, 2],
|
Chris@0
|
388 [2, 1],
|
Chris@0
|
389 ];
|
Chris@0
|
390 }
|
Chris@0
|
391
|
Chris@0
|
392 /**
|
Chris@0
|
393 * Performs destination ID test on source and destination fields.
|
Chris@0
|
394 *
|
Chris@0
|
395 * @param int $num_source_fields
|
Chris@0
|
396 * Number of source fields to test.
|
Chris@0
|
397 * @param int $num_destination_fields
|
Chris@0
|
398 * Number of destination fields to test.
|
Chris@0
|
399 *
|
Chris@0
|
400 * @dataProvider lookupDestinationIdMappingDataProvider
|
Chris@0
|
401 */
|
Chris@0
|
402 public function testLookupDestinationIdMapping($num_source_fields, $num_destination_fields) {
|
Chris@0
|
403 // Adjust the migration configuration according to the number of source and
|
Chris@0
|
404 // destination fields.
|
Chris@0
|
405 $this->sourceIds = [];
|
Chris@0
|
406 $this->destinationIds = [];
|
Chris@0
|
407 $source_id_values = [];
|
Chris@0
|
408 $nonexistent_id_values = [];
|
Chris@0
|
409 $row = $this->idMapDefaults();
|
Chris@0
|
410 for ($i = 1; $i <= $num_source_fields; $i++) {
|
Chris@0
|
411 $row["sourceid$i"] = "source_id_value_$i";
|
Chris@0
|
412 $source_id_values[] = "source_id_value_$i";
|
Chris@0
|
413 $nonexistent_id_values[] = "nonexistent_source_id_value_$i";
|
Chris@0
|
414 $this->sourceIds["source_id_property_$i"] = [];
|
Chris@0
|
415 }
|
Chris@0
|
416 $expected_result = [];
|
Chris@0
|
417 for ($i = 1; $i <= $num_destination_fields; $i++) {
|
Chris@0
|
418 $row["destid$i"] = "destination_id_value_$i";
|
Chris@0
|
419 $expected_result[] = "destination_id_value_$i";
|
Chris@0
|
420 $this->destinationIds["destination_id_property_$i"] = [];
|
Chris@0
|
421 }
|
Chris@16
|
422 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash($source_id_values);
|
Chris@0
|
423 $this->saveMap($row);
|
Chris@0
|
424 $id_map = $this->getIdMap();
|
Chris@0
|
425 // Test for a valid hit.
|
Chris@0
|
426 $destination_id = $id_map->lookupDestinationId($source_id_values);
|
Chris@0
|
427 $this->assertSame($expected_result, $destination_id);
|
Chris@0
|
428 // Test for a miss.
|
Chris@0
|
429 $destination_id = $id_map->lookupDestinationId($nonexistent_id_values);
|
Chris@0
|
430 $this->assertSame(0, count($destination_id));
|
Chris@0
|
431 }
|
Chris@0
|
432
|
Chris@0
|
433 /**
|
Chris@0
|
434 * Setup a database with the given rows.
|
Chris@0
|
435 *
|
Chris@0
|
436 * @param array $source_keys
|
Chris@0
|
437 * The source keys for the ID map table.
|
Chris@0
|
438 * @param array $dest_keys
|
Chris@0
|
439 * The destination keys for the ID map table.
|
Chris@0
|
440 * @param array $rows
|
Chris@0
|
441 * An array of source and destination value arrays for the ID map table.
|
Chris@0
|
442 *
|
Chris@0
|
443 * @return \Drupal\Tests\migrate\Unit\TestSqlIdMap
|
Chris@0
|
444 * An ID map instance for testing.
|
Chris@0
|
445 */
|
Chris@0
|
446 protected function setupRows($source_keys, $dest_keys, $rows) {
|
Chris@0
|
447 $this->database = $this->getDatabase([]);
|
Chris@0
|
448 $this->sourceIds = array_fill_keys($source_keys, []);
|
Chris@0
|
449 $this->destinationIds = array_fill_keys($dest_keys, []);
|
Chris@0
|
450
|
Chris@0
|
451 $db_keys = [];
|
Chris@0
|
452 foreach (array_keys($source_keys) as $i) {
|
Chris@0
|
453 $db_keys[] = 'sourceid' . ($i + 1);
|
Chris@0
|
454 }
|
Chris@0
|
455 foreach (array_keys($dest_keys) as $i) {
|
Chris@0
|
456 $db_keys[] = 'destid' . ($i + 1);
|
Chris@0
|
457 }
|
Chris@0
|
458 foreach ($rows as $row) {
|
Chris@0
|
459 $values = array_combine($db_keys, $row);
|
Chris@0
|
460 $source_values = array_slice($row, 0, count($source_keys));
|
Chris@16
|
461 $values['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash($source_values);
|
Chris@0
|
462 $this->saveMap($values);
|
Chris@0
|
463 }
|
Chris@0
|
464
|
Chris@0
|
465 return $this->getIdMap();
|
Chris@0
|
466 }
|
Chris@0
|
467
|
Chris@0
|
468 /**
|
Chris@0
|
469 * Tests lookupDestinationIds().
|
Chris@0
|
470 */
|
Chris@0
|
471 public function testLookupDestinationIds() {
|
Chris@0
|
472 // Simple map with one source and one destination ID.
|
Chris@0
|
473 $id_map = $this->setupRows(['nid'], ['nid'], [
|
Chris@0
|
474 [1, 101],
|
Chris@0
|
475 [2, 102],
|
Chris@0
|
476 [3, 103],
|
Chris@0
|
477 ]);
|
Chris@0
|
478
|
Chris@0
|
479 // Lookup nothing, gives nothing.
|
Chris@0
|
480 $this->assertEquals([], $id_map->lookupDestinationIds([]));
|
Chris@0
|
481 // Lookup by complete non-associative list.
|
Chris@0
|
482 $this->assertEquals([[101]], $id_map->lookupDestinationIds([1]));
|
Chris@0
|
483 $this->assertEquals([[102]], $id_map->lookupDestinationIds([2]));
|
Chris@0
|
484 $this->assertEquals([], $id_map->lookupDestinationIds([99]));
|
Chris@0
|
485 // Lookup by complete associative list.
|
Chris@0
|
486 $this->assertEquals([[101]], $id_map->lookupDestinationIds(['nid' => 1]));
|
Chris@0
|
487 $this->assertEquals([[102]], $id_map->lookupDestinationIds(['nid' => 2]));
|
Chris@0
|
488 $this->assertEquals([], $id_map->lookupDestinationIds(['nid' => 99]));
|
Chris@0
|
489
|
Chris@0
|
490 // Map with multiple source and destination IDs.
|
Chris@0
|
491 $id_map = $this->setupRows(['nid', 'language'], ['nid', 'langcode'], [
|
Chris@0
|
492 [1, 'en', 101, 'en'],
|
Chris@0
|
493 [1, 'fr', 101, 'fr'],
|
Chris@0
|
494 [1, 'de', 101, 'de'],
|
Chris@0
|
495 [2, 'en', 102, 'en'],
|
Chris@0
|
496 ]);
|
Chris@0
|
497
|
Chris@0
|
498 // Lookup nothing, gives nothing.
|
Chris@0
|
499 $this->assertEquals([], $id_map->lookupDestinationIds([]));
|
Chris@0
|
500 // Lookup by complete non-associative list.
|
Chris@0
|
501 $this->assertEquals([[101, 'en']], $id_map->lookupDestinationIds([1, 'en']));
|
Chris@0
|
502 $this->assertEquals([[101, 'fr']], $id_map->lookupDestinationIds([1, 'fr']));
|
Chris@0
|
503 $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds([2, 'en']));
|
Chris@0
|
504 $this->assertEquals([], $id_map->lookupDestinationIds([2, 'fr']));
|
Chris@0
|
505 $this->assertEquals([], $id_map->lookupDestinationIds([99, 'en']));
|
Chris@0
|
506 // Lookup by complete associative list.
|
Chris@0
|
507 $this->assertEquals([[101, 'en']], $id_map->lookupDestinationIds(['nid' => 1, 'language' => 'en']));
|
Chris@0
|
508 $this->assertEquals([[101, 'fr']], $id_map->lookupDestinationIds(['nid' => 1, 'language' => 'fr']));
|
Chris@0
|
509 $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds(['nid' => 2, 'language' => 'en']));
|
Chris@0
|
510 $this->assertEquals([], $id_map->lookupDestinationIds(['nid' => 2, 'language' => 'fr']));
|
Chris@0
|
511 $this->assertEquals([], $id_map->lookupDestinationIds(['nid' => 99, 'language' => 'en']));
|
Chris@0
|
512 // Lookup by partial non-associative list.
|
Chris@0
|
513 $this->assertEquals([[101, 'en'], [101, 'fr'], [101, 'de']], $id_map->lookupDestinationIds([1]));
|
Chris@0
|
514 $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds([2]));
|
Chris@0
|
515 $this->assertEquals([], $id_map->lookupDestinationIds([99]));
|
Chris@0
|
516 // Lookup by partial associative list.
|
Chris@0
|
517 $this->assertEquals([[101, 'en'], [101, 'fr'], [101, 'de']], $id_map->lookupDestinationIds(['nid' => 1]));
|
Chris@0
|
518 $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds(['nid' => 2]));
|
Chris@0
|
519 $this->assertEquals([], $id_map->lookupDestinationIds(['nid' => 99]));
|
Chris@16
|
520 $this->assertEquals([[101, 'en'], [101, 'fr'], [101, 'de']], $id_map->lookupDestinationIds(['nid' => 1, 'language' => NULL]));
|
Chris@16
|
521 $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds(['nid' => 2, 'language' => NULL]));
|
Chris@0
|
522 // Out-of-order partial associative list.
|
Chris@0
|
523 $this->assertEquals([[101, 'en'], [102, 'en']], $id_map->lookupDestinationIds(['language' => 'en']));
|
Chris@0
|
524 $this->assertEquals([[101, 'fr']], $id_map->lookupDestinationIds(['language' => 'fr']));
|
Chris@0
|
525 $this->assertEquals([], $id_map->lookupDestinationIds(['language' => 'zh']));
|
Chris@0
|
526 // Error conditions.
|
Chris@0
|
527 try {
|
Chris@0
|
528 $id_map->lookupDestinationIds([1, 2, 3]);
|
Chris@0
|
529 $this->fail('Too many source IDs should throw');
|
Chris@0
|
530 }
|
Chris@0
|
531 catch (MigrateException $e) {
|
Chris@17
|
532 $this->assertEquals("Extra unknown items for map migrate_map_sql_idmap_test in source IDs: array (\n 0 => 3,\n)", $e->getMessage());
|
Chris@0
|
533 }
|
Chris@0
|
534 try {
|
Chris@0
|
535 $id_map->lookupDestinationIds(['nid' => 1, 'aaa' => '2']);
|
Chris@0
|
536 $this->fail('Unknown source ID key should throw');
|
Chris@0
|
537 }
|
Chris@0
|
538 catch (MigrateException $e) {
|
Chris@17
|
539 $this->assertEquals("Extra unknown items for map migrate_map_sql_idmap_test in source IDs: array (\n 'aaa' => '2',\n)", $e->getMessage());
|
Chris@0
|
540 }
|
Chris@0
|
541
|
Chris@0
|
542 // Verify that we are looking up by source_id_hash when all source IDs are
|
Chris@0
|
543 // passed in.
|
Chris@0
|
544 $id_map->getDatabase()->update($id_map->mapTableName())
|
Chris@0
|
545 ->condition('sourceid1', 1)
|
Chris@0
|
546 ->condition('sourceid2', 'en')
|
Chris@0
|
547 ->fields([TestSqlIdMap::SOURCE_IDS_HASH => uniqid()])
|
Chris@0
|
548 ->execute();
|
Chris@0
|
549 $this->assertNotEquals([[101, 'en']], $id_map->lookupDestinationIds([1, 'en']));
|
Chris@0
|
550 }
|
Chris@0
|
551
|
Chris@0
|
552 /**
|
Chris@0
|
553 * Tests the getRowByDestination method.
|
Chris@0
|
554 */
|
Chris@0
|
555 public function testGetRowByDestination() {
|
Chris@0
|
556 $row = [
|
Chris@0
|
557 'sourceid1' => 'source_id_value_1',
|
Chris@0
|
558 'sourceid2' => 'source_id_value_2',
|
Chris@16
|
559 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_1']),
|
Chris@0
|
560 'destid1' => 'destination_id_value_1',
|
Chris@0
|
561 ] + $this->idMapDefaults();
|
Chris@0
|
562 $this->saveMap($row);
|
Chris@0
|
563 $row = [
|
Chris@0
|
564 'sourceid1' => 'source_id_value_3',
|
Chris@0
|
565 'sourceid2' => 'source_id_value_4',
|
Chris@16
|
566 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_3']),
|
Chris@0
|
567 'destid1' => 'destination_id_value_2',
|
Chris@0
|
568 ] + $this->idMapDefaults();
|
Chris@0
|
569 $this->saveMap($row);
|
Chris@0
|
570 $dest_id_values = ['destination_id_property' => $row['destid1']];
|
Chris@0
|
571 $id_map = $this->getIdMap();
|
Chris@0
|
572 $result_row = $id_map->getRowByDestination($dest_id_values);
|
Chris@0
|
573 $this->assertSame($row, $result_row);
|
Chris@0
|
574 // This value does not exist.
|
Chris@0
|
575 $dest_id_values = ['destination_id_property' => 'invalid_destination_id_property'];
|
Chris@0
|
576 $id_map = $this->getIdMap();
|
Chris@0
|
577 $result_row = $id_map->getRowByDestination($dest_id_values);
|
Chris@0
|
578 $this->assertFalse($result_row);
|
Chris@0
|
579 }
|
Chris@0
|
580
|
Chris@0
|
581 /**
|
Chris@16
|
582 * Data provider for testLookupSourceIdMapping().
|
Chris@0
|
583 *
|
Chris@0
|
584 * Scenarios to test (for both hits and misses) are:
|
Chris@0
|
585 * - Single-value destination ID to single-value source ID.
|
Chris@0
|
586 * - Multi-value destination ID to multi-value source ID.
|
Chris@0
|
587 * - Single-value destination ID to multi-value source ID.
|
Chris@0
|
588 * - Multi-value destination ID to single-value source ID.
|
Chris@0
|
589 *
|
Chris@0
|
590 * @return array
|
Chris@0
|
591 * An array of data values.
|
Chris@0
|
592 */
|
Chris@16
|
593 public function lookupSourceIdMappingDataProvider() {
|
Chris@0
|
594 return [
|
Chris@0
|
595 [1, 1],
|
Chris@0
|
596 [2, 2],
|
Chris@0
|
597 [1, 2],
|
Chris@0
|
598 [2, 1],
|
Chris@0
|
599 ];
|
Chris@0
|
600 }
|
Chris@0
|
601
|
Chris@0
|
602 /**
|
Chris@0
|
603 * Performs the source ID test on source and destination fields.
|
Chris@0
|
604 *
|
Chris@0
|
605 * @param int $num_source_fields
|
Chris@0
|
606 * Number of source fields to test.
|
Chris@0
|
607 * @param int $num_destination_fields
|
Chris@0
|
608 * Number of destination fields to test.
|
Chris@0
|
609 *
|
Chris@16
|
610 * @dataProvider lookupSourceIdMappingDataProvider
|
Chris@0
|
611 */
|
Chris@16
|
612 public function testLookupSourceIdMapping($num_source_fields, $num_destination_fields) {
|
Chris@0
|
613 // Adjust the migration configuration according to the number of source and
|
Chris@0
|
614 // destination fields.
|
Chris@0
|
615 $this->sourceIds = [];
|
Chris@0
|
616 $this->destinationIds = [];
|
Chris@0
|
617 $row = $this->idMapDefaults();
|
Chris@0
|
618 $source_ids_values = [];
|
Chris@0
|
619 $expected_result = [];
|
Chris@0
|
620 for ($i = 1; $i <= $num_source_fields; $i++) {
|
Chris@0
|
621 $row["sourceid$i"] = "source_id_value_$i";
|
Chris@0
|
622 $source_ids_values = [$row["sourceid$i"]];
|
Chris@0
|
623 $expected_result["source_id_property_$i"] = "source_id_value_$i";
|
Chris@0
|
624 $this->sourceIds["source_id_property_$i"] = [];
|
Chris@0
|
625 }
|
Chris@0
|
626 $destination_id_values = [];
|
Chris@0
|
627 $nonexistent_id_values = [];
|
Chris@0
|
628 for ($i = 1; $i <= $num_destination_fields; $i++) {
|
Chris@0
|
629 $row["destid$i"] = "destination_id_value_$i";
|
Chris@0
|
630 $destination_id_values["destination_id_property_$i"] = "destination_id_value_$i";
|
Chris@0
|
631 $nonexistent_id_values["destination_id_property_$i"] = "nonexistent_destination_id_value_$i";
|
Chris@0
|
632 $this->destinationIds["destination_id_property_$i"] = [];
|
Chris@0
|
633 }
|
Chris@16
|
634 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash($source_ids_values);
|
Chris@0
|
635 $this->saveMap($row);
|
Chris@0
|
636 $id_map = $this->getIdMap();
|
Chris@0
|
637 // Test for a valid hit.
|
Chris@16
|
638 $source_id = $id_map->lookupSourceId($destination_id_values);
|
Chris@0
|
639 $this->assertSame($expected_result, $source_id);
|
Chris@0
|
640 // Test for a miss.
|
Chris@16
|
641 $source_id = $id_map->lookupSourceId($nonexistent_id_values);
|
Chris@0
|
642 $this->assertSame(0, count($source_id));
|
Chris@0
|
643 }
|
Chris@0
|
644
|
Chris@0
|
645 /**
|
Chris@0
|
646 * Tests currentDestination() and currentSource().
|
Chris@0
|
647 */
|
Chris@0
|
648 public function testCurrentDestinationAndSource() {
|
Chris@0
|
649 // Simple map with one source and one destination ID.
|
Chris@0
|
650 $id_map = $this->setupRows(['nid'], ['nid'], [
|
Chris@0
|
651 [1, 101],
|
Chris@0
|
652 [2, 102],
|
Chris@0
|
653 [3, 103],
|
Chris@0
|
654 // Mock a failed row by setting the destination ID to NULL.
|
Chris@0
|
655 [4, NULL],
|
Chris@0
|
656 ]);
|
Chris@0
|
657
|
Chris@0
|
658 // The rows are ordered by destination ID so the failed row should be first.
|
Chris@0
|
659 $id_map->rewind();
|
Chris@0
|
660 $this->assertEquals([], $id_map->currentDestination());
|
Chris@0
|
661 $this->assertEquals(['nid' => 4], $id_map->currentSource());
|
Chris@0
|
662 $id_map->next();
|
Chris@0
|
663 $this->assertEquals(['nid' => 101], $id_map->currentDestination());
|
Chris@0
|
664 $this->assertEquals(['nid' => 1], $id_map->currentSource());
|
Chris@0
|
665 $id_map->next();
|
Chris@0
|
666 $this->assertEquals(['nid' => 102], $id_map->currentDestination());
|
Chris@0
|
667 $this->assertEquals(['nid' => 2], $id_map->currentSource());
|
Chris@0
|
668 $id_map->next();
|
Chris@0
|
669 $this->assertEquals(['nid' => 103], $id_map->currentDestination());
|
Chris@0
|
670 $this->assertEquals(['nid' => 3], $id_map->currentSource());
|
Chris@0
|
671 $id_map->next();
|
Chris@0
|
672 }
|
Chris@0
|
673
|
Chris@0
|
674 /**
|
Chris@0
|
675 * Tests the imported count method.
|
Chris@0
|
676 *
|
Chris@0
|
677 * Scenarios to test for:
|
Chris@0
|
678 * - No imports.
|
Chris@0
|
679 * - One import.
|
Chris@0
|
680 * - Multiple imports.
|
Chris@0
|
681 */
|
Chris@0
|
682 public function testImportedCount() {
|
Chris@0
|
683 $id_map = $this->getIdMap();
|
Chris@0
|
684 // Add a single failed row and assert zero imported rows.
|
Chris@0
|
685 $source = ['source_id_property' => 'source_value_failed'];
|
Chris@0
|
686 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
687 $destination = ['destination_id_property' => 'destination_value_failed'];
|
Chris@0
|
688 $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_FAILED);
|
Chris@14
|
689 $this->assertSame(0, $id_map->importedCount());
|
Chris@0
|
690
|
Chris@0
|
691 // Add an imported row and assert single count.
|
Chris@0
|
692 $source = ['source_id_property' => 'source_value_imported'];
|
Chris@0
|
693 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
694 $destination = ['destination_id_property' => 'destination_value_imported'];
|
Chris@0
|
695 $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_IMPORTED);
|
Chris@14
|
696 $this->assertSame(1, $id_map->importedCount());
|
Chris@0
|
697
|
Chris@0
|
698 // Add a row needing update and assert multiple imported rows.
|
Chris@0
|
699 $source = ['source_id_property' => 'source_value_update'];
|
Chris@0
|
700 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
701 $destination = ['destination_id_property' => 'destination_value_update'];
|
Chris@0
|
702 $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
|
Chris@14
|
703 $this->assertSame(2, $id_map->importedCount());
|
Chris@0
|
704 }
|
Chris@0
|
705
|
Chris@0
|
706 /**
|
Chris@0
|
707 * Tests the number of processed source rows.
|
Chris@0
|
708 *
|
Chris@0
|
709 * Scenarios to test for:
|
Chris@0
|
710 * - No processed rows.
|
Chris@0
|
711 * - One processed row.
|
Chris@0
|
712 * - Multiple processed rows.
|
Chris@0
|
713 */
|
Chris@0
|
714 public function testProcessedCount() {
|
Chris@0
|
715 $id_map = $this->getIdMap();
|
Chris@0
|
716 // Assert zero rows have been processed before adding rows.
|
Chris@14
|
717 $this->assertSame(0, $id_map->processedCount());
|
Chris@0
|
718 $row_statuses = [
|
Chris@0
|
719 MigrateIdMapInterface::STATUS_IMPORTED,
|
Chris@0
|
720 MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
|
Chris@0
|
721 MigrateIdMapInterface::STATUS_IGNORED,
|
Chris@0
|
722 MigrateIdMapInterface::STATUS_FAILED,
|
Chris@0
|
723 ];
|
Chris@0
|
724 // Create a mapping row for each STATUS constant.
|
Chris@0
|
725 foreach ($row_statuses as $status) {
|
Chris@0
|
726 $source = ['source_id_property' => 'source_value_' . $status];
|
Chris@0
|
727 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
728 $destination = ['destination_id_property' => 'destination_value_' . $status];
|
Chris@0
|
729 $id_map->saveIdMapping($row, $destination, $status);
|
Chris@0
|
730 if ($status == MigrateIdMapInterface::STATUS_IMPORTED) {
|
Chris@0
|
731 // Assert a single row has been processed.
|
Chris@14
|
732 $this->assertSame(1, $id_map->processedCount());
|
Chris@0
|
733 }
|
Chris@0
|
734 }
|
Chris@0
|
735 // Assert multiple rows have been processed.
|
Chris@14
|
736 $this->assertSame(count($row_statuses), $id_map->processedCount());
|
Chris@0
|
737 }
|
Chris@0
|
738
|
Chris@0
|
739 /**
|
Chris@0
|
740 * Data provider for testUpdateCount().
|
Chris@0
|
741 *
|
Chris@0
|
742 * Scenarios to test for:
|
Chris@0
|
743 * - No updates.
|
Chris@0
|
744 * - One update.
|
Chris@0
|
745 * - Multiple updates.
|
Chris@0
|
746 *
|
Chris@0
|
747 * @return array
|
Chris@0
|
748 * An array of data values.
|
Chris@0
|
749 */
|
Chris@0
|
750 public function updateCountDataProvider() {
|
Chris@0
|
751 return [
|
Chris@0
|
752 [0],
|
Chris@0
|
753 [1],
|
Chris@0
|
754 [3],
|
Chris@0
|
755 ];
|
Chris@0
|
756 }
|
Chris@0
|
757
|
Chris@0
|
758 /**
|
Chris@0
|
759 * Performs the update count test with a given number of update rows.
|
Chris@0
|
760 *
|
Chris@0
|
761 * @param int $num_update_rows
|
Chris@0
|
762 * The number of update rows to test.
|
Chris@0
|
763 *
|
Chris@0
|
764 * @dataProvider updateCountDataProvider
|
Chris@0
|
765 */
|
Chris@0
|
766 public function testUpdateCount($num_update_rows) {
|
Chris@0
|
767 for ($i = 0; $i < 5; $i++) {
|
Chris@0
|
768 $row = $this->idMapDefaults();
|
Chris@0
|
769 $row['sourceid1'] = "source_id_value_$i";
|
Chris@16
|
770 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]);
|
Chris@0
|
771 $row['destid1'] = "destination_id_value_$i";
|
Chris@0
|
772 $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
|
Chris@0
|
773 $this->saveMap($row);
|
Chris@0
|
774 }
|
Chris@0
|
775 for (; $i < 5 + $num_update_rows; $i++) {
|
Chris@0
|
776 $row = $this->idMapDefaults();
|
Chris@0
|
777 $row['sourceid1'] = "source_id_value_$i";
|
Chris@16
|
778 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]);
|
Chris@0
|
779 $row['destid1'] = "destination_id_value_$i";
|
Chris@0
|
780 $row['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
|
Chris@0
|
781 $this->saveMap($row);
|
Chris@0
|
782 }
|
Chris@0
|
783 $id_map = $this->getIdMap();
|
Chris@14
|
784 $this->assertSame($num_update_rows, $id_map->updateCount());
|
Chris@0
|
785 }
|
Chris@0
|
786
|
Chris@0
|
787 /**
|
Chris@0
|
788 * Data provider for testErrorCount().
|
Chris@0
|
789 *
|
Chris@0
|
790 * Scenarios to test for:
|
Chris@0
|
791 * - No errors.
|
Chris@0
|
792 * - One error.
|
Chris@0
|
793 * - Multiple errors.
|
Chris@0
|
794 *
|
Chris@0
|
795 * @return array
|
Chris@0
|
796 * An array of data values.
|
Chris@0
|
797 */
|
Chris@0
|
798 public function errorCountDataProvider() {
|
Chris@0
|
799 return [
|
Chris@0
|
800 [0],
|
Chris@0
|
801 [1],
|
Chris@0
|
802 [3],
|
Chris@0
|
803 ];
|
Chris@0
|
804 }
|
Chris@0
|
805
|
Chris@0
|
806 /**
|
Chris@0
|
807 * Performs error count test with a given number of error rows.
|
Chris@0
|
808 *
|
Chris@0
|
809 * @param int $num_error_rows
|
Chris@0
|
810 * Number of error rows to test.
|
Chris@0
|
811 *
|
Chris@0
|
812 * @dataProvider errorCountDataProvider
|
Chris@0
|
813 */
|
Chris@0
|
814 public function testErrorCount($num_error_rows) {
|
Chris@0
|
815 for ($i = 0; $i < 5; $i++) {
|
Chris@0
|
816 $row = $this->idMapDefaults();
|
Chris@0
|
817 $row['sourceid1'] = "source_id_value_$i";
|
Chris@16
|
818 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]);
|
Chris@0
|
819 $row['destid1'] = "destination_id_value_$i";
|
Chris@0
|
820 $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
|
Chris@0
|
821 $this->saveMap($row);
|
Chris@0
|
822 }
|
Chris@0
|
823 for (; $i < 5 + $num_error_rows; $i++) {
|
Chris@0
|
824 $row = $this->idMapDefaults();
|
Chris@0
|
825 $row['sourceid1'] = "source_id_value_$i";
|
Chris@16
|
826 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]);
|
Chris@0
|
827 $row['destid1'] = "destination_id_value_$i";
|
Chris@0
|
828 $row['source_row_status'] = MigrateIdMapInterface::STATUS_FAILED;
|
Chris@0
|
829 $this->saveMap($row);
|
Chris@0
|
830 }
|
Chris@0
|
831
|
Chris@14
|
832 $this->assertSame($num_error_rows, $this->getIdMap()->errorCount());
|
Chris@0
|
833 }
|
Chris@0
|
834
|
Chris@0
|
835 /**
|
Chris@0
|
836 * Tests setting a row source_row_status to STATUS_NEEDS_UPDATE.
|
Chris@0
|
837 */
|
Chris@0
|
838 public function testSetUpdate() {
|
Chris@0
|
839 $id_map = $this->getIdMap();
|
Chris@0
|
840 $row_statuses = [
|
Chris@0
|
841 MigrateIdMapInterface::STATUS_IMPORTED,
|
Chris@0
|
842 MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
|
Chris@0
|
843 MigrateIdMapInterface::STATUS_IGNORED,
|
Chris@0
|
844 MigrateIdMapInterface::STATUS_FAILED,
|
Chris@0
|
845 ];
|
Chris@0
|
846 // Create a mapping row for each STATUS constant.
|
Chris@0
|
847 foreach ($row_statuses as $status) {
|
Chris@0
|
848 $source = ['source_id_property' => 'source_value_' . $status];
|
Chris@0
|
849 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
850 $destination = ['destination_id_property' => 'destination_value_' . $status];
|
Chris@0
|
851 $id_map->saveIdMapping($row, $destination, $status);
|
Chris@0
|
852 $expected_results[] = [
|
Chris@0
|
853 'sourceid1' => 'source_value_' . $status,
|
Chris@16
|
854 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source),
|
Chris@0
|
855 'destid1' => 'destination_value_' . $status,
|
Chris@0
|
856 'source_row_status' => $status,
|
Chris@0
|
857 'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
|
Chris@0
|
858 'hash' => '',
|
Chris@0
|
859 ];
|
Chris@0
|
860 }
|
Chris@0
|
861 // Assert that test values exist.
|
Chris@0
|
862 $this->queryResultTest($this->getIdMapContents(), $expected_results);
|
Chris@0
|
863 // Mark each row as STATUS_NEEDS_UPDATE.
|
Chris@0
|
864 foreach ($row_statuses as $status) {
|
Chris@0
|
865 $id_map->setUpdate(['source_id_property' => 'source_value_' . $status]);
|
Chris@0
|
866 }
|
Chris@0
|
867 // Update expected results.
|
Chris@0
|
868 foreach ($expected_results as $key => $value) {
|
Chris@0
|
869 $expected_results[$key]['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
|
Chris@0
|
870 }
|
Chris@0
|
871 // Assert that updated expected values match.
|
Chris@0
|
872 $this->queryResultTest($this->getIdMapContents(), $expected_results);
|
Chris@0
|
873 // Assert an exception is thrown when source identifiers are not provided.
|
Chris@0
|
874 try {
|
Chris@0
|
875 $id_map->setUpdate([]);
|
Chris@0
|
876 $this->assertFalse(FALSE, 'MigrateException not thrown, when source identifiers were provided to update.');
|
Chris@0
|
877 }
|
Chris@0
|
878 catch (MigrateException $e) {
|
Chris@0
|
879 $this->assertTrue(TRUE, "MigrateException thrown, when source identifiers were not provided to update.");
|
Chris@0
|
880 }
|
Chris@0
|
881 }
|
Chris@0
|
882
|
Chris@0
|
883 /**
|
Chris@0
|
884 * Tests prepareUpdate().
|
Chris@0
|
885 */
|
Chris@0
|
886 public function testPrepareUpdate() {
|
Chris@0
|
887 $id_map = $this->getIdMap();
|
Chris@0
|
888 $row_statuses = [
|
Chris@0
|
889 MigrateIdMapInterface::STATUS_IMPORTED,
|
Chris@0
|
890 MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
|
Chris@0
|
891 MigrateIdMapInterface::STATUS_IGNORED,
|
Chris@0
|
892 MigrateIdMapInterface::STATUS_FAILED,
|
Chris@0
|
893 ];
|
Chris@0
|
894
|
Chris@0
|
895 // Create a mapping row for each STATUS constant.
|
Chris@0
|
896 foreach ($row_statuses as $status) {
|
Chris@0
|
897 $source = ['source_id_property' => 'source_value_' . $status];
|
Chris@0
|
898 $row = new Row($source, ['source_id_property' => []]);
|
Chris@0
|
899 $destination = ['destination_id_property' => 'destination_value_' . $status];
|
Chris@0
|
900 $id_map->saveIdMapping($row, $destination, $status);
|
Chris@0
|
901 $expected_results[] = [
|
Chris@0
|
902 'sourceid1' => 'source_value_' . $status,
|
Chris@0
|
903 'destid1' => 'destination_value_' . $status,
|
Chris@0
|
904 'source_row_status' => $status,
|
Chris@0
|
905 'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
|
Chris@0
|
906 'hash' => '',
|
Chris@0
|
907 ];
|
Chris@0
|
908 }
|
Chris@0
|
909
|
Chris@0
|
910 // Assert that test values exist.
|
Chris@0
|
911 $this->queryResultTest($this->getIdMapContents(), $expected_results);
|
Chris@0
|
912
|
Chris@0
|
913 // Mark all rows as STATUS_NEEDS_UPDATE.
|
Chris@0
|
914 $id_map->prepareUpdate();
|
Chris@0
|
915
|
Chris@0
|
916 // Update expected results.
|
Chris@0
|
917 foreach ($expected_results as $key => $value) {
|
Chris@0
|
918 $expected_results[$key]['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
|
Chris@0
|
919 }
|
Chris@0
|
920 // Assert that updated expected values match.
|
Chris@0
|
921 $this->queryResultTest($this->getIdMapContents(), $expected_results);
|
Chris@0
|
922 }
|
Chris@0
|
923
|
Chris@0
|
924 /**
|
Chris@0
|
925 * Tests the destroy method.
|
Chris@0
|
926 *
|
Chris@0
|
927 * Scenarios to test for:
|
Chris@0
|
928 * - No errors.
|
Chris@0
|
929 * - One error.
|
Chris@0
|
930 * - Multiple errors.
|
Chris@0
|
931 */
|
Chris@0
|
932 public function testDestroy() {
|
Chris@0
|
933 $id_map = $this->getIdMap();
|
Chris@0
|
934 // Initialize the ID map.
|
Chris@0
|
935 $id_map->getDatabase();
|
Chris@0
|
936 $map_table_name = $id_map->mapTableName();
|
Chris@0
|
937 $message_table_name = $id_map->messageTableName();
|
Chris@0
|
938 $row = new Row(['source_id_property' => 'source_value'], ['source_id_property' => []]);
|
Chris@0
|
939 $id_map->saveIdMapping($row, ['destination_id_property' => 2]);
|
Chris@0
|
940 $id_map->saveMessage(['source_id_property' => 'source_value'], 'A message');
|
Chris@0
|
941 $this->assertTrue($this->database->schema()->tableExists($map_table_name),
|
Chris@0
|
942 "$map_table_name exists");
|
Chris@0
|
943 $this->assertTrue($this->database->schema()->tableExists($message_table_name),
|
Chris@0
|
944 "$message_table_name exists");
|
Chris@0
|
945 $id_map->destroy();
|
Chris@0
|
946 $this->assertFalse($this->database->schema()->tableExists($map_table_name),
|
Chris@0
|
947 "$map_table_name does not exist");
|
Chris@0
|
948 $this->assertFalse($this->database->schema()->tableExists($message_table_name),
|
Chris@0
|
949 "$message_table_name does not exist");
|
Chris@0
|
950 }
|
Chris@0
|
951
|
Chris@0
|
952 /**
|
Chris@0
|
953 * Tests the getQualifiedMapTable method with a prefixed database.
|
Chris@0
|
954 */
|
Chris@0
|
955 public function testGetQualifiedMapTablePrefix() {
|
Chris@0
|
956 $connection_options = [
|
Chris@0
|
957 'database' => ':memory:',
|
Chris@0
|
958 'prefix' => 'prefix',
|
Chris@0
|
959 ];
|
Chris@0
|
960 $pdo = Connection::open($connection_options);
|
Chris@0
|
961 $this->database = new Connection($pdo, $connection_options);
|
Chris@0
|
962 $qualified_map_table = $this->getIdMap()->getQualifiedMapTableName();
|
Chris@0
|
963 // The SQLite driver is a special flower. It will prefix tables with
|
Chris@0
|
964 // PREFIX.TABLE, instead of the standard PREFIXTABLE.
|
Chris@0
|
965 // @see \Drupal\Core\Database\Driver\sqlite\Connection::__construct()
|
Chris@0
|
966 $this->assertEquals('prefix.migrate_map_sql_idmap_test', $qualified_map_table);
|
Chris@0
|
967 }
|
Chris@0
|
968
|
Chris@0
|
969 /**
|
Chris@0
|
970 * Tests all the iterator methods in one swing.
|
Chris@0
|
971 *
|
Chris@0
|
972 * The iterator methods are:
|
Chris@0
|
973 * - Sql::rewind()
|
Chris@0
|
974 * - Sql::next()
|
Chris@0
|
975 * - Sql::valid()
|
Chris@0
|
976 * - Sql::key()
|
Chris@0
|
977 * - Sql::current()
|
Chris@0
|
978 */
|
Chris@0
|
979 public function testIterators() {
|
Chris@0
|
980 for ($i = 0; $i < 3; $i++) {
|
Chris@0
|
981 $row = $this->idMapDefaults();
|
Chris@0
|
982 $row['sourceid1'] = "source_id_value_$i";
|
Chris@16
|
983 $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]);
|
Chris@0
|
984 $row['destid1'] = "destination_id_value_$i";
|
Chris@0
|
985 $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
|
Chris@0
|
986 $expected_results[serialize(['sourceid1' => $row['sourceid1']])] = ['destid1' => $row['destid1']];
|
Chris@0
|
987 $this->saveMap($row);
|
Chris@0
|
988 }
|
Chris@0
|
989
|
Chris@0
|
990 $this->assertSame(iterator_to_array($this->getIdMap()), $expected_results);
|
Chris@0
|
991 }
|
Chris@0
|
992
|
Chris@0
|
993 /**
|
Chris@0
|
994 * Retrieves the contents of an ID map.
|
Chris@0
|
995 *
|
Chris@0
|
996 * @return array
|
Chris@0
|
997 * The contents of an ID map.
|
Chris@0
|
998 */
|
Chris@0
|
999 private function getIdMapContents() {
|
Chris@0
|
1000 $result = $this->database
|
Chris@0
|
1001 ->select('migrate_map_sql_idmap_test', 't')
|
Chris@0
|
1002 ->fields('t')
|
Chris@0
|
1003 ->execute();
|
Chris@0
|
1004
|
Chris@0
|
1005 // The return value needs to be countable, or it will fail certain
|
Chris@0
|
1006 // assertions. iterator_to_array() will not suffice because it won't
|
Chris@0
|
1007 // respect the PDO fetch mode, if specified.
|
Chris@0
|
1008 $contents = [];
|
Chris@0
|
1009 foreach ($result as $row) {
|
Chris@0
|
1010 $contents[] = (array) $row;
|
Chris@0
|
1011 }
|
Chris@0
|
1012 return $contents;
|
Chris@0
|
1013 }
|
Chris@0
|
1014
|
Chris@17
|
1015 /**
|
Chris@17
|
1016 * Tests the delayed creation of the "map" and "message" migrate tables.
|
Chris@17
|
1017 */
|
Chris@17
|
1018 public function testMapTableCreation() {
|
Chris@17
|
1019 $id_map = $this->getIdMap();
|
Chris@17
|
1020 $map_table_name = $id_map->mapTableName();
|
Chris@17
|
1021 $message_table_name = $id_map->messageTableName();
|
Chris@17
|
1022
|
Chris@17
|
1023 // Check that tables names do exist.
|
Chris@17
|
1024 $this->assertEquals('migrate_map_sql_idmap_test', $map_table_name);
|
Chris@17
|
1025 $this->assertEquals('migrate_message_sql_idmap_test', $message_table_name);
|
Chris@17
|
1026
|
Chris@17
|
1027 // Check that tables don't exist.
|
Chris@17
|
1028 $this->assertFalse($this->database->schema()->tableExists($map_table_name));
|
Chris@17
|
1029 $this->assertFalse($this->database->schema()->tableExists($message_table_name));
|
Chris@17
|
1030
|
Chris@17
|
1031 $id_map->getDatabase();
|
Chris@17
|
1032
|
Chris@17
|
1033 // Check that tables do exist.
|
Chris@17
|
1034 $this->assertTrue($this->database->schema()->tableExists($map_table_name));
|
Chris@17
|
1035 $this->assertTrue($this->database->schema()->tableExists($message_table_name));
|
Chris@17
|
1036 }
|
Chris@17
|
1037
|
Chris@0
|
1038 }
|