On the ugly history of early open source CMSes (or why, surprisingly, I did not enjoy listening to Merlin Mann and John Gruber together in a podcast)

It was a perfect idea, or so I thought. Two of my favorite personalities from 5by5 podcasts were going to do a show together: John Gruber (of The Talk Show and Daring Fireball) was going to appear on Merlin Mann’s Back to Work podcast!

Unfortunately, when Merlin Mann’s fire met John Gruber’s ice, the result, like Derek Smalls, was lukewarm water.

Or maybe it was just because they spent the first several minutes of the podcast — all I managed to get through in one sitting (though to be sure, it’s all that’s relevant for this post) — talking about the early days of open source content management systems (CMSes). It maybe wasn’t really their fault. I reflexively dry heave when I hear words like PostNuke or Plone. They’re names I haven’t thought about in years, and haven’t thought about positively… well… ever. I dabbled with both of them in the early early days of CMSes, and quickly ran away.

But then Gruber and Mann (sounds like a comedy duo from the ’60s) got into something that really stings: they started professing love for Drupal (Merlin) and Movable Type (John). I cannot tell you how strongly I dislike both Drupal and Movable Type.

Gruber loves him some Movable Type

It’s been a point of pride for me since becoming a loyal Daring Fireball reader that I do not like Movable Type. The fact that Gruber uses Movable Type for Daring Fireball and is a vocal supporter of the platform, and the fact that I loathe Movable Type, is something I use to prove that I have not just become a devoted Gruber acolyte. I still think independently; I just happen to agree with him on almost everything he writes about.

One of Gruber’s biggest reasons for liking Movable Type, apparently, is the fact that it doesn’t serve content from the database; it publishes the entire site out to static HTML files. This is great for server performance under heavy loads, and has probably allowed him to continue to run Daring Fireball with a much lower-powered server than he’d need if he were using a database-intensive CMS. But in my own experience it also makes the process of using Movable Type a chore. Perhaps that’s because I’ve never actually used it directly myself; my work with it has been limited to setting up templates/themes/whatever-they-call-them-in-MT for other people. MT’s tools for working with stylesheets and templates are cumbersome, MT’s proprietary scripting language is tedious for “non-natives” like me, and having to republish the entire site to see changes to the templates is a real pain in the ass.

On the other hand, Gruber loves to rip on my personal favorite open source CMS (though surely he doesn’t know, nor would he care, that it’s my favorite), WordPress. And it is precisely because WordPress doesn’t publish static pages the way MT does that he hates it so much. He commonly refers to sites that crash under the weight of his referral traffic as being “fireballed” (clever), and sites running a stock installation of WordPress are notorious for this. But there are several caching plugins available for WordPress that can greatly boost its ability to handle peak traffic, in a much less intrusive way than MT’s static HTML publishing process. My plugin of choice these days is Quick Cache. The plugin’s tagline says it all: “Speed Without Compromise.” (I’m not-so-secretly hoping that Gruber links to this post on Daring Fireball, but then again, I’m not sure I want to risk being proven wrong.)

Merlin and Drupal, sittin’ in a tree

And then there’s Merlin, and Drupal. Oh, Merlin. Again my experience with Drupal is fairly limited. I tried using it to run this site for a brief period (which you can probably find if you dig in the archives… I believe it was around early 2006). I very quickly gave up. Drupal’s admin interface was clunky and unintuitive, but it was the fact that my site was almost instantly drowning in comment spam that killed the deal for me. In the time since then the only work I’ve done with Drupal has been focused on helping people move their sites off of it, but the fact that so many people want to do that says enough for me.

I find two major issues with a lot of open source CMSes (like Joomla and MODx, to name two others I’ve tried in the past) that are perfectly exemplified by Drupal and Movable Type.

First, unless you really know what you’re doing and put a lot of effort into it, your Drupal site is going to look like a Drupal site. (Yes, it’s true that as I am writing this I’m using a more-or-less stock WordPress template, so my site looks like WordPress, but that’s not the point; it’s easy to build a completely custom WordPress theme from scratch with little more than basic HTML/CSS skills.)

Second, and I touched on this with Movable Type, many of these systems have their own custom scripting languages or other idiosyncrasies to be learned, such that learning to use these systems is not substantially easier than just learning to code HTML/CSS.

