Migrating to WordPress from Movable Type

I wrote this about a year ago as a sort of log of my trials migrating from movable type blogging to wordpress. It’s somewhat tongue in cheek / stream of consciousness so take it for what it’s worth, a little insight into the mind of a developer 😉

Moving from movable type (old ass version) to brand spanking new wordpress.

who wants to deal with cgi-bins, I mean really

movable type has an export feature, yay. Seems like it’s supported with some old version of wordpress. Let’s see, ok, generates proprietary format but it makes sense, does an export, looks like this:

AUTHOR: ChefQuix
TITLE: A little bit of everything…
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
ALLOW PINGS: 1
PRIMARY CATEGORY: Armageddon
CATEGORY: Armageddon

DATE: 09/14/2003 10:52:19 PM
—–
BODY:
I’ve always wanted to write a blog,

Alright, so quickly install wordpress.

Let’s play around, old ass instructions say modify some file called import-mt.php.

http://codex.wordpress.org/Importing_from_Movable_Type_to_WordPress

Uhoh, this does not exist in the new wordpress. Not suprising, who’s really dealing with legacy shit like this anymore?

Ok, let’s see what new WP can do. Look, import from movable type is built into the tools, yay, wait what’s this, send out FTP credentials to some 3rd party site so they can FTP stuff in? Or WP can FTP stuff in? Is this really the best and most secure way to import files? Yikes.

Grab files manually, install plugin, match up old username with new username, yes, look at that, lots of imports, everything is working great! Closer inspection though..

Cut off blog entries! The old poor quote handling, poor quote exporting situation. And the IDs, not the same, how can I make an .htaccess rule to map from old to new? Not good enough!

Truncate wp_posts, wp_comments tables, lets do this again.

First things first – change old Movable Type export to include the ID.

in <mt>/lib/MT/ImportExport.pm add line in the export function:

POSTID: <$MTEntryID$>

Totally guessed at the template tag and it worked

now import.txt file as ID, will plugin work out of the box? probably not, but lets take a look

ok, import doesn’t support ID out of the box. Fair enough, it’s hard after all.

Add new case for the importer (in process_posts function):

} else if ( ‘POSTID:’ == $line ) {
$post->ID = trim( substr($line, strlen(‘POSTID:’)) );

Modify save_post function – post is saved using wp_insert_post function. Let’s take a look at what this function does and see how we can manually set the ID.

https://codex.wordpress.org/Function_Reference/wp_insert_post

Uhoh:

IMPORTANT: Setting a value for $post[‘ID’] WILL NOT create a post with that ID number. Setting this value will cause the function to update the post with that ID number with the other values specified in $post. In short, to insert a new post, $post[‘ID’] must be blank or not set at all.

Always roadblocks, so how do we work around this.

Lets take a stab in the dark, we’ll manually insert an empty table row with just the ID, then put the ID in the post variable and hope that wp_insert_post updates everything properly. Probably have to set post_date and post_date_gmt, I’m sure this is going to break a bit but oh well.

global $wpdb;

if (!empty($post->ID)) {
$wpdb->insert($wpdb->prefix . ‘posts’,array(‘ID’ => $post->ID),array(‘%d’));
}

scratch that, does wp_insert_post allow us to try to import the ID with the optional import_id parameter? Let’s try that less hacky way first
change modification back to:

} else if ( ‘POSTID:’ == $line ) {
$post->import_id = trim( substr($line, strlen(‘POSTID:’)) );

before we start the import up again, let’s try to clean up the file and fix some of these character encoding issues. Same old problem we always end up having – ‘,”,-,… – these characters always break. What’s the easiest solution? Load up the file in a trusty editor, find an offending character and search and replace. Get rid of the bad characters this way, then save it and do the import.

Ok, so the import runs again, but the IDs, they’re not matching up? What’s going on, time to dig deeper…

Add some debug code..

if (!empty($post->import_id)) {
printf(__(‘converting import_id %s’, ‘movabletype-importer’),$post->import_id);
$post->import_id = intval($post->import_id);
} else {
printf(__(‘wtf missing import_id’, ‘movabletype-importer’));
}

WTF? Importing post Are you also divergent, friend?…wtf missing import_id (2 comments)

Ok so that’s a problem it seems.

Ugh, bad code! Copy pasta from the wrong type of tag, of course it didn’t work. One more try, remove old POSTID bit and put in this:

} else if ( 0 === strpos($line, ‘POSTID:’) ) {
$post->import_id = trim( substr($line, strlen(‘POSTID:’)) );

Duhhhh think before writing code kiddos. Truncate wp_posts, wp_comments, and run one last time, this should fix everything for everyone in all instances…
And it works! Now that the IDs are normalized, I can htaccess example in old link from moving from MT to wordpress to make sure all pages get redirected to the new proper pages. Hoorray!

To make the redirects from the old URLs to the new ones, you just need to do a mysql query and copy and paste it into the WordPress .htaccess file:

mysql -u root -p -N -B -e “select concat(‘Redirect 301 /archives/000′, LPAD(ID,3,’0’), ‘.html /’, DATE_FORMAT(post_date, ‘%Y/%m/%d’), ‘/’, post_name, ‘/’) FROM perceptionalism_2.wp_posts”

(changing of course the user, database and what not for yourself).

This produces an output of:

Redirect 301 /archives/000005.html /2003/09/20/is-there-anybody-else-out-there-thinking/
Redirect 301 /archives/000007.html /2003/09/21/inspiration/
Redirect 301 /archives/000008.html /2003/09/29/wonder/
Redirect 301 /archives/000009.html /2003/09/23/are-you-a-bright/

….

And you’re done!