From Drupal to Movable Type

Published on:

I've just done a migration of a blog from Drupal to Movable Type. The process is pretty much undocumented out there, except for this helpful tutorial from Andrew Sterling Hanenkamp, which unfortunately will not work if you're using Drupal 6. Hence this little how-to, which works with Drupal 6, but that you'll have to adapt to your own Drupal installation.

Contrarily to Andrew's advice, I don't recommend running such a script from Drupal in preview mode: it's slower and more memory hungry than running it alone, plus you'll get an awful mix between the text you want to extract and the Drupal interface surrounding it but not interpreted as HTML (because of the "text/plain" header). Place it in a PHP file at the root of your site and simply run it from your browser (or the CLI).

Here's the beast:

# Comment the following two lines if you want to run this script from within Drupal
include_once './includes/';
header('Content-type: text/plain');
# Adapt the WHERE clause of this query to your own content and needs
$nids = db_query("select distinct n.nid from {node} n WHERE n.type = 'article'");
while ($node = node_load(db_fetch_object($nids)->nid, NULL, TRUE)) {
  print "AUTHOR: ".$node->name."\n";
  print "TITLE: ".$node->title."\n";
  print "STATUS: ".($node->status?"Publish":"Draft")."\n";
  print "ALLOW COMMENTS: ".($node->comment>0)."\n";
  print "CONVERT BREAKS: richtext\n";
  print "ALLOW PINGS: ".($node->comment>0)."\n";
  print "DATE: ".strftime("%m/%d/%Y %I:%M:%S %p", $node->created)."\n";
  foreach ($node->taxonomy as $vid => $term) {
    print "CATEGORY: ".$term->name."\n";
  $tag = array();
  foreach ($node->category as $category) {
    $tag[] = $category->title;
  print "TAGS: ".implode(",", $tag)."\n";
  print "-----\n";
  print "BODY:\n";
  print $node->body."\n";
# uncomment the following block if you want to search by node number/URL
  print "-----\n";
  print "KEYWORDS:\n";
  print "/node/".$node->nid.",".url('node/'.$node->nid)."\n";
  $comments = db_query("select * from {comments} c where c.nid = %d", $node->nid);
  while ($comment = db_fetch_object($comments)) {
    print "-----\n";
    print "COMMENT:\n";
    print "AUTHOR: ".$comment->name."\n";
    print "EMAIL: ".$comment->mail."\n";
    print "IP: ".$comment->hostname."\n";
    print "URL: ".$comment->homepage."\n";
    print "DATE: ".strftime("%m/%d/%Y %I:%M:%S %p", $comment->timestamp)."\n";
# Uncomment the following line if you want to keep comments titles
#    print "SUBJECT: ".$comment->subject."\n";
    print $comment->comment."\n";
  print "--------\n";

You'll have to:
  • adapt the WHERE clause of the first query to select the nodes you really want to extract
  • possibly add "EXCERPT :" and "EXTENDED BODY: " if you make use of excerpts and teasers
  • uncomment the "SUBJECT: " line if you really want to keep the comments titles. I commented it by default, as I find this ugly and useless in MT (strangely MT supports this metadata in the import format, but there's no such thing as a comment title in MT, so the title is prepended to the comment text with a big SUBJECT in front of it, something you certainly don't want if your blog isn't in English)
  • comment out the first two lines if you really want to run this from within Drupal

You may have to modify the AUTHOR output if you need to map existing authors in MT. MT expects the user name here, not the display name. If the authors do not exist, MT will create them on the fly during the import. Likewise, categories and tags will be created on the fly at import time if they don't exist already.

Finally, you can make use of the nice little trick Andrew's using with the keywords metadata so that your old URLs with node numbers can be mapped to the new ones on MT. If you want to do this, uncomment the relevant block in the code above, and place this in a .htaccess file at the root of your new site:

RewriteEngine on
RewriteRule ^(node/\d+)       /mt/mt-search.cgi?search=$1 [R,L]
RewriteRule ^(\d+/\d+/\d+/.*) /mt/mt-search.cgi?search=$1 [R,L]

However, if you are moving to a completely new domain, I would rather advise you to create a proper rewritemap from the old to the new URLs. This interesting exercise is out of scope of this little tutorial, so I'll leave it to you ;-).