diff --git a/plugins/FeedsUserProcessor.inc b/plugins/FeedsUserProcessor.inc index 912fbfa..94e70e2 100644 --- a/plugins/FeedsUserProcessor.inc +++ b/plugins/FeedsUserProcessor.inc @@ -105,6 +105,21 @@ class FeedsUserProcessor extends FeedsProcessor { if (empty($account->name) || empty($account->mail) || !valid_email_address($account->mail)) { throw new FeedsValidationException(t('User name missing or email not valid.')); } + + // Check when an user ID gets set or changed during processing if that user + // ID is not already in use. + if (!empty($account->uid)) { + $is_new = !empty($account->feeds_item->is_new); + $different = !empty($account->feeds_item->entity_id) && $account->feeds_item->entity_id != $account->uid; + if ($is_new || $different) { + $exists = entity_load_unchanged('user', $account->uid); + if ($exists) { + throw new FeedsValidationException(t('Could not update user ID to @uid since that ID is already in use.', array( + '@uid' => $account->uid, + ))); + } + } + } } /** @@ -122,6 +137,17 @@ class FeedsUserProcessor extends FeedsProcessor { unset($edit['pass']); } + // Check if the user ID changed when updating users. + if (!empty($account->feeds_item->entity_id) && $account->feeds_item->entity_id != $account->uid) { + // The user ID of the existing user is different. Try to update the user ID. + db_update('users') + ->fields(array( + 'uid' => $account->uid, + )) + ->condition('uid', $account->feeds_item->entity_id) + ->execute(); + } + user_save($account, $edit); // If an encrypted password was given, directly set this in the database. diff --git a/tests/feeds_processor_user.test b/tests/feeds_processor_user.test index 7b31af7..f4a6e42 100644 --- a/tests/feeds_processor_user.test +++ b/tests/feeds_processor_user.test @@ -205,6 +205,61 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase { } /** + * Tests if user ID's can be changed using the user ID target. + * + * Also checks if a clear error is reported when trying to change the + * user ID to something that is already in use. + */ + public function testUidUpdating() { + // Set to update existing users. + $this->setSettings('user_import', 'FeedsUserProcessor', array('update_existing' => FEEDS_UPDATE_EXISTING)); + + // Add mapping to user ID, but do not mark target as unique. + $this->addMappings('user_import', array( + 4 => array( + 'source' => 'uid', + 'target' => 'uid', + ), + )); + + // Create an account which user ID should be updated. + user_save(drupal_anonymous_user(), array( + 'uid' => 54, + 'name' => 'Morticia', + 'mail' => 'morticia@example.com', + 'pass' => 'mort', + 'status' => 1, + )); + + // Create account with uid 202. Importing an other account with uid 202 + // should fail. + user_save(drupal_anonymous_user(), array( + 'uid' => 202, + 'name' => 'Joe', + 'mail' => 'joe@example.com', + 'pass' => 'joe', + 'status' => 1, + )); + + // Import CSV file. + $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users.csv'); + $this->assertText('Created 1 user'); + $this->assertText('Updated 1 user'); + $this->assertText('Failed importing 3 users.'); + $this->assertText('Could not update user ID to 202 since that ID is already in use.'); + + // Assert Morticia's user ID got updated. + $account = user_load_by_name('Morticia'); + $this->assertEqual(201, $account->uid, 'Morticia now got user ID 201.'); + // Assert that Fester failed to import. + $this->assertFalse(user_load_by_name('Fester'), 'The account for Fester was not imported.'); + // Assert that user 202 did not change. + $account = user_load(202); + $this->assertEqual('Joe', $account->name, 'The user name of account 202 is still Joe.'); + $this->assertEqual('joe@example.com', $account->mail, 'The mail address of account 202 is still joe@example.com.'); + } + + /** * Tests mapping to role without automatically creating new roles. */ public function testRoleTargetWithoutRoleCreation() {