To migrate user accounts into Drupal, use the MigrateDestinationUser class:

// See below for an example of options argument
$options = array();

$this->destination = new MigrateDestinationUser($options);
$this->addFieldMapping('name', 'source_username');
$this->addFieldMapping('roles')
     ->defaultValue(DRUPAL_AUTHENTICATED_RID);
...

Fields

uid - The Drupal user ID. Usually this will be unmapped - the uid will be automatically assigned when the user record is created, and the map table will record the source key that generated this ID. You will need to map the uid when the system-of-record is DESTINATION (i.e., the purpose of your migration is updating existing users rather than importing new users). Also, if you want to maintain the same user ID as you had in the source system, you would map that ID to the uid as well as setting the is_new field to TRUE.

name - The Drupal username. Drupal requires usernames to be unique, which can be challenging when importing from a system which did not have the same constraint - this scenario is the most frequent reason to use the dedupe feature.

mail - The email address associated with the user account.

pass - The Drupal password. By default, the value mapped to this field is treated as a plaintext password, and will be encrypted when saved in the user account record. On Drupal 7, if the value you're mapping here is an MD5 password (as when migrating from an earlier version of Drupal), set the md5_password option to indicate that.

status - The status of the user account - 1 for active or 0 for blocked.

created - The date and time when the account was created. If no value is mapped from the source data, this will default to the time the account is imported by Migrate. Note that while this is ultimately stored as a UNIX timestamp, any absolute date/time string supported by strtotime() can be mapped to this (or generally any other timestamp field).

access - The date and time when the account was last accessed. See also created.

login - The date and time when the account was last logged in. See also created.

roles - The Drupal IDs (rids) of any roles to be assigned to the user account. Usually you have a single value such as DRUPAL_AUTHENTICATED_RID hard-coded via defaultValue(), but it can also be dynamically set. Usually you will map one of roles or role_names, not both.

role_names - The names of any roles to be assigned to the user account. Usually you have a single value such as 'authenticated user' hard-coded via defaultValue(), but it can also be dynamically set.

picture - The Drupal file ID of a picture associated with the user account. Note that because this is not a proper "field", just an integer column in the users table, the file field handler will not work (i.e., you can't map the file directly as you can with true fields). Thus, you will generally need to implement a separate MigrateDestinationFile migration to pull in the pictures and create file entities for them, then use sourceMigration() on your picture mapping to tie them to the user account.

signature - The content of the user's default signature.

signature_format - The text format (e.g., "Filtered HTML") to be used for the user signature.

timezone - The user's default timezone, e.g. "America/New_York".

language - The user's default language, e.g. "en".

theme - The name of the default theme for the user.

init - The initial email address for the Drupal account.

data - Storage for miscellaneous user data.

is_new (Drupal 7 only) - An option that, if set to TRUE, will create a new user account using the value mapped to uid as its ID, rather than generated a new sequential ID. Because the Migrate module maintains the mappings of source to destination IDs, and supports automatically substituting them with sourceMigration to maintain relationships, this is rarely necessary (even if you might think you need it at first glance).

Options

The following options may be provided to the MigrationDestinationUser in the constructor, for example:

    $this->destination = new MigrateDestinationUser(array('md5_passwords' => 1, 'language' => 'en', 'text_format' => 'filtered_html'));

Language

The language option will be applied as the default language for any user fields which are language-dependent. If unspecified, it will default to LANGUAGE_NONE.

Text format

The text format (e.g., 'filtered_html') will be applied as the default text format for any user fields which take a format. If unspecified, the default for the field will be applied.


MD5 passwords

{This section has errors. See https://www.drupal.org/node/1349758 , Unsalted MD5 passwords, To Drupal 7 for correct info.}
Drupal versions before 7.0 stored passwords as unsalted MD5 hashes. Drupal 7 by default uses sha512, and to support upgrades from Drupal 6 accepts an MD5 password with 'U' prepended on login. By setting the md5_passwords option to TRUE on MigrateDestinationUser, and mapping an md5 password field to 'pass', Migrate will automatically store the md5 password with the 'U' prepended so users will be able to login with the same password they previously used. Use this option when migrating to Drupal 7 from an earlier Drupal version, or from another system using unsalted MD5 passwords.

Comments

joetsuihk’s picture

My two bits on user pictures(Migrate 2.5, D7):

  1. Use a separate UserPictureMigration class (you see new IDs from file_managed table)
  2. In UserMigration, prepare(), use $this->handleSourceMigration('UserPicture', $row->uid); to assign fid
  3. Under normal user picture upload, a new entry on file_usage is created. You may want to insert a row too, during complete() and completeRollback()

Spend me two full day on this. Very confusing:
$this->addFieldMapping('picture')->defaultValue() need an int
but in
public function prepareRow() it shows file path(no effect even file path is correct)
and in
public function prepare() it needs fid

Jeff Turman’s picture

I had a problem using MigrateDestinationUser() with a previous file migration as suggested for the picture field. I'm not sure where the bug is, but I know it's in the MigrateDestinationUser() class somewhere. I just don't have time to break into the code right now.

While migrating users from a custom database, I created two migration classes: UserMigration and UserPhotoMigration. UserPhotoMigration runs fine, pulling all the user photos into the public://migrate-files directory. There are files named like so: 'floyd.jpg' and '123.jpg'. However, when associating the files to the 'picture' field in UserMigration, *only* files named with numbers were associated. Files that had regular letter characters in the name failed silently. Here's the typical code for that part of the migration:

<?php

       $this->addFieldMapping('picture', 'imageFile')
           ->sourceMigration('UserPhoto');

?>

I got tired of not being able to circumvent this problem with any built-in methods. So I replaced it with something like this:

<?php

    $this->addFieldMapping('picture', 'userPicFID')
         ->description(t('See prepareRow()'));

    public function prepareRow($row) {
        if (parent::prepareRow($row) === FALSE) {
            return FALSE;
        }
        // Separate query for image FID
        $source_id = $row->imageFile;
        $result = Database::getConnection('default', 'default')
            ->select('file_managed', 'fm')
            ->fields('fm', array('filename', 'fid'))
            ->condition('filename', $source_id)
            ->execute()
            ->fetchObject();
        if ($result) {
            $row->userPicFID = $result->fid;
        }
   }

?>

This could probably be abstracted more to make it efficient and use errors, also. The error handling was non-existent.

Hope this helps someone.

swelljoe’s picture

For the is_new field, following the documentation and entering "TRUE" has no effect. It has to be "1", and then after saving that change, it will make it possible to adding a mapping for the UID or NID. This is true of any of the migrations that support the is_new option.