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

11.01.2012

Пример класса для 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
Похожие записи

Комментарии

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

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

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

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

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

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

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

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

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

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