5 Steps to Moving from BlogCFC to MachBlog
In my case it was simply that the rest of my site is written in Mach ii. I wanted to leverage that site-wide allowing me to, for example, better integrate things like the ColdFusion Open-Source List with my blog. Part of this means customizing the blog functionality and it is my personal feeling that, while both BlogCFC and MachBlog are open-source and therefore customizable, MachBlog's use of a framework also makes it easier to comprehend, modify and maintain. I am sure that if Ray were to build BlogCFC today, he would use Model-Glue for these very reasons, so this is not meant as a criticism of BlogCFC, which has worked well and has a rich feature set in comparison to MachBlog at this point in time.
Getting Started
First, of course, you need to downoad MachBlog which is available at machblog.com, though Peter Farrell recommended I pull the SVN version as it is more up to date (http://svn1.cvsdude.com/mpwoodward/machblog). Next you will need both the Mach ii and ColdSpring frameworks, which you can put in the root of your local site.
The next thing I did was make some basic setup changes to the /config/mach-ii.xml.cfm file so that it was up and running for me to test my imports from BlogCFC. I also needed to avoid the machblog mapping for various reasons. This simply took a site-wide find and replace for "machblog. with just " and "/machblog with just " (you need the quote because there is a subfolder also called machblog under /org and leaving out the quote will kill all references to this folder).
1. Backup Your Current Install and Database
This seems obvious of course, but even though I won't discuss removing the old BlogCFC tables this is a key step before making any significant change (actually the tblBlogEntries plays a role in my code to support older entries). I started by backing up my remote MySQL database and restoring locally so that I would have all my entries.
You will also need to run the relevant database script for MachBlog. I chose to use the same database for my MachBlog tables as my BlogCFC ones. The code below assumes you have done that, and, as I said earlier, we will still refer to the old data to keep all our old URLs working, so keeping them in the same database makes sense.
2. Import Your Entries
My ColdFusion script that imports all your BlogCFC entries is based heavily upon the one provided and written by Andrew Powell for use with MSSQL datasources. This script has been tested against MySQL but should work for just about any type of datasource as there really isn't anything rdbms specific in here. I put this code in a template I called BlogCFCtoMachBlog.cfm which is in the zip attached to this post.
On another note, my BlogCFC install was older, so I had to comment out references to the views, released and mailed columns in the code (which were replaced with 0, 1 and 1 respectively in the insert statement).
<cfset dsn = "your_dsn"> <cfquery name="getUser" datasource="#dsn#"> select user_id from machblog_user WHERE first_name ='Default' AND last_name = 'User' </cfquery> <cfset user = getUser.user_id> <P>
<cfquery name="deletecat" datasource="#dsn#"> DELETE FROM machblog_comment </cfquery> <cfquery name="deletecat" datasource="#dsn#"> DELETE FROM machblog_category </cfquery> <cfquery name="deletecat" datasource="#dsn#"> DELETE FROM machblog_entry </cfquery> <cfquery name="deletecat" datasource="#dsn#"> DELETE FROM machblog_entry_category </cfquery> <P>
<cfquery name="insertCategories" datasource="#dsn#"> INSERT INTO machblog_category(category_id,category_name,created_by_id,dt_created,ip_created,is_active) SELECT categoryID, categoryName, '#user#', #DateDiff("s", DateConvert("utc2Local", "January 1 1970 00:00"), now())#000, '0.0.0.0', 1 FROM tblBlogCategories </cfquery> <P>
<cfquery name="getBlogCFCEntries" datasource="#dsn#"> SELECT * FROM tblBlogEntries </cfquery> <cfloop query="getBlogCFCEntries"> <cfquery name="insertEntries" datasource="#dsn#"> INSERT INTO machblog_entry(entry_id,title,body,dt_posted, dt_created,more_body,created_by_id,allow_comments,enclosure,enclosure_size,enclosure_mime_type,num_views,is_active,subscriber_email_sent,ip_created,allow_trackbacks) VALUES ('#getBlogCFCEntries.id#', <cfqueryparam cfsqltype="cf_sql_varchar" value="#getBlogCFCEntries.title#"/>, <cfqueryparam cfsqltype="cf_sql_varchar" value="#getBlogCFCEntries.body#"/>, #DateDiff("s", DateConvert("utc2Local", "January 1 1970 00:00"), getBlogCFCEntries.posted)#000, #DateDiff("s", DateConvert("utc2Local", "January 1 1970 00:00"), getBlogCFCEntries.posted)#000,<cfqueryparam cfsqltype="cf_sql_varchar" value="#getBlogCFCEntries.morebody#" />, '#user#', #getBlogCFCEntries.allowcomments#, '#getBlogCFCEntries.enclosure#',#getBlogCFCEntries.filesize#,'#getBlogCFCEntries.mimetype#',#getBlogCFCEntries.views#,#getBlogCFCEntries.released#,#getBlogCFCEntries.mailed#,'0.0.0.0',0) </cfquery> </cfloop> <P>
<cfquery name="insertEntryCategories" datasource="#dsn#"> INSERT INTO machblog_entry_category(entry_id,category_id) SELECT DISTINCT entryIDFK,categoryIDFK FROM tblBlogEntriesCategories </cfquery> <P>
<cfquery name="getBlogCFCComments" datasource="#dsn#"> SELECT * FROM tblBlogComments </cfquery> <cfloop query="getBlogCFCComments"> <cfquery name="insertComments" datasource="#dsn#"> INSERT INTO machblog_comment(comment_id,entry_id,name,email,comment,dt_created,is_subscribed,url,is_active,ip_created) VALUES ('#getBlogCFCComments.id#','#getBlogCFCComments.entryidfk#','#getBlogCFCComments.name#','#getBlogCFCComments.email#',<cfqueryparam cfsqltype="cf_sql_varchar" value="#getBlogCFCComments.comment#"/>,#DateDiff("s", DateConvert("utc2Local", "January 1 1970 00:00"), getBlogCFCComments.posted)#000,#getBlogCFCComments.subscribe#,<cfqueryparam cfsqltype="cf_sql_varchar" value="#getBlogCFCComments.website#"/>,1,'0.0.0.0') </cfquery> </cfloop>
After running this page, you should be able to run your local MachBlog install and see all your posts there just as they should be. Also, since the IDs are the same as the old IDs, translating old URLs into new ones isn't very difficult. Let's look at how.
3. Fix Old URL Links
First of all, BlogCFC used Friendly URLs (or SES URLs as some call them). While it is a priority feature for the next release of MachBlog (which I have actually committed myself to writing), it is currently not a supported feature. However, we can parse your old SES URLs using some of Ray's BlogCFC code and make sure the person linking ot a preexisting page gets to the right page. In my case, I also had some links that were from before BlogCFC implemented Friendly URLs, and those can be handled with a simple redirect.
However, direct page links aren't the only things to consider. Some people may have bookmarked a category or a day or month based link. The following script takes care of all those types of redirects so that just about any link someone had to your site should still work. I placed this file (index.cfm) in the directory of my old BlogCFC install since my BlogCFC and my MachBlog install directories are different. If they are the same, you will have a little more work to do since they would need to share an index.cfm file. Here's the code (which as you can see, takes liberally from Ray's parseses.cfm file):
<cfsetting enablecfoutputonly=true> <cfprocessingdirective pageencoding="utf-8"> <P>
<cfscript> /** * Parses my SES format. Demands /YYYY/MMMM/TITLE or /YYYY/MMMM/DDDD/TITLE * One line from MikeD * * @author Raymond Camden (ray@camdenfamily.com) * @version 1, June 23, 2005 */ function parseMySES() { //line below from Mike D. var urlVars=reReplaceNoCase(trim(cgi.path_info), '.+\.cfm/? *', ''); var r = structNew(); var theLen = listLen(urlVars,"/"); <P>
if(theLen lte 2) return r; r.year = listFirst(urlVars,"/"); r.month = listGetAt(urlVars,2,"/"); if(theLen is 4) { r.day = listGetAt(urlVars,3,"/"); } <P>
//r.title = replace(listLast(urlVars,"/"),"_"," ","all"); r.title = listLast(urlVars, "/"); return r; } </cfscript> <P>
<!--- if the entry already defined in the URL for old non-SES URLs ---> <cfif structKeyExists(url,"entry")> <cflocation url="/index.cfm?event=showEntry&entryId=#url.entry#" addtoken="false" /> </cfif> <P>
<!--- if someone came in with a category id ---> <cfif structKeyExists(url,"catid")> <cflocation url="/index.cfm?event=showEntriesByCategory&categoryId=#url.catid#" addtoken="false" /> </cfif> <P>
<!--- if someone is coming in with a date link ---> <cfif structKeyExists(url,"month") and structKeyExists(url,"year")> <cflocation url="http://remotesynth/index.cfm?event=showEntriesByMonth&month=#url.month#&year=#url.year#" addtoken="false" /> </cfif> <P>
<!--- Try to load my info from the URL ... ---> <cfset sesInfo = parseMySES() /> <P>
<cfif structIsEmpty(sesInfo)> <cflocation url="/index.cfm" addtoken="false" /> </cfif> <P>
<cfset datePosted = sesInfo.year & "-" & sesInfo.month & "-" & sesInfo.day /> <P>
<cfquery name="getOldURL" datasource="remotesy"> SELECT id FROM tblBlogEntries WHERE alias = <cfqueryparam cfsqltype="cf_sql_varchar" value="#sesInfo.title#" /> AND dateDiff(posted,<cfqueryparam value="#datePosted#" />) >=-1 </cfquery> <cfif getOldURL.recordCount eq 0> <cflocation url="/index.cfm" addtoken="false" /> <cfelse> <cflocation url="/index.cfm?event=showEntry&entryId=#getOldURL.id#" addtoken="false" /> </cfif>
Now you should go ahead and test some of your old format links and you will see that you are directed to the proper pages on MachBlog. However, many of your readers may never even visit your page and rather read the pages via RSS, and we need a solution for them.
4. Fix Old RSS Links
This step is much easier than the last, as the only two options for reading RSS is either to get the full feed or a category feed, which MachBlog also supports. I simply chose to do a redirect to the proper feed, as I have done this once in the past and it seemed to work just fine.
<cfif structKeyExists(url,"catid")> <cflocation url="/index.cfm?event=showCategoryRss&categoryId=#url.catid#"> <cfelse> <cflocation url="/index.cfm?event=showBlogRss" addtoken="false" /> </cfif>
5. Copy Enclosures
After the prior four steps you might feel you are done (I did), but you would have forgotten one important step. If any of your posts had enclosures, they are held in the "enclosures" directory beneath your BlogCFC install. I chose not to worry about direct links in this case as they would seem unlikely or infrequent. Therefore, I just downloaded all the files from my site and copied them into the "uploads/enclosures/" folder under my MachBlog install. That's it; now you are done.
Conclusion
Ok, so if you are me, you are not quite done. I have a lot of plans for the site including a new look that isn't yet supported as one of the included MachBlog skins. In addition, I hope to build better integration between the various sections of my site (like having related open-source projects with a post or integrating the open source updates with the list). This should be made easier not only because everything is now all running on Mach ii, but with the new module support in 1.5 beta, it should be more like plug and play (to a degree anyway). I also hope to integrate some new CF8 features into the site...so don't expect me to go live before 8 does. :) As I work through these portions of the site, I plan to cover some of these topics here as well.
