Drupal → Пример миграции контента из vBulletin 3 в Drupal 7: пользователи

09.01.2012

Пример класса для Migrate, для переноса пользователей из vBulletin 3.8.x в Drupal 7.x

class UsersMigration extends Migration {
  // vbulletin_group => drupal_role
  private $rolesMap = array(
    6 => 4,
    7 => 5,
    8 => 6,
  );

  public function __construct($arguments) {
    parent::__construct($arguments);
    
    // Source
    $query = Database::getConnection('default', 'vbulletin')->select('user', 'u');
    $query->leftJoin('avatar', 'a', 'a.avatarid = u.avatarid');
    $query->leftJoin('customavatar', 'c', 'c.userid = u.userid');
    $query->fields('u', array('userid', 'username', 'password', 'email', 'usertitle', 'joindate', 'lastvisit', 'lastactivity', 'avatarrevision', 'usergroupid'));
    $query->fields('a', array('avatarpath'));
    $query->fields('c', array('filename'));
    $query->condition('u.userid', 1, '!=');
    $query->orderBy('u.userid');
    $this->source = new MigrateSourceSQL($query, drupal_map_assoc(array('picture')), NULL, array('map_joinable' => FALSE));
    
    // Destination
    $this->destination = new MigrateDestinationUser();
    
    // Key schema
    $source_key_schema = array('userid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE));
    $this->map = new MigrateSQLMap($this->machineName, $source_key_schema, MigrateDestinationUser::getKeySchema());
    
    // Mapping
    $this->addFieldMapping('uid', 'userid');
    $this->addFieldMapping('is_new')->defaultValue(TRUE);
    $this->addFieldMapping('name', 'username')->dedupe('users', 'name');
    $this->addFieldMapping('pass', 'password');
    $this->addFieldMapping('mail', 'email');
    $this->addFieldMapping('signature', 'usertitle');
    $this->addFieldMapping('signature_format')->defaultValue('filtered_html');
    $this->addFieldMapping('created', 'joindate');
    $this->addFieldMapping('access', 'lastactivity');
    $this->addFieldMapping('login', 'lastvisit');
    $this->addFieldMapping('status')->defaultValue(1);
    $this->addFieldMapping('init', 'email');
    $this->addFieldMapping('picture', 'picture');
  }
  
  public function prepareRow($row) {
    if (parent::prepareRow($row) === FALSE) {
      return FALSE;
    }

    // Role
    if ($row->usergroupid && isset($this->rolesMap[$row->usergroupid])) {
      $row->usergroupid = $this->rolesMap[$row->usergroupid];
    }

    // Picture
    if ($row->avatarpath || $row->filename) {
      if ($row->avatarpath) {
        $picture_path = $row->avatarpath;
      }
      else {
        $picture_path = 'customavatars/avatar' . $row->userid . '_' . $row->avatarrevision . '.gif';
      }
      $picture_path = '/path/to/vbulletin/' . $picture_path;
      $picture = (object)array(
        'uri' => $picture_path,
        'filename' => basename($picture_path),
        'filemime' => file_get_mimetype($picture_path),
        'status' => FILE_STATUS_PERMANENT,
      );
      $picture = file_copy($picture, 'public://pictures', FILE_EXISTS_REPLACE);
      if ($picture) {
        $row->picture = $picture->fid;
      }
    }
  }
}

Аватар пользователя не является полем, поэтому приходится вручную копировать файлы (на d.org кстати предлагают писать для аватаров отдельный класс).

Пароли, естественно, переносу не поддаются.

Написанное актуально для
Migrate 7.x-2.8
Похожие записи

Комментарии

Это будет "одноразовая" миграция? Если прогнать ее еще раз, юзеры перезапишутся заново, или будет апдейт - старые останутся, новые добавятся? Спасибо :)

Если оставить код как есть, то при второй и последующих миграциях добавятся только отсутствующие, существующие не обновятся. Если убрать $this->addFieldMapping('is_new')->defaultValue(TRUE);, то по идее существующие должны изменится.

О, вот это отличная информация :) Как раз в планах перевести сайт на D7, затем слить туда форумы на старой вобле. А можно пример/статью, как перенести определенную ветку комментариев с воблы в D7 через Migrate? Готов спонсировать в разумных пределах :) Спасибо.

хотя немного соврал. система такая:

Делается импорт. Уже сделанный импорт можно откатить (т.е. удалит все импортированные данные) и сделать импорт по новой. Дальше можно только добавлять отсутствующие записи, обновлять существующие нельзя (точнее можно, почистив таблицу migrate_map_migratename и удалив поле is_new, но это кастыль). Про обновление без отката тут — http://drupal.org/node/1117454

А почему был выбран Migrate? Есть у него какие-нибудь принципиальные приемущества перед feeds?

Добрый вечер! Я начал с простого - решил перенести названия материалов определенного типа с одной БД (drupal 7) в другую БД (drupal 7). В итоге создал класс:
код
только в этом коде вкралась ошибка, которую я не могу найти. Этот код не создает в новой Базе данных материалов типа 'article' но при этом не выдает ошибок! Но если в строке ->fields('ns', array('nid', 'title', 'created', 'changed')) убрать 'nid', тогда ноды создаются, но выдается ошибка о том, что migrate не может сохранить данные в служебную таблицу map (в моём случае migrate_map_bankinode) из-за того, что значение 'nid' = null (это и понятно т.к. 'nid' убрал) и, соответственно, "откат" произведенной миграции становится невозможным. Есть идеи?

Mneznakomec
01.11.2013, 08:05

Юрий, чтобы задавать nid для ноды, нужто обязательно заполнить поле ноды is_new таким образом:

$this->addFieldMapping('is_new')->defaultValue(TRUE);

Это даст понять модулю, что вы хотите задавать свои nid. Это описано в документации.
Работает только в 7-ке.

Добавить комментарий