With roles, users and forum structure in place, we can now look at migrating threads from the vBulletin database threads table with something like the following in the vbulletin_forum.inc file
class vBulletinThreadMigration extends Migration {
public function __construct() {
parent::__construct();
$this->description = t('Migrate vBulletin forum threads');
// Set the source table's primary key
$this->map = new MigrateSQLMap(
$this->machineName,
array(
'threadid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'vBulletin forum threads',
'alias' => 't',
),
),
MigrateDestinationNode::getKeySchema(),
'for_forum_migration'
);
// Set the query to get the source object
$query = Database::getConnection('default', 'for_forum_migration')
->select('thread', 't')
->fields('t', array(
'threadid',
'title',
'firstpostid',
'lastpost',
'forumid',
'pollid',
'open',
'replycount',
'hiddencount',
'postusername',
'postuserid',
'lastposter',
'dateline',
'views',
'iconid',
'notes',
'visible',
'sticky',
'votenum',
'votetotal',
'attach',
'similar',
'deletedcount',
'lastpostid',
'description',
'prefixid',
'taglist',
'vbseo_linkbacks_no',
));
// vBulletin thread doesn't include the first post text, so get it by joining with the post table, matching firstpostid and postid
$query->join('post', 'p', "t.firstpostid = p.postid");
$query->addField('p', 'pagetext');
$this->source = new MigrateSourceSQL($query, array(), NULL, array('map_joinable' => FALSE));
// Define the destination as the D7 forum node
$this->destination = new MigrateDestinationNode('forum', array('text_format' => 'bbcode'));
// Map fields from vBulletin threads to D7 forum nodes
$this->addFieldMapping('uid', 'postuserid')
->sourceMigration('vBulletinUser');
$this->addFieldMapping('created', 'dateline');
$this->addFieldMapping('changed', 'lastpost');
$this->addFieldMapping('status', 'visible');
$this->addFieldMapping('promote')
->defaultValue(0);
$this->addFieldMapping('sticky', 'sticky');
$this->addFieldMapping('title', 'title');
$this->addFieldMapping('field_tags', 'taglist')
->separator(',');
$this->addFieldMapping('comment', 'open');
// vBulletin thread forumid needs to map to tid in the D7 forum table
$this->addFieldMapping('taxonomy_forums', 'forumid')
->sourceMigration('vBulletinForum');
$this->addFieldMapping('body', 'pagetext');
$this->addFieldMapping('pathauto')
->defaultValue(0);
$this->addFieldMapping('field_forum_icon', 'iconid');
// Flag up any issues to address
$this->addFieldMapping(NULL, 'deletedcount')
->description('Find out what deletedcount is for')
->issueGroup(t('Owner Issues'))
->issuePriority(MigrateFieldMapping::ISSUE_PRIORITY_MEDIUM)
->issueNumber(0012);
$this->addFieldMapping(NULL, 'votenum')
->description('Decide to drop or implement thread votes')
->issueGroup(t('Owner Issues'))
->issuePriority(MigrateFieldMapping::ISSUE_PRIORITY_MEDIUM)
->issueNumber(0012);
$this->addFieldMapping(NULL, 'votetotal')
->description('How does D7 calculate total and average votes')
->issueGroup(t('Owner Issues'))
->issuePriority(MigrateFieldMapping::ISSUE_PRIORITY_MEDIUM)
->issueNumber(0012);
// Unmapped source fields
$this->addFieldMapping(NULL, 'pollid') ->description(t('Used only once in vBulletin and not needed in D7'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'postusername') ->description(t('Username generated by postuserid and sourceMigration from vBulletinUser'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'lastposter') ->description(t('Used in vBulletin, but no need to migrate as D7 identifies last poster from post date'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'views') ->description(t('Used in vBulletin, but not obvious and probably not needed in D7'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'notes') ->description(t('Never used in vBulletin and not needed in D7'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'attach') ->description(t('Not used in vBulletin and not needed in D7'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'similar') ->description(t('Use D7 or a contrib to find similar content if this featured is needed'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'lastpostid') ->description(t('D7 creates this automatically from post created dates'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'description') ->description(t('Barely used in vBulletin and not needed in D7'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'prefixid') ->description(t('Not used in vBulletin and not needed in D7'))
->issueGroup(t('DNM'));
$this->addFieldMapping(NULL, 'vbseo_linkbacks_no') ->description(t('Always 0 in vBulletin and not needed in D7'))
->issueGroup(t('DNM'));
// Unmapped destination fields
$this->addFieldMapping('revision') ->description(t('vBulletin does not use node revisions so nothing to import'))
->issueGroup(t('DNM'));
$this->addFieldMapping('log') ->description(t('vBulletin did not use a thread log so nothing to import'))
->issueGroup(t('DNM'));
$this->addFieldMapping('language') ->description(t('English language only set at site level'))
->issueGroup(t('DNM'));
$this->addFieldMapping('tnid') ->description(t('No translation so tnid not required'))
->issueGroup(t('DNM'));
}
public function prepare($node, stdClass $row) {
if ($row->open == '1') {
$node->comment = '2';
}
}
}
When you start a thread in vBulletin, the text content of the thread is stored in the vBulletin database 'post' table in a 'pagetext' field, and linked back the thread with a 'firstpostid' reference. However, in D7 the first post is stored as 'body' text in the thread node. As a result, we need to join the vBulletin 'thread' source table with the 'post' table, matching the 'firstpostid' and 'postid' fields respectively, using...
$query->join('post', 'p', "t.firstpostid = p.postid");
$query->addField('p', 'pagetext');
The addFieldMApping then sources the pagetext field data so we can map it to the relevant D7 forum thread node's body field using...
$this->addFieldMapping('body', 'pagetext');