Of course, I know how to code HTML and CSS. That’s my job. I have “visual” mode disabled in the editor in WordPress. A CMS exists not just to shield you from writing code, but to make it easy to manage, organize, and re-organize large amounts of site content, while maintaining a consistent look and feel. But a good CMS goes beyond that. A good CMS puts the power to manage the website in the hands of people who don’t know, and don’t want to know, how to write code.

A little background

As I listened to Merlin Mann and John Gruber wistfully recall the glory days of crappy CMSes, I wondered why they had devoted so much time and attention to learning and working with those systems, while at the same time I had rejected them out of hand. (I also wondered why they were at roughly the same place in their careers as I was at the time, and now they’re “famous,” but that’s beside the point… or maybe not… read on.) Then it hit me: I didn’t like those CMSes because I had already built a few of my own and I liked them better.

Now, it’s true that I liked my CMSes better partly because, well, I had built them. And I think Merlin was spot-on in the podcast when he said that most systems worked great if you thought just like the developer. (Specifically, he said that Basecamp works great if you think like Jason Fried.) That’s a great point, and one I should not overlook. But there’s another aspect to this. Most of these open source CMSes are developed by online communities of… well… geeks. Sure, they take feature requests from users (I assume), but ultimately the main people giving the developers feedback on how the systems should work are other developers.

I’ve built a number of CMSes over my career. They’ve all been built to meet specific client/user needs, and always in direct consultation with those clients/users. Has that made them perfect, or made me impervious to casting my CMSes in my own image? Of course not. But it’s made it harder to hide away in my geek cave and crank out systems that only other geeks can use.

The first CMS I built was in the heady days of early 2000, just before the dot-com bust. I was working for a certain big box retailer’s dot-com subsidiary. (This was back in the days when certain big box retailers believed they could spin off dot-com subsidiaries as independent companies that issued their own stock and everyone got rich yay!!!)

The company had invested 7 figures in some colossal enterprise CMS that was going to take several months and thousands of hours of consultant time to customize to our needs. In the meantime, our staff of writers (yes, we had writers producing informative weekly articles for each “department” of the online store) would deliver their content to me and to the one other front-end developer who was good at HTML (I know, right?), and we were to manually convert them into HTML and put them into the static pages of the site. (As front-end developers, we were strictly forbidden any database access. Because, you know, we were dangerous. We might put HTML in it.)

After a few weeks, I decided this was a ridiculous arrangement, so over the weekend I scraped together a quick-and-dirty, database-free CMS that would allow the writers to enter their content directly. The system would merge their content with prebuilt page templates, and save the output as static HTML pages on the server.

And so a career as a CMS developer was born.

At my next several jobs, I built more CMSes, honing the process each time (and always starting from scratch, since my previous work was the IP of my former employers). And eventually, when I went out on my own in 2008 (not to mention my first failed attempt at full-time freelancing, in 2003, which is going to be the subject of a future post), it was natural that I’d create my own CMS, and this time since I own the IP, I can keep building on it and expanding its capabilities.

Does my CMS have the polish and ease-of-use of WordPress? Probably not, although I’ve had more than one client (more than two, even!) tell me they prefer my CMS over WordPress. But the stock version of WordPress has a fairly limited scope of capabilities (you’ve got your pages and you’ve got your posts and, hey, why would you need anything else?), and my CMS is more modular, with a number of other capabilities (built in event calendar with registration, ecommerce, custom forms, etc.) that can be turned on or off to suit the needs of the client. WordPress is highly extensible with plugins, of course, but I find that, in short, if a client needs a custom solution, they need a custom solution. My CMS is a shortcut to a custom solution.

So that’s why!

Along this mental journey through the littered landscape of dead (or dying) content management systems, I learned a few things. I learned why I never fell in love with those early CMSes. And I think I probably also learned why I’m not “famous” in the field of tech bloggers/podcasters. I’ve been too busy reinventing my own wheel for much of the past decade to have the time to devote to self-promotion (and I don’t mean that as a slight against Gruber and Mann) necessary to achieve that level of recognition.

Migrating from CakePHP 1.2 to 1.3: My Story (Part One of… Possibly More than One)

