xandeadx.ru Блог музицирующего веб-девелопера

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

Опубликовано в

Пример класса для Migrate, для переноса тем из vBulletin 3.8.x в Drupal 7.x с сохранением вложений (импорт ответов в темах будет в следующем посте):

class ThreadsMigration extends Migration {
  public function __construct($arguments) {
    parent::__construct($arguments);
    $this->dependencies = array(
      'Structure', // http://xandeadx.ru/blog/drupal/512
      'Users',     // http://xandeadx.ru/blog/drupal/510
    );
 
    // Source
    $query = Database::getConnection('default', 'vbulletin')->select('thread', 't');
    $query->leftJoin('post', 'p', 'p.postid = t.firstpostid');
    $query->fields('t', array('threadid', 'title', 'forumid', 'open', 'visible', 'postuserid', 'dateline', 'sticky', 'firstpostid'));
    $query->fields('p', array('pagetext'));
    $query->condition('open', 10, '!=');
    $this->source = new MigrateSourceSQL($query, drupal_map_assoc(array('attachments', 'attachments_name')), NULL, array('map_joinable' => FALSE));
 
    // Destination
    $this->destination = new MigrateDestinationNode('post');
 
    // Key schema
    $source_key_schema = array('threadid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE));
    $this->map = new MigrateSQLMap($this->machineName, $source_key_schema, MigrateDestinationNode::getKeySchema());
 
    // Mapping
    $this->addFieldMapping('title', 'title');
    $this->addFieldMapping('uid', 'userid')->sourceMigration('Users');
    $this->addFieldMapping('is_new')->defaultValue(TRUE);
    $this->addFieldMapping('created', 'dateline');
    $this->addFieldMapping('status', 'visible');
    $this->addFieldMapping('sticky', 'sticky');
    $this->addFieldMapping('comment', 'open');
    $this->addFieldMapping('body', 'pagetext');
    $this->addFieldMapping('body:format')->defaultValue('filtered_html');
    $this->addFieldMapping('field_section', 'forumid')->sourceMigration('Structure');
    $this->addFieldMapping('field_section:source_type')->defaultValue('tid');
    $this->addFieldMapping('field_section:create_term')->defaultValue(FALSE);
    $this->addFieldMapping('field_attachments', 'attachments');
    $this->addFieldMapping('field_attachments:destination_dir')->defaultValue('public://attachments');
    $this->addFieldMapping('field_attachments:destination_file', 'attachments_name');
    $this->addFieldMapping('field_attachments:file_replace')->defaultValue(FILE_EXISTS_ERROR);
    $this->addFieldMapping('field_attachments:source_dir')->defaultValue('/path/to/vbulletin/attachments/');
  }
 
  public function prepareRow($row) {
    if (parent::prepareRow($row) === FALSE) {
      return FALSE;
    }
 
    // Title
    $row->title = htmlspecialchars_decode($row->title);
 
    // Comment status
    if ($row->open == 1) {
      $row->open = 2;
    }
    else {
      $row->open = 1;
    }
 
    // Body
    $row->pagetext = bbcode_to_html($row->pagetext); // http://bit.ly/OrFVN5
 
    // Attachments
    $attachments = Database::getConnection('default', 'vbulletin')
      ->select('attachment', 'a')
      ->fields('a', array('attachmentid', 'filename', 'extension', 'userid'))
      ->condition('postid', $postid)
      ->execute();
    foreach ($attachments as $attachment) {
      $row->attachments[] = $attachment->userid . '/' . $attachment->attachmentid . '.attach';
      $row->attachments_name[] = $attachment->filename;
    }
  }
}

Перед импортом нужно:

  1. Создать тип материала post, или вписать существующий в MigrateDestinationNode('post').
  2. Добавить материалу поле field_section типа Term reference, или вписать существующее в $this->addFieldMapping('field_section', 'forumid').
  3. Добавить материалу поле field_attachments типа File, или вписать существующее в $this->addFieldMapping('field_attachments', 'attachments').
  4. В строчке ...->defaultValue('/path/to/vbulletin/attachments/'); прописать полный путь к папке с атачами.

В vBulletin есть опция, которая позволяет хранить вложения в папках вида attachments/1/2/3/4, где цифры берутся из идентификатора пользователя. Если опция включена, то вместо

$row->attachments[] = $attachment->userid . '/' . $attachment->attachmentid . '.attach';

пишем:

$row->attachments[] = implode('/', preg_split('//', $attachment->userid,  -1, PREG_SPLIT_NO_EMPTY)) . '/' . $attachment->attachmentid . '.attach';
Написанное актуально для Migrate 7.x-2.4
Похожие записи

Комментарии RSS

О, круто, спасибо :)

Не догнал пока две вещи.

1) Как ограничиться миграцией одной ветки, вместо кучи. Здесь копать?

$query->condition('open', 10, '!=');

2) "Импорт вложений происходит вручную"

Вообще не догнал, не высыпаюсь похоже :D

1. $query->condition('forumid', ...);

2. код по переносу вложений написан руками. если бы атачи в вобле имели нормальные имена, можно было бы возложить эту работу на migrate

Наверное, тут ошибка
->condition('postid', $postid)
->execute()
->fetchAll(); // не хватает

Оставить комментарий

Содержимое этого поля является приватным и не будет отображаться публично. Если у вас есть аккаунт в Gravatar, привязанный к этому e-mail адресу, то он будет использован для отображения аватара.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступные HTML теги: <a> <i> <b> <strong> <code> <ul> <ol> <li> <blockquote> <em> <s>
  • Строки и параграфы переносятся автоматически.
  • Подсветка кода осуществляется с помощью тегов: <code>, <css>, <html>, <ini>, <javascript>, <sql>, <php>. Поддерживаемые стили выделения кода: <foo>, [foo].

Подробнее о форматировании