WordPress Migration Notes

Migrating from Movable Type proves to be pretty much straight forward, as WordPress has already had a well written and documented Movable Type importer, that imports everything including all post entries, comments and trackbacks. However, getting the old permalink to forward to my new WordPress powered link might not be that trivial. One issue is the entry ID mapping. Movable Type does not include entry ID in the exported document, thus there is no way for WordPress to match the same ID upon importing. A quick hack to Movable Type's export and WordPress' import function is required to achieve this.

  1. Open [MT Installation]/lib/MT/App/CMS.pm, go to line 2970, and make the following change. This assumes Movable Type 2.661, and line number might be different if a different MT version is installed.

     CATEGORY: <$MTCategoryLabel$>
     </MTEntryCategories>
     DATE: <$MTEntryDate format="%m/%d/%Y %I:%M:%S %p"$>
    +POSTID: <$MTEntryID$>
     -----
     BODY:
     <$MTEntryBody convert_breaks="0"$>
    

    It adds entry ID into Movable Type export.

  2. Use Movable Type's user interface to export all entries, comments and trackbacks into a plain text file.

  3. Open [WP Installation]/wp-admin/import-mt.php, change line 2 to point MTEXPORT to the file exported in step 2, and make the following change in the same file. At around line 268,

                    $post_date = date('Y-m-d H:i:s', $post_date);
                    $post_date_gmt = get_gmt_from_date("$post_date");
                    break;
    +               case 'POSTID':
    +                   $post_id = $value;
    +                   break;
                default:
     //                 echo "n$key: $value";
                    break;
    

    At around line 280,

        } else {
            $post_author = checkauthor($post_author);//just so that if a post already exists, new users are not created by checkauthor
            $wpdb->query("INSERT INTO $tableposts (
    -               post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,  post_status, comment_status, ping_status, post_name, post_modified, post_modified_gmt)
    +               id, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,  post_status, comment_status, ping_status, post_name, post_modified, post_modified_gmt)
                VALUES
    -               ('$post_author', '$post_date', '$post_date_gmt', '$post_content', '$post_title', '$excerpt', '$post_status', '$comment_status', '$ping_status', '$post_name','$post_date', '$post_date_gmt')");
    +               ('$post_id', '$post_author', '$post_date', '$post_date_gmt', '$post_content', '$post_title', '$excerpt', '$post_status', '$comment_status', '$ping_status', '$post_name','$post_date', '$post_date_gmt')");
    -           $post_id = $wpdb->get_var("SELECT ID FROM $tableposts WHERE post_title = '$post_title' AND post_date = '$post_date'");
            if (0 != count($post_categories)) {
                foreach ($post_categories as $post_category) {
                // See if the category exists yet
    

    It makes WordPress' MT import script to use the entry ID provided in the exported file.

  4. Run the MT import script as usual, i.e. follow the instruction at http://[Your blogsite]/wp-admin/import-mt.php. It should then import all the Movable Type entries mapped to the right entry ID.

  5. Remember to disable the import script after it has been completed!

It is then possible to set up mod_rewrite in .htaccess to get WordPress to use the old URL format. For example, if in Movable Type the individual archive uses the /archives/[entry ID].php format, you can use the following rewrite rule:

RewriteEngine On
RewriteBase /
RewriteRule ^archives/^([0-9]{6}).php$ index.php?p=$1 [QSA]

However, if you are using a different permalink scheme under WordPress, then you need to make it to work differently. For example, this blog uses

/%year%/%monthnum%/%postname%/

as permalinks template. The easiest way I found is to actually do a redirection from the old URL to the new. Here is the re-write rule for my .htaccess:

RewriteEngine On
RewriteBase /
RewriteRule ^archives/^([0-9]{6}).php$ wp-redirect.php?p=$1 [QSA]

It has other rules required by the permalinks template, but I am only showing the extra one I got that handles my old permalinks. And inside wp-redirect.php, I have:

<?php
require('wp-blog-header.php');
if ($single) {
    foreach ($posts as $post) {
        start_wp();
        header("HTTP/1.1 301 Moved permanently");
        header('Location: '.get_permalink());
        exit;
    }
}
header("HTTP/1.1 404 Not Found");
?>

If a single post is loaded, the script will respond with a 301 permanent redirect to the new permalink. A 301 helps the search engine bots to understand that the new URL will be replacing the old.

So far it has been working quite well, and I have not lost anyone landing on my old links.


Update: For WordPress 1.5+, here is the preferred method. Instead of using a wp-redirect.php script,

  1. Install and activate the Permalink Redirect plugin.
  2. Use the following Apache mod_rewrite rule instead:
    RewriteEngine On
    RewriteBase /
    RewriteRule ^archives/^([0-9]{6}).php$ /?p=$1 [QSA]