summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt1
-rw-r--r--migrate_example/beer.inc2
-rw-r--r--migrate_example/migrate_example.install28
-rw-r--r--migrate_example/wine.inc52
-rw-r--r--migrate_example/wine.install.inc14
-rw-r--r--migrate_example/xml/positions.xml11
-rw-r--r--plugins/destinations/user.inc16
-rw-r--r--tests/plugins/destinations/comment.test8
-rw-r--r--tests/plugins/destinations/node.test4
-rw-r--r--tests/plugins/destinations/user.test18
-rw-r--r--tests/plugins/sources/xml.test4
11 files changed, 149 insertions, 9 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 6e45e3e..714ba49 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -11,6 +11,7 @@ should now be prepare($entity, stdClass $row).
Features and enhancements
- #1017246 - Added support for running migrations from the dashboard.
- #1004812 - Added schema-driven table destination plugin.
+- #1009708 - Added role destination plugin.
- #1005090 - Modified filefield property import to use JSON input.
- #730980 - Added more detailed reporting on import.
- #1142384 - Extended file field support to copy from remote URLs.
diff --git a/migrate_example/beer.inc b/migrate_example/beer.inc
index 7aa3e24..969863d 100644
--- a/migrate_example/beer.inc
+++ b/migrate_example/beer.inc
@@ -199,7 +199,7 @@ class BeerUserMigration extends BasicExampleMigration {
// value is provided in addition to a source field, the default value will
// be applied to any rows where the source field is empty or NULL.
$this->addFieldMapping('roles')
- ->defaultValue(drupal_map_assoc(array(2)));
+ ->defaultValue(2);
$this->addFieldMapping('field_migrate_example_gender', 'sex');
// The source field has beer names separated by a pipe character ('|'). By
diff --git a/migrate_example/migrate_example.install b/migrate_example/migrate_example.install
index c2d96ec..b5328be 100644
--- a/migrate_example/migrate_example.install
+++ b/migrate_example/migrate_example.install
@@ -193,3 +193,31 @@ function migrate_example_update_7006() {
$ret[] = t('Added sample data for table destinations.');
return $ret;
}
+
+/**
+ * Add data for testing/demonstrating roles.
+ */
+function migrate_example_update_7007() {
+ $ret = array();
+ db_add_field('migrate_example_wine_account', 'positions', array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ 'description' => 'Positions held',
+ )
+ );
+ $query = db_update('migrate_example_wine_account')
+ ->fields(array('positions' => '5'))
+ ->condition('accountid', 1)
+ ->execute();
+ db_update('migrate_example_wine_account')
+ ->fields(array('positions' => '18'))
+ ->condition('accountid', 3)
+ ->execute();
+ db_update('migrate_example_wine_account')
+ ->fields(array('positions' => '5,18'))
+ ->condition('accountid', 9)
+ ->execute();
+ $ret[] = t('Added positions field to migrate_example_wine_account table.');
+ return $ret;
+}
diff --git a/migrate_example/wine.inc b/migrate_example/wine.inc
index bc92b71..305b51d 100644
--- a/migrate_example/wine.inc
+++ b/migrate_example/wine.inc
@@ -179,11 +179,54 @@ class WineFileMigration extends AdvancedExampleMigration {
}
}
+class WineRoleMigration extends XMLMigration {
+ public function __construct() {
+ parent::__construct();
+ $this->description = t('XML feed (multi items) of roles (positions)');
+ $this->softDependencies = array('WineFile');
+
+ // There isn't a consistent way to automatically identify appropriate "fields"
+ // from an XML feed, so we pass an explicit list of source fields
+ $fields = array(
+ 'name' => t('Position name'),
+ );
+
+ // The source ID here is the one retrieved from each data item in the XML file, and
+ // used to identify specific items
+ $this->map = new MigrateSQLMap($this->machineName,
+ array(
+ 'sourceid' => array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ )
+ ),
+ MigrateDestinationRole::getKeySchema()
+ );
+
+ // This can also be an URL instead of a file path.
+ $xml_folder = DRUPAL_ROOT . '/' . drupal_get_path('module', 'migrate_example') . '/xml/';
+ $items_url = $xml_folder . 'positions.xml';
+ $item_xpath = '/positions/position'; // relative to document
+ $item_ID_xpath = 'sourceid'; // relative to item_xpath and gets assembled
+ // into full path /producers/producer/sourceid
+
+ $items_class = new MigrateItemsXML($items_url, $item_xpath, $item_ID_xpath);
+ $this->source = new MigrateSourceMultiItems($items_class, $fields);
+
+ $this->destination = new MigrateDestinationRole();
+
+ $this->addFieldMapping('name', 'name')
+ ->xpath('name');
+ $this->addUnmigratedDestinations(array('weight'));
+ }
+}
+
class WineUserMigration extends AdvancedExampleMigration {
public function __construct() {
parent::__construct();
$this->description = t('Wine Drinkers of the world');
- $this->dependencies = array('WinePrep', 'WineFile');
+ $this->dependencies = array('WinePrep', 'WineFile', 'WineRole');
$this->map = new MigrateSQLMap($this->machineName,
array('accountid' => array(
'type' => 'int',
@@ -197,7 +240,7 @@ class WineUserMigration extends AdvancedExampleMigration {
$query = db_select('migrate_example_wine_account', 'wa')
->fields('wa', array('accountid', 'status', 'posted', 'name',
'password', 'mail', 'last_access', 'last_login',
- 'original_mail', 'sig', 'sex', 'imageid'));
+ 'original_mail', 'sig', 'sex', 'imageid', 'positions'));
$this->source = new MigrateSourceSQL($query);
$this->destination = new MigrateDestinationUser();
@@ -210,8 +253,9 @@ class WineUserMigration extends AdvancedExampleMigration {
$this->addFieldMapping('login', 'last_login')
->description('See prepare method');
$this->addFieldMapping('pass', 'password');
- $this->addFieldMapping('roles')
- ->defaultValue(drupal_map_assoc(array(2)));
+ $this->addFieldMapping('roles', 'positions')
+ ->separator(',')
+ ->sourceMigration('WineRole');
$this->addFieldMapping('signature', 'sig');
$this->addFieldMapping('signature_format')
->defaultValue($this->basicFormat->format);
diff --git a/migrate_example/wine.install.inc b/migrate_example/wine.install.inc
index 0f3d260..f62aaaa 100644
--- a/migrate_example/wine.install.inc
+++ b/migrate_example/wine.install.inc
@@ -513,6 +513,12 @@ function migrate_example_wine_schema_account() {
'not null' => FALSE,
'description' => 'Image ID',
),
+ 'positions' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ 'description' => 'Positions held',
+ ),
),
'primary key' => array('accountid'),
);
@@ -1002,19 +1008,19 @@ function migrate_example_wine_data_producer() {
function migrate_example_wine_data_account() {
$fields = array('accountid', 'status', 'posted', 'last_access', 'last_login',
- 'name', 'sex', 'password', 'mail', 'original_mail', 'sig', 'imageid');
+ 'name', 'sex', 'password', 'mail', 'original_mail', 'sig', 'imageid', 'positions');
$query = db_insert('migrate_example_wine_account')
->fields($fields);
$data = array(
array(1, 1, '2010-03-30 10:31:05', '2010-04-30 18:25:24', '2010-04-30 14:01:02',
'darren', 'M', 'dpass', 'ddarren@example.com', 'darren@example.com',
- 'All about the Australians', NULL),
+ 'All about the Australians', NULL, '5'),
array(3, 0, '2007-03-15 10:31:05', '2007-06-10 04:11:38', '2007-06-10 04:11:38',
'emily', 'F', 'insecure', 'emily@example.com', 'emily@example.com',
- 'Sommelier to the stars', NULL),
+ 'Sommelier to the stars', NULL, '18'),
array(9, 1, '2004-02-29 10:31:05', '2004-02-29 10:31:05', '2004-02-29 10:31:05',
'fonzie', NULL, 'bike', 'thefonz@example.com', 'arthur@example.com',
- 'Aaay!', 1),
+ 'Aaay!', 1, '5,18'),
);
foreach ($data as $row) {
$query->values(array_combine($fields, $row));
diff --git a/migrate_example/xml/positions.xml b/migrate_example/xml/positions.xml
new file mode 100644
index 0000000..bd6517c
--- /dev/null
+++ b/migrate_example/xml/positions.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<positions>
+ <position>
+ <sourceid>5</sourceid>
+ <name>Taster</name>
+ </position>
+ <position>
+ <sourceid>18</sourceid>
+ <name>Vintner</name>
+ </position>
+</positions>
diff --git a/plugins/destinations/user.inc b/plugins/destinations/user.inc
index e291499..2e2b7ce 100644
--- a/plugins/destinations/user.inc
+++ b/plugins/destinations/user.inc
@@ -129,6 +129,12 @@ class MigrateDestinationUser extends MigrateDestinationEntity {
$old_account = $account;
}
+ // Role arrays need to be keyed by the role id, which isn't how the data
+ // naturally comes in. Fix them up.
+ if (is_array($account->roles)) {
+ $account->roles = drupal_map_assoc($account->roles);
+ }
+
$this->prepare($account, $row);
if (isset($account->uid) && !(isset($account->is_new) && $account->is_new)) {
@@ -157,3 +163,13 @@ class MigrateDestinationUser extends MigrateDestinationEntity {
return $return;
}
}
+
+class MigrateDestinationRole extends MigrateDestinationTable {
+ public function __construct() {
+ parent::__construct('role');
+ }
+
+ static public function getKeySchema() {
+ return MigrateDestinationTable::getKeySchema('role');
+ }
+}
diff --git a/tests/plugins/destinations/comment.test b/tests/plugins/destinations/comment.test
index d69ae62..6c971f7 100644
--- a/tests/plugins/destinations/comment.test
+++ b/tests/plugins/destinations/comment.test
@@ -33,6 +33,14 @@ class MigrateCommentUnitTest extends DrupalWebTestCase {
$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('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,
diff --git a/tests/plugins/destinations/node.test b/tests/plugins/destinations/node.test
index f9d65cd..5e445fc 100644
--- a/tests/plugins/destinations/node.test
+++ b/tests/plugins/destinations/node.test
@@ -33,6 +33,10 @@ class MigrateNodeUnitTest extends DrupalWebTestCase {
$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,
diff --git a/tests/plugins/destinations/user.test b/tests/plugins/destinations/user.test
index 2021814..de0c132 100644
--- a/tests/plugins/destinations/user.test
+++ b/tests/plugins/destinations/user.test
@@ -24,6 +24,20 @@ class MigrateUserUnitTest extends DrupalWebTestCase {
$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'));
+ // Confirm both roles were successfully imported
+ $result = db_select('role', 'r')
+ ->fields('r', array('rid', 'name'))
+ ->condition('name', array('Taster', 'Vintner'), 'IN')
+ ->execute();
+ $roles = array();
+ foreach ($result as $row) {
+ $roles[$row->name] = $row->rid;
+ }
+ $this->assertEqual(count($roles), 2, t('Both roles imported'));
$migration = Migration::getInstance('WineUser');
$result = $migration->processImport();
$this->assertEqual($result, Migration::RESULT_COMPLETED,
@@ -62,6 +76,8 @@ class MigrateUserUnitTest extends DrupalWebTestCase {
$this->assertEqual($users['darren']->status, $rows['darren']->status,
t('Statuses match'));
$this->assertNotNull($users['darren']->roles[2], t('Authenticated role'));
+ $this->assertNotNull($users['darren']->roles[$roles['Taster']], t('Taster role'));
+ $this->assertFalse(isset($users['darren']->roles[$roles['Vintner']]), t('No Vintner role'));
$this->assertEqual($users['darren']->created, strtotime($rows['darren']->posted),
t('Created times match'));
$this->assertEqual($users['darren']->access, strtotime($rows['darren']->last_access),
@@ -85,6 +101,8 @@ class MigrateUserUnitTest extends DrupalWebTestCase {
$this->assert(is_object($users['fonzie']->picture) &&
$users['fonzie']->picture->filename == 'DA-individual.thumbnail.png',
t('Picture migrated'));
+ $this->assertNotNull($users['fonzie']->roles[$roles['Taster']], t('Taster role'));
+ $this->assertNotNull($users['fonzie']->roles[$roles['Vintner']], t('Vintner role'));
// TODO: Theme, timezone, language
diff --git a/tests/plugins/sources/xml.test b/tests/plugins/sources/xml.test
index f5ba918..833936d 100644
--- a/tests/plugins/sources/xml.test
+++ b/tests/plugins/sources/xml.test
@@ -25,6 +25,10 @@ class MigrateXMLUnitTest extends DrupalWebTestCase {
$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,