For the past couple of years I’ve been working on a rapidly evolving CMS project called, not-so-creatively, cms34. It’s built on the open source CakePHP framework.

I love CakePHP. I’ve dabbled with a couple of other frameworks (notably, Zend Framework), and while CakePHP certainly isn’t perfect, I’ve found it by far the easiest to jump into and quickly get a powerful and reliable web application running.

When I started cms34 in late 2008, it was using CakePHP 1.2.0. Since then I’ve kept up with most of the minor point releases, upgrading as far as the current version, 1.2.7, as easily as simply swapping out the cake directory. And in that time, cms34 itself has gone through several major and minor revisions, currently up to what I’m calling version 3.2.

In preparation for version 3.3, I’ve decided to take the plunge and upgrade from CakePHP 1.2.x to the newly released CakePHP 1.3.0. Version 1.3 offers a number of improvements, but it also includes the kinds of changes typical of a major point release that mean an upgrade is not such a simple task. I’ve run into a few issues with the migration from 1.2.x to 1.3.x, many of which are not covered in the project’s official migration documentation, partly due to the incompleteness of the documentation, and partly due to some idiosyncrasies of my application that I wouldn’t expect the documentation to cover. But since I’m probably not in this boat alone, I thought I’d share some of the problems I encountered, and the solutions I found.

Getting started: RTFM

First things first. Download CakePHP 1.3.0. Be sure to get the release version (the one in the list with no hyphenated qualifiers after “1.3.0”). Unzip it and then follow the migration instructions to get started. For the most part this means swapping out the cake directory along with a couple of other files, and then going through all of the notes and making any necessary changes to your application.

In my own experience, I didn’t have to change much: I’ve been trying to keep up with the recommendations in the version 1.2 docs, so I haven’t been using any functionality that got dropped or deprecated. The writing has been on the wall for some time with most of these features and unless your application started with version 1.1 or 1.0, you’re probably not using any of these dead methods anyway.

A few specific issues I did need to address:

  1. Unlike with minor 1.2.x updates, there are a few files outside of the cake directory that need to be replaced. I found it best to just go through the entire release package and replace all files (except those I had modified) with their new versions.
  2. Update your config/core.php file, using the new version as a model. Mine had lots of changes, and I had stripped out all of the instructional comments to make the file less cumbersome to deal with. I wanted to keep those comments stripped out, so I just updated my file with what I needed, and then I kept the distribution’s version of the file in config as core.dist.php so I can refer back to it in the future if I run into any issues.
  3. There are some mixed messages in the documentation regarding the deprecation of AjaxHelper: the migration appendix says it’s deprecated but the main documentation doesn’t indicate that. I’m using it a fair amount and don’t want to have to rework all of that code, so for now I’m leaving it alone.
  4. JavascriptHelper is another matter, but since it appears there are perfect replacements for its functions now in HtmlHelper, I just did a straight-up find-and-replace, changing all instances of $javascript->link() to $html->script() and $javascript->codeBlock() to $html->scriptBlock(). I should note that so far I haven’t really tested any of this functionality to ensure that it’s still working, but no obvious errors have cropped up.

But wait, there’s more!

After following the migration docs, I was overly optimistic that things would just work. They didn’t. First up, I encountered this:

Notice (8): Undefined property: PagesController::$Session
[APP/controllers/app_controller.php, line 383]

Your line number will probably be different, but if you’re using sessions at all (and why wouldn’t you be?), you’ll get this error somewhere. It’s not mentioned in the migration docs, but I found out here that the Session component and helper are not instantiated automatically anymore. The solution is quite easy though. In app_controller.php just make sure that you add 'Session' to the arrays defined for var $components and var $helpers.

That was the biggest and most obvious problem I encountered. Once I had fixed that, I could at least get (some) pages to load, albeit with a few other issues. Namely, my theme was not being applied to the site. I’ll get to that in a minute though, because the problem I decided to fix next came in my CMS admin interface.

Pagination (even if you don’t want it)

I use the PaginatorHelper a lot, especially in the CMS admin. My CMS is modular: there’s a “module” (my term for any model-view-controller group) for pages, a module for blog posts, a module for uploaded files, a module for project porfolios, a module for the event calendar, etc. Each module is represented in the admin interface by a navigation tab, which when clicked takes the user to an index page with a paginated, tabular list of all of the records in the database for that module. In practice (on my own site — yes, I use my CMS to run my own site, of course!), it looks like this:

