'Node migration', 'description' => 'Test migration of node data', 'group' => 'Migrate', ); } function setUp() { parent::setUp('list', 'number', 'taxonomy', 'image', 'migrate', 'migrate_example'); } function testNodeImport() { $migration = Migration::getInstance('WineVariety'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Variety term import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineRegion'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Region term import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineBestWith'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('"Best With" term import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineFileCopy'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('File import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineRole'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Role import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineUser'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('User import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineProducer'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Producer node import returned RESULT_COMPLETED')); $migration = Migration::getInstance('WineWine'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import returned RESULT_COMPLETED')); // Gather wine and producer nodes, and their corresponding input data $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_producer'), TRUE); // Index by title $producer_nodes = array(); foreach ($rawnodes as $node) { $producer_nodes[$node->title] = $node; } $query = db_select('migrate_example_wine_producer', 'p') ->fields('p', array('producerid', 'name', 'body', 'excerpt', 'accountid')); // Region term is singletons, handled straighforwardly $query->leftJoin('migrate_example_wine_category_producer', 'reg', "p.producerid = reg.producerid"); $query->addField('reg', 'categoryid', 'region'); $result = $query->execute(); $producer_rows = array(); foreach ($result as $row) { $producer_rows[$row->name] = $row; } $this->assertEqual(count($producer_nodes), count($producer_rows), t('Counts of producer nodes and input rows match')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); // Index by title $wine_nodes = array(); foreach ($rawnodes as $node) { $wine_nodes[$node->title] = $node; } $query = db_select('migrate_example_wine', 'w') ->fields('w', array('wineid', 'name', 'body', 'excerpt', 'accountid', 'posted', 'last_changed', 'variety', 'region')); $query->leftJoin('migrate_example_wine_category_wine', 'cwbw', "w.wineid = cwbw.wineid"); $query->leftJoin('migrate_example_wine_categories', 'bw', "cwbw.categoryid = bw.categoryid AND bw.type = 'best_with'"); // Gives a single comma-separated list of related terms $query->groupBy('cwbw.wineid'); $query->addExpression('GROUP_CONCAT(bw.categoryid)', 'best_with'); $result = $query->execute(); $wine_rows = array(); foreach ($result as $row) { $wine_rows[$row->name] = $row; } $this->assertEqual(count($wine_nodes), count($wine_rows), t('Counts of wine nodes and input rows match')); // Test each base node field $producer_node = $producer_nodes['Montes']; $producer_row = $producer_rows['Montes']; $wine_node = $wine_nodes['Montes Classic Cabernet Sauvignon']; $wine_row = $wine_rows['Montes Classic Cabernet Sauvignon']; $user_migration = MigrationBase::getInstance('WineUser'); $mapped_uid = $user_migration->getMap()->lookupDestinationID(array($producer_row->accountid)); if (is_array($mapped_uid)) { $this->assertEqual($producer_node->uid, reset($mapped_uid), t('uid properly migrated')); } else { $this->error(t('Account ID !id not migrated', array('!id' => $producer_row->accountid))); } $this->assertEqual($wine_node->created, $wine_row->posted, t('created properly migrated')); $this->assertEqual($wine_node->changed, $wine_row->last_changed, t('changed properly migrated')); // Test Field API fields of all types // body_with_summary $body = field_get_items('node', $wine_node, 'body'); $this->assertEqual($body[0]['value'], 'REVIEW: ' . drupal_strtoupper($wine_row->body), t('body properly migrated')); $this->assertEqual($body[0]['summary'], $wine_row->excerpt, t('summary properly migrated')); // taxonomy_term_reference - single and multiple $variety = field_get_items('node', $wine_node, 'migrate_example_wine_varieties'); $variety_migration = MigrationBase::getInstance('WineVariety'); $mapped_tid = $variety_migration->getMap()->lookupDestinationID(array($wine_row->variety)); if (is_array($mapped_tid)) { $this->assertEqual($variety[0]['tid'], reset($mapped_tid), t('Single taxonomy_term_reference properly migrated')); } else { $this->error(t('Variety !var not migrated', array('!var' => $wine_row->variety))); } $best_with = field_get_items('node', $wine_node, 'migrate_example_wine_best_with'); $best_with_migration = MigrationBase::getInstance('WineBestWith'); $source_ids = explode(',', $wine_row->best_with); $mapped_tids = array(); foreach ($source_ids as $source_id) { $tid = $best_with_migration->getMap()->lookupDestinationID(array($source_id)); if ($tid) { $mapped_tids[reset($tid)] = reset($tid); } } $this->assertEqual(count($best_with), count($mapped_tids), t('Counts of Best With match')); foreach ($best_with as $current) { $this->assertNotNull($mapped_tids[$current['tid']], t('Multiple value taxonomy_term_reference properly migrated')); } // Test the vintages field (demonstrating prepareRow() works) - we know // the valid vintages for this node are 2006 and 2007 $expected = array(array('value' => 2006), array('value' => 2007)); $this->assertEqual($wine_node->field_migrate_example_top_vintag[LANGUAGE_NONE], $expected, t('Vintages match (prepareRow works)')); // Test updates // Capture original nodes $original_nodes = node_load_multiple(array(), array('type' => 'migrate_example_wine')); $update_migration = Migration::getInstance('WineUpdates'); $result = $update_migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine updates import returned RESULT_COMPLETED')); $final_nodes = node_load_multiple(array(), array('type' => 'migrate_example_wine'), TRUE); foreach ($original_nodes as $nid => $original_node) { foreach ($original_node as $field => $value) { if ($field == 'field_migrate_example_wine_ratin' || $field == 'changed' || $field == 'revision_timestamp') { if ($value == $final_nodes[$nid]->$field) { $this->error(t('Field !field should have changed but did not, value=!value', array('!field' => $field, '!value' => print_r($value, TRUE)))); } } else { if ($value != $final_nodes[$nid]->$field) { $this->error(t('Field !field mismatch: original !value1, result !value2', array('!field' => $field, '!value1' => print_r($value, TRUE), '!value2' => print_r($final_nodes[$nid]->$field, TRUE)))); } } } } // Test highwater marks - add new wines, modify an old one, and see what changes $fields = array('wineid', 'name', 'body', 'excerpt', 'accountid', 'posted', 'last_changed', 'variety', 'region', 'rating'); $query = db_insert('migrate_example_wine') ->fields($fields); $data = array( // Timestamps 1284008523, 1284120550 array(3, 'Schloss Muhlenhof Dornfelder', 'Juicy black & red berry fruits', 'Pretty good', 9, strtotime('2010-09-09 01:02:03'), strtotime('2010-09-10 08:09:10'), 25, 17, 95), // Timestamps 1286122209, 1286122209 array(4, 'Gachot-Monot Bourgogne Rge 06', 'Funky', 'Pair with white sauced dishes', 3, strtotime('2010-10-03 12:10:09'), strtotime('2010-10-03 12:10:09'), 26, 2, 85), ); foreach ($data as $row) { $query->values(array_combine($fields, $row)); } $query->execute(); db_update('migrate_example_wine') ->fields(array( 'body' => 'Not so much berry character', // Timestamp 1285058521 'last_changed' => strtotime('2010-10-21 04:42:01'), )) ->condition('wineid', 2) ->execute(); $migration = Migration::getInstance('WineWine'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); if (!$this->assertEqual(count($rawnodes), 4, t('Now 4 wine nodes exist'))) { $this->error(t('There are now !count nodes', array('!count' => count($rawnodes)))); } $nodes = node_load_multiple(FALSE, array('title' => 'Archeo Ruggero di Tasso Nero d\'Avola'), TRUE); $node = reset($nodes); $body = $node->body[LANGUAGE_NONE][0]['value']; if (!$this->assertEqual($body, 'REVIEW: NOT SO MUCH BERRY CHARACTER', t('Body updated'))) { $this->error(t('Actual body !body', array('!body' => $body))); } // Test rollback $result = $migration->processRollback(array('force' => TRUE)); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node rollback returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); $this->assertEqual(count($rawnodes), 0, t('All nodes deleted')); $count = db_select('migrate_map_winewine', 'map') ->fields('map', array('sourceid1')) ->countQuery() ->execute() ->fetchField(); $this->assertEqual($count, 0, t('Map cleared')); $count = db_select('migrate_message_winewine', 'msg') ->fields('msg', array('sourceid1')) ->countQuery() ->execute() ->fetchField(); $this->assertEqual($count, 0, t('Messages cleared')); // Now test highwater with unjoined map table $migration->getSource()->setMapJoinable(FALSE); $result = $migration->processImport(array('limit' => array('value' => 2, 'unit' => 'items'))); db_update('migrate_example_wine') ->fields(array( 'body' => 'Very berry', // Timestamp 1286008921 'last_changed' => strtotime('2010-10-02 04:42:01'), )) ->condition('wineid', 1) ->execute(); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); if (!$this->assertEqual(count($rawnodes), 4, t('Now 4 wine nodes exist'))) { $this->error(t('There are now !count nodes', array('!count' => count($rawnodes)))); } $nodes = node_load_multiple(FALSE, array('title' => 'Montes Classic Cabernet Sauvignon'), TRUE); $node = reset($nodes); $body = $node->body[LANGUAGE_NONE][0]['value']; if (!$this->assertEqual($body, 'REVIEW: VERY BERRY', t('Body updated'))) { $this->error(t('Actual body !body', array('!body' => $body))); } // Test itemlimit (joined map table) $result = $migration->processRollback(array('force' => TRUE)); $migration->getSource()->setMapJoinable(TRUE); $result = $migration->processImport(array('limit' => array('value' => 1, 'unit' => 'item'))); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import with itemlimit returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); $this->assertEqual(count($rawnodes), 1, t('One node imported')); // Test idlist (joined map table) $result = $migration->processRollback(array('force' => TRUE)); $result = $migration->processImport(array('idlist' => 2)); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import with idlist returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); $this->assertEqual(count($rawnodes), 1, t('One node imported')); $node = reset($rawnodes); $this->assertEqual($node->title, 'Archeo Ruggero di Tasso Nero d\'Avola', t('Single specified node imported')); // Test itemlimit (unjoined map table) $result = $migration->processRollback(array('force' => TRUE)); $migration->getSource()->setMapJoinable(FALSE); $result = $migration->processImport(array('limit' => array('value' => 1, 'unit' => 'item'))); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import with itemlimit returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); $this->assertEqual(count($rawnodes), 1, t('One node imported')); // Test idlist (unjoined map table) $result = $migration->processRollback(array('force' => TRUE)); $result = $migration->processImport(array('idlist' => 2)); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Wine node import with idlist returned RESULT_COMPLETED')); $rawnodes = node_load_multiple(FALSE, array('type' => 'migrate_example_wine'), TRUE); $this->assertEqual(count($rawnodes), 1, t('One node imported')); $node = reset($rawnodes); $this->assertEqual($node->title, 'Archeo Ruggero di Tasso Nero d\'Avola', t('Single specified node imported')); // Test integer highwater marks (http://drupal.org/node/1161612) $result = $migration->processRollback(array('force' => TRUE)); db_update('migrate_example_wine') ->fields(array('last_changed' => 100000000)) ->condition('wineid', 1) ->execute(); db_update('migrate_example_wine') ->fields(array('last_changed' => 200000000)) ->condition('wineid', 2) ->execute(); db_update('migrate_example_wine') ->fields(array('last_changed' => 300000000)) ->condition('wineid', 3) ->execute(); db_update('migrate_example_wine') ->fields(array('last_changed' => 400000000)) ->condition('wineid', 4) ->execute(); $result = $migration->processImport(); // Just a quick check to make sure we got four nodes with the right changed values $count = db_query("SELECT COUNT(nid) FROM {node} n INNER JOIN {migrate_map_winewine} map ON n.nid=map.destid1 WHERE n.changed = map.sourceid1*100000000")->fetchField(); $this->assertEqual($count, 4, t('Four nodes with updated changed values imported')); // We mark two nodes with higher updated values. If these end up being treated // as strings in saveHighwater(), the saved highwater mark will end up as // 500000000 instead of 1000000000. db_update('migrate_example_wine') ->fields(array('last_changed' => 1000000000)) ->condition('wineid', 2) ->execute(); db_update('migrate_example_wine') ->fields(array('last_changed' => 500000000)) ->condition('wineid', 3) ->execute(); $result = $migration->processImport(); $newHighwater = db_select('migrate_status', 'ms') ->fields('ms', array('highwater')) ->condition('machine_name', 'WineWine') ->execute() ->fetchField(); if (!$this->assertEqual($newHighwater, 1000000000, t('Correct highwater mark set'))) { $this->error(t('Unexpected highwater mark !highwater', array('!highwater' => $newHighwater))); } // Test for http://drupal.org/node/1037872 - updating with nid mapped and idlist $migration = Migration::getInstance('BeerTerm'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Beer term import returned RESULT_COMPLETED')); $migration = Migration::getInstance('BeerUser'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Beer user import returned RESULT_COMPLETED')); $migration = Migration::getInstance('BeerNode'); $result = $migration->processImport(); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Beer node import returned RESULT_COMPLETED')); db_update('migrate_map_beernode') ->fields(array('needs_update' => 1)) ->execute(); $result = $migration->processImport(array('idlist' => 99999999)); $this->assertEqual($result, Migration::RESULT_COMPLETED, t('Beer node update import returned RESULT_COMPLETED')); $result = db_select('migrate_message_beernode', 'msg') ->fields('msg', array('message')) ->execute(); foreach ($result as $row) { $this->error($row->message); } } }