Recently, other technical volunteers were pushing for Wordpress at an organization I do volunteer work for. This article is not Drupal vs. Wordpress. I found an enlightening Smashing Magazine article during our discussions which addresses that topic. At the end of the day, the simple fact that a vast majority of the volunteers were pushing for Wordpress was enough to justify the switch. It allowed others to take on more responsibilies. Ask any strapped volunteer, more help is worth it.
However, I was tasked with a lot of the finer points of migrating article content smoothly and switching our CiviCRM database over. I'll catalog my process in the hopes that it may help others in a similar situation.
I was a bit bummed there wasn't a slick Wordpress plugin to do it for me. However, Wordpress has some valuable resources and kudos to those willing to share their code. I had to operate on the cheap; so unfortunately I couldn't use the first cms2cms suggestion. Luckily, the software versions I was working with matched the second suggestion perfectly. It's a small Java class that does a basic migration of Drupal categories, posts, and comments. Luckily, I only had 10-20 Drupal users to migrate by hand and no custom content types.
The program assumes that Wordpress and Drupal are installed on the same database and its first step is to wipe the Wordpress content. So I fired up a local MySQL database and Apache server to install a fresh copy of Wordpress 3.5.1. I exported the Drupal database/filesystem from our web host brought it up on my local server as well. I then imported the Drupal database tables into the same local MySQL database as Wordpress. I ended up needing to do a minor tweak to the Java source:
Tweak that to match your Wordpress prefix. Mine was:
Similarly, you'll need to make another tweak to the connection string:
return DriverManager.getConnection("jdbc:mysql://localhost/database?" + "user=username&password=passwordtext");
With that, I ran the Java file in Eclipse and watched it migrate my content. I excitedly browsed to my local Wordpress site and much to surprise it worked fairly well right off the bat! However, there were two other edits I ended up making based on my own preferences.
Out-of-the-box, the Java program migrates both Drupal stories and pages as Wordpress pages:
//Pages and stories are created as pages if (type.equals("page") || type.equals("story")) strType="page"; else strType="post"; //forum posts and normal posts are both stored as posts
I feel that a Drupal story parallels a Wordpress post. So I made the following edit:
// Drupal pages created as Wordpress pages if (type.equals("page")) strType="page"; else strType="post"; // Drupal stories, forum posts, and normal posts are stored as Wordpress posts
Secondly, it appears I'd disobeyed a bit of recommended practice. My files directory was in an inproper location. So I had to tweak the following line to meet my needs:
After those changes, I ran the Java program locally again. It wiped the existing Wordpress content and performed the migration again. This time I found everything suitable. One of my primary concerns for SEO is that Drupal's clean URLs for the content would be migrated to matching clean URLs in Wordpress. The migration script preserved those URLs perfectly.
My organization had a staging environment where our new Wordpress site was getting themed and plugins configured. So, I felt the easiest way to get the migrated Drupal content from my local Wordpress environment to the staging environment was to use the export functionality locally. I then installed the Wordpress Importer plugin on the staging site and imported the file.
The final step was to take all the files from my Drupal filesystem and put them into /wp-content/uploads in our staging filesystem. All the Drupal content was migrated!
Luckily, our environment had the CiviCRM database separate from the CMS database. CiviCRM's table structures are the same, regardless of which CMS you use. This CiviCRM community forum post highlights several brave souls who've attempted the task before me. I found this thread and message most useful. So I took a full database export of the production CiviCRM data to be thorough and imported it into our staging CiviCRM database. Secondly, I took separate export as the forum poster suggested with the default options except:
I then installed the CiviCRM 4.1.6 plugin on our staging Wordpress site and configured it to connect to the staging CiviCRM database. I noted that upon initial configuration of the plugin, it wipes existing data in the CiviCRM tables even though I'd connected to a database with data. This is where the forum poster's suggestion came in useful. I used the second export described above (with the drops) and imported it into the staging CiviCRM database. I visited the CiviCRM plugin within Wordpress only to be met with:
Warning: require_once(CRM/Core/ClassLoader.php) [function.require-once]: failed to open stream: No such file or directory in /my/path/wordpress/wp-content/plugins/civicrm/civicrm.php on line 121
Fatal error: require_once() [function.require]: Failed opening required 'CRM/Core/ClassLoader.php' (include_path='.:/my/path/wordpress/wp-content/plugins/civicrm/civicrm/:/my/path/wordpress/wp-content/plugins/civicrm/civicrm//packages:.:/usr/lib/php:/usr/local/lib/php') in /my/path/wordpress/wp-content/plugins/civicrm/civicrm.php on line 121
The cache files built by the initial installation in /my/path/wordpress/wp-content/plugins/files/civicrm were screwing things up. I just deleted the contents of that directory entirely and visited the CiviCRM plugin page again. CiviCRM rebuilt its cache and much to my surprise, CiviCRM could work with this data straight away!
Theoretically, one should be able to upgrade from 4.1.6 to 4.3.3 without issue. However, in my case, the upgrade progress bar page was showing only  with "Retry" and "Skip" buttons that wouldn't do anything. Through troubleshooting I was only able to upgrade as far as CiviCRM 4.2.9 before I ran into that error.
Once I started to get settled in and explore the contact data, I noticed that each time I logged in with my administrative account a new contact would get created with the name and email address from my Wordpress user account. Additionally, one of the other volunteer admins was seeing my email address populated into his contact record.
At first I thought this had something to do with Wordpress Access Control introduced in CiviCRM 4.3.0 and the fact that we'd set up multiple roles using User Role Editor. However, as I should have figured, it was an artifact of my Drupal migration process. The duplicate administrative contacts were caused by pairing CMS user IDs with CRM user IDs in the CIVI_UF_MATCH table. The old Drupal user IDs were being pointed at CiviCRM contact IDs. The other volunteer admin's Wordpress user ID was the same number as my old Drupal user ID, hence the fact that he saw my email address populated into his contact form fields. Additionally, as the aforementioned forum post describes the duplicating contact records was generally due to problems in the CIVI_UF_MATCH table. So I fixed that table up by hand, setting CIVI_UF_MATCH.UF_ID to the Wordpress user ID. Once complete, all the contact duplication problems were resolved. Based on my reading, I believe you could truncate the table and just run Administer » Users and Permissions » Synchronize Users to Contacts. However, as I said earlier my administrative user account population is fairly small (10-20) so fixing it by hand worked well enough for me.
Another issue that cropped up had less to do with the migration and I believe is just generally a Wordpress/CiviCRM issue. The timestamps of our contact edits were coming up incorrect. It seems timezone information is read from the wp-settings.php file rather than value configured in Settings. I had to change the following line in wp-settings.php:
// WordPress calculates offsets from UTC. date_default_timezone_set( 'UTC' );
Changing UTC to a valid PHP timezone string fixed the incorrect CiviCRM timestamps for us.
At the time of writing this article we've been up and running on the new CMS and CRM combination happily for several weeks. Hopefully this helps someone out. Feel free to comment! Thanks to all those above who shared their code and to forum community members followed up with their resolution. No one likes running into DenverCoder9.