Unfortunately, the pagination was mysteriously hosed, with the following error:

Unsupported operand types in CAKE/libs/view/helpers/paginator.php
on line 616

What the…? Well, as it turns out, the methods $paginator->prev(), $paginator->next() and $paginator->numbers() have had changes to their input parameters that are currently not very well documented, in that the documentation doesn’t mention that they exist. They are mentioned in the API, but as usually happens when I refer to the API, I found it wanting, to the point that I resorted to digging into the source code directly to try to make sense of what these methods actually do.

In short, where you could previously pass these methods a URL as a string (as the second parameter for prev() and next() and the first for numbers()), now they expect arrays. And numbers(), in particular, really doesn’t like that parameter to be a string (because at one point it uses the += operator to merge two arrays, one of which is the first input parameter), resulting in the Unsupported operand type error.

Fortunately, in my case at least, I found that I didn’t need to pass the URL into any of these methods at all, and that just removing them altogether from the calls fixed the problem.

There was an ancillary problem once I got past the PHP error: inactive “Previous” and “Next” links were appearing on the page when there was no pagination. This was an unwanted addition, but I quickly realized this was an intentional change, and is well-documented. I was able quite easily to make them go away with a little CSS:

span.prev, span.next { display: none; }

With that minor crisis resolved, I could move back to the matter of the theme not showing up.

Changing themes

First, some background on my CMS: I’ve built the application so that I can have a single “core” system that works for numerous client websites, organized in a way that it’s easy to deploy updates across a number of separate sites. The system is also built to support multiple sites running on a single installation (by way of a Site model, with every piece of data in every other model having a site_id field keying the content to the proper site).

There are two key features of CakePHP that I rely on to make this all work: the look-and-feel (and site-specific view functionality) of each site is managed using Themes, and any site-specific controllers and views are handled with Plugins.

It is documented, unfortunately not in the migration appendix, that version 1.3 of CakePHP has changed how theme assets (static files like images, JavaScript and CSS) are organized. Now, instead of placing these in a directory under app/webroot/themed, you create a webroot directory inside the appropriate theme folder in app/views/themed. This is nice, in that now all of the files for a theme are in one location. It can cause a performance hit though, as these files are now being processed through PHP. You can still put the files under app/webroot to avoid this performance hit, but, annoyingly, the path has changed, as noted in the documentation. I decided to go with the new approach under app/views, as performance is not a major issue with the current implementations of my CMS, and the benefit of a single, consolidated directory for each theme is worth the trade-off. If performance does become an issue, though, at least now I know what to do about it.

More to come…?

After completing the above changes, I spent some time exploring my test application, both the user-facing site and the CMS admin interface, and so far I haven’t come across any other problems. Which is not to say I’m ready to roll this out to all of my clients tomorrow morning. I want to make the switch soon, as maintaining two separate code bases is a cumbersome task for a solo freelancer. But while things look good for now, this kind of major upgrade requires some solid testing and troubleshooting. If I run across any other issues, I’ll post them in Part Two.

New room34/music site launched

My brief foray with Bandcamp is over, and a brand new room34/music site has officially launched!

This new version, I am proud to say, runs on cms34, a Content Management System I developed based on the CakePHP framework. I’ve been running numerous client sites on it for the past couple of years, along with my own Room 34 Creative Services site, but this is the first time I’ve really pushed its capabilities on a site of my own. The site has a few tricks up its sleeve (although most are in the admin interface right now), and more is on the way, including automatic transcoding of MP3s into Ogg Vorbis format for playback in the Firefox and Chrome web browsers.

Yadda yadda yadda. It’s not about the web geekitude (well, maybe for me it is)… it’s about the music. I’ve posted streaming and downloadable MP3s, cover art, background information, and CD purchase links for about a half dozen of my most recent projects, and over the coming weeks I’ll be filling in the rest of my “back catalog” going back to at least 2001, and perhaps even to my debut “album” from 1992, if I can round up the old cassette currently decaying in a box in the basement somewhere.